From 28147da44377b2ec5c9d3428ce5f0435c37138cc Mon Sep 17 00:00:00 2001 From: Nilton Constantino Date: Sun, 21 Jun 2026 08:31:14 +0100 Subject: [PATCH] implements PLN-0008 --- .../GON/StageEditor/StageEditorColors.cs | 4 + .../GON/StageEditor/StageEditorState.cs | 7 ++ .../GON/StageEditor/StageInspectorPanel.cs | 7 ++ .../Editor/GON/StageEditor/StageMapCanvas.cs | 111 +++++++++++++++++- 4 files changed, 128 insertions(+), 1 deletion(-) diff --git a/Assets/Scripts/Editor/GON/StageEditor/StageEditorColors.cs b/Assets/Scripts/Editor/GON/StageEditor/StageEditorColors.cs index 0effd62..9ff0452 100644 --- a/Assets/Scripts/Editor/GON/StageEditor/StageEditorColors.cs +++ b/Assets/Scripts/Editor/GON/StageEditor/StageEditorColors.cs @@ -12,6 +12,10 @@ namespace Editor.GON.StageEditor public static readonly Color PreviewFill = new(1f, 1f, 1f, 0.18f); public static readonly Color PreviewStroke = new(1f, 1f, 1f, 0.9f); public static readonly Color SelectionStroke = new(1f, 0.85f, 0.25f, 1f); + public static readonly Color WorldSyncFootprint = new(1f, 0.1f, 0.95f, 0.42f); + public static readonly Color WorldSyncAnchor = new(0.05f, 0.9f, 1f, 0.48f); + public static readonly Color WorldSyncLift = new(1f, 0.16f, 0.14f, 0.48f); + public static readonly Color WorldSyncSocket = new(1f, 0.9f, 0.12f, 0.9f); public static Color FromHtml(string html) { diff --git a/Assets/Scripts/Editor/GON/StageEditor/StageEditorState.cs b/Assets/Scripts/Editor/GON/StageEditor/StageEditorState.cs index e74bd22..e491be0 100644 --- a/Assets/Scripts/Editor/GON/StageEditor/StageEditorState.cs +++ b/Assets/Scripts/Editor/GON/StageEditor/StageEditorState.cs @@ -7,6 +7,7 @@ namespace Editor.GON.StageEditor public StageLogicalLayer activeLayer = StageLogicalLayer.Structural; public StagePaletteEntry activePaletteEntry; public StageObjectDefinition selectedObject; + public bool showWorldSyncUnderlay = true; public event Action Changed; @@ -37,6 +38,12 @@ namespace Editor.GON.StageEditor NotifyChanged(); } + public void SetWorldSyncUnderlayVisible(bool visible) + { + showWorldSyncUnderlay = visible; + NotifyChanged(); + } + public void NotifyChanged() { Changed?.Invoke(); diff --git a/Assets/Scripts/Editor/GON/StageEditor/StageInspectorPanel.cs b/Assets/Scripts/Editor/GON/StageEditor/StageInspectorPanel.cs index 04de5b9..3bf204a 100644 --- a/Assets/Scripts/Editor/GON/StageEditor/StageInspectorPanel.cs +++ b/Assets/Scripts/Editor/GON/StageEditor/StageInspectorPanel.cs @@ -169,6 +169,13 @@ namespace Editor.GON.StageEditor } sync.EnsureDefaults(); + var underlay = new Toggle("Show Underlay") + { + value = state.showWorldSyncUnderlay + }; + underlay.RegisterValueChangedCallback(evt => state.SetWorldSyncUnderlayVisible(evt.newValue)); + Add(underlay); + AddReadOnlyLine("World Stage", string.IsNullOrEmpty(sync.worldStageDisplayName) ? sync.worldStageId : sync.worldStageDisplayName); diff --git a/Assets/Scripts/Editor/GON/StageEditor/StageMapCanvas.cs b/Assets/Scripts/Editor/GON/StageEditor/StageMapCanvas.cs index 6593d8f..4c6e5d7 100644 --- a/Assets/Scripts/Editor/GON/StageEditor/StageMapCanvas.cs +++ b/Assets/Scripts/Editor/GON/StageEditor/StageMapCanvas.cs @@ -1,4 +1,5 @@ using System; +using Intrepid.Gameplay.Journey; using UnityEngine; using UnityEngine.UIElements; @@ -495,6 +496,8 @@ namespace Editor.GON.StageEditor DrawInfiniteGrid(p); + DrawWorldSyncUnderlay(p); + DrawLowerFloors(p); DrawCells(p, floor, 1f); @@ -504,6 +507,51 @@ namespace Editor.GON.StageEditor DrawHoverCell(p); DrawPreview(p); } + + private void DrawWorldSyncUnderlay(Painter2D p) + { + var sync = stage.worldSync; + if (!state.showWorldSyncUnderlay || sync is null || !sync.HasSync) + { + return; + } + + sync.EnsureDefaults(); + var cellsPerWorldTile = sync.worldTileSize / Mathf.Max(0.01f, stage.cellSize); + if (cellsPerWorldTile <= 0f) + { + return; + } + + foreach (var tile in sync.worldTiles) + { + DrawHatching(p, WorldTileRect(tile, cellsPerWorldTile), StageEditorColors.WorldSyncFootprint); + } + + foreach (var endpoint in sync.expectedEndpoints) + { + if (endpoint is null) + { + continue; + } + + var rect = WorldTileRect(endpoint.worldTile, cellsPerWorldTile); + switch (endpoint.kind) + { + case JEndpointKind.Anchor: + DrawHatching(p, rect.Expanded(-3f), StageEditorColors.WorldSyncAnchor); + break; + case JEndpointKind.Lift: + DrawHatching(p, rect.Expanded(-6f), StageEditorColors.WorldSyncLift); + break; + case JEndpointKind.Socket: + DrawSocketFaceHint(p, rect, endpoint.socketFace); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + } private void DrawLowerFloors(Painter2D p) { @@ -919,6 +967,15 @@ namespace Editor.GON.StageEditor rect.height * cellPixels); } + private Rect WorldTileRect(JWorldTile tile, float cellsPerWorldTile) + { + return new Rect( + pan.x + tile.x * cellsPerWorldTile * cellPixels, + pan.y + tile.y * cellsPerWorldTile * cellPixels, + cellsPerWorldTile * cellPixels, + cellsPerWorldTile * cellPixels); + } + private Rect GetResizeHandleRect(StageObjectDefinition obj) { var rect = GridRect(obj.Bounds); @@ -960,6 +1017,58 @@ namespace Editor.GON.StageEditor p.LineTo(b); p.Stroke(); } + + private void DrawHatching(Painter2D p, Rect rect, Color color) + { + if (rect.width <= 0f || rect.height <= 0f) + { + return; + } + + StrokeRect(p, rect, color.WithAlpha(Mathf.Min(0.85f, color.a + 0.12f)), 1.5f); + + var spacing = Mathf.Clamp(cellPixels * 2f, 10f, 28f); + var width = Mathf.Clamp(cellPixels * 0.08f, 1.25f, 3f); + for (var d = -rect.height; d < rect.width; d += spacing) + { + var start = d < 0f + ? new Vector2(rect.xMin, rect.yMin - d) + : new Vector2(rect.xMin + d, rect.yMin); + var end = d + rect.height < rect.width + ? new Vector2(rect.xMin + d + rect.height, rect.yMax) + : new Vector2(rect.xMax, rect.yMin + rect.width - d); + DrawLine(p, start, end, color, width); + } + } + + private void DrawSocketFaceHint(Painter2D p, Rect rect, JSocketFace face) + { + var color = StageEditorColors.WorldSyncSocket; + var inset = Mathf.Clamp(cellPixels * 0.25f, 4f, 14f); + var width = Mathf.Clamp(cellPixels * 0.16f, 3f, 8f); + + switch (face) + { + case JSocketFace.North: + DrawLine(p, new Vector2(rect.xMin + inset, rect.yMin), new Vector2(rect.xMax - inset, rect.yMin), + color, width); + break; + case JSocketFace.South: + DrawLine(p, new Vector2(rect.xMin + inset, rect.yMax), new Vector2(rect.xMax - inset, rect.yMax), + color, width); + break; + case JSocketFace.East: + DrawLine(p, new Vector2(rect.xMax, rect.yMin + inset), new Vector2(rect.xMax, rect.yMax - inset), + color, width); + break; + case JSocketFace.West: + DrawLine(p, new Vector2(rect.xMin, rect.yMin + inset), new Vector2(rect.xMin, rect.yMax - inset), + color, width); + break; + default: + throw new ArgumentOutOfRangeException(nameof(face), face, null); + } + } } internal static class StageEditorRectExtensions @@ -975,4 +1084,4 @@ namespace Editor.GON.StageEditor return color; } } -} \ No newline at end of file +}