fix(input): Phase K live-test fixes pt2 — visible cursor in chase, free-fly discoverable
Two issues from the K-fix1 launch (2026-04-26 user report):
1. Mouse pointer invisible after login.
Root cause: CameraController.EnterChaseMode invokes
ModeChanged?.Invoke(IsChaseMode) — passing TRUE when chase
becomes active. The OnCameraModeChanged handler interpreted
that bool as `isFlyMode`, so chase entry wrongly triggered
the Raw cursor branch (raw = invisible pointer). The bool is
unreliable: ToggleFly passes IsFlyMode, ExitChaseMode passes
IsFlyMode, but EnterChaseMode passes IsChaseMode. Read the
controller state directly inside the handler instead — fly
mode IS the only state that needs Raw, everything else stays
Normal so the user can click panels / future selectables.
2. No way to enter free-fly mode.
The DebugPanel already had a "Toggle Free-Fly Mode" button
wired in K.2, but the user didn't know to look there. Added
two more discovery paths:
- Keyboard shortcut: Ctrl+Shift+F → AcdreamToggleFlyMode
in RetailDefaults() (retail leaves Ctrl+Shift+F unbound;
Ctrl+F is unused too, so this is conflict-free).
- View → Camera submenu in the ImGui MainMenuBar with a
"Enter / Exit Free-Fly Mode" entry whose label flips with
the active state. Shortcut hint shows "Ctrl+Shift+F".
The keyboard handler now also cancels _playerModeAutoEntry on
manual fly toggle (matches the DebugPanel button + new menu
entry — user's choice wins, the chase camera doesn't snap on
top of the fly camera mid-inspection).
Also corrected the View → Debug menu shortcut hint (was "F1",
actual binding is Ctrl+F1 since K.1c).
Tests still 1220 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bc9ee9fdfa
commit
6481169cb9
2 changed files with 50 additions and 15 deletions
|
|
@ -3987,19 +3987,23 @@ public sealed class GameWindow : IDisposable
|
|||
return new System.Numerics.Quaternion(0f, 0f, z, w);
|
||||
}
|
||||
|
||||
private void OnCameraModeChanged(bool isFlyMode)
|
||||
private void OnCameraModeChanged(bool _modeBool)
|
||||
{
|
||||
if (_input is null) return;
|
||||
var mouse = _input.Mice.FirstOrDefault();
|
||||
if (mouse is null) return;
|
||||
|
||||
// K-fix1 (2026-04-26): cursor visible by default in chase / orbit
|
||||
// modes — the user needs to click panels, dropdowns, the future
|
||||
// selection picker, etc. Mouse-look (raw mode) only happens
|
||||
// transiently while MMB is held (HideCursorForMouseLook /
|
||||
// RestoreCursorAfterMouseLook). Fly mode still needs raw because
|
||||
// it's a continuous look-and-fly affordance.
|
||||
bool needsRawCursor = isFlyMode;
|
||||
// K-fix2 (2026-04-26): the bool passed to ModeChanged is NOT
|
||||
// reliably "isFlyMode" — CameraController.EnterChaseMode invokes
|
||||
// it with IsChaseMode (true), CameraController.ToggleFly invokes
|
||||
// it with IsFlyMode, and CameraController.ExitChaseMode invokes
|
||||
// it with IsFlyMode. Reading the controller state directly is
|
||||
// the only correct gate. Cursor visible by default in chase /
|
||||
// orbit modes; Raw cursor only in fly mode (continuous
|
||||
// look-and-fly affordance). Mouse-look (raw mode) when MMB is
|
||||
// held is handled separately by HideCursorForMouseLook /
|
||||
// RestoreCursorAfterMouseLook.
|
||||
bool needsRawCursor = _cameraController?.IsFlyMode == true;
|
||||
mouse.Cursor.CursorMode = needsRawCursor ? CursorMode.Raw : CursorMode.Normal;
|
||||
_capturedMouse = needsRawCursor ? mouse : null;
|
||||
}
|
||||
|
|
@ -4330,10 +4334,27 @@ public sealed class GameWindow : IDisposable
|
|||
&& ImGuiNET.ImGui.MenuItem("Chat"))
|
||||
_chatPanel.IsVisible = !_chatPanel.IsVisible;
|
||||
if (_debugPanel is not null
|
||||
&& ImGuiNET.ImGui.MenuItem("Debug", "F1"))
|
||||
&& ImGuiNET.ImGui.MenuItem("Debug", "Ctrl+F1"))
|
||||
_debugPanel.IsVisible = !_debugPanel.IsVisible;
|
||||
ImGuiNET.ImGui.EndMenu();
|
||||
}
|
||||
// K-fix2 (2026-04-26): Camera submenu — discoverable
|
||||
// free-fly toggle for users who don't know the
|
||||
// Ctrl+Shift+F shortcut or the Debug-panel button.
|
||||
if (ImGuiNET.ImGui.BeginMenu("Camera"))
|
||||
{
|
||||
if (_cameraController is not null)
|
||||
{
|
||||
string flyLabel = _cameraController.IsFlyMode
|
||||
? "Exit Free-Fly Mode" : "Enter Free-Fly Mode";
|
||||
if (ImGuiNET.ImGui.MenuItem(flyLabel, "Ctrl+Shift+F"))
|
||||
{
|
||||
_playerModeAutoEntry?.Cancel();
|
||||
_cameraController.ToggleFly();
|
||||
}
|
||||
}
|
||||
ImGuiNET.ImGui.EndMenu();
|
||||
}
|
||||
ImGuiNET.ImGui.EndMainMenuBar();
|
||||
}
|
||||
|
||||
|
|
@ -5327,6 +5348,12 @@ public sealed class GameWindow : IDisposable
|
|||
break;
|
||||
|
||||
case AcDream.UI.Abstractions.Input.InputAction.AcdreamToggleFlyMode:
|
||||
// K-fix2 (2026-04-26): manual fly toggle pre-empts the
|
||||
// auto-entry trigger so the chase camera doesn't snap on
|
||||
// top of the fly camera mid-inspection. Mirrors the
|
||||
// DebugPanel "Toggle Free-Fly Mode" button + Camera menu
|
||||
// entry.
|
||||
_playerModeAutoEntry?.Cancel();
|
||||
_cameraController?.ToggleFly();
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -325,12 +325,11 @@ public sealed class KeyBindings
|
|||
b.Add(new(new KeyChord(Key.Down, ModifierMask.Ctrl), InputAction.ScrollDown));
|
||||
|
||||
// ── Acdream debug actions: relocated to Ctrl+F* to avoid retail
|
||||
// conflicts. AcdreamToggleFlyMode + AcdreamTogglePlayerMode have
|
||||
// NO keyboard binding in retail-default; K.2 adds a DebugPanel
|
||||
// button for free-fly toggle and player-mode is auto-entered at
|
||||
// login. AcdreamRmbOrbitHold is intentionally absent — retail
|
||||
// binds RMB to SelectRight; the chase-camera orbit lives behind
|
||||
// a debug-mode flag in K.2.
|
||||
// conflicts. AcdreamTogglePlayerMode has NO keyboard binding
|
||||
// in retail-default (player-mode is auto-entered at login).
|
||||
// AcdreamRmbOrbitHold is intentionally absent — retail binds
|
||||
// RMB to SelectRight; the chase-camera orbit lives behind a
|
||||
// debug-mode flag in K.2.
|
||||
b.Add(new(new KeyChord(Key.F1, ModifierMask.Ctrl), InputAction.AcdreamToggleDebugPanel));
|
||||
b.Add(new(new KeyChord(Key.F2, ModifierMask.Ctrl), InputAction.AcdreamToggleCollisionWires));
|
||||
b.Add(new(new KeyChord(Key.F3, ModifierMask.Ctrl), InputAction.AcdreamDumpNearby));
|
||||
|
|
@ -339,6 +338,15 @@ public sealed class KeyBindings
|
|||
b.Add(new(new KeyChord(Key.F9, ModifierMask.Ctrl), InputAction.AcdreamSensitivityUp));
|
||||
b.Add(new(new KeyChord(Key.F10, ModifierMask.Ctrl), InputAction.AcdreamCycleWeather));
|
||||
|
||||
// K-fix2 (2026-04-26): free-fly toggle keyboard shortcut.
|
||||
// Retail leaves Ctrl+Shift+F unbound (retail F = SelectionPickUp,
|
||||
// Ctrl+F = unused) so this is non-conflicting. Also discoverable
|
||||
// via View → Camera in the ImGui MainMenuBar and the
|
||||
// "Toggle Free-Fly Mode" button in the Debug panel.
|
||||
b.Add(new(
|
||||
new KeyChord(Key.F, ModifierMask.Ctrl | ModifierMask.Shift),
|
||||
InputAction.AcdreamToggleFlyMode));
|
||||
|
||||
// K-fix1 (2026-04-26): RMB-hold camera orbit. Coexists with the
|
||||
// SelectRight Press binding above — Press fires on click,
|
||||
// AcdreamRmbOrbitHold fires on hold/release transitions so the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue