diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs
index bba630e7..7c6bfd22 100644
--- a/src/AcDream.App/Rendering/GameWindow.cs
+++ b/src/AcDream.App/Rendering/GameWindow.cs
@@ -2137,6 +2137,19 @@ public sealed class GameWindow : IDisposable
}
}
}
+
+ // Phase D.2b-A — placeholder inventory window. Starts HIDDEN; F12
+ // (InputAction.ToggleInventoryPanel) reveals it via the UiRoot window
+ // manager. Throwaway scaffolding: Sub-phase B replaces the body with the
+ // real gmInventoryUI (0x21000023) nested layout, keeping the same name.
+ var inventoryWindow = new AcDream.App.UI.UiNineSlicePanel(ResolveChrome)
+ {
+ Left = 220, Top = 120, Width = 320, Height = 400,
+ Visible = false,
+ };
+ _uiHost.Root.AddChild(inventoryWindow);
+ _uiHost.RegisterWindow(AcDream.App.UI.WindowNames.Inventory, inventoryWindow);
+ Console.WriteLine("[D.2b-A] placeholder inventory window registered (F12 toggles).");
}
// Phase N.4+N.5 — WB rendering pipeline foundation. The modern path is
@@ -11420,6 +11433,13 @@ public sealed class GameWindow : IDisposable
switch (action)
{
+ case AcDream.UI.Abstractions.Input.InputAction.ToggleInventoryPanel:
+ // Retail F12 (rebindable). Gated upstream by WantsKeyboard, so it
+ // does not fire while the chat input holds focus. Null _uiHost =
+ // retail UI off (ACDREAM_RETAIL_UI unset) → no-op.
+ _uiHost?.ToggleWindow(AcDream.App.UI.WindowNames.Inventory);
+ break;
+
case AcDream.UI.Abstractions.Input.InputAction.AcdreamToggleDebugPanel:
foreach (var panel in EnumerateDebugPanel())
{
diff --git a/src/AcDream.App/UI/UiHost.cs b/src/AcDream.App/UI/UiHost.cs
index 718d5cbd..8e4c66f3 100644
--- a/src/AcDream.App/UI/UiHost.cs
+++ b/src/AcDream.App/UI/UiHost.cs
@@ -103,6 +103,14 @@ public sealed class UiHost : System.IDisposable
_ => UiMouseButton.Left,
};
+ // ── Window manager forwarders (delegate to UiRoot) ─────────────────
+
+ /// Register a top-level window for Show/Hide/Toggle. See .
+ public void RegisterWindow(string name, UiElement window) => Root.RegisterWindow(name, window);
+
+ /// Toggle a registered window's visibility; returns the new IsVisible.
+ public bool ToggleWindow(string name) => Root.ToggleWindow(name);
+
public void Dispose()
{
TextRenderer.Dispose();