Files
tbd-station-14/Content.Client/Administration/UI/SpawnExplosion/ExplosionDebugOverlay.cs
2023-10-19 12:34:31 -07:00

199 lines
6.5 KiB
C#

using System.Linq;
using System.Numerics;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Enums;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
namespace Content.Client.Administration.UI.SpawnExplosion;
[UsedImplicitly]
public sealed class ExplosionDebugOverlay : Overlay
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
public Dictionary<int, List<Vector2i>>? SpaceTiles;
public Dictionary<EntityUid, Dictionary<int, List<Vector2i>>> Tiles = new();
public List<float> Intensity = new();
public float TotalIntensity;
public float Slope;
public ushort SpaceTileSize;
public override OverlaySpace Space => OverlaySpace.WorldSpace | OverlaySpace.ScreenSpace;
public Matrix3 SpaceMatrix;
public MapId Map;
private readonly Font _font;
public ExplosionDebugOverlay()
{
IoCManager.InjectDependencies(this);
var cache = IoCManager.Resolve<IResourceCache>();
_font = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 8);
}
protected override void Draw(in OverlayDrawArgs args)
{
if (Map != args.Viewport.Eye?.Position.MapId)
return;
if (Tiles.Count == 0 && SpaceTiles == null)
return;
switch (args.Space)
{
case OverlaySpace.ScreenSpace:
DrawScreen(args);
break;
case OverlaySpace.WorldSpace:
DrawWorld(args);
break;
}
}
private void DrawScreen(OverlayDrawArgs args)
{
var handle = args.ScreenHandle;
Box2 gridBounds;
var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
var xformSystem = _entityManager.System<TransformSystem>();
foreach (var (gridId, tileSets) in Tiles)
{
if (!_entityManager.TryGetComponent(gridId, out MapGridComponent? grid))
continue;
var gridXform = xformQuery.GetComponent(gridId);
var (_, _, matrix, invMatrix) = xformSystem.GetWorldPositionRotationMatrixWithInv(gridXform, xformQuery);
gridBounds = invMatrix.TransformBox(args.WorldBounds).Enlarged(grid.TileSize * 2);
DrawText(handle, gridBounds, matrix, tileSets, grid.TileSize);
}
if (SpaceTiles == null)
return;
gridBounds = Matrix3.Invert(SpaceMatrix).TransformBox(args.WorldBounds);
DrawText(handle, gridBounds, SpaceMatrix, SpaceTiles, SpaceTileSize);
}
private void DrawText(
DrawingHandleScreen handle,
Box2 gridBounds,
Matrix3 transform,
Dictionary<int, List<Vector2i>> tileSets,
ushort tileSize)
{
for (var i = 1; i < Intensity.Count; i++)
{
if (!tileSets.TryGetValue(i, out var tiles))
continue;
foreach (var tile in tiles)
{
var centre = (tile + Vector2Helpers.Half) * tileSize;
// is the center of this tile visible to the user?
if (!gridBounds.Contains(centre))
continue;
var worldCenter = transform.Transform(centre);
var screenCenter = _eyeManager.WorldToScreen(worldCenter);
if (Intensity[i] > 9)
screenCenter += new Vector2(-12, -8);
else
screenCenter += new Vector2(-8, -8);
handle.DrawString(_font, screenCenter, Intensity[i].ToString("F2"));
}
}
if (tileSets.TryGetValue(0, out var set))
{
var epicenter = set.First();
var worldCenter = transform.Transform((epicenter + Vector2Helpers.Half) * tileSize);
var screenCenter = _eyeManager.WorldToScreen(worldCenter) + new Vector2(-24, -24);
var text = $"{Intensity[0]:F2}\nΣ={TotalIntensity:F1}\nΔ={Slope:F1}";
handle.DrawString(_font, screenCenter, text);
}
}
private void DrawWorld(in OverlayDrawArgs args)
{
var handle = args.WorldHandle;
Box2 gridBounds;
var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
var xformSystem = _entityManager.System<TransformSystem>();
foreach (var (gridId, tileSets) in Tiles)
{
if (!_entityManager.TryGetComponent(gridId, out MapGridComponent? grid))
continue;
var gridXform = xformQuery.GetComponent(gridId);
var (_, _, worldMatrix, invWorldMatrix) = xformSystem.GetWorldPositionRotationMatrixWithInv(gridXform, xformQuery);
gridBounds = invWorldMatrix.TransformBox(args.WorldBounds).Enlarged(grid.TileSize * 2);
handle.SetTransform(worldMatrix);
DrawTiles(handle, gridBounds, tileSets, SpaceTileSize);
}
if (SpaceTiles == null)
return;
gridBounds = Matrix3.Invert(SpaceMatrix).TransformBox(args.WorldBounds).Enlarged(2);
handle.SetTransform(SpaceMatrix);
DrawTiles(handle, gridBounds, SpaceTiles, SpaceTileSize);
handle.SetTransform(Matrix3.Identity);
}
private void DrawTiles(
DrawingHandleWorld handle,
Box2 gridBounds,
Dictionary<int, List<Vector2i>> tileSets,
ushort tileSize)
{
for (var i = 0; i < Intensity.Count; i++)
{
var color = ColorMap(Intensity[i]);
var colorTransparent = color;
colorTransparent.A = 0.2f;
if (!tileSets.TryGetValue(i, out var tiles))
continue;
foreach (var tile in tiles)
{
var centre = (tile + Vector2Helpers.Half) * tileSize;
// is the center of this tile visible to the user?
if (!gridBounds.Contains(centre))
continue;
var box = Box2.UnitCentered.Translated(centre);
handle.DrawRect(box, color, false);
handle.DrawRect(box, colorTransparent);
}
}
}
private Color ColorMap(float intensity)
{
var frac = 1 - intensity / Intensity[0];
Color result;
if (frac < 0.5f)
result = Color.InterpolateBetween(Color.Red, Color.Orange, frac * 2);
else
result = Color.InterpolateBetween(Color.Orange, Color.Yellow, (frac - 0.5f) * 2);
return result;
}
}