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;
public Action<float>? OnRadarRangeChanged;
+ /// <summary>
+ /// Raised if the user left-clicks on the radar control with the relevant entitycoordinates.
+ /// </summary>
+ public Action<EntityCoordinates>? OnRadarClick;
+
public RadarControl()
{
IoCManager.InjectDependencies(this);
}
}
+ 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);
+ }
+
+ /// <summary>
+ /// Gets the entitycoordinates of where the mouseposition is, relative to the control.
+ /// </summary>
+ [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);
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<MapGridComponent>(ourGridId, out var ourGrid))
+ if (_entManager.TryGetComponent<MapGridComponent>(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);
}
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);
}
// Detailed view
- DrawGrid(handle, matty, grid, color, true);
+ DrawGrid(handle, matty, fixturesComp, grid, color, true);
DrawDocks(handle, grid.Owner, matty);
}
}
}
- 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<Vector2>();
var tileTris = new ValueList<Vector2>();
- Span<Vector2> 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<Vector2>();
+ // TODO: Engine pr
+ Span<Vector2> 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)
{
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;
+ }
+
+ vert.Y = -vert.Y;
+ return ScalePosition(vert);
+ }
+
+ interiorTris.Add(AdjustedVert(verts[0]));
+ interiorTris.Add(AdjustedVert(verts[1]));
+ interiorTris.Add(AdjustedVert(verts[3]));
- tileTris.Add(tileVerts[1]);
- tileTris.Add(tileVerts[3]);
- tileTris.Add(tileVerts[2]);
+ 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++)
{
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();
{
return value * MinimapScale + MidPoint;
}
+
+ private Vector2 InverseScalePosition(Vector2 value)
+ {
+ return (value - MidPoint) / MinimapScale;
+ }
}