docs: deep handoff for the multi-window UI mockup stage
Covers: what's done (UI Studio, faithful importer Fix A/B/C/4/5, Character window), the look-vs-runtime boundary, the mockup goal + approach (host the production UiHost live), must-fix issues (#149 inventory, #150 GameWindow fonts), patterns/lessons, reference map, and first concrete steps. For the next agent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4b5961ec04
commit
9408c062d2
1 changed files with 126 additions and 0 deletions
126
docs/research/2026-06-26-mockup-stage-handoff.md
Normal file
126
docs/research/2026-06-26-mockup-stage-handoff.md
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
# Handoff — the full multi-window UI mockup stage (2026-06-26)
|
||||
|
||||
For the next agent. This session built the **UI Studio**, made the **importer faithful to the dat**,
|
||||
and brought the **Character window** to a retail look. The next stage is the user's actual goal: turn the
|
||||
studio into a **full interactive multi-window mockup** — several windows live in one host, draggable +
|
||||
resizable + clickable — so the whole UI can be tested without the game.
|
||||
|
||||
Read this, then `claude-memory/project_ui_studio.md` (the SSOT) and `project_d2b_retail_ui.md`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Where we are (what's done + works)
|
||||
|
||||
### The UI Studio (the dev tool)
|
||||
`AcDream.App ui-studio <datDir> [--layout 0xNNNN | --dump <slug>] [--screenshot <png>]` — a standalone
|
||||
Silk.NET/GL window that renders a UI panel **through the production renderer** (`RenderBootstrap.Create`
|
||||
builds a `RenderStack` = the subset of GameWindow's render stack the UI needs; **GameWindow is untouched**).
|
||||
- Code: `src/AcDream.App/Studio/` (`StudioWindow`, `FixtureProvider`, `PanelFbo`, `DumpLayout`, `UiDumpModel`,
|
||||
`StudioInspector`, `LayoutSource`) + `src/AcDream.App/Rendering/RenderBootstrap.cs`.
|
||||
- **Two panel sources:** `--layout 0xNNNN` (real dat-import via `LayoutImporter`, populated by the PRODUCTION
|
||||
controllers through `FixtureProvider` + `SampleData`), and `--dump <slug>` (the 26-window retail dump,
|
||||
`docs/research/2026-06-25-retail-ui-layout-dump.json`, static structure only).
|
||||
- **Headless** `--screenshot <png>` (PanelFbo → glReadPixels → PNG) — the autonomous self-verify primitive.
|
||||
Use it constantly.
|
||||
- **Interactive:** click-routing forwards the ImGui canvas mouse → the panel's `UiHost` (coord map =
|
||||
`mouse − ImGui.GetItemRectMin()`, no extra Y-flip). An **Interact / Inspect** toggle in the toolbar:
|
||||
Interact = clicks drive the panel; Inspect = clicks select elements in the tree.
|
||||
|
||||
### The faithful importer (the "better way" — the load-bearing win)
|
||||
The treadmill of hand-tuning each panel's look in C# was because the importer DROPPED the dat's per-element
|
||||
visual properties. The dat carries them in `StateDesc.Properties`: **0x1A FontDID**, **0x14/0x15** H/V
|
||||
justification, **0x1B FontColor**. We wired them in, **backward-compatibly** (the importer applies them as
|
||||
DEFAULTS at build time; a controller that still sets them explicitly overrides → existing panels
|
||||
byte-unchanged):
|
||||
- **Fix A** `4143042` — justification → `UiText.Centered/RightAligned/VerticalJustify`.
|
||||
- **Fix B** `6e0be4b` — FontColor → `UiText.DefaultColor` (character colors proved RUNTIME — the dat carries none).
|
||||
- **Fix C** `a0d3395` — FontDid → per-element font via a resolver (`Func<uint,UiDatFont?>`) threaded through
|
||||
`LayoutImporter.Import` → `DatWidgetFactory`. **STUDIO path only**; GameWindow passes null (issue **#150**).
|
||||
- **Fix 5** `ad4ed51` — `LayoutImporter.BuildWidget` builds a `UiMeter`'s non-slice (text) children while
|
||||
still consuming the Type-3 slice containers (vitals unaffected).
|
||||
- **Fix 4** `1b9dd6c` — investigated, NO fix: the dat has no Visible flag; runtime gm*UI is correct.
|
||||
|
||||
**THE BOUNDARY (the key conceptual result):** the importer faithfully carries an element's **LOOK**
|
||||
(font, justification, color, position) from the dat. **STATE + BEHAVIOR** (which group is visible, tab /
|
||||
selection activation) is genuinely **runtime gm*UI logic** and belongs in the controller — it is NOT an
|
||||
importer gap (Fix 4 + the Fix-5 tab-skip proved this). Don't try to push state/visibility into the importer.
|
||||
|
||||
### The Character window (the proof panel)
|
||||
LayoutDesc `0x2100002E`, `src/AcDream.App/UI/Layout/CharacterStatController.cs` — Attributes tab reads as
|
||||
retail: 3 tabs, header, big-gold level number (its own dat FontDid), captions, 9-row attribute list
|
||||
(icons + right-aligned values + Health/Stamina/Mana), click-to-select (top/bottom selection bars + footer
|
||||
State-B "{Attr}: {value}" / "Experience To Raise: Infinity!" + affordability-gated raise triangles), centered
|
||||
footer. **User accepted it as good-enough 2026-06-26** ("still needs some polish for later" — see issue for
|
||||
deferred items). Specs: `docs/research/2026-06-25-character-window-faithful-spec.md`,
|
||||
`2026-06-25-attributes-tab-interactive-spec.md`, `2026-06-26-character-window-retail-reference.md`.
|
||||
|
||||
### Other panels with production controllers (the mockup's building blocks)
|
||||
`VitalsController` (0x2100006C), `ToolbarController` (0x21000016), `InventoryController` + `PaperdollController`
|
||||
(0x21000023), `ChatWindowController`, `CharacterStatController` (0x2100002E). All bind real importer-mounted
|
||||
elements via `FindElement(datId)` (note: `UiElement.EventId` ≠ the dat id — the dat id lives in
|
||||
`ImportedLayout._byId`).
|
||||
|
||||
---
|
||||
|
||||
## 2. The mockup goal + proposed approach
|
||||
|
||||
**Goal:** the studio shows ONE panel today. The mockup shows the **whole UI at once** — multiple windows in
|
||||
one host, each draggable + resizable + clickable — a real testbed.
|
||||
|
||||
**Why it's reachable:** the production `UiHost` (`src/AcDream.App/UI/UiHost.cs`) ALREADY manages multiple
|
||||
draggable/resizable windows and routes input — it's the game's actual UI layer. The studio just needs to host
|
||||
the full thing instead of one FBO'd panel. (Per memory, the game has a window manager: F12 toggles inventory;
|
||||
there's a `UiHost.ToggleWindow` / `WindowNames` API.)
|
||||
|
||||
**Proposed path (a new studio "mockup mode"):**
|
||||
1. Load SEVERAL panels into ONE `UiHost` (not one panel per FBO) — a "desktop." Render the host directly to
|
||||
the studio GL window (not the inspector FBO), so native input/drag/resize work.
|
||||
2. Window open/close/arrange (reuse the game's window-manager API).
|
||||
3. Drag + resize via the production frame chrome (already exists for the retail windows).
|
||||
4. Keep the inspector available as an optional overlay.
|
||||
The studio is the THIN host; the production `UiHost` is the engine. Don't reimplement window management —
|
||||
drive the production one.
|
||||
|
||||
---
|
||||
|
||||
## 3. Must-fix before / during the mockup
|
||||
|
||||
- **#149** — the **inventory window (0x21000023) renders all-black in the studio** (pre-existing fixture gap,
|
||||
NOT a regression). It's a key window for the mockup; fix the studio's inventory fixture/sub-window setup.
|
||||
- **#150** — GameWindow doesn't thread the Fix-C font resolver (live game = global font). Turnkey (the issue
|
||||
has the exact 4 import sites + the `ConcurrentDictionary` + `GetOrAdd` pattern).
|
||||
- **Character deferred polish** — the user flagged "some polish for later" (level-glyph fidelity, icon
|
||||
crispness, sample strings). Filed as an issue; the user will enumerate.
|
||||
|
||||
## 4. Patterns + lessons (don't relearn these the hard way)
|
||||
|
||||
- **Faithful-panel pattern:** bind real importer-mounted elements via `FindElement(datId)`; `EventId` ≠ dat id.
|
||||
- **Importer dat-fidelity:** the look comes from the dat; when re-deriving fonts/colors/positions in code feels
|
||||
like a treadmill, AUDIT what the dat element carries vs what the importer drops, then wire it backward-compat.
|
||||
- **The boundary:** look = importer; state/behavior = runtime controller. Don't fight it.
|
||||
- **Apparatus over speculation:** for a layout bug, DUMP the actual rendered rects (walk the tree, print
|
||||
abs rect + visible + text). One position dump cracked the footer-overlap after FIVE speculative passes.
|
||||
cdb is for runtime *behavior* questions, not "why is our element at the wrong place."
|
||||
- **Watch subagents for scope creep:** the Fix-C subagent finished its task then committed unrequested AP-58 +
|
||||
#148 (reverted per the user, kept in reflog `46c5cd2`/`82e13b7`). Constrain dispatches to the assigned task.
|
||||
- **Shared-infra changes:** regression-screenshot vitals + toolbar (the canaries) every time; chat is the one
|
||||
panel the studio can't easily preview, so never change global `UiText`/`UiMeter` behavior without verifying it.
|
||||
|
||||
## 5. Reference map
|
||||
|
||||
- Studio spec/plan: `docs/superpowers/specs/2026-06-25-ui-studio-previewer-design.md`,
|
||||
`docs/superpowers/plans/2026-06-25-ui-studio-previewer.md`; dump sweep `docs/research/2026-06-25-studio-dump-panel-sweep.md`.
|
||||
- Character window: the three specs above + the retail reference.
|
||||
- Importer audit (this session): the dat carries FontDID/justification/FontColor in `StateDesc.Properties`;
|
||||
`ElementReader`/`LayoutImporter`/`DatWidgetFactory`/`UiText` are the wiring path.
|
||||
- The retail UI dump: `docs/research/2026-06-25-retail-ui-layout-dump.json` (26 windows, real ids + rects + sprites).
|
||||
- Deferred studio features (the original plan, Tasks 5-8): live 3-D doll, markup hot-reload, editable props,
|
||||
camera sliders — secondary to the mockup.
|
||||
- Memory SSOT: `claude-memory/project_ui_studio.md`, `project_d2b_retail_ui.md`.
|
||||
|
||||
## 6. First concrete steps for the next agent
|
||||
|
||||
1. Fix **#149** (inventory studio render) — you need the inventory window for any real mockup.
|
||||
2. Prototype **mockup mode**: render the production `UiHost` (with vitals + toolbar + character + chat opened)
|
||||
directly to the studio GL window, native input. Confirm drag + resize + click work through the production host.
|
||||
3. Then iterate window open/close/arrange + the desktop layout.
|
||||
Loading…
Add table
Add a link
Reference in a new issue