# MOUSELOOK_PLAN — scope: mouse movement as a cockpit axis **Status: SCOPED, NOT IMPLEMENTED.** Written 2026-07-26 at the author's request, alongside the mouse-BUTTON support that did ship (4.11.565). Read §2 before agreeing to build it — the hard part is not reading the mouse. --- ## 1. What shipped, and what this is instead **Shipped:** mouse *buttons*, as key names (`MOUSE4`, `MOUSE5`, `MOUSEMIDDLE`, `MOUSELEFT`, `MOUSERIGHT`). Zero new machinery — Win32 hands mouse buttons out as virtual keys and the binding path already stores VKs and polls `GetAsyncKeyState`, so five table entries were the whole change. **This document:** mouse *movement* driving `JoystickX`/`JoystickY` (torso twist and aim) — the thing a modern player means by "mouse look". That is a real feature, not a table entry, for three reasons that have nothing to do with reading the device. ## 2. The three real problems ### 2.1 The cursor is already spoken for ⚠ (the blocking one) The glass cockpit's whole premise is that **every one of the 72 pod buttons is a mouse target** — left-click presses, right-click latches, and under the exploded layout there are seven separate windows to click in. Mouse-look wants the opposite: a captured, hidden, recentred cursor that never touches a button. These cannot both be true at once, so the feature is really a **mode question**, and the answer decides the whole design: | Model | Feel | Cost | |---|---|---| | **A. Hold-to-look** (`key MOUSE5 mouselook` or a modifier) | Cursor stays free; press to steer, release to click buttons | No mode confusion, discoverable, but you cannot look and hold a trigger comfortably | | **B. Toggle** (a key flips captured/free) | Full mouse-look while engaged | Needs a visible on-screen indicator or players get stuck "unable to click anything" | | **C. Region** (look while the pointer is over the 3D view, click when over a display) | No mode at all | Fails in the exploded layout (displays are separate windows) and near the surround's corner MFDs, which overlap the view by design | | **D. Always captured**, panel clicks via a "release" key | Cleanest for a shooter | Throws away the cockpit's defining interaction; **not recommended** | **Recommendation: A, with B as an option.** A costs nothing when unbound and cannot strand a player. It is also the only one that behaves identically in the surround and exploded layouts. ### 2.2 The pod's channels are POSITIONAL; a mouse is not `JoystickX`/`JoystickY` are absolute stick deflections in −1..1 that `MechControlsMapper` interprets per control mode. A mouse produces *deltas*. Bridging that is a design choice, not a conversion: - **Accumulate** (recommended): integrate deltas into the channel, clamp to ±1 — a "virtual stick". Reuses every existing rule (composition, the #36 release edge, the gait detent). - **Rate**: treat the delta as a velocity of torso angle. Feels better for aiming, but the mapper has no rate input — it would mean a new channel semantic and a new path through the mapper. Bigger and less authentic. With Accumulate, the stick does not spring back (a mouse has no centre). Options, all cheap: a `spring ` trailing option that decays toward 0, and/or a recentre key (0x42 torso centre is already bound to the Up arrow). ### 2.3 Control mode changes what it means BASIC steers with the stick; MID/ADV twist the torso with it and steer with the pedals ([[experience-levels]], [[pod-hardware]]). So mouse-look **steers the mech in BASIC and aims the torso in MID/ADV** — authentic, but it will read as a bug to anyone who hasn't been told. The docs must say so, and the feature is most useful in MID/ADV. ## 3. Proposed shape (if we build it) New row type — the sanctioned way to extend the grammar (old builds skip unknown rows with a logged warning, so a player's file stays forward-compatible): ``` mouseaxis axis [invert] [sensitivity ] [spring ] [deadzone ] key mouselook # hold-to-look (model A) ``` Example default (shipped commented out): ``` #mouseaxis X axis JoystickX sensitivity 1.0 spring 0 #mouseaxis Y axis JoystickY sensitivity 1.0 spring 0 invert #key MOUSE5 mouselook ``` ### Where the code goes | Piece | Where | Notes | |---|---|---| | Raw delta capture | `L4PADRIO` (new), fed from the window proc | **`WM_INPUT` (RawInput)**, not `WM_MOUSEMOVE`: relative motion, no cursor clamping at screen edges, no pointer acceleration. Register `HID_USAGE_GENERIC_MOUSE` with `RIDEV_INPUTSINK` off (foreground only). | | Capture/hide | same | `SetCapture` + `ShowCursor(FALSE)` + recentre per frame while engaged; release on focus loss | | Bindings | `L4PADBINDINGS` | `mouseAxisBindings[]` + the `mouselook` action, parallel to `padAxisBindings` | | Channel write | `PadRIO::Poll` | Beside the pad/joy axis writes, with the SAME per-binding previous-value array so it inherits the #36 release edge and the #24 disconnect rule | | Docs | `bindings.txt` header, `docs/CONTROLS.md`, `docs/CONTROLS.html` | including the control-mode caveat | Estimated size: ~250 lines plus docs. No engine or reconstruction changes — this is entirely in the glass desktop layer, like PadRIO itself. ## 4. Authenticity note **The pod had no mouse.** There is nothing to reconstruct here and no binary behaviour to be faithful to — this is a desktop-convenience layer, exactly like PadRIO and the glass cockpit itself. That is fine (the layer exists precisely so developers and players can fly without a cabinet), but it means every decision above is a *design* decision and should be judged on feel, not fidelity. It also means it must stay out of the pod build's path: gate it the way PadRIO is gated, so `BT_PLATFORM=pod` never sees it. ## 5. Verification plan 1. `mouseaxis` rows parse; unknown-option rows warn and skip (grammar-compatibility rule). 2. Hold-to-look engages/releases; cursor visible again on release AND on focus loss (the #24 disconnect rule, mouse edition). 3. Channel values track motion, clamp at ±1, and release cleanly to 0 (the #36 latch bug is exactly the hazard here). 4. **Panel clicks still work** while a mouselook binding exists but is not engaged — in BOTH the surround and exploded layouts. This is the regression that matters. 5. Control-mode sweep: BASIC steers, MID/ADV twists — confirmed against `[mppr]` trace. 6. Pod + dev profiles: no mouse path constructed at all. ## 6. Open questions 1. Model A or B (§2.1)? Everything else follows from it. 2. Should mouse-look imply a crosshair/reticle change, so the player can see it is engaged? 3. Does the exploded layout need its own answer, given the seven windows each have their own client area and the main window may not have focus? 4. Is this wanted for the tester builds at all, or only for the operator/dev seat? It is not pod-authentic, and the cockpit's mouse-click identity is a feature people have praised. ## Key Relationships - Extends: [[glass-cockpit]] (PadRIO, the desktop input layer) · Constrained by: [[pod-hardware]] (the RIO channel model), [[experience-levels]] (control modes) - Prior art in-tree: `L4JOY` (DirectInput layer + the wizard) is the closest analogue for adding a whole new input device cleanly.