From 3b6f293dc8d68e8dbdb861488461a612185c6d94 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 16 Jun 2026 22:44:52 +0200 Subject: [PATCH] feat(D.5.1): mount the toolbar window under ACDREAM_RETAIL_UI Wire IconComposer + ToolbarController.Bind + the LayoutDesc 0x21000016 import into the if (_options.RetailUi) block in GameWindow, mirroring the vitals/chat pattern. Add UseItemByGuid helper (direct send, no proximity gate) near the B.4b use-item path. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/AcDream.App/Rendering/GameWindow.cs | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 1488fc3a..2c19fde5 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -1780,6 +1780,11 @@ public sealed class GameWindow : IDisposable return (t, w, h); } + // Phase D.5.1 — icon composer for the toolbar shortcut slots. + // Constructed once here so the closure below can capture it; needs + // the same cache reference that ResolveChrome uses above. + var iconComposer = new AcDream.App.UI.IconComposer(_dats!, cache); + // Phase D.2b — optional retail stylesheet. controls.ini lives under // the AC install (ACDREAM_AC_DIR); absent → source-verified fallback. var controls = _options.AcDir is { } acDir @@ -1902,6 +1907,29 @@ public sealed class GameWindow : IDisposable } else Console.WriteLine("[D.2b] chat: LayoutDesc 0x21000006 not found."); + // Phase D.5.1 — toolbar window, data-driven from LayoutDesc 0x21000016 + // (gmToolbarUI). Mirrors the vitals/chat import+bind+mount pattern above. + AcDream.App.UI.Layout.ImportedLayout? toolbarLayout; + lock (_datLock) + toolbarLayout = AcDream.App.UI.Layout.LayoutImporter.Import( + _dats!, 0x21000016u, ResolveChrome, vitalsDatFont); + if (toolbarLayout is not null) + { + AcDream.App.UI.Layout.ToolbarController.Bind( + toolbarLayout, Items, + () => Shortcuts, + iconIds: (icon, under, over) => iconComposer.GetIcon(icon, under, over), + useItem: guid => UseItemByGuid(guid)); + + var toolbarRoot = toolbarLayout.Root; + toolbarRoot.Left = 10; toolbarRoot.Top = 300; + toolbarRoot.Anchors = AcDream.App.UI.AnchorEdges.Left | AcDream.App.UI.AnchorEdges.Top; + toolbarRoot.Draggable = true; + _uiHost.Root.AddChild(toolbarRoot); + Console.WriteLine("[D.5.1] retail toolbar window from LayoutDesc importer (0x21000016)."); + } + else Console.WriteLine("[D.5.1] toolbar: LayoutDesc 0x21000016 not found."); + // Drain plugin-registered markup panels (buffered before the GL // window opened) into the same UiRoot tree. A faulty plugin markup // file is isolated — logged + skipped, never crashes the client. @@ -11594,6 +11622,17 @@ public sealed class GameWindow : IDisposable } } + // Phase D.5.1 — direct use-by-guid for toolbar shortcut clicks. + // Mirrors the B.4b far-range send path; no proximity / auto-walk needed + // for items already in the player's inventory. + private void UseItemByGuid(uint guid) + { + if (_liveSession is null) return; + var seq = _liveSession.NextGameActionSequence(); + var body = AcDream.Core.Net.Messages.InteractRequests.BuildUse(seq, guid); + _liveSession.SendGameAction(body); + } + private void SendPickUp(uint itemGuid) { if (_liveSession is null