diff --git a/Content.Client/Shuttles/UI/RadarControl.cs b/Content.Client/Shuttles/UI/RadarControl.cs index d6d0cb1164..e5bd2bd8cb 100644 --- a/Content.Client/Shuttles/UI/RadarControl.cs +++ b/Content.Client/Shuttles/UI/RadarControl.cs @@ -1,10 +1,13 @@ using Content.Shared.Shuttles.BUIStates; using Content.Shared.Shuttles.Components; +using JetBrains.Annotations; using Content.Shared.Shuttles.Systems; using Robust.Client.Graphics; +using Robust.Client.Input; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Collections; +using Robust.Shared.Input; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Physics; @@ -71,6 +74,11 @@ public sealed class RadarControl : Control public Action? OnRadarRangeChanged; + /// + /// Raised if the user left-clicks on the radar control with the relevant entitycoordinates. + /// + public Action? OnRadarClick; + public RadarControl() { IoCManager.InjectDependencies(this); @@ -103,6 +111,43 @@ public sealed class RadarControl : Control } } + protected override void KeyBindUp(GUIBoundKeyEventArgs args) + { + base.KeyBindUp(args); + + if (_coordinates == null || _rotation == null || args.Function != EngineKeyFunctions.UIClick || + OnRadarClick == null) + { + return; + } + + var a = InverseScalePosition(args.RelativePosition); + var relativeWorldPos = new Vector2(a.X, -a.Y); + relativeWorldPos = _rotation.Value.RotateVec(relativeWorldPos); + var coords = _coordinates.Value.Offset(relativeWorldPos); + OnRadarClick?.Invoke(coords); + } + + /// + /// Gets the entitycoordinates of where the mouseposition is, relative to the control. + /// + [PublicAPI] + public EntityCoordinates GetMouseCoordinates(ScreenCoordinates screen) + { + if (_coordinates == null || _rotation == null) + { + return EntityCoordinates.Invalid; + } + + var pos = screen.Position / UIScale - GlobalPosition; + + var a = InverseScalePosition(pos); + var relativeWorldPos = new Vector2(a.X, -a.Y); + relativeWorldPos = _rotation.Value.RotateVec(relativeWorldPos); + var coords = _coordinates.Value.Offset(relativeWorldPos); + return coords; + } + protected override void MouseWheel(GUIMouseWheelEventArgs args) { base.MouseWheel(args); @@ -169,17 +214,18 @@ public sealed class RadarControl : Control var offset = _coordinates.Value.Position; var offsetMatrix = Matrix3.CreateInverseTransform( mapPosition.Position, - xform.WorldRotation - _rotation.Value); + xform.WorldRotation + _rotation.Value); // Draw our grid in detail var ourGridId = _coordinates.Value.GetGridUid(_entManager); - if (_entManager.TryGetComponent(ourGridId, out var ourGrid)) + if (_entManager.TryGetComponent(ourGridId, out var ourGrid) && + fixturesQuery.TryGetComponent(ourGridId, out var ourFixturesComp)) { var ourGridMatrix = xformQuery.GetComponent(ourGridId.Value).WorldMatrix; Matrix3.Multiply(in ourGridMatrix, in offsetMatrix, out var matrix); - DrawGrid(handle, matrix, ourGrid, Color.MediumSpringGreen, true); + DrawGrid(handle, matrix, ourFixturesComp, ourGrid, Color.MediumSpringGreen, true); DrawDocks(handle, ourGridId.Value, matrix); } @@ -196,7 +242,7 @@ public sealed class RadarControl : Control foreach (var grid in _mapManager.FindGridsIntersecting(mapPosition.MapId, new Box2(mapPosition.Position - MaxRadarRange, mapPosition.Position + MaxRadarRange))) { - if (grid.Owner == ourGridId) + if (grid.Owner == ourGridId || !fixturesQuery.TryGetComponent(grid.Owner, out var fixturesComp)) continue; var gridBody = bodyQuery.GetComponent(grid.Owner); @@ -278,7 +324,7 @@ public sealed class RadarControl : Control } // Detailed view - DrawGrid(handle, matty, grid, color, true); + DrawGrid(handle, matty, fixturesComp, grid, color, true); DrawDocks(handle, grid.Owner, matty); } @@ -349,32 +395,29 @@ public sealed class RadarControl : Control } } - private void DrawGrid(DrawingHandleScreen handle, Matrix3 matrix, MapGridComponent grid, Color color, bool drawInterior) + private void DrawGrid(DrawingHandleScreen handle, Matrix3 matrix, FixturesComponent fixturesComp, MapGridComponent grid, Color color, bool drawInterior) { var rator = grid.GetAllTilesEnumerator(); var edges = new ValueList(); var tileTris = new ValueList(); - Span tileVerts = new Vector2[4]; - // Originally I used fixtures but this was a massive hassle - // Long-term it's probably better due to less data getting drawn but this is what it is for now. - while (rator.MoveNext(out var tileRef)) + if (drawInterior) { - var tileVec = (Vector2) tileRef.Value.GridIndices * grid.TileSize; + var interiorTris = new ValueList(); + // TODO: Engine pr + Span verts = new Vector2[8]; - if (drawInterior) + foreach (var fixture in fixturesComp.Fixtures.Values) { - tileVerts[0] = tileVec; - tileVerts[1] = tileVec + new Vector2(grid.TileSize, 0f); - tileVerts[2] = tileVec + new Vector2(grid.TileSize, grid.TileSize); - tileVerts[3] = tileVec + new Vector2(0f, grid.TileSize); - - // If the fixture has any points out of range we won't draw any of it. var invalid = false; + var poly = (PolygonShape) fixture.Shape; - for (var i = 0; i < 4; i++) + for (var i = 0; i < poly.VertexCount; i++) { - var vert = matrix.Transform(tileVerts[i]); + var vert = poly.Vertices[i]; + vert = new Vector2(MathF.Round(vert.X), MathF.Round(vert.Y)); + + vert = matrix.Transform(vert); if (vert.Length > RadarRange) { @@ -382,22 +425,41 @@ public sealed class RadarControl : Control break; } - vert.Y = -vert.Y; - tileVerts[i] = ScalePosition(vert); + verts[i] = vert; } if (invalid) continue; - tileTris.Add(tileVerts[0]); - tileTris.Add(tileVerts[1]); - tileTris.Add(tileVerts[3]); + Vector2 AdjustedVert(Vector2 vert) + { + if (vert.Length > RadarRange) + { + vert = vert.Normalized * RadarRange; + } - tileTris.Add(tileVerts[1]); - tileTris.Add(tileVerts[3]); - tileTris.Add(tileVerts[2]); + vert.Y = -vert.Y; + return ScalePosition(vert); + } + + interiorTris.Add(AdjustedVert(verts[0])); + interiorTris.Add(AdjustedVert(verts[1])); + interiorTris.Add(AdjustedVert(verts[3])); + + interiorTris.Add(AdjustedVert(verts[1])); + interiorTris.Add(AdjustedVert(verts[2])); + interiorTris.Add(AdjustedVert(verts[3])); } + handle.DrawPrimitives(DrawPrimitiveTopology.TriangleList, interiorTris.Span, color.WithAlpha(0.05f)); + } + + while (rator.MoveNext(out var tileRef)) + { + // TODO: Short-circuit interior chunk nodes + // This can be optimised a lot more if required. + Vector2? tileVec = null; + // Iterate edges and see which we can draw for (var i = 0; i < 4; i++) { @@ -409,26 +471,27 @@ public sealed class RadarControl : Control Vector2 start; Vector2 end; + tileVec ??= (Vector2) tileRef.Value.GridIndices * grid.TileSize; // Draw line // Could probably rotate this but this might be faster? switch (dir) { case DirectionFlag.South: - start = tileVec; - end = tileVec + new Vector2(grid.TileSize, 0f); + start = tileVec.Value; + end = tileVec.Value + new Vector2(grid.TileSize, 0f); break; case DirectionFlag.East: - start = tileVec + new Vector2(grid.TileSize, 0f); - end = tileVec + new Vector2(grid.TileSize, grid.TileSize); + start = tileVec.Value + new Vector2(grid.TileSize, 0f); + end = tileVec.Value + new Vector2(grid.TileSize, grid.TileSize); break; case DirectionFlag.North: - start = tileVec + new Vector2(grid.TileSize, grid.TileSize); - end = tileVec + new Vector2(0f, grid.TileSize); + start = tileVec.Value + new Vector2(grid.TileSize, grid.TileSize); + end = tileVec.Value + new Vector2(0f, grid.TileSize); break; case DirectionFlag.West: - start = tileVec + new Vector2(0f, grid.TileSize); - end = tileVec; + start = tileVec.Value + new Vector2(0f, grid.TileSize); + end = tileVec.Value; break; default: throw new NotImplementedException(); @@ -456,4 +519,9 @@ public sealed class RadarControl : Control { return value * MinimapScale + MidPoint; } + + private Vector2 InverseScalePosition(Vector2 value) + { + return (value - MidPoint) / MinimapScale; + } }