feat(D.2b): wire UiHost input + moveable windows (UiRoot window-drag + WantCapture gate)
- UiElement: add Draggable flag; left-drag on a draggable element repositions it as a floating window instead of starting a drag-drop sequence. - UiRoot: add WantsMouse/WantsKeyboard properties (mirrors ImGui's WantCaptureMouse pattern); add FindDraggable helper; inject _windowDragTarget state machine into OnMouseDown/OnMouseMove/OnMouseUp so draggable windows track the pointer offset. - UiNineSlicePanel: set Draggable=true so retail window frames are movable by default. - GameWindow: OR _uiHost?.Root.WantsMouse|WantsKeyboard into the SilkMouseSource wantCaptureMouse/wantCaptureKeyboard delegates and the direct MouseMove gate so game actions (movement, world-pick) are suppressed while the pointer is over a retail window — no double-handling with the InputDispatcher. - GameWindow: wire all Silk Mice/Keyboards to UiHost after construction so the UiRoot tree receives live input. - Tests: 3 new UiRootInputTests covering WantsMouse hit-test, window-drag reposition, and non-draggable panel immobility. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2f4520ee12
commit
4acecffcd6
5 changed files with 124 additions and 5 deletions
|
|
@ -978,8 +978,10 @@ public sealed class GameWindow : IDisposable
|
|||
_kbSource = new AcDream.App.Input.SilkKeyboardSource(firstKb);
|
||||
_mouseSource = new AcDream.App.Input.SilkMouseSource(
|
||||
firstMouse,
|
||||
wantCaptureMouse: () => DevToolsEnabled && ImGuiNET.ImGui.GetIO().WantCaptureMouse,
|
||||
wantCaptureKeyboard: () => DevToolsEnabled && ImGuiNET.ImGui.GetIO().WantCaptureKeyboard);
|
||||
wantCaptureMouse: () => (DevToolsEnabled && ImGuiNET.ImGui.GetIO().WantCaptureMouse)
|
||||
|| (_uiHost?.Root.WantsMouse ?? false),
|
||||
wantCaptureKeyboard: () => (DevToolsEnabled && ImGuiNET.ImGui.GetIO().WantCaptureKeyboard)
|
||||
|| (_uiHost?.Root.WantsKeyboard ?? false));
|
||||
_mouseSource.ModifierProbe = () => _kbSource.CurrentModifiers;
|
||||
_inputDispatcher = new AcDream.UI.Abstractions.Input.InputDispatcher(
|
||||
_kbSource, _mouseSource, _keyBindings);
|
||||
|
|
@ -1045,7 +1047,8 @@ public sealed class GameWindow : IDisposable
|
|||
// K.1b §E: explicit WantCaptureMouse defense-in-depth on the
|
||||
// surviving direct-mouse handler. Suppresses RMB orbit /
|
||||
// FlyCamera look while ImGui has the mouse focus.
|
||||
if (DevToolsEnabled && ImGuiNET.ImGui.GetIO().WantCaptureMouse)
|
||||
if ((DevToolsEnabled && ImGuiNET.ImGui.GetIO().WantCaptureMouse)
|
||||
|| (_uiHost?.Root.WantsMouse ?? false))
|
||||
{
|
||||
_lastMouseX = pos.X;
|
||||
_lastMouseY = pos.Y;
|
||||
|
|
@ -1745,6 +1748,13 @@ public sealed class GameWindow : IDisposable
|
|||
_vitalsVm ??= new AcDream.UI.Abstractions.Panels.Vitals.VitalsVM(Combat, LocalPlayer);
|
||||
_uiHost = new AcDream.App.UI.UiHost(_gl, shadersDir, _debugFont);
|
||||
|
||||
// Feed Silk input to the UiRoot tree so windows drag / close / select.
|
||||
// UiRoot consumes UI events; the game InputDispatcher (subscribed to the
|
||||
// same devices) is gated off via WantCaptureMouse/Keyboard above when the
|
||||
// pointer is over a widget — no double-handling.
|
||||
foreach (var m in _input!.Mice) _uiHost.WireMouse(m);
|
||||
foreach (var kb in _input!.Keyboards) _uiHost.WireKeyboard(kb);
|
||||
|
||||
var cache = _textureCache!;
|
||||
(uint, int, int) ResolveChrome(uint id)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue