Atmos Debug Overlay expansion (#2626)

* Atmos Debug Overlay: Add a way of showing blocked directions

* Atmos Debug Overlay: Adjustable modes client-side

* Atmos Debug Overlay: Fix atvrange help text

* Atmos Debug Overlay: More flexible and clear gas ID specification
This commit is contained in:
20kdc
2020-11-28 13:45:52 +00:00
committed by GitHub
parent 97973c3e78
commit bb22da6827
7 changed files with 238 additions and 42 deletions

View File

@@ -54,7 +54,7 @@ namespace Content.Client.Atmos
var gridBounds = new Box2(mapGrid.WorldToLocal(worldBounds.BottomLeft), mapGrid.WorldToLocal(worldBounds.TopRight));
for (var pass = 0; pass < 3; pass++)
for (var pass = 0; pass < 2; pass++)
{
foreach (var tile in mapGrid.GetTilesIntersecting(gridBounds))
{
@@ -64,17 +64,65 @@ namespace Content.Client.Atmos
var data = (SharedAtmosDebugOverlaySystem.AtmosDebugOverlayData) dataMaybeNull!;
if (pass == 0)
{
// -- Mole Count --
float total = 0;
foreach (float f in data.Moles)
{
total += f;
switch (_atmosDebugOverlaySystem.CfgMode) {
case AtmosDebugOverlayMode.TotalMoles:
foreach (float f in data.Moles)
{
total += f;
}
break;
case AtmosDebugOverlayMode.GasMoles:
total = data.Moles[_atmosDebugOverlaySystem.CfgSpecificGas];
break;
case AtmosDebugOverlayMode.Temperature:
total = data.Temperature;
break;
}
var interp = total / (Atmospherics.MolesCellStandard * 2);
var res = Color.InterpolateBetween(Color.Red, Color.Green, interp).WithAlpha(0.75f);
var interp = ((total - _atmosDebugOverlaySystem.CfgBase) / _atmosDebugOverlaySystem.CfgScale);
Color res;
if (_atmosDebugOverlaySystem.CfgCBM)
{
// Greyscale interpolation
res = Color.InterpolateBetween(Color.Black, Color.White, interp);
}
else
{
// Red-Green-Blue interpolation
if (interp < 0.5f)
{
res = Color.InterpolateBetween(Color.Red, Color.Green, interp * 2);
}
else
{
res = Color.InterpolateBetween(Color.Green, Color.Blue, (interp - 0.5f) * 2);
}
}
res = res.WithAlpha(0.75f);
drawHandle.DrawRect(Box2.FromDimensions(mapGrid.LocalToWorld(new Vector2(tile.X, tile.Y)), new Vector2(1, 1)), res);
}
else if (pass == 1)
{
// -- Blocked Directions --
void CheckAndShowBlockDir(AtmosDirection dir)
{
if (data.BlockDirection.HasFlag(dir))
{
var atmosAngle = dir.ToAngle();
var atmosAngleOfs = atmosAngle.ToVec() * 0.45f;
var atmosAngleOfsR90 = new Vector2(atmosAngleOfs.Y, -atmosAngleOfs.X);
var tileCentre = new Vector2(tile.X + 0.5f, tile.Y + 0.5f);
var basisA = mapGrid.LocalToWorld(tileCentre + atmosAngleOfs - atmosAngleOfsR90);
var basisB = mapGrid.LocalToWorld(tileCentre + atmosAngleOfs + atmosAngleOfsR90);
drawHandle.DrawLine(basisA, basisB, Color.Azure);
}
}
CheckAndShowBlockDir(AtmosDirection.North);
CheckAndShowBlockDir(AtmosDirection.South);
CheckAndShowBlockDir(AtmosDirection.East);
CheckAndShowBlockDir(AtmosDirection.West);
// -- Pressure Direction --
if (data.PressureDirection != AtmosDirection.Invalid)
{
var atmosAngle = data.PressureDirection.ToAngle();
@@ -84,9 +132,7 @@ namespace Content.Client.Atmos
var basisB = mapGrid.LocalToWorld(tileCentre + atmosAngleOfs);
drawHandle.DrawLine(basisA, basisB, Color.Blue);
}
}
else if (pass == 2)
{
// -- Excited Groups --
if (data.InExcitedGroup)
{
var tilePos = new Vector2(tile.X, tile.Y);

View File

@@ -0,0 +1,125 @@
using JetBrains.Annotations;
using Robust.Client.Interfaces.Console;
using Content.Client.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems;
using Content.Shared.Atmos;
using System;
namespace Content.Client.Commands
{
[UsedImplicitly]
internal sealed class AtvRangeCommand : IConsoleCommand
{
public string Command => "atvrange";
public string Description => "Sets the atmos debug range (as two floats, start [red] and end [blue])";
public string Help => "atvrange <start> <end>";
public bool Execute(IDebugConsole console, params string[] args)
{
if (args.Length != 2)
{
console.AddLine(Help);
return false;
}
if (!float.TryParse(args[0], out var xStart))
{
console.AddLine("Bad float START");
return false;
}
if (!float.TryParse(args[1], out var xEnd))
{
console.AddLine("Bad float END");
return false;
}
if (xStart == xEnd)
{
console.AddLine("Scale cannot be zero, as this would cause a division by zero in AtmosDebugOverlay.");
return false;
}
var sys = EntitySystem.Get<AtmosDebugOverlaySystem>();
sys.CfgBase = xStart;
sys.CfgScale = xEnd - xStart;
return false;
}
}
[UsedImplicitly]
internal sealed class AtvModeCommand : IConsoleCommand
{
public string Command => "atvmode";
public string Description => "Sets the atmos debug mode. This will automatically reset the scale.";
public string Help => "atvmode <TotalMoles/GasMoles/Temperature> [<gas ID (for GasMoles)>]";
public bool Execute(IDebugConsole console, params string[] args)
{
if (args.Length < 1)
{
console.AddLine(Help);
return false;
}
if (!Enum.TryParse<AtmosDebugOverlayMode>(args[0], out var xMode))
{
console.AddLine("Invalid mode");
return false;
}
int xSpecificGas = 0;
float xBase = 0;
float xScale = Atmospherics.MolesCellStandard * 2;
if (xMode == AtmosDebugOverlayMode.GasMoles)
{
if (args.Length != 2)
{
console.AddLine("A target gas must be provided for this mode.");
return false;
}
if (!AtmosCommandUtils.TryParseGasID(args[1], out xSpecificGas))
{
console.AddLine("Gas ID not parsable or out of range.");
return false;
}
}
else
{
if (args.Length != 1)
{
console.AddLine("No further information is required for this mode.");
return false;
}
if (xMode == AtmosDebugOverlayMode.Temperature)
{
// Red is 100C, Green is 20C, Blue is -60C
xBase = Atmospherics.T20C + 80;
xScale = -160;
}
}
var sys = EntitySystem.Get<AtmosDebugOverlaySystem>();
sys.CfgMode = xMode;
sys.CfgSpecificGas = xSpecificGas;
sys.CfgBase = xBase;
sys.CfgScale = xScale;
return false;
}
}
[UsedImplicitly]
internal sealed class AtvCBMCommand : IConsoleCommand
{
public string Command => "atvcbm";
public string Description => "Changes from red/green/blue to greyscale";
public string Help => "atvcbm <true/false>";
public bool Execute(IDebugConsole console, params string[] args)
{
if (args.Length != 1)
{
console.AddLine(Help);
return false;
}
if (!bool.TryParse(args[0], out var xFlag))
{
console.AddLine("Invalid flag");
return false;
}
var sys = EntitySystem.Get<AtmosDebugOverlaySystem>();
sys.CfgCBM = xFlag;
return false;
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using Content.Client.Atmos;
using Content.Shared.GameObjects.EntitySystems.Atmos;
using Content.Shared.Atmos;
using Content.Shared.GameTicking;
using JetBrains.Annotations;
using Robust.Client.Interfaces.Graphics.Overlays;
@@ -20,6 +21,19 @@ namespace Content.Client.GameObjects.EntitySystems
private readonly Dictionary<GridId, AtmosDebugOverlayMessage> _tileData =
new();
// Configuration set by debug commands and used by AtmosDebugOverlay {
/// <summary>Value source for display</summary>
public AtmosDebugOverlayMode CfgMode;
/// <summary>This is subtracted from value (applied before CfgScale)</summary>
public float CfgBase = 0;
/// <summary>The value is divided by this (applied after CfgBase)</summary>
public float CfgScale = Atmospherics.MolesCellStandard * 2;
/// <summary>Gas ID used by GasMoles mode</summary>
public int CfgSpecificGas = 0;
/// <summary>Uses black-to-white interpolation (as opposed to red-green-blue) for colourblind users</summary>
public bool CfgCBM = false;
// }
public override void Initialize()
{
base.Initialize();
@@ -83,4 +97,11 @@ namespace Content.Client.GameObjects.EntitySystems
return srcMsg.OverlayData[relative.X + (relative.Y * LocalViewRange)];
}
}
internal enum AtmosDebugOverlayMode
{
TotalMoles,
GasMoles,
Temperature
}
}

View File

@@ -144,20 +144,13 @@ namespace Content.Server.Atmos
public string Help => "addgas <X> <Y> <GridId> <Gas> <moles>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
{
var gasId = -1;
var gas = (Gas) (-1);
if (args.Length < 5) return;
if(!int.TryParse(args[0], out var x)
|| !int.TryParse(args[1], out var y)
|| !int.TryParse(args[2], out var id)
|| !(int.TryParse(args[3], out gasId) || Enum.TryParse(args[3], true, out gas))
|| !(AtmosCommandUtils.TryParseGasID(args[3], out var gasId))
|| !float.TryParse(args[4], out var moles)) return;
if (gas != (Gas) (-1))
{
gasId = (int)gas;
}
var gridId = new GridId(id);
var mapMan = IoCManager.Resolve<IMapManager>();
@@ -198,14 +191,7 @@ namespace Content.Server.Atmos
return;
}
if (gasId != -1)
{
tile.Air.AdjustMoles(gasId, moles);
gam.Invalidate(indices);
return;
}
tile.Air.AdjustMoles(gas, moles);
tile.Air.AdjustMoles(gasId, moles);
gam.Invalidate(indices);
}
}
@@ -218,16 +204,11 @@ namespace Content.Server.Atmos
public string Help => "fillgas <GridId> <Gas> <moles>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
{
var gasId = -1;
var gas = (Gas) (-1);
if (args.Length < 3) return;
if(!int.TryParse(args[0], out var id)
|| !(int.TryParse(args[1], out gasId) || Enum.TryParse(args[1], true, out gas))
|| !(AtmosCommandUtils.TryParseGasID(args[1], out var gasId))
|| !float.TryParse(args[2], out var moles)) return;
if (gas != (Gas) (-1))
gasId = (int)gas;
var gridId = new GridId(id);
var mapMan = IoCManager.Resolve<IMapManager>();
@@ -256,14 +237,7 @@ namespace Content.Server.Atmos
foreach (var tile in gam)
{
if (gasId != -1)
{
tile.Air?.AdjustMoles(gasId, moles);
gam.Invalidate(tile.GridIndices);
continue;
}
tile.Air?.AdjustMoles(gas, moles);
tile.Air?.AdjustMoles(gasId, moles);
gam.Invalidate(tile.GridIndices);
}
}

View File

@@ -104,7 +104,7 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
var gases = new float[Atmospherics.TotalNumberOfGases];
if (tile?.Air == null)
{
return new AtmosDebugOverlayData(0, gases, AtmosDirection.Invalid, false);
return new AtmosDebugOverlayData(0, gases, AtmosDirection.Invalid, false, tile?.BlockedAirflow ?? AtmosDirection.Invalid);
}
else
{
@@ -112,7 +112,7 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
{
gases[i] = tile.Air.GetMoles(i);
}
return new AtmosDebugOverlayData(tile.Air.Temperature, gases, tile.PressureDirectionForDebugOverlay, tile.ExcitedGroup != null);
return new AtmosDebugOverlayData(tile.Air.Temperature, gases, tile.PressureDirectionForDebugOverlay, tile.ExcitedGroup != null, tile.BlockedAirflow);
}
}

View File

@@ -0,0 +1,28 @@
#nullable enable
using System;
using Content.Shared.Atmos;
namespace Content.Shared.Atmos
{
public class AtmosCommandUtils
{
/// <summary>
/// Gas ID parser for atmospherics commands.
/// This is so there's a central place for this logic for if the Gas enum gets removed.
/// </summary>
public static bool TryParseGasID(string str, out int x)
{
x = -1;
if (Enum.TryParse<Gas>(str, true, out var gas))
{
x = (int) gas;
}
else
{
if (!int.TryParse(str, out x))
return false;
}
return ((x >= 0) && (x < Atmospherics.TotalNumberOfGases));
}
}
}

View File

@@ -23,13 +23,15 @@ namespace Content.Shared.GameObjects.EntitySystems.Atmos
public readonly float[] Moles;
public readonly AtmosDirection PressureDirection;
public readonly bool InExcitedGroup;
public readonly AtmosDirection BlockDirection;
public AtmosDebugOverlayData(float temperature, float[] moles, AtmosDirection pressureDirection, bool inExcited)
public AtmosDebugOverlayData(float temperature, float[] moles, AtmosDirection pressureDirection, bool inExcited, AtmosDirection blockDirection)
{
Temperature = temperature;
Moles = moles;
PressureDirection = pressureDirection;
InExcitedGroup = inExcited;
BlockDirection = blockDirection;
}
}