Loom: world atlas overlay (Ctrl+M zone picker)#275
Conversation
Adds a modal overlay invoked by Ctrl+M from any tab that shows every
zone in the project as a compact one-line summary:
* Hollow's Edge 3 portals 7 spawns 2 triggers
Ravensreach 12 portals 24 spawns 6 triggers
Sunken Keep 4 portals 18 spawns 11 triggers
The "*" pip marks the currently-loaded zone. Clicking a row loads that
zone (via GUE_JumpToEntity, which fires the existing CZone event so the
real zone-load path with save-prompt runs unchanged) and closes the
overlay. Esc also closes.
Why a separate overlay from the command palette: the palette is
free-text find-anywhere; the atlas is a spatial overview for zones with
per-zone metadata at a glance. Different jobs, different shapes,
different hotkeys.
Per-zone counts (portals / spawns / triggers) walk the Area's existing
fixed-size arrays (PortalName$[99], SpawnActor[999], TriggerScript$[149])
on each open -- so the figures are always current, even if the user just
added a portal in the Zones tab and immediately Ctrl+M'd to compare.
Branch is stacked on top of #274 (which is stacked on #273 on #271).
Completes the four-PR Loom series.
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: a83b24bc6e
ℹ️ 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".
| If EID = ATL_List | ||
| Local sel = FUI_SendMessage(ATL_List, M_GETSELECTED) |
There was a problem hiding this comment.
Sync atlas state when titlebar close button is used
Atlas_HandleEvent only handles ATL_List events, so it ignores the window's own close event; in F-UI, clicking the titlebar X emits a "Closed" event for the window handle (FUI_CreateEvent Handle(gad), "Closed"), but ATL_Open is never cleared in that path. After closing with X, the next Ctrl+M is treated as a close (because ATL_Open is still true), so the atlas requires two keypresses to reopen and contradicts the expected “X closes; Ctrl+M reopens” flow.
Useful? React with 👍 / 👎.
…ment
Three classes of bugs surfaced when actually launching GUE. All four
Loom features (palette, conscience ribbon, xref nav, atlas) were hit
because they share the same primitives. Fixed in one commit on the top
of the stack so the fixes propagate as the underlying PRs merge.
1. F-UI Window gadgets don't respond to M_HIDE / M_SHOW -- only to
M_CLOSE / M_OPEN. (Confirmed by reading F-UI.bb's per-widget
Select on Message: every other gadget has Case M_HIDE -> hide, but
the Window branch has Case M_CLOSE -> hide.) Result: all three
modals -- palette, findings, atlas -- stayed visible from creation
instead of starting hidden. That's why the atlas was popping up on
launch with no zones listed (Atlas_Repopulate is only called from
Atlas_Open, never from Init, so the auto-shown window had just the
initial hint and an empty list).
2. F-UI listbox and combobox have M_GETSELECTED / M_GETINDEX SWAPPED:
ComboBox: M_GETSELECTED -> active item HANDLE
M_GETINDEX -> 1-based int
ListBox: M_GETSELECTED -> 1-based int
M_GETINDEX -> active item HANDLE
I had matched the combobox shape everywhere, which made every
listbox click read an integer-as-handle, then M_GETDATA on an int
returned garbage, then ListAt(..., garbage) returned Null. Result:
palette click, atlas click, conscience-finding click all silently
did nothing.
This same inversion broke the listbox-side of GUE_JumpToEntity --
the picker-walk for "faction" and "animset" kinds never found its
target. Which is why the new ">" cross-ref buttons in the actor
editor (PR #274) clicked but didn't navigate. Fixed by branching on
a per-kind isList flag in GUE_JumpToEntity and using M_GETINDEX
(not M_GETSELECTED) on the listbox path.
3. Conscience ribbon widgets were placed at Y=2, inside the menu bar's
Y=0..20 region. The menu bar's mouse capture / render order made
the "Issues..." button visually fight the menu strip ("blurry text"
per the bug report) and the click hit-test never reached the button.
Plus the button was created with Flags=0 instead of CS_BORDER,
stripping the visible border. Moved the ribbon to Y=24 (overlays
the right side of the tab title strip, which has no tab title that
far right) and restored CS_BORDER.
Also converted the For Each iterators from the
`Local X.Type \n For X = Each Type` shape to the canonical inline
`For X.Type = Each Type` shape that every other GUE module uses. The
pre-declared form happens to work for Items/Spells (the conscience
validator did find one issue at runtime) but the canonical form is
the established pattern; matching it removes a class of "did this
silently fail to bind?" doubt for future debugging.
All four engine targets compile clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Pushed 9c937af — fix-up commit on top of this branch addressing four runtime bugs reported during smoke test:
All four engine targets compile clean. Because this branch sits at the top of the stack, the fixes will land alongside the four feature commits when the stack merges (or rebase down into the underlying PRs if you'd prefer them per-PR — say the word and I'll split them). 🤖 Generated with Claude Code |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9c937af716
ℹ️ 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".
| FUI_SendMessage(CP_Window, M_OPEN) | ||
| FUI_SendMessage(CP_Window, M_BRINGTOFRONT) | ||
| CP_Open = True |
There was a problem hiding this comment.
Synchronize palette state on titlebar close
CP_Open is only flipped in CmdPalette_Open/CmdPalette_Close, but the window can also be closed via the titlebar X (F-UI emits a "Closed" event for the window handle). In that path CP_Open stays True, so the next Ctrl+K goes through the close branch instead of reopening, requiring two keypresses to bring the palette back. Please handle the window "Closed" event (or query M_VISIBLE) to keep CP_Open in sync with actual window state.
Useful? React with 👍 / 👎.
Two remaining bugs after the first fix-up. Both surfaced clearly from
the user's smoke test:
1. CROSS-REF / PALETTE / ATLAS: "the correct element is selected but
the tab doesn't switch."
F-UI's Tab `Case M_SETINDEX` handler does set `Tab\actTabPage`
internally, but the visible tab does not switch when invoked from
outside the click path. Suspected cause: the implementation has a
nested-For-loop iterator with both loops named `tabp`:
For tabp.TabPage = Each TabPage ' outer
If Count = Param1
Tab\actTabPage = tabp
For tabp.TabPage = Each TabPage ' inner, shadows outer
...rebuild every page...
Next
Exit
In non-Strict Blitz, `For X = Each Type` implicitly declares X at
function scope; the inner re-declaration likely corrupts state in a
way that nullifies the assignment by the time the next FUI_Update
renders.
Bypass M_SETINDEX with `GUE_SetActiveTab(idx)` in CommandPalette.bb
that does the same work but with distinct iterator names (`probe`
for the search, `sib` for the rebuild pass), then call it from
GUE_JumpToEntity in place of `FUI_SendMessage(TabMain, M_SETINDEX,
tabIdx)`. Still fires the Case TabMain event afterward so the
existing leave/enter dispatcher runs its hide/show logic.
2. CONSCIENCE RIBBON: Issues button at Y=24 is invisible.
The tab title strip occupies Y=20..40 (TABPAGE_HEIGHT = 20), so
Y=24 puts the button behind that strip and behind whatever the
tabs render. Y=2 (previous attempt) was inside the menu bar's
click-capture zone. There is no usable top strip in WMain that's
free of both regions.
Move to the bottom of WMain instead: rowY = sh - 22. The bottom
strip is the only horizontal band that has nothing in it on any
tab. Computed from GraphicsHeight() at Init so it works in any
window size.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Second fix-up (bd77a71) addressing the two bugs left after the first round. 1. Tab doesn't switch (palette / atlas / cross-ref all) Your "the right entity gets selected but the tab doesn't switch" was the giveaway. The picker walk worked, only the tab visual was failing. F-UI's Bypassed it with a tiny 2. Issues button invisible Y=2 was inside the menu bar's click zone. Y=24 turned out to be inside the tab title strip (Y=20..40, TABPAGE_HEIGHT=20). No top strip in WMain is free of both. Moved to the bottom of the window — the only horizontal band that has nothing in it on any tab. 🤖 Generated with Claude Code |
|
Closing this PR. Pivoting from "port Loom concepts into the existing GUE" to building a fresh |
Summary
Fourth and final of the Loom-concept PRs. Stacked on top of #274 (on #273 on #271).
Adds a modal overlay invoked by Ctrl+M from any tab that shows every zone in the project as a compact one-line summary:
The
*pip marks the currently-loaded zone. Clicking a row loads that zone (closing the overlay); Esc also closes.Why a separate overlay from the command palette
The palette is free-text find-anywhere across every entity type. The atlas is a spatial overview for zones with per-zone metadata at a glance — portal/spawn/trigger counts you can compare side-by-side instead of one at a time. Different jobs, different shapes, different hotkeys.
How it reuses earlier PRs
Clicking a row calls
GUE_JumpToEntity(""zone"", Handle(Ar))— the same primitive PR #271 introduced and PRs #273 / #274 extended. The atlas adds zero new dispatch infrastructure.Always-current counts
The per-zone counts walk the
Areatype's existing fixed-size arrays (PortalName$[99],SpawnActor[999],TriggerScript$[149]) on each open. So if you add a portal in the Zones tab and immediately Ctrl+M, the new portal is reflected. No caching, no staleness.Blast radius
src/Modules/WorldAtlas.bbsrc/GUE.bbgets four hook lines (include, init, per-frame poll, per-event dispatch)Server/Client/Project ManagerunaffectedFuture room to grow (out of scope)
Test plan
*prefix matching the zone currently loaded in the Zones tab*now points to the just-loaded zoneFour-PR series wrap-up
Together,
#271+#273+#274+ this PR port four hero concepts from the Loom redesign brief into the existing F-UI editor:Issues...modal>buttons in actor editorThe series introduces one general-purpose primitive —
GUE_JumpToEntity(kind$, refID)— that future work can plug into without revisiting any of these landings. The remaining Loom concepts (visible threads overlay, session timeline scrubber, aesthetic toggle, walk-in playtest, single-workspace shell) either require infrastructure that doesn't exist yet (universal undo, validator framework, server-bridge) or are technically impractical in F-UI's draw model and were correctly left out.🤖 Generated with Claude Code