Input: generic action vocabulary (da_*) + per-controller translators; addon controller support #12
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Tracking issue for the input-system design refinement settled 2026-10-23 (design of record: da-game
docs/input-system.md; implementation lands in PR #9). Filed for the record — the work is already scoped and underway, so this can be closed as soon as it's served its tracking purpose.The model
Three vocabularies, two translations, and the game speaks only one of them:
controller.gd, per controller type) — authored artifacts that declare "this button is this generic action": they consume runtime events and emit generic actions. We ship ours; addon mods ship theirs — this is how non-standard controllers get supported, by mapping their information to the generic input. Two authoring paths cover different gaps: a controller that is a SteamVR/OpenXR citizen but has no shipped config needs no addon (the user maps our generic action names in the runtime's binding UI — the Index case); a source that is not a runtime citizen at all (DIY trackers, hand-tracking cameras, wheels) needs an addon translator, which may stand up its ownXRControllerTrackerand feed poses + inputs.da_-namespaced, addressed per hand ascontroller/<hand>/<name>:da_button_primary(anchored: the A/X position),da_button_secondary(B/Y),da_trigger_primary,da_trigger_primary_analog,da_grip_primary,da_grip_primary_analog,da_menu_action,da_stick,da_stick_click, plusda_touch_*for the capacitive surface.Rules that come with it
da_*name is forever — runtime bindings are keyed by action name, so renaming orphans users' saved bindings.Rename pass (the work this tracks)
The inherited OpenXR action names (
ax_button,by_button,primary, ...) are template vocabulary, not ours. The pass renames the action map's input actions to the generic names, re-points InputContract / the Quest translator / presets / rig provider configs at them, and re-verifies (input_check + full suite sweep + boot).Scoping calls (Lantern's, correct here if wrong):
aim_pose,grip_pose, ...). Poses are the tracking critical path and Godot derives tracker pose names from them; renaming is a separate, headset-verified change.da_button_primaryis anchored to the A/X (lower) face button,da_button_secondaryto B/Y (upper), per the Quest layout the generics are designed against.Implemented in PR #9 (
2230310), restacked through #10 (c53df2a) and #11 (750c606): the action map, InputContract, Quest translator, presets, rig provider configs, ArmsView's analog reads,tests/input_check.gd, anddocs/input-system.mdall speak theda_*vocabulary now. Suite sweeps green at every stack level (7/7, 8/8, 9/9) with clean real boots.Ready to close whenever — leaving the close to Zach per org policy.
Vocabulary v2 (2026-10-23 review, supersedes the naming in this issue's original text where they differ; implemented in PR #9
344ccaa):da_button_primary_touch,da_trigger_primary_touch,da_stick_touch(replacing theda_touch_*front-loaded names). No suffix = the control's primary channel.da_extra_0…da_extra_10— eleven blank booleans with no base-game meaning (state for mods; targets for SteamVR chords and spare hardware).da_extra_0is the odd-surface slot by convention and inherits the thumbrest/trackpad-touch bindings formerly onda_touch_rest. Richer extra channels, if ever needed, are a mod concern grown by addition — explicitly out of base-game scope. System:da_menu(wasda_menu_action— functions are not buttons).da_selectdeleted (template leftover, never allocated).da_pad/da_pad_clickfolded: trackpad paths now bind the stick actions — one 2D position control in the generics.Two gaps between this issue's addon-controller goal and what
RigInputdoes today, plus one doc fix.1. The active translator is whichever folder is listed first, not the connected hardware.
RigInput._ready()(src/input/generic/rig_input.gd:76-80) runsdiscover_controllers()and takescontrollers[0]. The discovery loop (rig_input.gd:59-71) walksDirAccess.get_next()and never sorts, so the order is whatever the filesystem or pack returns.With only
quest_touch/that's fine, but once an addon ships a second translator folder, which one wins is effectively arbitrary. The choice never looks at the controllers actually connected, and nothing re-selects when the user switches controllers mid-session.Suggested shape:
controller.jsondeclares the OpenXR interaction profiles it handles, for example"profiles": ["/interaction_profiles/oculus/touch_controller"].RigInputpicks by the tracker's current profile:XRServer.get_tracker("left_hand").profile, or theXRController3D's tracker.profile_changed, which both the tracker andXRController3Demit.2. The SteamVR pause hold claims left
da_button_primary.On SteamVR, pause is hard-wired to holding left
da_button_primary(X) for 2.0 s (rig_input.gd:115-137). That's documented as a deliberate exception.The catch is that
da_button_primaryis also one of the generics, the inputs base game content is meant to rely on. So the first feature that reads a left-X hold will collide with pause, and withhold_to_pauseoff, any feature that reads a left-X press will pause the game on every press.Worth reserving now, before gameplay claims X. Either:
da_button_primaryis reserved on SteamVR.For the first option, the existing System action
da_menufits: SteamVR's synthesized Quest binding already put it on X click (docs/input-system.md:153-158), andRigInputignores it on SteamVR today (rig_input.gd:138-141). The extras (da_extra_0toda_extra_10) are defined as having no base-game meaning (src/input/generic/input_contract.gd:58-66), so they're not a good home for pause.3. Doc drift.
The status paragraph at the top of
docs/input-system.md(lines 3-8) still says the in-game hold timer was "removed when this design was adopted". Principle 1 (lines 12-21) says gesture disambiguation belongs to the binding layer, "not game code", and the lead-in to the pause table (lines 133-134) calls all three mechanisms "binding data". The v1 implementation notes (lines 249-251) sayRigInputmakes pause from the MENU rising edge, which is only true off SteamVR.All of these are contradicted later in the same document (line 138, lines 254-256 and 261-270) and by
RigInput, which runs a game-code hold timer on left X. The header and principle 1 should point at the exception instead of denying it.