From 38034c1c6003a262f32c4fc53f5c55ab280cf892 Mon Sep 17 00:00:00 2001 From: wixoaGit Date: Thu, 21 Nov 2024 00:05:28 -0500 Subject: [PATCH] Implement the `screen_loc` edge anchors `LEFT`/`RIGHT`/`TOP`/`BOTTOM` are no longer the same as `WEST`/`EAST`/`NORTH`/`SOUTH` Rendered icon size is taken into account instead of the map's icon size. --- OpenDreamClient/Rendering/DreamViewOverlay.cs | 3 +- OpenDreamShared/Dream/ScreenLocation.cs | 63 ++++++++++++------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/OpenDreamClient/Rendering/DreamViewOverlay.cs b/OpenDreamClient/Rendering/DreamViewOverlay.cs index 55eb129c44..9fa9171912 100644 --- a/OpenDreamClient/Rendering/DreamViewOverlay.cs +++ b/OpenDreamClient/Rendering/DreamViewOverlay.cs @@ -672,7 +672,8 @@ private void CollectVisibleSprites(ViewAlgorithm.Tile?[,] tiles, EntityUid gridU if (sprite.ScreenLocation.MapControl != null) // Don't render screen objects meant for other map controls continue; - Vector2 position = sprite.ScreenLocation.GetViewPosition(worldAABB.BottomLeft, _interfaceManager.View, EyeManager.PixelsPerMeter); + Vector2i dmiIconSize = sprite.Icon.DMI?.IconSize ?? new(EyeManager.PixelsPerMeter, EyeManager.PixelsPerMeter); + Vector2 position = sprite.ScreenLocation.GetViewPosition(worldAABB.BottomLeft, _interfaceManager.View, EyeManager.PixelsPerMeter, dmiIconSize); Vector2 iconSize = sprite.Icon.DMI == null ? Vector2.Zero : sprite.Icon.DMI.IconSize / (float)EyeManager.PixelsPerMeter; for (int x = 0; x < sprite.ScreenLocation.RepeatX; x++) { for (int y = 0; y < sprite.ScreenLocation.RepeatY; y++) { diff --git a/OpenDreamShared/Dream/ScreenLocation.cs b/OpenDreamShared/Dream/ScreenLocation.cs index 27cef2ec09..7e4c39b85c 100644 --- a/OpenDreamShared/Dream/ScreenLocation.cs +++ b/OpenDreamShared/Dream/ScreenLocation.cs @@ -6,18 +6,23 @@ using System.Linq; using System.Text; using Robust.Shared.Log; +using Robust.Shared.Maths; namespace OpenDreamShared.Dream; public enum HorizontalAnchor { + West, Left, Center, + East, Right } public enum VerticalAnchor { + South, Bottom, Center, + North, Top } @@ -35,13 +40,13 @@ public sealed class ScreenLocation { private static ISawmill Sawmill => Logger.GetSawmill("opendream.screen_loc_parser"); - private static string[] _keywords = { + private static string[] _keywords = [ "CENTER", "WEST", "EAST", "LEFT", "RIGHT", "NORTH", "SOUTH", "TOP", "BOTTOM", "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT" - }; + ]; public ScreenLocation(int x, int y, int pixelOffsetX, int pixelOffsetY, ScreenLocation? range = null) { X = x - 1; @@ -66,20 +71,22 @@ public ScreenLocation(string screenLocation) { ParseScreenLoc(screenLocation); } - public Vector2 GetViewPosition(Vector2 viewOffset, ViewRange view, float iconSize) { - float x = (X + PixelOffsetX / iconSize); + public Vector2 GetViewPosition(Vector2 viewOffset, ViewRange view, float tileSize, Vector2i iconSize) { + float x = (X + PixelOffsetX / tileSize); x += HorizontalAnchor switch { - HorizontalAnchor.Left => 0, + HorizontalAnchor.West or HorizontalAnchor.Left => 0, HorizontalAnchor.Center => view.CenterX, - HorizontalAnchor.Right => view.Width - 1, + HorizontalAnchor.East => view.Width - 1, + HorizontalAnchor.Right => view.Width - (iconSize.X / tileSize), _ => throw new Exception($"Invalid horizontal anchor {HorizontalAnchor}") }; - float y = (Y + PixelOffsetY / iconSize); + float y = (Y + PixelOffsetY / tileSize); y += VerticalAnchor switch { - VerticalAnchor.Bottom => 0, + VerticalAnchor.South or VerticalAnchor.Bottom => 0, VerticalAnchor.Center => view.CenterY, - VerticalAnchor.Top => view.Height - 1, + VerticalAnchor.North => view.Height - 1, + VerticalAnchor.Top => view.Height - (iconSize.Y / tileSize), _ => throw new Exception($"Invalid vertical anchor {VerticalAnchor}") }; @@ -109,7 +116,7 @@ private void ParseScreenLoc(string screenLoc) { if (mapControlSplitIndex > 0) { string mapControl = rangeSplit[0].Substring(0, mapControlSplitIndex); - if (char.IsAsciiLetter(mapControl[0]) && mapControl.IndexOfAny(new[] { '+', '-' }) == -1 && !_keywords.Contains(mapControl)) { + if (char.IsAsciiLetter(mapControl[0]) && mapControl.IndexOfAny(['+', '-']) == -1 && !_keywords.Contains(mapControl)) { MapControl = mapControl; coordinateSplit[0] = coordinateSplit[0].Substring(mapControlSplitIndex + 1); } @@ -121,10 +128,14 @@ private void ParseScreenLoc(string screenLoc) { (HorizontalAnchor, VerticalAnchor) = coordinateSplit[0].Trim() switch { "CENTER" => (HorizontalAnchor.Center, VerticalAnchor.Center), - "NORTHWEST" or "TOPLEFT" => (HorizontalAnchor.Left, VerticalAnchor.Top), - "NORTHEAST" or "TOPRIGHT" => (HorizontalAnchor.Right, VerticalAnchor.Top), - "SOUTHWEST" or "BOTTOMLEFT" => (HorizontalAnchor.Left, VerticalAnchor.Bottom), - "SOUTHEAST" or "BOTTOMRIGHT" => (HorizontalAnchor.Right, VerticalAnchor.Bottom), + "NORTHWEST" => (HorizontalAnchor.West, VerticalAnchor.North), + "TOPLEFT" => (HorizontalAnchor.Left, VerticalAnchor.Top), + "NORTHEAST" => (HorizontalAnchor.East, VerticalAnchor.North), + "TOPRIGHT" => (HorizontalAnchor.Right, VerticalAnchor.Top), + "SOUTHWEST" => (HorizontalAnchor.West, VerticalAnchor.South), + "BOTTOMLEFT" => (HorizontalAnchor.Left, VerticalAnchor.Bottom), + "SOUTHEAST" => (HorizontalAnchor.East, VerticalAnchor.South), + "BOTTOMRIGHT" => (HorizontalAnchor.Right, VerticalAnchor.Bottom), _ => throw new Exception($"Invalid screen_loc {screenLoc}") }; @@ -143,9 +154,7 @@ private bool ParseScreenLocCoordinate(string coordinate, bool isHorizontal) { List pieces = new(); StringBuilder currentPiece = new(); - for (int i = 0; i < coordinate.Length; i++) { - char c = coordinate[i]; - + foreach (var c in coordinate) { switch (c) { case ' ' or '\t': continue; @@ -193,23 +202,35 @@ private bool ParseScreenLocCoordinate(string coordinate, bool isHorizontal) { break; case "WEST": - case "LEFT": // Yes, this sets the horizontal anchor regardless of the isHorizontal arg. // Every macro sets their respective axis regardless of which coordinate it's in - HorizontalAnchor = HorizontalAnchor.Left; + HorizontalAnchor = HorizontalAnchor.West; settingHorizontal = true; break; case "EAST": + HorizontalAnchor = HorizontalAnchor.East; + settingHorizontal = true; + break; + case "NORTH": + VerticalAnchor = VerticalAnchor.North; + settingHorizontal = false; + break; + case "SOUTH": + VerticalAnchor = VerticalAnchor.South; + settingHorizontal = false; + break; + case "LEFT": + HorizontalAnchor = HorizontalAnchor.Left; + settingHorizontal = true; + break; case "RIGHT": HorizontalAnchor = HorizontalAnchor.Right; settingHorizontal = true; break; - case "NORTH": case "TOP": VerticalAnchor = VerticalAnchor.Top; settingHorizontal = false; break; - case "SOUTH": case "BOTTOM": VerticalAnchor = VerticalAnchor.Bottom; settingHorizontal = false;