459 lines
22 KiB
Markdown
459 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.
|
|
- The intro cutscene is also played in the selected language when its
|
|
voice-over file (`svfrintr.res`/`svgeintr.res` under `res/data/`) is
|
|
present; otherwise the English intro plays.
|
|
|
|
## 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).
|
|
- **Menu movement**: while the Controller Options tab is open, the menu's own
|
|
thumbstick snap-turn and smooth-move (see `player_position`) are disabled, so
|
|
pressing inputs to assign them doesn't move you away from the screen.
|
|
- **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. They are on the menu's Cheats tab
|
|
instead, along with four switches for unlimited health, energy, ammo and
|
|
items. Those are not saved to the config.
|
|
- `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.
|