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