using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.Pinpointer;
+using Robust.Client.GameObjects;
using Robust.Client.Graphics;
+using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input;
public sealed class NavMapControl : MapGridControl
{
[Dependency] private readonly IEntityManager _entManager = default!;
+ private SharedTransformSystem _transform;
public EntityUid? MapUid;
-
public Dictionary<EntityCoordinates, (bool Visible, Color Color)> TrackedCoordinates = new();
private Vector2 _offset;
private bool _draggin;
-
private bool _recentering = false;
-
- private float _recenterMinimum = 0.05f;
+ private readonly float _recenterMinimum = 0.05f;
+ private readonly Font _font;
+ private static readonly Color TileColor = new(30, 67, 30);
+ private static readonly Color BeaconColor = Color.FromSrgb(TileColor.WithAlpha(0.8f));
// TODO: https://github.com/space-wizards/RobustToolbox/issues/3818
private readonly Label _zoom = new()
public NavMapControl() : base(8f, 128f, 48f)
{
IoCManager.InjectDependencies(this);
+
+ _transform = _entManager.System<SharedTransformSystem>();
+ var cache = IoCManager.Resolve<IResourceCache>();
+ _font = new VectorFont(cache.GetResource<FontResource>("/EngineFonts/NotoSans/NotoSans-Regular.ttf"), 16);
+
RectClipContent = true;
HorizontalExpand = true;
VerticalExpand = true;
}
var offset = _offset;
- var tileColor = new Color(30, 67, 30);
var lineColor = new Color(102, 217, 102);
if (_entManager.TryGetComponent<PhysicsComponent>(MapUid, out var physics))
verts[i] = Scale(new Vector2(vert.X, -vert.Y));
}
- handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts[..poly.VertexCount], tileColor);
+ handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts[..poly.VertexCount], TileColor);
}
}
}
}
}
+
+ // Beacons
+ var labelOffset = new Vector2(0.5f, 0.5f) * MinimapScale;
+ var rectBuffer = new Vector2(5f, 3f);
+
+ foreach (var beacon in navMap.Beacons)
+ {
+ var position = beacon.Position - offset;
+
+ position = Scale(position with { Y = -position.Y });
+
+ handle.DrawCircle(position, MinimapScale / 2f, beacon.Color);
+ var textDimensions = handle.GetDimensions(_font, beacon.Text, 1f);
+
+ var labelPosition = position + labelOffset;
+ handle.DrawRect(new UIBox2(labelPosition, labelPosition + textDimensions + rectBuffer * 2), BeaconColor);
+ handle.DrawString(_font, labelPosition + rectBuffer, beacon.Text, beacon.Color);
+ }
}
private Vector2 Scale(Vector2 position)
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
+using Content.Server.Warps;
using Content.Shared.Pinpointer;
using Content.Shared.Tag;
using Robust.Shared.GameStates;
{
[Dependency] private readonly TagSystem _tags = default!;
+ private EntityQuery<PhysicsComponent> _physicsQuery;
+ private EntityQuery<TagComponent> _tagQuery;
+
public override void Initialize()
{
base.Initialize();
+
+ _physicsQuery = GetEntityQuery<PhysicsComponent>();
+ _tagQuery = GetEntityQuery<TagComponent>();
+
SubscribeLocalEvent<AnchorStateChangedEvent>(OnAnchorChange);
SubscribeLocalEvent<ReAnchorEvent>(OnReAnchor);
+ SubscribeLocalEvent<StationGridAddedEvent>(OnStationInit);
+ SubscribeLocalEvent<NavMapComponent, ComponentStartup>(OnNavMapStartup);
SubscribeLocalEvent<NavMapComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<NavMapComponent, GridSplitEvent>(OnNavMapSplit);
- SubscribeLocalEvent<StationGridAddedEvent>(OnStationInit);
+
+ SubscribeLocalEvent<NavMapBeaconComponent, ComponentStartup>(OnNavMapBeaconStartup);
+ SubscribeLocalEvent<NavMapBeaconComponent, AnchorStateChangedEvent>(OnNavMapBeaconAnchor);
}
private void OnStationInit(StationGridAddedEvent ev)
{
var comp = EnsureComp<NavMapComponent>(ev.GridId);
- var physicsQuery = GetEntityQuery<PhysicsComponent>();
- var tagQuery = GetEntityQuery<TagComponent>();
- RefreshGrid(comp, Comp<MapGridComponent>(ev.GridId), physicsQuery, tagQuery);
+ RefreshGrid(comp, Comp<MapGridComponent>(ev.GridId));
+ }
+
+ private void OnNavMapBeaconStartup(EntityUid uid, NavMapBeaconComponent component, ComponentStartup args)
+ {
+ RefreshNavGrid(uid);
+ }
+
+ private void OnNavMapBeaconAnchor(EntityUid uid, NavMapBeaconComponent component, ref AnchorStateChangedEvent args)
+ {
+ RefreshNavGrid(uid);
+ }
+
+ /// <summary>
+ /// Refreshes the grid for the corresponding beacon.
+ /// </summary>
+ /// <param name="uid"></param>
+ private void RefreshNavGrid(EntityUid uid)
+ {
+ var xform = Transform(uid);
+
+ if (!CanBeacon(uid, xform) || !TryComp<NavMapComponent>(xform.GridUid, out var navMap))
+ return;
+
+ Dirty(xform.GridUid.Value, navMap);
+ }
+
+ private bool CanBeacon(EntityUid uid, TransformComponent? xform = null)
+ {
+ if (!Resolve(uid, ref xform))
+ return false;
+
+ return xform.GridUid != null && xform.Anchored;
+ }
+
+ private void OnNavMapStartup(EntityUid uid, NavMapComponent component, ComponentStartup args)
+ {
+ if (!TryComp<MapGridComponent>(uid, out var grid))
+ return;
+
+ RefreshGrid(component, grid);
}
private void OnNavMapSplit(EntityUid uid, NavMapComponent component, ref GridSplitEvent args)
{
- var physicsQuery = GetEntityQuery<PhysicsComponent>();
- var tagQuery = GetEntityQuery<TagComponent>();
var gridQuery = GetEntityQuery<MapGridComponent>();
foreach (var grid in args.NewGrids)
{
var newComp = EnsureComp<NavMapComponent>(grid);
- RefreshGrid(newComp, gridQuery.GetComponent(grid), physicsQuery, tagQuery);
+ RefreshGrid(newComp, gridQuery.GetComponent(grid));
}
- RefreshGrid(component, gridQuery.GetComponent(uid), physicsQuery, tagQuery);
+ RefreshGrid(component, gridQuery.GetComponent(uid));
}
- private void RefreshGrid(NavMapComponent component, MapGridComponent grid, EntityQuery<PhysicsComponent> physicsQuery, EntityQuery<TagComponent> tagQuery)
+ private void RefreshGrid(NavMapComponent component, MapGridComponent grid)
{
component.Chunks.Clear();
component.Chunks[chunkOrigin] = chunk;
}
- RefreshTile(grid, component, chunk, tile.Value.GridIndices, physicsQuery, tagQuery);
+ RefreshTile(grid, component, chunk, tile.Value.GridIndices);
}
}
data.Add(index, chunk.TileData);
}
+ var beaconQuery = AllEntityQuery<NavMapBeaconComponent, TransformComponent>();
+ var beacons = new List<NavMapBeacon>();
+
+ while (beaconQuery.MoveNext(out var beaconUid, out var beacon, out var xform))
+ {
+ if (xform.GridUid != uid || !CanBeacon(beaconUid, xform))
+ continue;
+
+ // TODO: Make warp points use metadata name instead.
+ string? name = beacon.Text;
+
+ if (name == null)
+ {
+ if (TryComp<WarpPointComponent>(beaconUid, out var warpPoint) && warpPoint.Location != null)
+ {
+ name = warpPoint.Location;
+ }
+ else
+ {
+ name = MetaData(beaconUid).EntityName;
+ }
+ }
+
+ beacons.Add(new NavMapBeacon(beacon.Color, name, xform.LocalPosition));
+ }
+
// TODO: Diffs
args.State = new NavMapComponentState()
{
TileData = data,
+ Beacons = beacons,
};
}
if (navMap.Chunks.TryGetValue(chunkOrigin, out var chunk))
{
- var physicsQuery = GetEntityQuery<PhysicsComponent>();
- var tagQuery = GetEntityQuery<TagComponent>();
- RefreshTile(oldGrid, navMap, chunk, ev.TilePos, physicsQuery, tagQuery);
+ RefreshTile(oldGrid, navMap, chunk, ev.TilePos);
}
}
var tile = grid.LocalToTile(xform.Coordinates);
var chunkOrigin = SharedMapSystem.GetChunkIndices(tile, ChunkSize);
- var physicsQuery = GetEntityQuery<PhysicsComponent>();
- var tagQuery = GetEntityQuery<TagComponent>();
if (!navMap.Chunks.TryGetValue(chunkOrigin, out var chunk))
{
navMap.Chunks[chunkOrigin] = chunk;
}
- RefreshTile(grid, navMap, chunk, tile, physicsQuery, tagQuery);
+ RefreshTile(grid, navMap, chunk, tile);
}
- private void RefreshTile(MapGridComponent grid, NavMapComponent component, NavMapChunk chunk, Vector2i tile,
- EntityQuery<PhysicsComponent> physicsQuery,
- EntityQuery<TagComponent> tagQuery)
+ private void RefreshTile(MapGridComponent grid, NavMapComponent component, NavMapChunk chunk, Vector2i tile)
{
var relative = SharedMapSystem.GetChunkRelative(tile, ChunkSize);
while (enumerator.MoveNext(out var ent))
{
- if (!physicsQuery.TryGetComponent(ent, out var body) ||
+ if (!_physicsQuery.TryGetComponent(ent, out var body) ||
!body.CanCollide ||
!body.Hard ||
body.BodyType != BodyType.Static ||
- (!_tags.HasTag(ent.Value, "Wall", tagQuery) &&
- !_tags.HasTag(ent.Value, "Window", tagQuery)))
+ (!_tags.HasTag(ent.Value, "Wall", _tagQuery) &&
+ !_tags.HasTag(ent.Value, "Window", _tagQuery)))
{
continue;
}