Skip to content

Commit

Permalink
Implement the screen_loc edge anchors (#2106)
Browse files Browse the repository at this point in the history
  • Loading branch information
wixoaGit authored Dec 18, 2024
1 parent 5483541 commit 4b8dc3a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 22 deletions.
3 changes: 2 additions & 1 deletion OpenDreamClient/Rendering/DreamViewOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down
65 changes: 44 additions & 21 deletions OpenDreamShared/Dream/ScreenLocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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;
Expand All @@ -66,20 +71,24 @@ 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) {
// TODO: LEFT/RIGHT/TOP/BOTTOM need to stick to the edge of the visible map if the map's container is smaller than the map itself

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}")
};

Expand Down Expand Up @@ -109,7 +118,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);
}
Expand All @@ -121,10 +130,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}")
};

Expand All @@ -143,9 +156,7 @@ private bool ParseScreenLocCoordinate(string coordinate, bool isHorizontal) {
List<string> 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;
Expand Down Expand Up @@ -193,23 +204,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;
Expand Down

0 comments on commit 4b8dc3a

Please sign in to comment.