using System;
namespace AcDream.App.UI.Layout;
///
/// Per-window controller for the vitals layout (LayoutDesc 0x2100006C).
/// Mirrors retail gmVitalsUI::PostInit: grab the three meter elements
/// by their dat element ids and bind live data providers (fill fraction + cur/max
/// text) to each. This is the ONLY per-window code in the whole importer โ pure
/// data wiring, not graphics.
///
/// The slice sprites + dat font on each are already
/// set by during tree construction; this controller
/// only binds the dynamic vitals data. Do not touch meter rendering fields here.
///
/// Element ids confirmed from
/// docs/research/2026-06-15-layoutdesc-format.md ยง11
/// (vitals window 0x2100006C dump).
///
public static class VitalsController
{
/// Dat element id for the Health meter (0x100000E6).
public const uint Health = 0x100000E6;
/// Dat element id for the Stamina meter (0x100000EC).
public const uint Stamina = 0x100000EC;
/// Dat element id for the Mana meter (0x100000EE).
public const uint Mana = 0x100000EE;
///
/// Bind live vitals data providers to the Health, Stamina, and Mana meter
/// elements found in . Any meter whose id is absent
/// from the layout is silently skipped โ partial layouts (e.g. test fakes)
/// do not cause errors.
///
/// Imported vitals layout tree.
/// Provider returning Health fill fraction [0..1].
/// Provider returning Stamina fill fraction [0..1].
/// Provider returning Mana fill fraction [0..1].
/// Provider returning Health "cur/max" overlay text.
/// Provider returning Stamina "cur/max" overlay text.
/// Provider returning Mana "cur/max" overlay text.
public static void Bind(
ImportedLayout layout,
Func healthPct,
Func staminaPct,
Func manaPct,
Func healthText,
Func staminaText,
Func manaText)
{
BindMeter(layout, Health, healthPct, healthText);
BindMeter(layout, Stamina, staminaPct, staminaText);
BindMeter(layout, Mana, manaPct, manaText);
}
private static void BindMeter(
ImportedLayout layout, uint id,
Func pct,
Func text)
{
if (layout.FindElement(id) is UiMeter m)
{
m.Fill = () => pct();
m.Label = () => text();
}
// Silently skip if the id is absent โ missing meters are not an error.
}
}