1
0

ExplosionDebugOverlay.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using System.Linq;
  2. using System.Numerics;
  3. using JetBrains.Annotations;
  4. using Robust.Client.GameObjects;
  5. using Robust.Client.Graphics;
  6. using Robust.Client.ResourceManagement;
  7. using Robust.Shared.Enums;
  8. using Robust.Shared.Map;
  9. using Robust.Shared.Map.Components;
  10. namespace Content.Client.Administration.UI.SpawnExplosion;
  11. [UsedImplicitly]
  12. public sealed class ExplosionDebugOverlay : Overlay
  13. {
  14. [Dependency] private readonly IEntityManager _entityManager = default!;
  15. [Dependency] private readonly IEyeManager _eyeManager = default!;
  16. public Dictionary<int, List<Vector2i>>? SpaceTiles;
  17. public Dictionary<EntityUid, Dictionary<int, List<Vector2i>>> Tiles = new();
  18. public List<float> Intensity = new();
  19. public float TotalIntensity;
  20. public float Slope;
  21. public ushort SpaceTileSize;
  22. public override OverlaySpace Space => OverlaySpace.WorldSpace | OverlaySpace.ScreenSpace;
  23. public Matrix3x2 SpaceMatrix;
  24. public MapId Map;
  25. private readonly Font _font;
  26. public ExplosionDebugOverlay()
  27. {
  28. IoCManager.InjectDependencies(this);
  29. var cache = IoCManager.Resolve<IResourceCache>();
  30. _font = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 8);
  31. }
  32. protected override void Draw(in OverlayDrawArgs args)
  33. {
  34. if (Map != args.Viewport.Eye?.Position.MapId)
  35. return;
  36. if (Tiles.Count == 0 && SpaceTiles == null)
  37. return;
  38. switch (args.Space)
  39. {
  40. case OverlaySpace.ScreenSpace:
  41. DrawScreen(args);
  42. break;
  43. case OverlaySpace.WorldSpace:
  44. DrawWorld(args);
  45. break;
  46. }
  47. }
  48. private void DrawScreen(OverlayDrawArgs args)
  49. {
  50. var handle = args.ScreenHandle;
  51. Box2 gridBounds;
  52. var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
  53. var xformSystem = _entityManager.System<TransformSystem>();
  54. foreach (var (gridId, tileSets) in Tiles)
  55. {
  56. if (!_entityManager.TryGetComponent(gridId, out MapGridComponent? grid))
  57. continue;
  58. var gridXform = xformQuery.GetComponent(gridId);
  59. var (_, _, matrix, invMatrix) = xformSystem.GetWorldPositionRotationMatrixWithInv(gridXform, xformQuery);
  60. gridBounds = invMatrix.TransformBox(args.WorldBounds).Enlarged(grid.TileSize * 2);
  61. DrawText(handle, gridBounds, matrix, tileSets, grid.TileSize);
  62. }
  63. if (SpaceTiles == null)
  64. return;
  65. Matrix3x2.Invert(SpaceMatrix, out var invSpace);
  66. gridBounds = invSpace.TransformBox(args.WorldBounds);
  67. DrawText(handle, gridBounds, SpaceMatrix, SpaceTiles, SpaceTileSize);
  68. }
  69. private void DrawText(
  70. DrawingHandleScreen handle,
  71. Box2 gridBounds,
  72. Matrix3x2 transform,
  73. Dictionary<int, List<Vector2i>> tileSets,
  74. ushort tileSize)
  75. {
  76. for (var i = 1; i < Intensity.Count; i++)
  77. {
  78. if (!tileSets.TryGetValue(i, out var tiles))
  79. continue;
  80. foreach (var tile in tiles)
  81. {
  82. var centre = (tile + Vector2Helpers.Half) * tileSize;
  83. // is the center of this tile visible to the user?
  84. if (!gridBounds.Contains(centre))
  85. continue;
  86. var worldCenter = Vector2.Transform(centre, transform);
  87. var screenCenter = _eyeManager.WorldToScreen(worldCenter);
  88. if (Intensity[i] > 9)
  89. screenCenter += new Vector2(-12, -8);
  90. else
  91. screenCenter += new Vector2(-8, -8);
  92. handle.DrawString(_font, screenCenter, Intensity[i].ToString("F2"));
  93. }
  94. }
  95. if (tileSets.TryGetValue(0, out var set))
  96. {
  97. var epicenter = set.First();
  98. var worldCenter = Vector2.Transform((epicenter + Vector2Helpers.Half) * tileSize, transform);
  99. var screenCenter = _eyeManager.WorldToScreen(worldCenter) + new Vector2(-24, -24);
  100. var text = $"{Intensity[0]:F2}\nΣ={TotalIntensity:F1}\nΔ={Slope:F1}";
  101. handle.DrawString(_font, screenCenter, text);
  102. }
  103. }
  104. private void DrawWorld(in OverlayDrawArgs args)
  105. {
  106. var handle = args.WorldHandle;
  107. Box2 gridBounds;
  108. var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
  109. var xformSystem = _entityManager.System<TransformSystem>();
  110. foreach (var (gridId, tileSets) in Tiles)
  111. {
  112. if (!_entityManager.TryGetComponent(gridId, out MapGridComponent? grid))
  113. continue;
  114. var gridXform = xformQuery.GetComponent(gridId);
  115. var (_, _, worldMatrix, invWorldMatrix) = xformSystem.GetWorldPositionRotationMatrixWithInv(gridXform, xformQuery);
  116. gridBounds = invWorldMatrix.TransformBox(args.WorldBounds).Enlarged(grid.TileSize * 2);
  117. handle.SetTransform(worldMatrix);
  118. DrawTiles(handle, gridBounds, tileSets, SpaceTileSize);
  119. }
  120. if (SpaceTiles == null)
  121. return;
  122. Matrix3x2.Invert(SpaceMatrix, out var invSpace);
  123. gridBounds = invSpace.TransformBox(args.WorldBounds).Enlarged(2);
  124. handle.SetTransform(SpaceMatrix);
  125. DrawTiles(handle, gridBounds, SpaceTiles, SpaceTileSize);
  126. handle.SetTransform(Matrix3x2.Identity);
  127. }
  128. private void DrawTiles(
  129. DrawingHandleWorld handle,
  130. Box2 gridBounds,
  131. Dictionary<int, List<Vector2i>> tileSets,
  132. ushort tileSize)
  133. {
  134. for (var i = 0; i < Intensity.Count; i++)
  135. {
  136. var color = ColorMap(Intensity[i]);
  137. var colorTransparent = color;
  138. colorTransparent.A = 0.2f;
  139. if (!tileSets.TryGetValue(i, out var tiles))
  140. continue;
  141. foreach (var tile in tiles)
  142. {
  143. var centre = (tile + Vector2Helpers.Half) * tileSize;
  144. // is the center of this tile visible to the user?
  145. if (!gridBounds.Contains(centre))
  146. continue;
  147. var box = Box2.UnitCentered.Translated(centre);
  148. handle.DrawRect(box, color, false);
  149. handle.DrawRect(box, colorTransparent);
  150. }
  151. }
  152. }
  153. private Color ColorMap(float intensity)
  154. {
  155. var frac = 1 - intensity / Intensity[0];
  156. Color result;
  157. if (frac < 0.5f)
  158. result = Color.InterpolateBetween(Color.Red, Color.Orange, frac * 2);
  159. else
  160. result = Color.InterpolateBetween(Color.Orange, Color.Yellow, (frac - 0.5f) * 2);
  161. return result;
  162. }
  163. }