mirror of
https://github.com/space-wizards/space-station-14.git
synced 2026-02-15 03:31:30 +01:00
navmap stuff
This commit is contained in:
@@ -15,9 +15,9 @@ public sealed partial class CrewMonitoringNavMapControl : NavMapControl
|
||||
|
||||
public CrewMonitoringNavMapControl() : base()
|
||||
{
|
||||
WallColor = new Color(192, 122, 196);
|
||||
TileColor = new(71, 42, 72);
|
||||
BackgroundColor = Color.FromSrgb(TileColor.WithAlpha(BackgroundOpacity));
|
||||
NavData.WallColor = Color.FromSrgb(new Color(192, 122, 196));
|
||||
NavData.TileColor = Color.FromSrgb(new(71, 42, 72));
|
||||
BackgroundColor = NavData.TileColor.WithAlpha(BackgroundOpacity);
|
||||
|
||||
_trackedEntityLabel = new Label
|
||||
{
|
||||
@@ -41,7 +41,7 @@ public sealed partial class CrewMonitoringNavMapControl : NavMapControl
|
||||
};
|
||||
|
||||
_trackedEntityPanel.AddChild(_trackedEntityLabel);
|
||||
this.AddChild(_trackedEntityPanel);
|
||||
AddChild(_trackedEntityPanel);
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
@@ -56,7 +56,7 @@ public sealed partial class CrewMonitoringNavMapControl : NavMapControl
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ((var netEntity, var blip) in TrackedEntities)
|
||||
foreach (var (netEntity, blip) in TrackedEntities)
|
||||
{
|
||||
if (netEntity != Focus)
|
||||
continue;
|
||||
|
||||
389
Content.Client/Pinpointer/NavMapData.cs
Normal file
389
Content.Client/Pinpointer/NavMapData.cs
Normal file
@@ -0,0 +1,389 @@
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Pinpointer;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Pinpointer;
|
||||
|
||||
public sealed class NavMapData
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
|
||||
// Default colors
|
||||
public Color WallColor = Color.ToSrgb(new Color(102, 217, 102));
|
||||
public Color TileColor = new(30, 67, 30);
|
||||
|
||||
/// <summary>
|
||||
/// Offset for the data to be drawn at.
|
||||
/// </summary>
|
||||
public Vector2 Offset;
|
||||
|
||||
public List<(Vector2, Vector2)> TileLines = new();
|
||||
public List<(Vector2, Vector2)> TileRects = new();
|
||||
|
||||
public Dictionary<Vector2i, Vector2[]> TilePolygons = new();
|
||||
|
||||
private Dictionary<Vector2i, Vector2i> _horizLines = new();
|
||||
private Dictionary<Vector2i, Vector2i> _horizLinesReversed = new();
|
||||
private Dictionary<Vector2i, Vector2i> _vertLines = new();
|
||||
private Dictionary<Vector2i, Vector2i> _vertLinesReversed = new();
|
||||
|
||||
protected float FullWallInstep = 0.165f;
|
||||
protected float ThinWallThickness = 0.165f;
|
||||
protected float ThinDoorThickness = 0.30f;
|
||||
|
||||
// TODO: Power should be updating it on its own.
|
||||
/// <summary>
|
||||
/// Called if navmap updates
|
||||
/// </summary>
|
||||
public event Action? OnUpdate;
|
||||
|
||||
public NavMapData()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
}
|
||||
|
||||
public void Draw(DrawingHandleBase handle, Func<Vector2, Vector2> scale, Box2 localAABB)
|
||||
{
|
||||
var verts = new ValueList<Vector2>(TileLines.Count * 2);
|
||||
|
||||
// Draw floor tiles
|
||||
if (TilePolygons.Count != 0)
|
||||
{
|
||||
foreach (var tri in TilePolygons.Values)
|
||||
{
|
||||
verts.Clear();
|
||||
|
||||
foreach (var vert in tri)
|
||||
{
|
||||
verts.Add(new Vector2(vert.X, -vert.Y));
|
||||
}
|
||||
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts.Span, TileColor);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw map lines
|
||||
if (TileLines.Count != 0)
|
||||
{
|
||||
verts.Clear();
|
||||
|
||||
foreach (var (o, t) in TileLines)
|
||||
{
|
||||
var origin = scale.Invoke(o - Offset);
|
||||
var terminus = scale.Invoke(t - Offset);
|
||||
|
||||
verts.Add(origin);
|
||||
verts.Add(terminus);
|
||||
}
|
||||
|
||||
if (verts.Count > 0)
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, verts.Span, WallColor);
|
||||
}
|
||||
|
||||
// Draw map rects
|
||||
if (TileRects.Count != 0)
|
||||
{
|
||||
var rects = new ValueList<Vector2>(TileRects.Count * 8);
|
||||
|
||||
foreach (var (lt, rb) in TileRects)
|
||||
{
|
||||
var leftTop = scale.Invoke(lt - Offset);
|
||||
var rightBottom = scale.Invoke(rb - Offset);
|
||||
|
||||
var rightTop = new Vector2(rightBottom.X, leftTop.Y);
|
||||
var leftBottom = new Vector2(leftTop.X, rightBottom.Y);
|
||||
|
||||
rects.Add(leftTop);
|
||||
rects.Add(rightTop);
|
||||
rects.Add(rightTop);
|
||||
rects.Add(rightBottom);
|
||||
rects.Add(rightBottom);
|
||||
rects.Add(leftBottom);
|
||||
rects.Add(leftBottom);
|
||||
rects.Add(leftTop);
|
||||
}
|
||||
|
||||
if (rects.Count > 0)
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, rects.Span, WallColor);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateNavMap(EntityUid entity)
|
||||
{
|
||||
// Clear stale values
|
||||
TilePolygons.Clear();
|
||||
TileLines.Clear();
|
||||
TileRects.Clear();
|
||||
|
||||
UpdateNavMapFloorTiles(entity);
|
||||
UpdateNavMapWallLines(entity);
|
||||
UpdateNavMapAirlocks(entity);
|
||||
}
|
||||
|
||||
private void UpdateNavMapFloorTiles(Entity<MapGridComponent?> entity)
|
||||
{
|
||||
if (!_entManager.TryGetComponent(entity.Owner, out entity.Comp))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var lookup = _entManager.System<EntityLookupSystem>();
|
||||
var tiles = _entManager.System<SharedMapSystem>().GetAllTilesEnumerator(entity.Owner, entity.Comp);
|
||||
|
||||
while (tiles.MoveNext(out var tile))
|
||||
{
|
||||
var box = lookup.GetLocalBounds(tile.Value.GridIndices, entity.Comp.TileSize);
|
||||
box = new Box2(box.Left, -box.Bottom, box.Right, -box.Top);
|
||||
var arr = new Vector2[4];
|
||||
|
||||
arr[0] = box.BottomLeft;
|
||||
arr[1] = box.BottomRight;
|
||||
arr[2] = box.TopRight;
|
||||
arr[3] = box.TopLeft;
|
||||
|
||||
TilePolygons[tile.Value.GridIndices] = arr;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateNavMapWallLines(Entity<MapGridComponent?, NavMapComponent?> entity)
|
||||
{
|
||||
if (!_entManager.TryGetComponent(entity.Owner, out entity.Comp1) ||
|
||||
!_entManager.TryGetComponent(entity.Owner, out entity.Comp2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We'll use the following dictionaries to combine collinear wall lines
|
||||
_horizLines.Clear();
|
||||
_horizLinesReversed.Clear();
|
||||
_vertLines.Clear();
|
||||
_vertLinesReversed.Clear();
|
||||
|
||||
const int southMask = (int) AtmosDirection.South << (int) NavMapChunkType.Wall;
|
||||
const int eastMask = (int) AtmosDirection.East << (int) NavMapChunkType.Wall;
|
||||
const int westMask = (int) AtmosDirection.West << (int) NavMapChunkType.Wall;
|
||||
const int northMask = (int) AtmosDirection.North << (int) NavMapChunkType.Wall;
|
||||
|
||||
foreach (var (chunkOrigin, chunk) in entity.Comp2.Chunks)
|
||||
{
|
||||
for (var i = 0; i < SharedNavMapSystem.ArraySize; i++)
|
||||
{
|
||||
var tileData = chunk.TileData[i] & SharedNavMapSystem.WallMask;
|
||||
if (tileData == 0)
|
||||
continue;
|
||||
|
||||
tileData >>= (int) NavMapChunkType.Wall;
|
||||
|
||||
var relativeTile = SharedNavMapSystem.GetTileFromIndex(i);
|
||||
var tile = (chunk.Origin * SharedNavMapSystem.ChunkSize + relativeTile) * entity.Comp1.TileSize;
|
||||
|
||||
if (tileData != SharedNavMapSystem.AllDirMask)
|
||||
{
|
||||
AddRectForThinWall(tileData, tile);
|
||||
continue;
|
||||
}
|
||||
|
||||
tile = tile with { Y = -tile.Y };
|
||||
NavMapChunk? neighborChunk;
|
||||
|
||||
// North edge
|
||||
var neighborData = 0;
|
||||
if (relativeTile.Y != SharedNavMapSystem.ChunkSize - 1)
|
||||
neighborData = chunk.TileData[i+1];
|
||||
else if (entity.Comp2.Chunks.TryGetValue(chunkOrigin + Vector2i.Up, out neighborChunk))
|
||||
neighborData = neighborChunk.TileData[i + 1 - SharedNavMapSystem.ChunkSize];
|
||||
|
||||
if ((neighborData & southMask) == 0)
|
||||
{
|
||||
AddOrUpdateNavMapLine(tile + new Vector2i(0, -entity.Comp1.TileSize),
|
||||
tile + new Vector2i(entity.Comp1.TileSize, -entity.Comp1.TileSize), _horizLines,
|
||||
_horizLinesReversed);
|
||||
}
|
||||
|
||||
// East edge
|
||||
neighborData = 0;
|
||||
if (relativeTile.X != SharedNavMapSystem.ChunkSize - 1)
|
||||
neighborData = chunk.TileData[i + SharedNavMapSystem.ChunkSize];
|
||||
else if (entity.Comp2.Chunks.TryGetValue(chunkOrigin + Vector2i.Right, out neighborChunk))
|
||||
neighborData = neighborChunk.TileData[i + SharedNavMapSystem.ChunkSize - SharedNavMapSystem.ArraySize];
|
||||
|
||||
if ((neighborData & westMask) == 0)
|
||||
{
|
||||
AddOrUpdateNavMapLine(tile + new Vector2i(entity.Comp1.TileSize, -entity.Comp1.TileSize),
|
||||
tile + new Vector2i(entity.Comp1.TileSize, 0), _vertLines, _vertLinesReversed);
|
||||
}
|
||||
|
||||
// South edge
|
||||
neighborData = 0;
|
||||
if (relativeTile.Y != 0)
|
||||
neighborData = chunk.TileData[i - 1];
|
||||
else if (entity.Comp2.Chunks.TryGetValue(chunkOrigin + Vector2i.Down, out neighborChunk))
|
||||
neighborData = neighborChunk.TileData[i - 1 + SharedNavMapSystem.ChunkSize];
|
||||
|
||||
if ((neighborData & northMask) == 0)
|
||||
{
|
||||
AddOrUpdateNavMapLine(tile, tile + new Vector2i(entity.Comp1.TileSize, 0), _horizLines,
|
||||
_horizLinesReversed);
|
||||
}
|
||||
|
||||
// West edge
|
||||
neighborData = 0;
|
||||
if (relativeTile.X != 0)
|
||||
neighborData = chunk.TileData[i - SharedNavMapSystem.ChunkSize];
|
||||
else if (entity.Comp2.Chunks.TryGetValue(chunkOrigin + Vector2i.Left, out neighborChunk))
|
||||
neighborData = neighborChunk.TileData[i - SharedNavMapSystem.ChunkSize + SharedNavMapSystem.ArraySize];
|
||||
|
||||
if ((neighborData & eastMask) == 0)
|
||||
{
|
||||
AddOrUpdateNavMapLine(tile + new Vector2i(0, -entity.Comp1.TileSize), tile, _vertLines,
|
||||
_vertLinesReversed);
|
||||
}
|
||||
|
||||
// Add a diagonal line for interiors. Unless there are a lot of double walls, there is no point combining these
|
||||
TileLines.Add((tile + new Vector2(0, -entity.Comp1.TileSize), tile + new Vector2(entity.Comp1.TileSize, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
// Record the combined lines
|
||||
foreach (var (origin, terminal) in _horizLines)
|
||||
{
|
||||
TileLines.Add((origin, terminal));
|
||||
}
|
||||
|
||||
foreach (var (origin, terminal) in _vertLines)
|
||||
{
|
||||
TileLines.Add((origin, terminal));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateNavMapAirlocks(Entity<MapGridComponent?, NavMapComponent?> entity)
|
||||
{
|
||||
if (!_entManager.TryGetComponent(entity.Owner, out entity.Comp1) ||
|
||||
!_entManager.TryGetComponent(entity.Owner, out entity.Comp2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var chunk in entity.Comp2.Chunks.Values)
|
||||
{
|
||||
for (var i = 0; i < SharedNavMapSystem.ArraySize; i++)
|
||||
{
|
||||
var tileData = chunk.TileData[i] & SharedNavMapSystem.AirlockMask;
|
||||
if (tileData == 0)
|
||||
continue;
|
||||
|
||||
tileData >>= (int) NavMapChunkType.Airlock;
|
||||
|
||||
var relative = SharedNavMapSystem.GetTileFromIndex(i);
|
||||
var tile = (chunk.Origin * SharedNavMapSystem.ChunkSize + relative) * entity.Comp1.TileSize;
|
||||
|
||||
// If the edges of an airlock tile are not all occupied, draw a thin airlock for each edge
|
||||
if (tileData != SharedNavMapSystem.AllDirMask)
|
||||
{
|
||||
AddRectForThinAirlock(tileData, tile);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise add a single full tile airlock
|
||||
TileRects.Add((new Vector2(tile.X + FullWallInstep, -tile.Y - FullWallInstep),
|
||||
new Vector2(tile.X - FullWallInstep + 1f, -tile.Y + FullWallInstep - 1)));
|
||||
|
||||
TileLines.Add((new Vector2(tile.X + 0.5f, -tile.Y - FullWallInstep),
|
||||
new Vector2(tile.X + 0.5f, -tile.Y + FullWallInstep - 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRectForThinWall(int tileData, Vector2i tile)
|
||||
{
|
||||
var leftTop = new Vector2(-0.5f, 0.5f - ThinWallThickness);
|
||||
var rightBottom = new Vector2(0.5f, 0.5f);
|
||||
|
||||
for (var i = 0; i < SharedNavMapSystem.Directions; i++)
|
||||
{
|
||||
var dirMask = 1 << i;
|
||||
if ((tileData & dirMask) == 0)
|
||||
continue;
|
||||
|
||||
var tilePosition = new Vector2(tile.X + 0.5f, -tile.Y - 0.5f);
|
||||
|
||||
// TODO NAVMAP
|
||||
// Consider using faster rotation operations, given that these are always 90 degree increments
|
||||
var angle = -((AtmosDirection) dirMask).ToAngle();
|
||||
TileRects.Add((angle.RotateVec(leftTop) + tilePosition, angle.RotateVec(rightBottom) + tilePosition));
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRectForThinAirlock(int tileData, Vector2i tile)
|
||||
{
|
||||
var leftTop = new Vector2(-0.5f + FullWallInstep, 0.5f - FullWallInstep - ThinDoorThickness);
|
||||
var rightBottom = new Vector2(0.5f - FullWallInstep, 0.5f - FullWallInstep);
|
||||
var centreTop = new Vector2(0f, 0.5f - FullWallInstep - ThinDoorThickness);
|
||||
var centreBottom = new Vector2(0f, 0.5f - FullWallInstep);
|
||||
|
||||
for (var i = 0; i < SharedNavMapSystem.Directions; i++)
|
||||
{
|
||||
var dirMask = 1 << i;
|
||||
if ((tileData & dirMask) == 0)
|
||||
continue;
|
||||
|
||||
var tilePosition = new Vector2(tile.X + 0.5f, -tile.Y - 0.5f);
|
||||
var angle = -((AtmosDirection) dirMask).ToAngle();
|
||||
TileRects.Add((angle.RotateVec(leftTop) + tilePosition, angle.RotateVec(rightBottom) + tilePosition));
|
||||
TileLines.Add((angle.RotateVec(centreTop) + tilePosition, angle.RotateVec(centreBottom) + tilePosition));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddOrUpdateNavMapLine(
|
||||
Vector2i origin,
|
||||
Vector2i terminus,
|
||||
Dictionary<Vector2i, Vector2i> lookup,
|
||||
Dictionary<Vector2i, Vector2i> lookupReversed)
|
||||
{
|
||||
Vector2i foundTermius;
|
||||
Vector2i foundOrigin;
|
||||
|
||||
// Does our new line end at the beginning of an existing line?
|
||||
if (lookup.Remove(terminus, out foundTermius))
|
||||
{
|
||||
DebugTools.Assert(lookupReversed[foundTermius] == terminus);
|
||||
|
||||
// Does our new line start at the end of an existing line?
|
||||
if (lookupReversed.Remove(origin, out foundOrigin))
|
||||
{
|
||||
// Our new line just connects two existing lines
|
||||
DebugTools.Assert(lookup[foundOrigin] == origin);
|
||||
lookup[foundOrigin] = foundTermius;
|
||||
lookupReversed[foundTermius] = foundOrigin;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Our new line precedes an existing line, extending it further to the left
|
||||
lookup[origin] = foundTermius;
|
||||
lookupReversed[foundTermius] = origin;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Does our new line start at the end of an existing line?
|
||||
if (lookupReversed.Remove(origin, out foundOrigin))
|
||||
{
|
||||
// Our new line just extends an existing line further to the right
|
||||
DebugTools.Assert(lookup[foundOrigin] == origin);
|
||||
lookup[foundOrigin] = terminus;
|
||||
lookupReversed[terminus] = foundOrigin;
|
||||
return;
|
||||
}
|
||||
|
||||
// Completely disconnected line segment.
|
||||
lookup.Add(origin, terminus);
|
||||
lookupReversed.Add(terminus, origin);
|
||||
}
|
||||
}
|
||||
@@ -45,13 +45,7 @@ public partial class NavMapControl : MapGridControl
|
||||
public Dictionary<EntityCoordinates, (bool Visible, Color Color)> TrackedCoordinates = new();
|
||||
public Dictionary<NetEntity, NavMapBlip> TrackedEntities = new();
|
||||
|
||||
public List<(Vector2, Vector2)> TileLines = new();
|
||||
public List<(Vector2, Vector2)> TileRects = new();
|
||||
public List<(Vector2[], Color)> TilePolygons = new();
|
||||
|
||||
// Default colors
|
||||
public Color WallColor = new(102, 217, 102);
|
||||
public Color TileColor = new(30, 67, 30);
|
||||
public NavMapData NavData = new();
|
||||
|
||||
// Constants
|
||||
protected float UpdateTime = 1.0f;
|
||||
@@ -61,22 +55,13 @@ public partial class NavMapControl : MapGridControl
|
||||
protected static float MaxDisplayedRange = 128f;
|
||||
protected static float DefaultDisplayedRange = 48f;
|
||||
protected float MinmapScaleModifier = 0.075f;
|
||||
protected float FullWallInstep = 0.165f;
|
||||
protected float ThinWallThickness = 0.165f;
|
||||
protected float ThinDoorThickness = 0.30f;
|
||||
|
||||
// Local variables
|
||||
private float _updateTimer = 1.0f;
|
||||
private Dictionary<Color, Color> _sRGBLookUp = new();
|
||||
protected Color BackgroundColor;
|
||||
protected float BackgroundOpacity = 0.9f;
|
||||
private int _targetFontsize = 8;
|
||||
|
||||
private Dictionary<Vector2i, Vector2i> _horizLines = new();
|
||||
private Dictionary<Vector2i, Vector2i> _horizLinesReversed = new();
|
||||
private Dictionary<Vector2i, Vector2i> _vertLines = new();
|
||||
private Dictionary<Vector2i, Vector2i> _vertLinesReversed = new();
|
||||
|
||||
// Components
|
||||
private NavMapComponent? _navMap;
|
||||
private MapGridComponent? _grid;
|
||||
@@ -119,7 +104,7 @@ public partial class NavMapControl : MapGridControl
|
||||
_transformSystem = EntManager.System<SharedTransformSystem>();
|
||||
_navMapSystem = EntManager.System<SharedNavMapSystem>();
|
||||
|
||||
BackgroundColor = Color.FromSrgb(TileColor.WithAlpha(BackgroundOpacity));
|
||||
BackgroundColor = Color.FromSrgb(NavData.TileColor.WithAlpha(BackgroundOpacity));
|
||||
|
||||
RectClipContent = true;
|
||||
HorizontalExpand = true;
|
||||
@@ -179,13 +164,12 @@ public partial class NavMapControl : MapGridControl
|
||||
|
||||
public void ForceNavMapUpdate()
|
||||
{
|
||||
EntManager.TryGetComponent(MapUid, out _navMap);
|
||||
EntManager.TryGetComponent(MapUid, out _grid);
|
||||
EntManager.TryGetComponent(MapUid, out _xform);
|
||||
EntManager.TryGetComponent(MapUid, out _physics);
|
||||
EntManager.TryGetComponent(MapUid, out _fixtures);
|
||||
if (MapUid == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateNavMap();
|
||||
NavData.UpdateNavMap(MapUid.Value);
|
||||
}
|
||||
|
||||
public void CenterToCoordinates(EntityCoordinates coordinates)
|
||||
@@ -228,7 +212,7 @@ public partial class NavMapControl : MapGridControl
|
||||
{
|
||||
if (!blip.Selectable)
|
||||
continue;
|
||||
|
||||
|
||||
var currentDistance = (_transformSystem.ToMapCoordinates(blip.Coordinates).Position - worldPosition).Length();
|
||||
|
||||
if (closestDistance < currentDistance || currentDistance * MinimapScale > MaxSelectableDistance)
|
||||
@@ -293,80 +277,11 @@ public partial class NavMapControl : MapGridControl
|
||||
if (_physics != null)
|
||||
offset += _physics.LocalCenter;
|
||||
|
||||
var offsetVec = new Vector2(offset.X, -offset.Y);
|
||||
|
||||
// Wall sRGB
|
||||
if (!_sRGBLookUp.TryGetValue(WallColor, out var wallsRGB))
|
||||
{
|
||||
wallsRGB = Color.ToSrgb(WallColor);
|
||||
_sRGBLookUp[WallColor] = wallsRGB;
|
||||
}
|
||||
|
||||
// Draw floor tiles
|
||||
if (TilePolygons.Any())
|
||||
{
|
||||
Span<Vector2> verts = new Vector2[8];
|
||||
|
||||
foreach (var (polygonVerts, polygonColor) in TilePolygons)
|
||||
{
|
||||
for (var i = 0; i < polygonVerts.Length; i++)
|
||||
{
|
||||
var vert = polygonVerts[i] - offset;
|
||||
verts[i] = ScalePosition(new Vector2(vert.X, -vert.Y));
|
||||
}
|
||||
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts[..polygonVerts.Length], polygonColor);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw map lines
|
||||
if (TileLines.Any())
|
||||
{
|
||||
var lines = new ValueList<Vector2>(TileLines.Count * 2);
|
||||
|
||||
foreach (var (o, t) in TileLines)
|
||||
{
|
||||
var origin = ScalePosition(o - offsetVec);
|
||||
var terminus = ScalePosition(t - offsetVec);
|
||||
|
||||
lines.Add(origin);
|
||||
lines.Add(terminus);
|
||||
}
|
||||
|
||||
if (lines.Count > 0)
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, lines.Span, wallsRGB);
|
||||
}
|
||||
|
||||
// Draw map rects
|
||||
if (TileRects.Any())
|
||||
{
|
||||
var rects = new ValueList<Vector2>(TileRects.Count * 8);
|
||||
|
||||
foreach (var (lt, rb) in TileRects)
|
||||
{
|
||||
var leftTop = ScalePosition(lt - offsetVec);
|
||||
var rightBottom = ScalePosition(rb - offsetVec);
|
||||
|
||||
var rightTop = new Vector2(rightBottom.X, leftTop.Y);
|
||||
var leftBottom = new Vector2(leftTop.X, rightBottom.Y);
|
||||
|
||||
rects.Add(leftTop);
|
||||
rects.Add(rightTop);
|
||||
rects.Add(rightTop);
|
||||
rects.Add(rightBottom);
|
||||
rects.Add(rightBottom);
|
||||
rects.Add(leftBottom);
|
||||
rects.Add(leftBottom);
|
||||
rects.Add(leftTop);
|
||||
}
|
||||
|
||||
if (rects.Count > 0)
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, rects.Span, wallsRGB);
|
||||
}
|
||||
NavData.Offset = new Vector2(offset.X, -offset.Y);
|
||||
NavData.Draw(handle, ScalePosition, Box2.UnitCentered);
|
||||
|
||||
// Invoke post wall drawing action
|
||||
if (PostWallDrawingAction != null)
|
||||
PostWallDrawingAction.Invoke(handle);
|
||||
PostWallDrawingAction?.Invoke(handle);
|
||||
|
||||
// Beacons
|
||||
if (_beacons.Pressed)
|
||||
@@ -436,279 +351,18 @@ public partial class NavMapControl : MapGridControl
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
// Update the timer
|
||||
// TODO: Sub to state changes.
|
||||
_updateTimer += args.DeltaSeconds;
|
||||
|
||||
if (_updateTimer >= UpdateTime)
|
||||
{
|
||||
_updateTimer -= UpdateTime;
|
||||
|
||||
UpdateNavMap();
|
||||
if (MapUid != null)
|
||||
NavData.UpdateNavMap(MapUid.Value);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdateNavMap()
|
||||
{
|
||||
// Clear stale values
|
||||
TilePolygons.Clear();
|
||||
TileLines.Clear();
|
||||
TileRects.Clear();
|
||||
|
||||
UpdateNavMapFloorTiles();
|
||||
UpdateNavMapWallLines();
|
||||
UpdateNavMapAirlocks();
|
||||
}
|
||||
|
||||
private void UpdateNavMapFloorTiles()
|
||||
{
|
||||
if (_fixtures == null)
|
||||
return;
|
||||
|
||||
var verts = new Vector2[8];
|
||||
|
||||
foreach (var fixture in _fixtures.Fixtures.Values)
|
||||
{
|
||||
if (fixture.Shape is not PolygonShape poly)
|
||||
continue;
|
||||
|
||||
for (var i = 0; i < poly.VertexCount; i++)
|
||||
{
|
||||
var vert = poly.Vertices[i];
|
||||
verts[i] = new Vector2(MathF.Round(vert.X), MathF.Round(vert.Y));
|
||||
}
|
||||
|
||||
TilePolygons.Add((verts[..poly.VertexCount], TileColor));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateNavMapWallLines()
|
||||
{
|
||||
if (_navMap == null || _grid == null)
|
||||
return;
|
||||
|
||||
// We'll use the following dictionaries to combine collinear wall lines
|
||||
_horizLines.Clear();
|
||||
_horizLinesReversed.Clear();
|
||||
_vertLines.Clear();
|
||||
_vertLinesReversed.Clear();
|
||||
|
||||
const int southMask = (int) AtmosDirection.South << (int) NavMapChunkType.Wall;
|
||||
const int eastMask = (int) AtmosDirection.East << (int) NavMapChunkType.Wall;
|
||||
const int westMask = (int) AtmosDirection.West << (int) NavMapChunkType.Wall;
|
||||
const int northMask = (int) AtmosDirection.North << (int) NavMapChunkType.Wall;
|
||||
|
||||
foreach (var (chunkOrigin, chunk) in _navMap.Chunks)
|
||||
{
|
||||
for (var i = 0; i < SharedNavMapSystem.ArraySize; i++)
|
||||
{
|
||||
var tileData = chunk.TileData[i] & SharedNavMapSystem.WallMask;
|
||||
if (tileData == 0)
|
||||
continue;
|
||||
|
||||
tileData >>= (int) NavMapChunkType.Wall;
|
||||
|
||||
var relativeTile = SharedNavMapSystem.GetTileFromIndex(i);
|
||||
var tile = (chunk.Origin * SharedNavMapSystem.ChunkSize + relativeTile) * _grid.TileSize;
|
||||
|
||||
if (tileData != SharedNavMapSystem.AllDirMask)
|
||||
{
|
||||
AddRectForThinWall(tileData, tile);
|
||||
continue;
|
||||
}
|
||||
|
||||
tile = tile with { Y = -tile.Y };
|
||||
NavMapChunk? neighborChunk;
|
||||
|
||||
// North edge
|
||||
var neighborData = 0;
|
||||
if (relativeTile.Y != SharedNavMapSystem.ChunkSize - 1)
|
||||
neighborData = chunk.TileData[i+1];
|
||||
else if (_navMap.Chunks.TryGetValue(chunkOrigin + Vector2i.Up, out neighborChunk))
|
||||
neighborData = neighborChunk.TileData[i + 1 - SharedNavMapSystem.ChunkSize];
|
||||
|
||||
if ((neighborData & southMask) == 0)
|
||||
{
|
||||
AddOrUpdateNavMapLine(tile + new Vector2i(0, -_grid.TileSize),
|
||||
tile + new Vector2i(_grid.TileSize, -_grid.TileSize), _horizLines,
|
||||
_horizLinesReversed);
|
||||
}
|
||||
|
||||
// East edge
|
||||
neighborData = 0;
|
||||
if (relativeTile.X != SharedNavMapSystem.ChunkSize - 1)
|
||||
neighborData = chunk.TileData[i + SharedNavMapSystem.ChunkSize];
|
||||
else if (_navMap.Chunks.TryGetValue(chunkOrigin + Vector2i.Right, out neighborChunk))
|
||||
neighborData = neighborChunk.TileData[i + SharedNavMapSystem.ChunkSize - SharedNavMapSystem.ArraySize];
|
||||
|
||||
if ((neighborData & westMask) == 0)
|
||||
{
|
||||
AddOrUpdateNavMapLine(tile + new Vector2i(_grid.TileSize, -_grid.TileSize),
|
||||
tile + new Vector2i(_grid.TileSize, 0), _vertLines, _vertLinesReversed);
|
||||
}
|
||||
|
||||
// South edge
|
||||
neighborData = 0;
|
||||
if (relativeTile.Y != 0)
|
||||
neighborData = chunk.TileData[i - 1];
|
||||
else if (_navMap.Chunks.TryGetValue(chunkOrigin + Vector2i.Down, out neighborChunk))
|
||||
neighborData = neighborChunk.TileData[i - 1 + SharedNavMapSystem.ChunkSize];
|
||||
|
||||
if ((neighborData & northMask) == 0)
|
||||
{
|
||||
AddOrUpdateNavMapLine(tile, tile + new Vector2i(_grid.TileSize, 0), _horizLines,
|
||||
_horizLinesReversed);
|
||||
}
|
||||
|
||||
// West edge
|
||||
neighborData = 0;
|
||||
if (relativeTile.X != 0)
|
||||
neighborData = chunk.TileData[i - SharedNavMapSystem.ChunkSize];
|
||||
else if (_navMap.Chunks.TryGetValue(chunkOrigin + Vector2i.Left, out neighborChunk))
|
||||
neighborData = neighborChunk.TileData[i - SharedNavMapSystem.ChunkSize + SharedNavMapSystem.ArraySize];
|
||||
|
||||
if ((neighborData & eastMask) == 0)
|
||||
{
|
||||
AddOrUpdateNavMapLine(tile + new Vector2i(0, -_grid.TileSize), tile, _vertLines,
|
||||
_vertLinesReversed);
|
||||
}
|
||||
|
||||
// Add a diagonal line for interiors. Unless there are a lot of double walls, there is no point combining these
|
||||
TileLines.Add((tile + new Vector2(0, -_grid.TileSize), tile + new Vector2(_grid.TileSize, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
// Record the combined lines
|
||||
foreach (var (origin, terminal) in _horizLines)
|
||||
{
|
||||
TileLines.Add((origin, terminal));
|
||||
}
|
||||
|
||||
foreach (var (origin, terminal) in _vertLines)
|
||||
{
|
||||
TileLines.Add((origin, terminal));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateNavMapAirlocks()
|
||||
{
|
||||
if (_navMap == null || _grid == null)
|
||||
return;
|
||||
|
||||
foreach (var chunk in _navMap.Chunks.Values)
|
||||
{
|
||||
for (var i = 0; i < SharedNavMapSystem.ArraySize; i++)
|
||||
{
|
||||
var tileData = chunk.TileData[i] & SharedNavMapSystem.AirlockMask;
|
||||
if (tileData == 0)
|
||||
continue;
|
||||
|
||||
tileData >>= (int) NavMapChunkType.Airlock;
|
||||
|
||||
var relative = SharedNavMapSystem.GetTileFromIndex(i);
|
||||
var tile = (chunk.Origin * SharedNavMapSystem.ChunkSize + relative) * _grid.TileSize;
|
||||
|
||||
// If the edges of an airlock tile are not all occupied, draw a thin airlock for each edge
|
||||
if (tileData != SharedNavMapSystem.AllDirMask)
|
||||
{
|
||||
AddRectForThinAirlock(tileData, tile);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise add a single full tile airlock
|
||||
TileRects.Add((new Vector2(tile.X + FullWallInstep, -tile.Y - FullWallInstep),
|
||||
new Vector2(tile.X - FullWallInstep + 1f, -tile.Y + FullWallInstep - 1)));
|
||||
|
||||
TileLines.Add((new Vector2(tile.X + 0.5f, -tile.Y - FullWallInstep),
|
||||
new Vector2(tile.X + 0.5f, -tile.Y + FullWallInstep - 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRectForThinWall(int tileData, Vector2i tile)
|
||||
{
|
||||
var leftTop = new Vector2(-0.5f, 0.5f - ThinWallThickness);
|
||||
var rightBottom = new Vector2(0.5f, 0.5f);
|
||||
|
||||
for (var i = 0; i < SharedNavMapSystem.Directions; i++)
|
||||
{
|
||||
var dirMask = 1 << i;
|
||||
if ((tileData & dirMask) == 0)
|
||||
continue;
|
||||
|
||||
var tilePosition = new Vector2(tile.X + 0.5f, -tile.Y - 0.5f);
|
||||
|
||||
// TODO NAVMAP
|
||||
// Consider using faster rotation operations, given that these are always 90 degree increments
|
||||
var angle = -((AtmosDirection) dirMask).ToAngle();
|
||||
TileRects.Add((angle.RotateVec(leftTop) + tilePosition, angle.RotateVec(rightBottom) + tilePosition));
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRectForThinAirlock(int tileData, Vector2i tile)
|
||||
{
|
||||
var leftTop = new Vector2(-0.5f + FullWallInstep, 0.5f - FullWallInstep - ThinDoorThickness);
|
||||
var rightBottom = new Vector2(0.5f - FullWallInstep, 0.5f - FullWallInstep);
|
||||
var centreTop = new Vector2(0f, 0.5f - FullWallInstep - ThinDoorThickness);
|
||||
var centreBottom = new Vector2(0f, 0.5f - FullWallInstep);
|
||||
|
||||
for (var i = 0; i < SharedNavMapSystem.Directions; i++)
|
||||
{
|
||||
var dirMask = 1 << i;
|
||||
if ((tileData & dirMask) == 0)
|
||||
continue;
|
||||
|
||||
var tilePosition = new Vector2(tile.X + 0.5f, -tile.Y - 0.5f);
|
||||
var angle = -((AtmosDirection) dirMask).ToAngle();
|
||||
TileRects.Add((angle.RotateVec(leftTop) + tilePosition, angle.RotateVec(rightBottom) + tilePosition));
|
||||
TileLines.Add((angle.RotateVec(centreTop) + tilePosition, angle.RotateVec(centreBottom) + tilePosition));
|
||||
}
|
||||
}
|
||||
|
||||
protected void AddOrUpdateNavMapLine(
|
||||
Vector2i origin,
|
||||
Vector2i terminus,
|
||||
Dictionary<Vector2i, Vector2i> lookup,
|
||||
Dictionary<Vector2i, Vector2i> lookupReversed)
|
||||
{
|
||||
Vector2i foundTermius;
|
||||
Vector2i foundOrigin;
|
||||
|
||||
// Does our new line end at the beginning of an existing line?
|
||||
if (lookup.Remove(terminus, out foundTermius))
|
||||
{
|
||||
DebugTools.Assert(lookupReversed[foundTermius] == terminus);
|
||||
|
||||
// Does our new line start at the end of an existing line?
|
||||
if (lookupReversed.Remove(origin, out foundOrigin))
|
||||
{
|
||||
// Our new line just connects two existing lines
|
||||
DebugTools.Assert(lookup[foundOrigin] == origin);
|
||||
lookup[foundOrigin] = foundTermius;
|
||||
lookupReversed[foundTermius] = foundOrigin;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Our new line precedes an existing line, extending it further to the left
|
||||
lookup[origin] = foundTermius;
|
||||
lookupReversed[foundTermius] = origin;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Does our new line start at the end of an existing line?
|
||||
if (lookupReversed.Remove(origin, out foundOrigin))
|
||||
{
|
||||
// Our new line just extends an existing line further to the right
|
||||
DebugTools.Assert(lookup[foundOrigin] == origin);
|
||||
lookup[foundOrigin] = terminus;
|
||||
lookupReversed[terminus] = foundOrigin;
|
||||
return;
|
||||
}
|
||||
|
||||
// Completely disconnected line segment.
|
||||
lookup.Add(origin, terminus);
|
||||
lookupReversed.Add(terminus, origin);
|
||||
}
|
||||
|
||||
protected Vector2 GetOffset()
|
||||
{
|
||||
return Offset + (_physics?.LocalCenter ?? new Vector2());
|
||||
|
||||
@@ -20,9 +20,7 @@ public sealed partial class PowerMonitoringConsoleNavMapControl : NavMapControl
|
||||
|
||||
private readonly Color[] _powerCableColors = { Color.OrangeRed, Color.Yellow, Color.LimeGreen };
|
||||
private readonly Vector2[] _powerCableOffsets = { new Vector2(-0.2f, -0.2f), Vector2.Zero, new Vector2(0.2f, 0.2f) };
|
||||
private Dictionary<Color, Color> _sRGBLookUp = new Dictionary<Color, Color>();
|
||||
|
||||
public PowerMonitoringCableNetworksComponent? PowerMonitoringCableNetworks;
|
||||
public List<PowerMonitoringConsoleLineGroup> HiddenLineGroups = new();
|
||||
public List<PowerMonitoringConsoleLine> PowerCableNetwork = new();
|
||||
public List<PowerMonitoringConsoleLine> FocusCableNetwork = new();
|
||||
@@ -34,20 +32,19 @@ public sealed partial class PowerMonitoringConsoleNavMapControl : NavMapControl
|
||||
|
||||
private MapGridComponent? _grid;
|
||||
|
||||
public PowerMonitoringConsoleNavMapControl() : base()
|
||||
public PowerMonitoringConsoleNavMapControl()
|
||||
{
|
||||
// Set colors
|
||||
TileColor = new Color(30, 57, 67);
|
||||
WallColor = new Color(102, 164, 217);
|
||||
BackgroundColor = Color.FromSrgb(TileColor.WithAlpha(BackgroundOpacity));
|
||||
NavData.TileColor = Color.FromSrgb(new Color(30, 57, 67));
|
||||
BackgroundColor = NavData.TileColor.WithAlpha(BackgroundOpacity);
|
||||
|
||||
PostWallDrawingAction += DrawAllCableNetworks;
|
||||
|
||||
NavData.OnUpdate += UpdateNavMap;
|
||||
}
|
||||
|
||||
protected override void UpdateNavMap()
|
||||
private void UpdateNavMap()
|
||||
{
|
||||
base.UpdateNavMap();
|
||||
|
||||
if (Owner == null)
|
||||
return;
|
||||
|
||||
@@ -64,14 +61,14 @@ public sealed partial class PowerMonitoringConsoleNavMapControl : NavMapControl
|
||||
return;
|
||||
|
||||
// Draw full cable network
|
||||
if (PowerCableNetwork != null && PowerCableNetwork.Count > 0)
|
||||
if (PowerCableNetwork.Count > 0)
|
||||
{
|
||||
var modulator = (FocusCableNetwork != null && FocusCableNetwork.Count > 0) ? Color.DimGray : Color.White;
|
||||
var modulator = (FocusCableNetwork.Count > 0) ? Color.DimGray : Color.White;
|
||||
DrawCableNetwork(handle, PowerCableNetwork, modulator);
|
||||
}
|
||||
|
||||
// Draw focus network
|
||||
if (FocusCableNetwork != null && FocusCableNetwork.Count > 0)
|
||||
if (FocusCableNetwork.Count > 0)
|
||||
DrawCableNetwork(handle, FocusCableNetwork, Color.White);
|
||||
}
|
||||
|
||||
@@ -106,15 +103,8 @@ public sealed partial class PowerMonitoringConsoleNavMapControl : NavMapControl
|
||||
|
||||
if (cableNetwork.Count > 0)
|
||||
{
|
||||
var color = _powerCableColors[cableNetworkIdx] * modulator;
|
||||
|
||||
if (!_sRGBLookUp.TryGetValue(color, out var sRGB))
|
||||
{
|
||||
sRGB = Color.ToSrgb(color);
|
||||
_sRGBLookUp[color] = sRGB;
|
||||
}
|
||||
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, cableNetwork.Span, sRGB);
|
||||
var color = Color.ToSrgb(_powerCableColors[cableNetworkIdx] * modulator);
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, cableNetwork.Span, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,15 +154,9 @@ public sealed partial class PowerMonitoringConsoleNavMapControl : NavMapControl
|
||||
|
||||
if (cableVertexUV.Count > 0)
|
||||
{
|
||||
var color = _powerCableColors[cableNetworkIdx] * modulator;
|
||||
var color = Color.ToSrgb(_powerCableColors[cableNetworkIdx] * modulator);
|
||||
|
||||
if (!_sRGBLookUp.TryGetValue(color, out var sRGB))
|
||||
{
|
||||
sRGB = Color.ToSrgb(color);
|
||||
_sRGBLookUp[color] = sRGB;
|
||||
}
|
||||
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleList, cableVertexUV.Span, sRGB);
|
||||
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleList, cableVertexUV.Span, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,7 +220,7 @@ public sealed partial class PowerMonitoringConsoleNavMapControl : NavMapControl
|
||||
if (neighbor)
|
||||
{
|
||||
// Add points
|
||||
AddOrUpdateNavMapLine(tile, tile + new Vector2i(_grid.TileSize, 0), horizLines, horizLinesReversed);
|
||||
NavData.AddOrUpdateNavMapLine(tile, tile + new Vector2i(_grid.TileSize, 0), horizLines, horizLinesReversed);
|
||||
}
|
||||
|
||||
// North
|
||||
@@ -254,7 +238,7 @@ public sealed partial class PowerMonitoringConsoleNavMapControl : NavMapControl
|
||||
if (neighbor)
|
||||
{
|
||||
// Add points
|
||||
AddOrUpdateNavMapLine(tile + new Vector2i(0, -_grid.TileSize), tile, vertLines, vertLinesReversed);
|
||||
NavData.AddOrUpdateNavMapLine(tile + new Vector2i(0, -_grid.TileSize), tile, vertLines, vertLinesReversed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.Pinpointer;
|
||||
using Content.Client.SurveillanceCamera;
|
||||
using Content.Shared.StationAi;
|
||||
using Content.Shared.NPC;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.StationAi;
|
||||
|
||||
@@ -20,10 +21,12 @@ public sealed class StationAiOverlay : Overlay
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
private HashSet<Entity<StationAiVisionComponent>> _seeds = new();
|
||||
private HashSet<Entity<SurveillanceCameraVisualsComponent>> _seeds = new();
|
||||
|
||||
private IRenderTexture? _staticTexture;
|
||||
public IRenderTexture? _stencilTexture;
|
||||
public IRenderTexture? _blep;
|
||||
|
||||
protected NavMapData _data = new();
|
||||
|
||||
public StationAiOverlay()
|
||||
{
|
||||
@@ -32,11 +35,11 @@ public sealed class StationAiOverlay : Overlay
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (_stencilTexture?.Texture.Size != args.Viewport.Size)
|
||||
if (_blep?.Texture.Size != args.Viewport.Size)
|
||||
{
|
||||
_staticTexture?.Dispose();
|
||||
_stencilTexture?.Dispose();
|
||||
_stencilTexture = _clyde.CreateRenderTarget(args.Viewport.Size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "station-ai-stencil");
|
||||
_blep?.Dispose();
|
||||
_blep = _clyde.CreateRenderTarget(args.Viewport.Size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "station-ai-stencil");
|
||||
_staticTexture = _clyde.CreateRenderTarget(args.Viewport.Size,
|
||||
new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb),
|
||||
name: "station-ai-static");
|
||||
@@ -61,10 +64,12 @@ public sealed class StationAiOverlay : Overlay
|
||||
var cleared = new HashSet<Vector2i>();
|
||||
var opaque = new HashSet<Vector2i>();
|
||||
var occluders = new HashSet<Entity<OccluderComponent>>();
|
||||
var viewportTiles = new HashSet<Vector2i>();
|
||||
|
||||
if (grid != null)
|
||||
{
|
||||
_data.UpdateNavMap(gridUid);
|
||||
_data.Offset = Vector2.Zero;
|
||||
|
||||
// Code based upon https://github.com/OpenDreamProject/OpenDream/blob/c4a3828ccb997bf3722673620460ebb11b95ccdf/OpenDreamShared/Dream/ViewAlgorithm.cs
|
||||
var tileEnumerator = maps.GetTilesEnumerator(gridUid, grid, expandedBounds, ignoreEmpty: false);
|
||||
|
||||
@@ -100,15 +105,6 @@ public sealed class StationAiOverlay : Overlay
|
||||
|
||||
foreach (var seed in _seeds)
|
||||
{
|
||||
if (!seed.Comp.Enabled)
|
||||
continue;
|
||||
|
||||
// TODO: Iterate tiles direct.
|
||||
if (!seed.Comp.Occluded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
var range = 7.5f;
|
||||
boundary.Clear();
|
||||
seedTiles.Clear();
|
||||
@@ -220,76 +216,42 @@ public sealed class StationAiOverlay : Overlay
|
||||
visibleTiles.Add(tile);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Combine tiles into viewer draw-calls
|
||||
var gridMatrix = xforms.GetWorldMatrix(gridUid);
|
||||
var matty = Matrix3x2.Multiply(gridMatrix, invMatrix);
|
||||
|
||||
// Draw visible tiles to stencil
|
||||
worldHandle.RenderInRenderTarget(_stencilTexture!, () =>
|
||||
{
|
||||
if (!gridUid.IsValid())
|
||||
return;
|
||||
|
||||
worldHandle.SetTransform(matty);
|
||||
|
||||
foreach (var tile in visibleTiles)
|
||||
{
|
||||
var aabb = lookups.GetLocalBounds(tile, grid!.TileSize);
|
||||
worldHandle.DrawRect(aabb, Color.White);
|
||||
}
|
||||
},
|
||||
Color.Transparent);
|
||||
|
||||
// Create static texture
|
||||
var curTime = IoCManager.Resolve<IGameTiming>().RealTime;
|
||||
|
||||
var noiseTexture = _entManager.System<SpriteSystem>()
|
||||
.GetFrame(new SpriteSpecifier.Rsi(new ResPath("/Textures/Interface/noise.rsi"), "noise"), curTime);
|
||||
|
||||
// Once this is gucci optimise rendering.
|
||||
worldHandle.RenderInRenderTarget(_staticTexture!,
|
||||
() =>
|
||||
{
|
||||
// TODO: Handle properly
|
||||
if (!gridUid.IsValid())
|
||||
return;
|
||||
|
||||
worldHandle.SetTransform(matty);
|
||||
|
||||
tileEnumerator = maps.GetTilesEnumerator(gridUid, grid!, worldBounds, ignoreEmpty: false);
|
||||
|
||||
while (tileEnumerator.MoveNext(out var tileRef))
|
||||
{
|
||||
if (visibleTiles.Contains(tileRef.GridIndices))
|
||||
continue;
|
||||
|
||||
var bounds = lookups.GetLocalBounds(tileRef, grid!.TileSize);
|
||||
worldHandle.DrawTextureRect(noiseTexture, bounds, Color.White.WithAlpha(80));
|
||||
}
|
||||
|
||||
},
|
||||
Color.Black);
|
||||
}
|
||||
// Not on a grid
|
||||
else
|
||||
|
||||
// TODO: Combine tiles into viewer draw-calls
|
||||
var matrix = xforms.GetWorldMatrix(gridUid);
|
||||
var matty = Matrix3x2.Multiply(matrix, invMatrix);
|
||||
|
||||
// Draw visible tiles to stencil
|
||||
worldHandle.RenderInRenderTarget(_blep!, () =>
|
||||
{
|
||||
worldHandle.RenderInRenderTarget(_stencilTexture!, () =>
|
||||
{
|
||||
},
|
||||
Color.Transparent);
|
||||
if (!gridUid.IsValid())
|
||||
return;
|
||||
|
||||
worldHandle.RenderInRenderTarget(_staticTexture!,
|
||||
() =>
|
||||
{
|
||||
worldHandle.SetTransform(Matrix3x2.Identity);
|
||||
worldHandle.DrawRect(worldBounds, Color.Black);
|
||||
}, Color.Black);
|
||||
}
|
||||
worldHandle.SetTransform(matty);
|
||||
|
||||
foreach (var tile in visibleTiles)
|
||||
{
|
||||
var aabb = lookups.GetLocalBounds(tile, grid!.TileSize);
|
||||
worldHandle.DrawRect(aabb, Color.White);
|
||||
}
|
||||
},
|
||||
Color.Transparent);
|
||||
|
||||
// Create background texture.
|
||||
worldHandle.RenderInRenderTarget(_staticTexture!,
|
||||
() =>
|
||||
{
|
||||
worldHandle.SetTransform(invMatrix);
|
||||
worldHandle.DrawRect(worldAabb, Color.Black);
|
||||
worldHandle.SetTransform(matty);
|
||||
|
||||
_data.Draw(worldHandle, vec => new Vector2(vec.X, -vec.Y), worldAabb);
|
||||
}, Color.Transparent);
|
||||
|
||||
// Use the lighting as a mask
|
||||
worldHandle.UseShader(_proto.Index<ShaderPrototype>("StencilMask").Instance());
|
||||
worldHandle.DrawTextureRect(_stencilTexture!.Texture, worldBounds);
|
||||
worldHandle.DrawTextureRect(_blep!.Texture, worldBounds);
|
||||
|
||||
// Draw the static
|
||||
worldHandle.UseShader(_proto.Index<ShaderPrototype>("StencilDraw").Instance());
|
||||
|
||||
Reference in New Issue
Block a user