using AcDream.App.UI; using AcDream.App.UI.Layout; namespace AcDream.App.Tests.UI.Layout; /// /// Retail's "Side By Side Vitals" character option swaps which of the TWO /// complete vitals windows is visible — nothing is rearranged in place: /// gmFloatyVitalsUI::UpdateFromPlayerModule @0x004CF140 (stacked /// visible iff the bit is CLEAR), gmFloatySideVitalsUI:: /// UpdateFromPlayerModule @0x004D0810 (side row visible iff SET), and the /// live flip in gmGamePlayUI::RecvNotice_PlayerOptionChanged @0x004E9DA0. /// The bit is PlayerModule::SideBySideVitals @0x005D3070 = /// CharacterOptions1 0x00200000 (option id 0x13) — ACE-confirmed. /// public sealed class VitalsSideBySideControllerTests { [Fact] public void FirstTick_AppliesTheCurrentBit_BothDirections() { var (root, stacked, side) = Windows(); bool bit = false; var controller = new VitalsSideBySideController( root, () => bit, WindowNames.Vitals, WindowNames.SideVitals); controller.Tick(); Assert.True(stacked.Visible); Assert.False(side.Visible); Assert.False(controller.Applied!.Value); } [Fact] public void FirstTick_WithBitSet_ShowsTheSideRow() { var (root, stacked, side) = Windows(); var controller = new VitalsSideBySideController( root, () => true, WindowNames.Vitals, WindowNames.SideVitals); controller.Tick(); Assert.False(stacked.Visible); Assert.True(side.Visible); } [Fact] public void BitEdge_SwapsLive_BothDirections() { // The Character tab's checkbox (or the inbound PlayerModule blob) // flips the stored bit; the next frame swaps the windows — retail's // RecvNotice_PlayerOptionChanged live apply. var (root, stacked, side) = Windows(); bool bit = false; var controller = new VitalsSideBySideController( root, () => bit, WindowNames.Vitals, WindowNames.SideVitals); controller.Tick(); bit = true; controller.Tick(); Assert.False(stacked.Visible); Assert.True(side.Visible); bit = false; controller.Tick(); Assert.True(stacked.Visible); Assert.False(side.Visible); } [Fact] public void SteadyBit_DoesNotReassertVisibility() { // Edge-detected: a steady bit must not fight other visibility // machinery every frame (only the option EDGE applies, mirroring // retail's notice-driven apply rather than a per-frame force). var (root, stacked, side) = Windows(); var controller = new VitalsSideBySideController( root, () => false, WindowNames.Vitals, WindowNames.SideVitals); controller.Tick(); // Simulate an out-of-band hide (e.g. a future toggle surface). stacked.Visible = false; controller.Tick(); Assert.False(stacked.Visible); } private static (UiRoot Root, UiPanel Stacked, UiPanel Side) Windows() { var root = new UiRoot { Width = 800, Height = 600 }; var stacked = new UiPanel { Width = 160, Height = 58 }; var side = new UiPanel { Width = 460, Height = 26, Visible = false }; root.AddChild(stacked); root.AddChild(side); root.RegisterWindow(WindowNames.Vitals, stacked, stacked, null); root.RegisterWindow(WindowNames.SideVitals, side, side, null); return (root, stacked, side); } }