Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the screen_loc edge anchors #2106

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) {
wixoaGit marked this conversation as resolved.
Show resolved Hide resolved
// 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
Loading