Commit graph

3 commits

Author SHA1 Message Date
Erik
9ed9d8dbd9 fix(studio): Task 4 — bind PaperdollController + wire empty-slot sprites
FixtureProvider.Populate for 0x21000023 was binding only
InventoryController and omitting PaperdollController, so the
~21 equip slots rendered empty even though sample equipped items
existed in the table.  Also, the three per-list empty-slot
sprites were not being resolved from the dat (contentsEmpty /
sideBagEmpty / mainPackEmpty all defaulted to 0), so the slot cells
had no background art.

Fixes:
- FixtureProvider.Populate gains a DatCollection dats param
  (mirrors the GameWindow.OnLoad lookup at line 2233-2235).
  The 0x21000023 case now resolves all three empty sprites via
  ItemListCellTemplate.ResolveEmptySprite and passes them to
  InventoryController.Bind.
- PaperdollController.Bind is now called after InventoryController
  in the same 0x21000023 case, matching GameWindow:2257-2265
  (same layout subtree, contentsEmpty as the equip-slot placeholder,
  sendWield: null since there is no live session in the studio).
- StudioWindow.OnLoad passes _dats! to the updated Populate signature.

SampleData.AddEquipped was already correct: MoveItem(guid, PlayerGuid,
-1, equipMask) at ClientObjectTable.cs:134 sets
CurrentlyEquippedLocation = newEquipLocation and calls Reindex which
places the item in _containerIndex[PlayerGuid].  No SampleData change
needed.

Tests: 2 new assertions in FixtureProviderTests —
  sideBags_matchInventoryControllerFilter (Type.HasFlag(Container)
  || ItemsCapacity > 0 filter must match both bags) and
  equippedItems_retainLocationAndAreInContents (equipped items have
  CurrentlyEquippedLocation != None AND appear in GetContents so the
  paperdoll controller can find them).  604 pass / 2 skip / 0 fail.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 15:59:13 +02:00
Erik
0bdc866c15 feat(studio): FixtureProvider — sample data populates the 2-D panels
Task 4 of the UI Studio plan: adds SampleData (static ClientObjectTable
builder with a synthetic player, 6 loose items, 2 side bags, and 3 equipped
pieces) and FixtureProvider (switches on layoutId and calls the production
controller Bind methods — VitalsController, ToolbarController,
InventoryController — so the studio previews panels with plausible data
instead of empty widgets).

Icon ids approach: raw-resolve stub — resolves the base iconId via
RenderStack.ResolveChrome and returns the GL handle directly. This is v1
(single-layer icon); the full 5-layer IconComposer composite is a live-game
concern, not a layout-preview concern.

StudioWindow wires FixtureProvider.Populate after _source.Load; the
ClientObjectTable is stored on _objects so controller event subscriptions
(ObjectAdded/ObjectMoved) remain live for the window's lifetime.

4 new FixtureProviderTests (SampleTable_hasPackContents,
SampleTable_hasWeaponAndArmor, SampleTable_hasEquippedItems,
SampleTable_hasSideBags) — all pass. Full App suite: 602 passed / 2
skipped (pre-existing) / 0 failed. Build green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 15:45:11 +02:00
Erik
df6b5b3b39 feat(studio): StudioWindow + LayoutSource — render a dat panel standalone
Task 2 of the acdream UI Studio plan. Adds three new files under
src/AcDream.App/Studio/ and one new test file:

- StudioOptions.cs: record + Parse() for the ui-studio CLI args (positional
  dat dir or ACDREAM_DAT_DIR, --layout 0xNNNN, --markup <path>; defaults to
  vitals 0x2100006C when neither layout nor markup given).
- LayoutSource.cs: wraps LayoutImporter.Import for dat-backed layouts; markup
  path sets LastError "markup unsupported (Task 6)" and returns null for now.
  Exposes Kind / LayoutId / MarkupPath / LastError / CurrentLayout / Reload().
- StudioWindow.cs: Silk.NET 1280×720 GL 4.3 window; boots RenderBootstrap,
  wires input to UiHost, loads the panel via LayoutSource, adds the root to
  UiHost.Root.AddChild. QualitySettings resolved the same way GameWindow.Run()
  does (SettingsStore → QualitySettings.From → WithEnvOverrides).
- Program.cs: ui-studio dispatch at the top of top-level statements (before
  the dat-dir parse) so `dotnet run -- ui-studio` routes to StudioWindow.
- LayoutSourceTests.cs: dat-gated test (skips when dats absent); verifies that
  the vitals LayoutDesc (0x2100006C) loads, root is non-null, byId contains the
  vitals root element (0x100005F9), and Kind == DatLayout. Passes (1/1 with dats
  present; silently skips on CI).

Note: the spec asserts FindElement(0x2100006Cu) — that id is the LayoutDesc
dat id, not a widget element id. The actual vitals root element id is 0x100005F9
(confirmed from the vitals_2100006C.json fixture). The test uses the correct
element id and documents the discrepancy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 14:26:47 +02:00