d8324d409e
build / build (push) Successful in 3m24s
- Free view: hold a mapped input (default: left grip) and that thumbstick drives the engine's mouse look, with the stick's normal bindings suspended while held. Also available for the right stick, unbound by default. - Cyberspace actions: eleven thrust/climb/dive/bank/roll actions with their own bindings, active only in cyberspace. The normal movement actions are inactive there, and capture exclusivity only compares actions that can be active together, so one input can be bound in both sets. - Cyberspace pitch and bank scale with thumbstick deflection instead of running at full strength. - Remove the toggle_freelook action; bind the automap view to the right stick click by default. - Engine patches: 24 exposes whether the player is in cyberspace, 25 lets the controller code scale cyberspace pitch and bank.
451 lines
22 KiB
Markdown
451 lines
22 KiB
Markdown
# Persistent configuration (`questshock.config.json`)
|
|
|
|
QuestShock can load a persistent, human-editable configuration file at
|
|
startup, in addition to (and independent of) the engine's own `prefs.txt`.
|
|
|
|
- **Location**: `/sdcard/questshock/questshock.config.json` - the same
|
|
folder you already copy `res/data`/`res/sound` into (see README.md
|
|
section 5.1).
|
|
- **Format**: plain JSON, grouped by concern. Each top-level key is a
|
|
*group*; each key inside a group is one *option*.
|
|
- **Loading**: read automatically at app startup, before the splash screen,
|
|
if the file exists. If it doesn't, `questshock.config.default.json` (same
|
|
folder) is used instead - a copy bundled with the app, refreshed on every
|
|
launch, never overwriting your own saved `questshock.config.json`. If
|
|
neither file exists, the engine behaves as it did before this file
|
|
existed (driven by `prefs.txt` as usual).
|
|
- **Saving**: never automatic. In-headset, open the menu (controller menu
|
|
button) and press **Save Configuration** to write the file from your
|
|
current live settings, overwriting it if present. Press **Load
|
|
Configuration** to re-read the file and apply it without restarting the
|
|
app.
|
|
- **Live vs. restart-required**: every option below is tagged as either
|
|
*live-appliable* (applying it while already playing takes effect
|
|
immediately) or *restart-required*. Pressing **Load Configuration**
|
|
applies every live-appliable change straight away; if the file also
|
|
changes something restart-required, a dialog lists exactly which
|
|
option(s) need it and offers:
|
|
- **Dismiss** - keep playing with the live-appliable changes already
|
|
applied; the restart-required option(s) stay as they were.
|
|
- **Restart Now** - relaunches the app, which re-runs this same startup
|
|
load and so applies every group in the file, including the
|
|
restart-required ones.
|
|
|
|
(Every option currently documented below is live-appliable, so this
|
|
dialog won't actually appear yet - it's built in for options added in a
|
|
future version that do need a restart.)
|
|
- Unrecognized groups/keys are ignored (harmless if you're editing the file
|
|
in advance for a future version). An invalid value for a *specific*
|
|
option (see each option's possible values below) is logged and that one
|
|
option is skipped - every other valid option in the file still applies.
|
|
A file that isn't valid JSON at all is ignored entirely, with nothing
|
|
applied.
|
|
- `questshock.config.json` and `prefs.txt` are fully independent - loading
|
|
or saving one never reads or writes the other.
|
|
|
|
## Example
|
|
|
|
```json
|
|
{
|
|
"video_options": {
|
|
"renderer": "opengl",
|
|
"resolution": "1024x768",
|
|
"initial_screen_width_m": 1.6,
|
|
"initial_screen_distance_m": 2.0,
|
|
"game_screen_width_m": 2.8,
|
|
"game_screen_distance_m": 2.0,
|
|
"screen_width_offset_m": 1.0,
|
|
"screen_width_step_m": 0.6,
|
|
"screen_distance_offset_m": 1.0,
|
|
"screen_distance_step_m": 0.5
|
|
},
|
|
"general": {
|
|
"language": "english"
|
|
},
|
|
"player_position": {
|
|
"x": 0.0,
|
|
"z": 0.0,
|
|
"yaw_degrees": 0.0
|
|
},
|
|
"player_controls": {
|
|
"move_forward": "left_thumbstick_up",
|
|
"move_back": "left_thumbstick_down",
|
|
"strafe_left": "left_thumbstick_left",
|
|
"strafe_right": "left_thumbstick_right",
|
|
"turn_left": "right_thumbstick_left",
|
|
"turn_right": "right_thumbstick_right",
|
|
"jump": "left_thumbstick_click",
|
|
"mouse_click": "right_a",
|
|
"mouse_double_click": "right_b",
|
|
"stand": "right_thumbstick_up",
|
|
"prone": "right_thumbstick_down",
|
|
"map_view": "right_thumbstick_click",
|
|
"fire_weapon": "right_trigger"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Video Options (`video_options`)
|
|
|
|
### `renderer`
|
|
|
|
Which renderer the game uses to draw the 3D view.
|
|
|
|
- **Type**: enum
|
|
- **Possible values**: `"software"`, `"opengl"`
|
|
- **Restart required?**: No (live-appliable)
|
|
|
|
### `resolution`
|
|
|
|
The game's internal rendering resolution.
|
|
|
|
- **Type**: enum
|
|
- **Possible values**: `"320x200"`, `"320x400"`, `"640x400"`, `"640x480"`, `"1024x768"`
|
|
- **Restart required?**: No (live-appliable)
|
|
|
|
### `initial_screen_width_m`, `initial_screen_distance_m`, `game_screen_width_m`, `game_screen_distance_m`
|
|
|
|
The virtual screen's physical width and distance from the player (both in
|
|
meters) - the game shows two independently configurable screen
|
|
"profiles", switched automatically based on what's currently on screen:
|
|
|
|
- **Initial Screen** (`initial_screen_*`) - the splash screen, intro
|
|
cutscenes, and the game's own main menu.
|
|
- **Game Screen** (`game_screen_*`) - actual gameplay (the 3D view,
|
|
automap, cyberspace, etc.).
|
|
|
|
Switching happens automatically - no player action needed - the instant
|
|
the game itself transitions between these (e.g. starting/loading a game,
|
|
or returning to the menu).
|
|
|
|
- **Type**: number (meters)
|
|
- **Possible values**: the in-headset Video Options tab offers 5 presets
|
|
each - widths `1.0`, `1.6` (the original, pre-this-feature default),
|
|
`2.2`, `2.8`, `3.4`; distances `1.0`, `1.5`, `2.0` (the original,
|
|
pre-this-feature default), `2.5`, `3.0` - but a hand-edited value
|
|
doesn't need to match a preset exactly (it's clamped to a sane range -
|
|
width `[0.2, 10.0]`, distance `[0.5, 10.0]` - rather than snapped or
|
|
rejected; the Video Options tab just shows no button selected for an
|
|
in-between value).
|
|
- **Restart required?**: No (live-appliable)
|
|
- **Note**: the screen is always flat - there's no curve option.
|
|
|
|
### `screen_width_offset_m`, `screen_width_step_m`, `screen_distance_offset_m`, `screen_distance_step_m`
|
|
|
|
Reshapes the 5 preset buttons the Video Options tab offers for width and
|
|
distance (above) - config-file-only, there's no in-headset control for
|
|
these. Shared by both **Initial Screen** and **Game Screen** (both
|
|
columns' buttons show the same 5 values per row) - this only changes
|
|
what the buttons offer, not either profile's current value.
|
|
|
|
Preset button `index` (0-4) shows `offset + step * index`. For example,
|
|
a distance offset of `0` and step of `2` shows buttons `0`, `2`, `4`,
|
|
`6`, `8`; the defaults below reproduce this feature's original launch
|
|
presets exactly.
|
|
|
|
- **Type**: number (meters)
|
|
- **Default values**: width offset `1.0`, step `0.6` (buttons `1.0`,
|
|
`1.6`, `2.2`, `2.8`, `3.4`); distance offset `1.0`, step `0.5` (buttons
|
|
`1.0`, `1.5`, `2.0`, `2.5`, `3.0`).
|
|
- **Restart required?**: No (live-appliable)
|
|
- **Note**: not clamped - an unusual offset/step (e.g. negative step) is
|
|
accepted as-is. A resulting preset value outside the current value's
|
|
own clamp range (see above) still clamps normally when that preset
|
|
button is actually pressed.
|
|
|
|
## General (`general`)
|
|
|
|
### `language`
|
|
|
|
The game's UI/text language - both the game's own resource strings and this
|
|
project's own menu/keyboard chrome text (title bar, buttons, etc.).
|
|
|
|
- **Type**: enum
|
|
- **Possible values**: `"english"`, `"french"`, `"german"`
|
|
- **Restart required?**: No (live-appliable) - applies the same way the
|
|
game's own in-game options menu applies a language change (reloads the
|
|
language-specific resource files and refreshes the inventory/MFD/side-icon
|
|
UI immediately).
|
|
- **Note**: French and German both need their own full resource pack
|
|
(`frnstrng.res`/`mfdfrn.res`, `gerstrng.res`/`mfdger.res` under
|
|
`res/data/`) - if any of those files aren't present, the switch is
|
|
refused (logged, `questshock.config.json` and the current language are
|
|
left unchanged) rather than leaving the game with no valid resource file
|
|
open. See README.md section 3 ("Game assets") for where `mfdfrn.res`/
|
|
`mfdger.res` come from - the GOG Enhanced Edition installer alone doesn't
|
|
include them.
|
|
|
|
## Player Position (`player_position`)
|
|
|
|
Where the player is virtually standing/facing, independent of - and not
|
|
reset by - starting a new game or loading a save (same independence from
|
|
`prefs.txt`/savegames as every other group here). Set by moving around
|
|
in-headset (menu open, left thumbstick snap-turns, right thumbstick smooth-
|
|
moves) to line yourself up with the game quad ("virtual screen"). Height is
|
|
never included here - it always comes from your real tracked headset
|
|
height, not this file.
|
|
|
|
**Startup fallback**: only applied at startup if all three fields (`x`,
|
|
`z`, `yaw_degrees`) are present - a config file with none of them (or none
|
|
at all), or a partial/hand-edited one missing any of the three, falls back
|
|
to an automatic recenter instead (see **Reset Position** below), using
|
|
your real head pose at that moment. A complete saved position is applied
|
|
as-is, with no such recenter.
|
|
|
|
**Reset Position** (Main Menu tab) is a live-only action, not a config
|
|
value: it moves you to the centre in front of the game quad, based on where
|
|
your head actually is right now. It resets only your *position*, not which
|
|
way you're facing, so the screen does not rotate to follow your gaze - press
|
|
it while looking off to one side and the screen stays off to the other side.
|
|
The automatic recenter at startup (when there's no saved position) does
|
|
face the screen towards where you're looking. Reset Position never reads or
|
|
writes `questshock.config.json`.
|
|
|
|
### `x`, `z`
|
|
|
|
Horizontal position, in meters, on the play space's floor plane.
|
|
|
|
- **Type**: number
|
|
- **Restart required?**: No (live-appliable)
|
|
|
|
### `yaw_degrees`
|
|
|
|
Which way the player is virtually facing, in degrees.
|
|
|
|
- **Type**: number
|
|
- **Restart required?**: No (live-appliable)
|
|
|
|
## Player Controls (`player_controls`)
|
|
|
|
Maps each of 57 in-game actions to a physical controller input: 9
|
|
movement/click actions, 2 free-view actions, 11 cyberspace actions, and 35
|
|
for the engine's own keyboard hotkeys and firing (posture, save/load, weapon
|
|
select, MFD panels, etc. - see the hotkey table below). Some actions are bound by default (see the default-input
|
|
columns); the rest are unbound and can be bound on demand. Assign them in the
|
|
**Controller Options** menu tab: tap an action's binding button, then press
|
|
the button or stick direction to use ("Press a button…"); tap it again, or
|
|
wait 8 seconds, to cancel without changing it.
|
|
|
|
- **Type**: one enum-string field per action (below)
|
|
- **Restart required?**: No (live-appliable) - a rebind takes effect
|
|
immediately, and persists across restarts once saved (**Save
|
|
Configuration**, same as every other group here).
|
|
- **Not included here**: opening/closing the VR menu itself is a fixed,
|
|
non-remappable button (see "Menu button" below) - there's no
|
|
`menu_toggle` field, and the Controller Options tab never lets you
|
|
reassign it. This guarantees you can always reach this tab and press
|
|
**Reset to Defaults** to recover from any bad rebind, no matter what else
|
|
you've reassigned.
|
|
- **Reset to Defaults**: restores the "Default input" column below for
|
|
every action not overridden by a `player_controls` group in
|
|
`questshock.config.default.json` - if that file defines one (it doesn't,
|
|
out of the box), the values it specifies are applied on top of the table
|
|
below instead, so you can customize what "reset" means without a rebuild.
|
|
This is independent of your own `questshock.config.json` - resetting
|
|
doesn't read or write that file, just the live bindings (**Save
|
|
Configuration** afterward to persist them).
|
|
|
|
### Actions
|
|
|
|
| Action key | Default input | Effect |
|
|
|---|---|---|
|
|
| `move_forward` | `left_thumbstick_up` | Walk forward |
|
|
| `move_back` | `left_thumbstick_down` | Walk backward |
|
|
| `strafe_left` | `left_thumbstick_left` | Step sideways, left |
|
|
| `strafe_right` | `left_thumbstick_right` | Step sideways, right |
|
|
| `turn_left` | `right_thumbstick_left` | Turn left |
|
|
| `turn_right` | `right_thumbstick_right` | Turn right |
|
|
| `jump` | `left_thumbstick_click` | Jump |
|
|
| `mouse_click` | `right_a` | Click - operates the keyboard/game quad's cursor, whichever the pointing hand's ray is over |
|
|
| `mouse_double_click` | `right_b` | Double-click - game quad only (e.g. using an inventory item); has no effect over the menu or keyboard |
|
|
| `free_left_thumbstick_view` | `left_squeeze` | Hold to look around with the left thumbstick (see below) |
|
|
| `free_right_thumbstick_view` | `none` | Hold to look around with the right thumbstick (see below) |
|
|
|
|
Movement actions bound to a thumbstick direction are suppressed while the
|
|
VR menu is open, since the same physical stick already snap-turns/smooth-
|
|
moves the player in that state (see `player_position` above) - this is the
|
|
one case where a binding's effect depends on whether the menu is open, and
|
|
it only ever affects the 8 thumbstick-direction inputs below.
|
|
|
|
**Free view** (`free_left_thumbstick_view`, `free_right_thumbstick_view`) is
|
|
the engine's mouse look driven by a thumbstick. While the bound input is held,
|
|
that stick looks around instead of doing its normal job: left/right turns the
|
|
view, up/down looks up and down, in proportion to how far the stick is pushed.
|
|
The stick's own direction bindings (move, strafe, turn, stand/prone) are
|
|
suspended while it is held, and the cursor stays centred in the view. Release
|
|
the input to return to normal. It has no effect while the VR menu is open.
|
|
|
|
### Cyberspace actions
|
|
|
|
Cyberspace has its own set of movement actions, active only while the player
|
|
is in cyberspace. While in cyberspace the normal movement actions
|
|
(`move_*`, `strafe_*`, `turn_*`, `jump`, `stand`, `crouch`, `prone`) are
|
|
inactive, and the cyberspace actions are inactive everywhere else. Each set
|
|
has its own bindings, so one input can be bound in both (for example the left
|
|
stick up is `move_forward` on foot and `cyber_climb` in cyberspace);
|
|
the Controller Options tab only reports a conflict between actions that can
|
|
be active at the same time. Free view, clicking and firing work in both.
|
|
|
|
Pitch and bank (`cyber_climb`, `cyber_dive`, `cyber_bank_*` and the four
|
|
diagonals) are proportional when bound to a thumbstick direction: pushing the
|
|
stick further turns faster, from 20% of full speed just past the trigger point
|
|
to 60% at full deflection. Bound to a button they run at full speed. Thrust and
|
|
roll are always full speed.
|
|
|
|
| Action key | Default input | Keyboard equivalent | Effect |
|
|
|---|---|---|---|
|
|
| `cyber_thrust` | `right_thumbstick_up` | `s` | Thrust forward |
|
|
| `cyber_climb` | `left_thumbstick_up` | `w` | Pitch up |
|
|
| `cyber_dive` | `left_thumbstick_down` | `x` | Pitch down |
|
|
| `cyber_bank_left` | `left_thumbstick_left` | `a` | Bank left |
|
|
| `cyber_bank_right` | `left_thumbstick_right` | `d` | Bank right |
|
|
| `cyber_roll_left` | `right_thumbstick_left` | `e` | Roll left |
|
|
| `cyber_roll_right` | `right_thumbstick_right` | `q` | Roll right |
|
|
| `cyber_climb_left` | `none` | Keypad 7 | Pitch up and bank left |
|
|
| `cyber_climb_right` | `none` | Keypad 9 | Pitch up and bank right |
|
|
| `cyber_dive_left` | `none` | Keypad 1 | Pitch down and bank left |
|
|
| `cyber_dive_right` | `none` | Keypad 3 | Pitch down and bank right |
|
|
|
|
`mouse_click` additionally behaves differently depending on the menu:
|
|
while the VR menu is open, its "click" is always whichever hand's trigger
|
|
is used to interact with the menu (so you can never lock yourself out of
|
|
this settings screen by rebinding `mouse_click` elsewhere); once the menu
|
|
is closed, both the on-screen keyboard (if it's still open) and the game
|
|
quad use your actual `mouse_click` binding. The default (`right_a`) is a
|
|
specific button on the right controller, so only the right hand's ray clicks;
|
|
bind the `trigger` identifier (see below) for either hand to click.
|
|
|
|
### Hotkey actions
|
|
|
|
The engine's own keyboard hotkeys (`HotKeyLookup[]` in `Prefs.c`) plus
|
|
firing, as 35 bindable actions. `stand` (`right_thumbstick_up`), `prone`
|
|
(`right_thumbstick_down`), `map_view` (`right_thumbstick_click`) and
|
|
`fire_weapon` (`right_trigger`) are bound by default; the rest are unbound
|
|
(`none`). Each fires once per press, like pressing the key on a real
|
|
keyboard (there is no hold behavior).
|
|
|
|
| Action key | Keyboard equivalent | Effect |
|
|
|---|---|---|
|
|
| `stand` | `t` | Stand up |
|
|
| `crouch` | `g` | Crouch |
|
|
| `prone` | `b` | Go prone |
|
|
| `pause` | `p` | Pause the game |
|
|
| `full_view` | Ctrl+F | Switch to the fullscreen view loop |
|
|
| `normal_view` | Ctrl+D | Switch to the normal gameplay view |
|
|
| `map_view` | Ctrl+A | Switch to the automap view |
|
|
| `save_game` | Ctrl+S | Save the game |
|
|
| `load_game` | Ctrl+L | Load the game |
|
|
| `select_grenade` | Ctrl+' | Select the next grenade type |
|
|
| `arm_grenade` | Alt+' | Arm the selected grenade |
|
|
| `select_drug` | Ctrl+; | Select the next drug/patch |
|
|
| `use_drug` | Alt+; | Use the selected drug/patch |
|
|
| `toggle_online_help` | Ctrl+H | Toggle the online help overlay |
|
|
| `show_help` | Alt+O | Show the help screen |
|
|
| `toggle_music` | Ctrl+M | Toggle music |
|
|
| `quit` | Ctrl+Q | Quit the game - opt-in only; nothing binds this by default |
|
|
| `cycle_weapon_next` | Tab | Ready the next weapon |
|
|
| `cycle_weapon_prev` | Shift+Tab | Ready the previous weapon |
|
|
| `cycle_detail` | Ctrl+1 | Cycle the graphics detail level |
|
|
| `reload_weapon_primary` | Ctrl+Backspace | Reload the current weapon's primary ammo |
|
|
| `reload_weapon_secondary` | Alt+Backspace | Reload the current weapon's secondary ammo |
|
|
| `hud_color` | Alt+H | Cycle the HUD color scheme |
|
|
| `clear_fullscreen` | Backspace | Close a fullscreen view (e.g. a datapad or email) |
|
|
| `mfd_left_1`-`mfd_left_5` | F1-F5 | Set the left MFD panel to Weapon/Item/Map/Target/Info |
|
|
| `mfd_right_1`-`mfd_right_5` | F6-F10 | Set the right MFD panel to Weapon/Item/Map/Target/Info |
|
|
| `fire_weapon` | Enter | Fire the readied weapon at the cursor (the engine's default fire key). Clicking in the 3D view with `mouse_click` also fires; this is a separate button for it |
|
|
|
|
**Not exposed** (other `HotKeyLookup[]` entries):
|
|
- `keypad 0`-`keypad 9`: a controller button per digit is not useful; use the
|
|
on-screen keyboard.
|
|
- `toggle_freelook` (F): the free-view actions cover mouse look.
|
|
- The 4 `cheat_*` entries: debug cheats.
|
|
- `mac_help` (disabled) and `audiolog_cancel` (its build flag is not
|
|
defined): they are not real hotkeys in this build.
|
|
- `toggle_opengl` (Ctrl+G): the Video Options tab's Renderer buttons already
|
|
toggle the same setting.
|
|
- The 10 numeric hardware-item hotkeys (bio scan, fullscreen, 360 view,
|
|
lantern, shield, infrared, nav unit, data reader, booster, jumpjets): their
|
|
registered keys never match a real keypress in the engine.
|
|
|
|
### Raw input identifiers
|
|
|
|
Every raw physical input available to bind an action to, with its generic
|
|
OpenXR interaction-profile component name and its Meta Quest Touch control
|
|
name. Two symmetric identifiers (`trigger`, `squeeze`) are also accepted, but
|
|
only for `mouse_click`/`mouse_double_click`: they mean "either hand's own
|
|
trigger/grip, whichever hand is pointing". Every other identifier below
|
|
refers to one specific control.
|
|
|
|
| Identifier | OpenXR component (Touch) | Meta Quest control |
|
|
|---|---|---|
|
|
| `left_trigger` | `/user/hand/left/input/trigger/value` | Left Trigger |
|
|
| `right_trigger` | `/user/hand/right/input/trigger/value` | Right Trigger |
|
|
| `left_squeeze` | `/user/hand/left/input/squeeze/value` | Left Grip |
|
|
| `right_squeeze` | `/user/hand/right/input/squeeze/value` | Right Grip |
|
|
| `left_x` | `/user/hand/left/input/x/click` | X Button |
|
|
| `left_y` | `/user/hand/left/input/y/click` | Y Button |
|
|
| `right_a` | `/user/hand/right/input/a/click` | A Button |
|
|
| `right_b` | `/user/hand/right/input/b/click` | B Button |
|
|
| `left_thumbstick_click` | `/user/hand/left/input/thumbstick/click` | Left Thumbstick Click |
|
|
| `right_thumbstick_click` | `/user/hand/right/input/thumbstick/click` | Right Thumbstick Click |
|
|
| `left_thumbstick_up/down/left/right` | `/user/hand/left/input/thumbstick` (digitized) | Left Thumbstick, tilted |
|
|
| `right_thumbstick_up/down/left/right` | `/user/hand/right/input/thumbstick` (digitized) | Right Thumbstick, tilted |
|
|
| `trigger` | either hand's trigger | Either Trigger (`mouse_click`/`mouse_double_click` only) |
|
|
| `squeeze` | either hand's grip | Either Grip (`mouse_click`/`mouse_double_click` only) |
|
|
| `none` | - | Unbound - the action never fires |
|
|
|
|
**Menu button** (left controller, Touch/Vive/generic alike) is not in this
|
|
list - it always opens/closes the VR menu and can never be reassigned.
|
|
|
|
**Other supported controllers**: HTC Vive wands have no A/B/X/Y and no
|
|
analog grip - `left_x`/`left_y`/`right_a`/`right_b` simply never fire on
|
|
that profile, and `left/right_squeeze` are a plain click rather than
|
|
analog. Their trackpad stands in for the thumbstick identifiers above
|
|
(same digitization, just a trackpad instead of a stick). A bare-minimum
|
|
OpenXR controller (`khr/simple_controller`, used as a fallback when
|
|
neither Touch nor Vive bindings are suggested) only has `left_trigger`/
|
|
`right_trigger` (via its `select/click` component) and the menu button -
|
|
every other identifier above simply never fires on it, which is why the
|
|
Controller Options tab shows a note and hides irrelevant rows when this
|
|
profile is active.
|
|
|
|
### Controller profile files (`controller_profiles/`)
|
|
|
|
The Controller Options tab shows a labeled illustration of whichever
|
|
controller is actually active, driven by `res/controller_profiles/*.json`
|
|
(bundled with the app, copied to `/sdcard/questshock/controller_profiles/`
|
|
on every launch, refreshing the known bundled files without touching any
|
|
extra ones you add there yourself). Each file:
|
|
|
|
```json
|
|
{
|
|
"name": "Meta Quest Touch",
|
|
"interaction_profile": "/interaction_profiles/oculus/touch_controller",
|
|
"image": "touch.png",
|
|
"controls": [
|
|
{"id": "right_b", "label": "B", "anchor_x": 0.76, "anchor_y": 0.22}
|
|
]
|
|
}
|
|
```
|
|
|
|
- `interaction_profile` - the OpenXR interaction profile path this file
|
|
describes; matched against whichever one is actually bound at runtime.
|
|
Falls back to `generic.json` if nothing matches.
|
|
- `image` - filename (same folder) of the controller illustration.
|
|
- `controls` - one entry per labeled point on that illustration: `id` is a
|
|
raw input identifier from the table above (thumbstick directions share
|
|
one `left_thumbstick`/`right_thumbstick` entry, since they're the same
|
|
physical stick); `anchor_x`/`anchor_y` are 0-1 fractions of the image for
|
|
positioning that label's pointer line.
|
|
|
|
This is presentation data only - adding real support for a new controller
|
|
still needs matching bindings in the app itself; a profile file with no
|
|
corresponding code-level support just never gets matched.
|
|
|
|
### Fatal startup error
|
|
|
|
If the OpenXR runtime rejects any of the three supported controller
|
|
profiles' bindings at launch (an app bug, not something you did), a
|
|
non-cancelable dialog explains this and exits - this should never happen
|
|
in a normal build.
|