Loom (Alpha) #3 of 4: top-down zone map surface#294
Conversation
Adds the second surface in the Loom alpha: a top-down 2D map of the zone selected from the atlas. Renders every waypoint, spawn point, trigger volume, and portal pulled from the Area type's fixed-size arrays, scaled to fit the visible area. Click a marker to select it. The selection sets ZoneMap_SelectedKind$ / ZoneMap_SelectedIndex, which PR #4's composer panel will consume. Why a top-down 2D map and not a literal 3D viewport: The Loom design's "world scene" is stylized 2D SVG with a fake 3/4 perspective -- the design medium never assumed real 3D. ClientAreas's LoadArea (which Loom would need for a true 3D render) is deeply entangled with GUE's UI substrate: GY_Cam, GY_CreateProgressBar, ResolutionType, RandomImages, GetMusicName$, GetTexture, the Gooey lib. Pulling all of that into Loom would lock the two editors together at the UI layer, which is exactly what Loom is supposed to decouple. The 2D map ships now, does the alpha job, and stays faithful to the design's aesthetic. A literal 3D viewport can land as a beta refactor once LoadArea's data path is decoupled from its UI path (or once Loom defines its own zone-mesh loader). What's in (src/Modules/Loom/ZoneMap.bb): - ZoneMap_Open(handle) -- switches into map mode, recomputes the view's bounding box from the placed entities so the view scales to fit any size zone. - ZoneMap_RenderAndUpdate(sw, sh) -- per-frame; paints the chrome + entities + selection ring, hit-tests the mouse, returns True when the user wants to go back to the atlas. - World->screen projection (X, Z) -> (px, py) with Z inverted so north renders up. - Marker styles per kind: waypoint -> small dust-gray dot trigger -> red diamond with parchment inner spawn -> brass ring with dark inner portal -> arcane-blue pin with portal name label below - Top ribbon: brand on the left, zone name centered, hover-styled "< Back to Atlas" button on the right. - Footer: selection hint that updates to show the current pick. - Pulsing arcane ring highlights the active selection. State machine in Loom.bb: Two modes -- LOOM_MODE_ATLAS and LOOM_MODE_MAP. Clicking a zone in the atlas calls ZoneMap_Open and flips to MAP. From MAP, the Back button or Esc returns to ATLAS. From ATLAS, Esc exits Loom. (Esc on MAP only returns to atlas, never exits Loom directly, so the user can't accidentally kill the editor mid-inspection.) All five engine targets compile clean. Loom.exe grew from 2.3 MB (atlas) to 2.35 MB (atlas + map). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4452c785d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Waypoints firstFound (drawn underneath everything else) | ||
| Local i = 0 | ||
| For i = 0 To 1999 | ||
| If ZM_Area\WaypointX#[i] <> 0.0 Or ZM_Area\WaypointZ#[i] <> 0.0 |
There was a problem hiding this comment.
Filter waypoints by slot validity, not coordinate value
Using WaypointX/Z != 0 to decide whether a waypoint exists will misclassify real data: valid waypoints placed at (0, *, 0) are dropped, while deleted waypoints can remain visible because deletion resets PrevWaypoint/links but does not clear stored coordinates (see waypoint deletion flow in GUE.bb). Since the same predicate is used for map content and bounds, stale coordinates can also distort the computed zoom/extent for the whole zone. This should follow the same slot-validity rule used by the editor/runtime (e.g., PrevWaypoint != 2005) rather than coordinate non-zero checks.
Useful? React with 👍 / 👎.
|
|
||
| // Spawns | ||
| For i = 0 To 999 | ||
| If ZM_Area\SpawnActor[i] > 0 |
There was a problem hiding this comment.
Gate spawn markers on SpawnMax instead of SpawnActor
This loop treats any slot with SpawnActor > 0 as an active spawn, but area tooling and server logic use SpawnMax as the enable/disable flag (GetSpawnPoint and spawn update paths check SpawnMax > 0). In GUE, disabling a spawn often sets SpawnMax to 0 without clearing actor metadata, so the map will render and allow selecting spawns that are actually disabled in gameplay.
Useful? React with 👍 / 👎.
|
Closing this PR. After landing #292 (skeleton + Project Manager launcher), the user's feedback on the alpha was that the zone-only browse model wasn't useful enough -- the project's actors, items, spells, and factions were loaded into memory but never surfaced. Pivoting to an entity browser + threads model: every entity kind browsable, composer renders every kind, reference fields become clickable chips that jump and leave a back-stack trail. That replaces the zone atlas, zone map, and zone-only composer this PR series built. New work lands as one PR off develop. |
Summary
Third of four PRs building the Loom alpha. Stacked on top of #293 (loom-atlas), which is stacked on #292 (loom-skeleton).
Adds the second surface in the Loom alpha: a top-down 2D map of the zone selected from the atlas. Renders every waypoint, spawn point, trigger volume, and portal pulled from the
Areatype's fixed-size arrays, scaled to fit the visible area. Click a marker to select it.Why 2D map and not literal 3D viewport
The Loom design's ""world scene"" is itself stylized 2D SVG with a fake 3/4 perspective — the design medium never assumed real 3D.
ClientAreas.bb'sLoadArea(which Loom would need for a true 3D render) is deeply entangled with GUE's UI substrate:GY_Cam,GY_CreateProgressBar,ResolutionType,RandomImages,GetMusicName$,GetTexture, the Gooey lib. Pulling all of that into Loom would lock the two editors together at the UI layer, which is exactly what Loom is supposed to decouple.The 2D map ships now, does the alpha job, and stays faithful to the design's aesthetic. A literal 3D viewport can land as a beta refactor once
LoadArea's data path is decoupled from its UI path (or once Loom defines its own zone-mesh loader).What's in (src/Modules/Loom/ZoneMap.bb)
ZoneMap_Open(handle)— switches into map mode, recomputes the view's bounding box from the placed entities so the view scales to fit any size zone.ZoneMap_RenderAndUpdate(sw, sh)— per-frame; paints the chrome + entities + selection ring, hit-tests the mouse, returnsTruewhen the user wants to go back to the atlas.(X, Z) -> (px, py)with Z inverted so north renders up.< Back to Atlasbutton on the right.State machine in Loom.bb
Two modes —
LOOM_MODE_ATLASandLOOM_MODE_MAP. Clicking a zone in the atlas callsZoneMap_Openand flips to MAP. From MAP, the Back button or Esc returns to ATLAS. From ATLAS, Esc exits Loom. (Esc on MAP only returns to atlas, never exits Loom directly, so the user can't accidentally kill the editor mid-inspection.)Blast radius
src/Loom.bb: include block + main loop changed to a two-mode state machine.LoomSelectedZoneis now consumed byZoneMap_Openinstead of producing a toast.src/Modules/Loom/ZoneMap.bb: new file.Test plan
compile.batbuilds clean.Loom (Alpha).LOOM / Zone Mapon left, zone name centered,< Back to Atlasbutton on right.🤖 Generated with Claude Code