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;
};
}