using AcDream.App.Rendering; using AcDream.App.UI; using AcDream.App.UI.Layout; using AcDream.Core.Items; using AcDream.Core.Net.Messages; using DatReaderWriter; namespace AcDream.App.Studio; /// /// Populates a loaded panel with sample data by calling the production /// controller Bind methods against . /// /// /// The studio is intentionally thin — there is no live game session, no /// server connection, and no network. FixtureProvider bridges that gap by /// feeding static fixtures (vitals percentages, a fake inventory, empty /// shortcut lists) so the bound widgets show plausible state instead of /// empty zeroes. /// /// /// /// IconIds approach: raw-resolve stub — resolve the base iconId /// via and return the GL handle /// directly. This is intentionally simpler than GameWindow's full /// (5-layer composite). The raw icon is enough /// to confirm the grid cells draw something in the studio; the full /// compositor is the live-game concern, not the layout preview concern. /// /// public static class FixtureProvider { /// /// Populate with sample data appropriate for /// . Calls the production controller Bind /// methods so the panel's widgets drive off the same code path as the /// full game. /// /// The LayoutDesc dat id used to import the layout. /// The imported layout whose widgets to populate. /// The live render stack (for /// and ). /// A already seeded by /// . /// The live DAT collection used to resolve per-list empty-slot sprites /// (same lookup GameWindow.OnLoad performs for the production binding). public static void Populate( uint layoutId, ImportedLayout layout, RenderStack stack, ClientObjectTable objects, DatCollection dats) { switch (layoutId) { case 0x2100006Cu: // vitals VitalsController.Bind(layout, healthPct: () => SampleData.HealthPct, staminaPct: () => SampleData.StaminaPct, manaPct: () => SampleData.ManaPct, healthText: () => "80/100", staminaText: () => "60/100", manaText: () => "90/100"); break; case 0x21000016u: // toolbar ToolbarController.Bind( layout, objects, shortcuts: () => System.Array.Empty(), iconIds: MakeIconIds(stack), useItem: _ => { }, combatState: null, peaceDigits: null, warDigits: null, emptyDigits: null, sendAddShortcut: null, sendRemoveShortcut: null); break; case 0x21000023u: // inventory + paperdoll { // Resolve the per-list empty-slot art from the dat cell template, matching the // exact lookup GameWindow.OnLoad performs (UIElement_ItemList::InternalCreateItem // 0x004e3570 → attr 0x1000000e → catalog 0x21000037 → ItemSlot_Empty). uint contentsEmpty = ItemListCellTemplate.ResolveEmptySprite(dats, 0x21000021u, 0x100001C6u); uint sideBagEmpty = ItemListCellTemplate.ResolveEmptySprite(dats, 0x21000022u, 0x100001CAu); uint mainPackEmpty = ItemListCellTemplate.ResolveEmptySprite(dats, 0x21000022u, 0x100001C9u); var iconIds = MakeIconIds(stack); InventoryController.Bind( layout, objects, playerGuid: () => SampleData.PlayerGuid, iconIds: iconIds, strength: () => 100, datFont: stack.VitalsDatFont, contentsEmptySprite: contentsEmpty, sideBagEmptySprite: sideBagEmpty, mainPackEmptySprite: mainPackEmpty); // Bind the paperdoll equip slots (same imported subtree as the inventory). // Mirrors GameWindow:2257-2265: PaperdollController.Bind with contentsEmpty as // emptySlotSprite (each slot shows the same square-frame placeholder as the grid). PaperdollController.Bind( layout, objects, playerGuid: () => SampleData.PlayerGuid, iconIds: iconIds, sendWield: null, // no live session in the studio emptySlotSprite: contentsEmpty, datFont: stack.VitalsDatFont); break; } default: // Unknown layout — no-op; the panel renders structurally. break; } } // ── Helpers ───────────────────────────────────────────────────────────── /// /// Build the iconIds delegate for toolbar / inventory controllers. /// /// /// Raw-resolve stub: resolve the base (arg 2) /// via and return its GL handle. /// The remaining args (type, underlayId, overlayId, effects) are ignored /// for the studio — a single-layer icon is sufficient for layout preview. /// /// /// This is what the task spec calls "v1 raw-resolve stub". /// private static Func MakeIconIds(RenderStack stack) => (_, iconId, _, _, _) => { if (iconId == 0u) return 0u; var (handle, _, _) = stack.ResolveChrome(iconId); return handle; }; }