From 3843dda03eccff9b8427b9582c8dbf2fe6a11488 Mon Sep 17 00:00:00 2001 From: Madison Date: Sun, 4 Oct 2026 22:11:28 +0900 Subject: [PATCH] VR_ARCHITECTURE.md: the Frame controller map as one table, what the grips rely on (dev only) --- docs/VR_ARCHITECTURE.md | 96 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 6 deletions(-) diff --git a/docs/VR_ARCHITECTURE.md b/docs/VR_ARCHITECTURE.md index e6fe375..ab4ad6b 100644 --- a/docs/VR_ARCHITECTURE.md +++ b/docs/VR_ARCHITECTURE.md @@ -96,12 +96,93 @@ and only does the client frame. Per-frame client state runs on the left eye (`cl ## 4. Controls -`OpenXrInput.c`: actions are the Quest ones plus `viewkey` and `bumperkey`. Profiles suggested on the Frame build, -each logged with the runtime's answer: Frame, Index, Touch (Pico isn't touched). `TBXR_UpdateFrameLayout` maps the Frame's -buttons into the Quest shape when the runtime reports the Frame profile active: A crouch, B jump, left bumper or right X -torch, View tap or right Y screen view, right Menu pause, View held 1 s / 3 s recentre. Left-handed schemes swap which -state the bits land on. Compared with `standard.md`: Menu and View follow it; A and B keep the game's crouch and jump -rather than the standard's jump/back; there's no VR settings page and no dominant-hand setting beyond `vr_control_scheme`. +Source of the layout: Half-Life's own gamepad layout from the 25th anniversary update (`valve/controller_configs/xbox_controller_config_standard.vdf`), +with the VR parts added (grips, head look). It replaced the first Frame map (the Quest layout moved around) after the second wear, and replaces +`standard.md` sections 1 and 2 where they differ: B is crouch (not back), A jump, X use, Y reload, bumpers and D-pad pick weapons, right stick click is the +flashlight. Menu and View kept their system jobs (Menu pause, View recentre) as in the standard. + +Code: `VrFrameMap.c` is the map as one table (`rows[]`: physical input, context, action); `VrInputFrame.c` turns it into the Quest-shaped states that +`VrInputDefault.c` reads (dominant hand: trigger, backpack grip, turn stick, use on the stick-click bit, crouch and jump on its two buttons; other hand: steady on +the grip, move stick, torch and screen view on its two buttons, laser on its stick-click bit) and into commands for what the scheme code doesn't have +(alt fire, reload, weapon select, last weapon, crowbar, quick save, menu keys, recentre). `OpenXrInput.c` reads the physical buttons (new `dpad*` actions) and logs the +profile. It only runs when the runtime reports the Frame profile active (or `diag_press` is in use). Contexts: menu (`cls.key_dest != key_game`), weapon hand +behind the head, other hand behind the head (not in multiplayer), multiplayer, and the other grip's mode (decided at press time). + +Scheme code kept as it was: aim from the controller, crowbar swing (weapon velocity), flashlight beam from the off hand, two-handed hold and scope (`vr_weapon_stabilised`, +`+alt1`), backpack grab, physical ducking (`vr_enable_crouching`), room-scale walking, haptics, usable-object highlight. Server side (`hlsdk-xash3d/dlls/player.cpp`, +`PlayerUse`): `+use` finds usable things within `PLAYER_HAND_SEARCH_RADIUS` of the *weapon hand's* position in front of the hand's direction (64 units; 24 and a wide cone +when `vr_gesture_triggered_use` is 1), and `+use2` does the same from the off hand but only when that cvar is 1. So hand-origin use already exists and needs no DLL change; the +grips need the cvar at 1 and the client's automatic gesture use switched off (`VR_FrameHandUse()`, `VrInputDefault.c`). The reach for `+use` is therefore 24 units (0.6 m), which also +applies to X. + +Changed defaults on the Frame (saved settings are updated once, `vr_frame_map`): `vr_quick_crouchjump` 0 (double clicking A would be a second crouch input), `vr_gesture_triggered_use` 1 (see above). +Not carried: walk/slow (`+speed`, was the off trigger; the stick is analog), weapon select on the turn stick (it fought the turn). + +Not kept from the standard: dominant-hand setting beyond `vr_control_scheme`, no VR settings page. + +The table, generated by `tools/steam_frame/tests/test_frame_map --markdown`: + +| Frame input | Playing | Notes | +| --- | --- | --- | +| weapon hand trigger | fire | weapon hand trigger | +| other hand trigger | alt fire | other hand trigger | +| A | jump | | +| B | crouch (hold) | | +| X | use | | +| Y | reload | | +| left stick click | crouch (toggle) | | +| right stick click | quick save | off hand behind the head | +| right stick click | flashlight | | +| View (short) | quick save | off hand behind the head | +| View (short) | screen view / scoreboard | the scoreboard | +| View (short) | flashlight | | +| left stick up | move | move | +| left stick down | move | move | +| left stick left | move | move | +| left stick right | move | move | +| right stick left | turn | snap or smooth turn | +| right stick right | turn | snap or smooth turn | +| right stick up | quick load | off hand behind the head | +| right stick up | screen view / scoreboard | flat screen view, the scoreboard in multiplayer | +| right stick down | laser sight / scope steady | laser sight, steadies a scope | +| left bumper | previous weapon | | +| right bumper | next weapon | | +| D-pad up | previous weapon | alias of the left bumper | +| D-pad down | next weapon | alias of the right bumper | +| D-pad right | last weapon | | +| D-pad left | crowbar | | +| weapon hand grip | backpack weapon | the crowbar, from behind the head | +| weapon hand grip | use | alias of X: grab, push, pull, press | +| other hand grip | hold the gun steady | two-handed hold, scope: near the weapon | +| other hand grip | use (other hand) | grab with this hand: well away from the weapon | +| Menu (short) | pause | | +| Menu (hold 0.5 s) | quick save | held for half a second | +| View (hold 1 s) | recentre | | +| View (hold 3 s) | recentre and set height | | + +| Frame input | In a menu | Notes | +| --- | --- | --- | +| weapon hand trigger | menu click | pointer click | +| A | menu confirm | | +| B | menu back | | +| Menu (short) | menu back | alias of B | +| View (short) | menu back | alias of B | +| D-pad up | menu up | | +| D-pad down | menu down | | +| D-pad left | menu left | | +| D-pad right | menu right | | +| left stick up | menu up | alias of the D-pad | +| left stick down | menu down | alias of the D-pad | +| left stick left | menu left | alias of the D-pad | +| left stick right | menu right | alias of the D-pad | +| left bumper | menu previous tab | previous tab or page | +| right bumper | menu next tab | next tab or page | +| right stick up | menu scroll up | scroll | +| right stick down | menu scroll down | scroll | + +Aliases (one action, two inputs): use on X and the weapon hand's grip; previous / next weapon on the bumpers and D-pad up / down; flashlight on the right stick click and View; +quick save on Menu held and (hand behind the head) the right stick click and View; menu back on B, Menu and View; menu up/down/left/right on the D-pad and left stick. The host +test fails on any other action with two inputs, on any input doing two things in one context, and on an action nothing reaches. ## 5. Diagnostics (Frame build, `vr-diag.ini` in the data folder) @@ -113,6 +194,9 @@ Set with `tools/steam_frame/deploy.sh --diag KEY=VAL`, removed with `--diag-rese | `diag_yaw` | synthetic head yaw in degrees (turning left is positive); the hands follow | | `autostart`, `map` | load a map without the menus after 150 rendered frames (`map` implies `autostart`; default `c1a0`) | | `dump_frame` | on rendered frame N: `vr-dumps/vr-eye0.bmp`, `vr-eye1.bmp` (one synchronous readback each, with the driver's GL) and `vr-state.txt` (poses, FOVs, each eye's pose in head space, connection state, and 80 `probe` lines: rays from the left eye through a pixel grid traced into the world, with depth and the disparity a correct pair should show; `tools/steam_frame/analyze_stereo.py` matches the right eye there and compares). The log gets the driver's framebuffer bindings, viewport and scissor and the percentage of pixels that aren't black | +| `diag_roll` | synthetic head roll in degrees (tilting left is positive); with `force_render`. The HUD should stay level with the world | +| `diag_press` | holds buttons down: `A@300+30, LG@400+20` is A from 300 frames after the map starts for 30 frames, then the left grip (names: LT RT LG RG LB RB LC RC A B X Y MENU MENUHOLD VIEW UP DOWN LEFT RIGHT, LS/RS + UP DOWN LEFT RIGHT). Runs the map with no controllers; each press is logged `[vr] input -> action` | +| `diag_gap` | metres between the synthetic hands (default 0.5), for the two-handed hold (under 0.35) against the grab (over 0.55) | | `cmd` | console commands (`;` between them) about 300 rendered frames after the map starts: `sv_cheats 1; impulse 101` for the suit and weapons, `vr_hud_distance 2`, `vr_hand_model 0` | | `probe` | right before the dump, clear each eye to a flat colour (red, blue) instead: tests the readback and the swapchain, not the game | | `exit_after` | after N XR frames, leave through the normal shutdown |