Files
tbd-station-14/Content.Client/Administration/UI/SpawnExplosion/ExplosionDebugOverlay.cs
Leon Friedrich 56168e592e Explosion refactor (#5230)
* Explosions

* fix yaml typo

and prevent silly UI inputs

* oop

* Use modified contains() checks

And remove IEnumerable

* Buff nuke, nerf meteors

* optimize the entity lookup stuff a bit

* fix tile (0,0) error

forgot to do an initial Enumerator.MoveNext(), so the first tile was always the "null" tile.

* remove celebration

* byte -> int

* remove diag edge tile dict

* fix one bug

but there is another

* fix the other bug

turns out dividing a ushort leads to rounding errors.  Why TF is the grid tile size even a ushort in the first place.

* improve edge map

* fix minor bug

If the initial-explosion tile had an airtight entity on it, the tile was processed twice.

* some reviews (transform queries, eye.mapid, and tilesizes in overlays)

* Apply suggestions from code review

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>

* is map paused

* GetAllTiles ignores space by default

* WriteLine -> WriteError

* First -> FirstOrDefault()

* default prototype const string

* entity query

* misc review changes

* grid edge max distance

* fix fire texture defn

bad use of type serializer and ioc-resolves

* Remove ExplosionLaunched

And allow nukes to throw items towards the outer part of an explosion

* no hot-reload disclaimer

* replace prototype id string with int index

* optimise damage a tiiiiny bit.

* entity queries

* comments

* misc mirror comments

* cvars

* admin logs

* move intensity-per-state to prototype

* update tile event to ECS event

* git mv

* Tweak rpg & minibomb

also fix merge bug

* you don't exist anymore go away

* Fix build

Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2022-03-31 21:39:26 -05:00

194 lines
6.2 KiB
C#

using JetBrains.Annotations;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Enums;
using Robust.Shared.Map;
using System.Linq;
namespace Content.Client.Administration.UI.SpawnExplosion;
[UsedImplicitly]
public sealed class ExplosionDebugOverlay : Overlay
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
public Dictionary<int, List<Vector2i>>? SpaceTiles;
public Dictionary<GridId, 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>();
foreach (var (gridId, tileSets) in Tiles)
{
if (!_mapManager.TryGetGrid(gridId, out var grid))
continue;
var gridXform = xformQuery.GetComponent(grid.GridEntityId);
var (_, _, matrix, invMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(xformQuery);
gridBounds = invMatrix.TransformBox(args.WorldBounds);
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 = ((Vector2) tile + 0.5f) * 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 += (-12, -8);
else
screenCenter += (-8, -8);
handle.DrawString(_font, screenCenter, Intensity![i].ToString("F2"));
}
}
if (tileSets.ContainsKey(0))
{
var epicenter = tileSets[0].First();
var worldCenter = transform.Transform(((Vector2) epicenter + 0.5f) * tileSize);
var screenCenter = _eyeManager.WorldToScreen(worldCenter) + (-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>();
foreach (var (gridId, tileSets) in Tiles)
{
if (!_mapManager.TryGetGrid(gridId, out var grid))
continue;
var gridXform = xformQuery.GetComponent(grid.GridEntityId);
var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(xformQuery);
gridBounds = invWorldMatrix.TransformBox(args.WorldBounds);
handle.SetTransform(worldMatrix);
DrawTiles(handle, gridBounds, tileSets, SpaceTileSize);
}
if (SpaceTiles == null)
return;
gridBounds = Matrix3.Invert(SpaceMatrix).TransformBox(args.WorldBounds);
handle.SetTransform(SpaceMatrix);
DrawTiles(handle, gridBounds, SpaceTiles, SpaceTileSize);
}
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 = ((Vector2) tile + 0.5f) * 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;
}
}