# Handoff — D.2b inventory: A + B-Grid shipped, #145 fixed, B-Controller next **Date:** 2026-06-21 **From:** the session that shipped the **window manager (Sub-phase A)**, **B-Grid** (inventory sub-window mount + grid), and fixed **#145** (ZLevel z-order). All committed on branch `claude/hopeful-maxwell-214a12`, tip `4904ff4`. Full suite green (2767). **Predecessor handoff:** `docs/research/2026-06-20-window-manager-inventory-handoff.md` (the A→B→C arc). This doc supersedes it for "what's next." **Line numbers drift — grep the symbol.** --- ## 0. What shipped this session - **Sub-phase A — window manager.** `UiRoot` named-window registry (`RegisterWindow` / `ShowWindow` / `HideWindow` / `ToggleWindow` / `BringToFront`), raise-on-click, and F12 → toggle via the **existing** `InputAction.ToggleInventoryPanel`. `UiHost` forwarders. Spec `docs/superpowers/specs/2026-06-20-d2b-window-manager-design.md`; plan `…/plans/2026-06-20-d2b-window-manager.md`. Commits `6409038`/`036db8b`/`882b4dd`/`e3152ad`. Visually confirmed (F12 toggles, click raises, chat-focus gate). - **Cross-check correction:** retail's inventory key is **F12** (`ToggleInventoryPanel`), NOT `I` (`I` = the `Laugh` emote per `retail-default.keymap.txt:246`). The handoff guessed I. - **Sub-phase B-Grid — inventory frame.** `UiItemList` N-cell **grid mode** (`Columns`/`CellWidth`/`CellHeight`/`CellOffset`/`LayoutCells`; single-cell toolbar preserved) + the **sub-window mount** in `LayoutImporter.Resolve` + the `GameWindow` swap of the A placeholder for `LayoutImporter.Import(0x21000023)`. Spec `…/specs/2026-06-20-d2b-inventory-grid-mount-design.md`; plan `…/plans/2026-06-20-d2b-inventory-grid-mount.md`. Commits `4fd4b09`/`85098f5`/`7d971a2`. - **#145 — ZLevel z-order (DONE `45a5cc5`).** The importer mapped `ZOrder ← ReadOrder` only, so the gmInventoryUI full-window backdrop (`0x100001D0`, ReadOrder 4) painted over the panels (ReadOrder 1-3). Now `ZOrder = ReadOrder − ZLevel·10000` (higher ZLevel = further back). See §3. --- ## 1. Read first - This doc + the two B-Grid spec/plan files above. - `docs/research/2026-06-16-ui-panels-synthesis.md` §4 (the core-panels build plan). - `docs/research/2026-06-16-inventory-deep-dive.md` (gmInventoryUI nesting + wire catalog). - `claude-memory/project_d2b_retail_ui.md` (toolkit crib — updated this session). - `claude-memory/project_object_item_model.md` (the `ClientObjectTable` — B-Controller's data source). --- ## 2. Decomposition + status Sub-phase B was decomposed into four steps (approved this session): | Step | Status | |---|---| | **B-Grid** — UiItemList grid + sub-window mount | ✅ **SHIPPED** (mount works for all 3 panels; paperdoll equip-slot positions visually confirmed) | | **B-Controller** — populate grids + burden meter + captions | ⬜ **NEXT** (see §5) | | **B-Wire** — wire gaps (DropItem/ViewContents/…) | ⬜ pending | | **B-Drag** — inventory cell as drag SOURCE (reuse the shipped spine) | ⬜ pending | | **Sub-phase C** — paperdoll doll + per-slot equip art | ⬜ pending (the wrong-slot-graphics fix lives here) | --- ## 3. Key discoveries (durable, non-obvious) 1. **The nested panels are Type-0 inheritors, not game-class Types.** `gmInventoryUI 0x21000023`'s three panels — paperdoll `0x100001CD`, backpack `0x100001CE`, 3D-items `0x100001CF` — are **Type-0, media-less, childless leaves** that nest via `BaseElement`+`BaseLayoutId` (BaseLayoutId → `0x21000024`/`0x21000022`/`0x21000021`). The research agent's "game-class Type + recursive Import" model was WRONG — confirmed by dumping `0x21000023`. 2. **The mount = inheritance carrying base children.** `ElementReader.Merge` dropped the base's children. The mount (`LayoutImporter.ShouldMountBaseChildren` + the `Resolve` tail) attaches a base's resolved subtree when the derived element is a pure container (no own children, no own media) inheriting from a base WITH children. Inert for media-bearing inheritors (close button/title) and childless style prototypes (vitals/chat/toolbar). 3. **ZLevel z-order: higher = further back.** `DatWidgetFactory` folds `ZLevel` into `ZOrder` (`ReadOrder − ZLevel·10000`). ZLevels observed: vitals all **0**; toolbar **0,1,2**; chat **0,900**; inventory **0,10,50,100** (backdrop 100). Vitals unchanged; **chat + toolbar shifted to their dat layering — needs a visual regression confirm (see §6).** 4. **The paperdoll equip slots need `0x10000032` (UiItemSlot) registration.** They resolve to type `0x10000032`, which the factory does NOT register, so they fall back to a generic `UiDatElement` sprite (the uniform blue border seen on screen) instead of per-slot silhouettes. This + the dressed doll is **Sub-phase C**. --- ## 4. Current visual state (F12 with ACDREAM_RETAIL_UI=1) The inventory window opens and renders the nested frame: outer chrome + title + the **paperdoll equip slots correctly positioned** over the backdrop. **Gaps (all expected — next sub-steps):** - Equip slots draw a generic border, not per-slot silhouettes → **C**. - Backpack strip + 3D-items contents look empty (the panels mounted; their content is unpopulated) → **B-Controller**. - Item cells empty everywhere (no items bound) → **B-Controller**. --- ## 5. B-Controller — the next step **Goal:** make the inventory show your live contents — populate the backpack/3D-items grids from `ClientObjectTable`, drive the burden meter, render the captions. The `gm*UI::PostInit` analogue. **READY:** - `ClientObjectTable.GetContents(containerGuid)` → ordered guids; `Get(guid)` → icon fields (`src/AcDream.Core/Items/ClientObjectTable.cs`). The player's own pack is already in the table from the CreateObject stream — **no new wire needed for the own-pack path** (B-Wire is for other containers + live deltas). - `UiItemList` grid mode (B-Grid) — set `Columns`/`CellWidth`/`CellHeight` (read the cell pitch from the nested layout's item template) then `Flush()` + `AddItem()` per item. - `IconComposer` for the cell icons; `UiItemSlot.SetItem(guid, iconTex)`. - `ImportedLayout.FindElement(id)` to bind by id (the burden meter, the lists). - The burden meter is element `0x100001D9` (Type 7 → `UiMeter`); drive fill via `SetAttribute_Float`-equivalent (`UiMeter.Fill`); load ratio = burden/maxBurden. **MISSING / to build:** - `InventoryController`: find-by-id bind of the burden meter + the backpack/3D-items lists from `invLayout` (the `ImportedLayout` built in `GameWindow`); subscribe to `ClientObjectTable` `ObjectAdded/Moved/Removed`; rebuild cells. - **Grid params:** dump `0x21000022` (backpack) + `0x21000021` (3D-items) to read the item-list element sizes + cell template (geometry suggests backpack ~1 col, 3D-items ~6 cols of 36×36). - **Type-0 text captions** ("Burden", "Contents of Backpack") don't render today — `UiDatElement` doesn't draw text. Decide: promote those Type-0 elements to `UiText`, or a caption pass. - Burden meter: verify `BuildMeter` produces a valid meter for the backpack meter's child shape (it may differ from the vitals 3-slice shape). **Brainstorm Qs (B-Controller):** Where does `InventoryController` get `invLayout` (expose the `ImportedLayout` from `GameWindow`, or import inside the controller)? Cell pitch source (dump vs hardcode 36)? Type-0 caption rendering (UiText promotion vs a caption helper)? --- ## 6. Open items / caveats - **⚠ Confirm chat + toolbar didn't regress from the #145 ZLevel fix** (chat ZLevel 900, toolbar 1,2). The user looked but didn't explicitly confirm; first thing to eyeball next session. - Type-0 text captions don't render (see §5). - The B-Drag step reuses the **already-shipped** drag spine (`UiItemSlot` is a full drag source + drop target; `IItemListDragHandler`/`ItemDragPayload`/`ShortcutStore`/the AddShortcut wire all exist) — do NOT rebuild it. It needs the inventory cell as a SOURCE + the `SourceKind==Inventory` branch in `ToolbarController.HandleDropRelease`. --- ## 7. Branch state All work is on `claude/hopeful-maxwell-214a12` (tip `4904ff4`), which is `main` (`a391b86`) + this session's A + B-Grid + #145 commits (a clean fast-forward chain — `main` is an ancestor). Decide at the start of the next session: **fast-forward `main` to `4904ff4` and start a fresh worktree off `main`** (matches the prior-arc pattern), or continue this branch. --- ## 8. New-session prompt (paste into a fresh session) > Continue acdream's D.2b retail-UI inventory arc. **Read > `docs/research/2026-06-21-d2b-bgrid-shipped-bcontroller-next-handoff.md` first.** Sub-phase A > (window manager, F12) and B-Grid (inventory sub-window mount + UiItemList grid) shipped, and #145 > (ZLevel z-order — the backdrop now sits behind the panels) is fixed — all on > `claude/hopeful-maxwell-214a12` (tip `4904ff4`; `main` is an ancestor, so ff `main` and branch > fresh, or continue). F12 now shows the nested inventory frame with the paperdoll equip slots > correctly positioned, but the backpack/3D-items panels are empty and the equip slots show a > generic border. **Next: B-Controller** — bind the imported `gmInventoryUI` tree by id and > populate the backpack/3D-items grids from `ClientObjectTable.GetContents(player)` + drive the > burden meter (`0x100001D9`) + render the Type-0 captions. Use the full brainstorm → spec → plan → > subagent-driven flow; mandatory grep-named→cross-ref→pseudocode→port for any wire format; > conformance tests throughout. Reuse the shipped grid + window manager + drag spine — don't > rebuild. **First, eyeball chat + toolbar for any z-order regression from the #145 ZLevel fix.** > After B-Controller: B-Wire (wire gaps), B-Drag (inventory drag SOURCE), then Sub-phase C > (paperdoll doll + per-slot equip art — the wrong-graphics fix; needs `0x10000032` UiItemSlot > registration). **MEMORY.md index line:** - [Handoff: D.2b A+B-Grid shipped, #145 fixed, B-Controller next (2026-06-21)](research/2026-06-21-d2b-bgrid-shipped-bcontroller-next-handoff.md) — window manager (F12) + inventory sub-window mount (inheritance-children, NOT game-class Type) + UiItemList grid all shipped; #145 ZLevel z-order fixed (backdrop behind panels). Next B-Controller (populate grids + burden meter from ClientObjectTable). Paperdoll equip slots need 0x10000032; chat/toolbar ZLevel-regression unconfirmed.