Skip to content

Input map format

VGAI Reference 0.3

Planned versioned generated-schema truth covering Typed input actions, devices, prompts, and rebinding.

planned · generated · immutable Reference 0.3

Lifecycle and constraints

Detailed constraints will publish with the generated or reviewed entry.

Runnable Learn material

Generated format inventory

Inventory only — AC-REF-002 is not passed. Valid parser-verified examples, narrative guidance, complete cross-field/runtime constraints, and version history remain deferred. This page must not be treated as a complete format contract.

Source: packages/engine/schemas/inputmap.schema.json · 50 branch-sensitive field records · 35 source-described.

input-map · file · 50 fields
Field / branchTypeRequiredDefaultConstraintsDescription
# $ object yes none {"additionalProperties":false} Missing source description
# $.version number yes none none Input map file format version (RESERVED — no range check yet)
# $.actions object yes none {"additionalProperties":{"type":"object","properties":{"valueType":{"default":"digital","description":"This action's declared value shape (F1, spec §12). 'digital' (boolean, with pressed/justPressed/justReleased edges) is the default when omitted, matching every action authored before F1. 'scalar' is a single deadzone-rescaled float axis. 'vector2' is a radial-deadzoned, unit-circle-normalized {x,y}. 'pointerDelta' is a per-frame {x,y} movement delta, summed across sources. 'pointerPosition' is an absolute {x,y}, last-write-wins across sources. InputManager enforces this at read time: reading an action through the wrong typed getter (e.g. getScalar on a 'digital' action) throws.","type":"string","enum":["digital","scalar","vector2","pointerDelta","pointerPosition"]},"bindings":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"key","description":"Binding kind: a keyboard key (KeyboardEvent.code)"},"code":{"type":"string","description":"KeyboardEvent.code value, e.g. \"KeyW\", \"Space\", \"ArrowUp\""}},"required":["type","code"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"mouse_button","description":"Binding kind: a mouse button"},"button":{"type":"number","description":"MouseEvent.button index (0 = left, 1 = middle, 2 = right)"}},"required":["type","button"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"mouse_move","description":"Binding kind: raw mouse movement (F2, spec §12 \"Complete Device Backends\"). Feeds a 'pointerDelta'-valueType action with the raw accumulated mouse delta (no deadzone), and can also feed a 'vector2'-valueType action (the same delta, radial-deadzoned + unit-circle-clamped via `deadzone`)."},"deadzone":{"description":"Radial deadzone magnitude applied only when this binding feeds a 'vector2'-valueType action (default 0 — no deadzone; ignored for 'pointerDelta' reads, which are never deadzoned).","type":"number"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"gamepad_button","description":"Binding kind: a gamepad face/shoulder button"},"button":{"type":"number","description":"Standard Gamepad API button index"}},"required":["type","button"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"gamepad_axis","description":"Binding kind: a single thresholded gamepad axis"},"axis":{"type":"number","description":"Standard Gamepad API axis index"},"direction":{"type":"string","enum":["positive","negative"],"description":"Which side of the deadzone counts as \"pressed\""},"deadzone":{"description":"Deadzone magnitude (default 0.15 if omitted)","type":"number"}},"required":["type","axis","direction"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"gamepad_axis_pair","description":"Binding kind: a coupled (x, y) gamepad axis pair, e.g. a stick used as a 2D vector (look/aim/movement) (F2, spec §12 \"Complete Device Backends\"). Feeds a 'vector2'-valueType action: (xAxis, yAxis) read together, radial-deadzoned + unit-circle-clamped the same way a real analog stick is."},"xAxis":{"type":"number","description":"Standard Gamepad API axis index for the X component"},"yAxis":{"type":"number","description":"Standard Gamepad API axis index for the Y component"},"deadzone":{"description":"Deadzone magnitude (default 0.15 if omitted)","type":"number"}},"required":["type","xAxis","yAxis"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"test_axis","description":"Binding kind: an injected synthetic scalar value for a 'scalar'-valueType action (InputManager.injectAxis/getScalar) — the \"injected test input\" backend named in F2, built in F1 as the typed scalar value model's testable source."},"sourceId":{"type":"string","description":"Names the injected test source this binding reads (InputManager.injectAxis)."},"deadzone":{"description":"1D deadzone magnitude applied to the injected raw value before combine (default 0 — no deadzone). Values below it read as 0; values at/above it rescale from 0 (at the deadzone edge) to ±1 (at |raw| = 1), sign preserved.","type":"number"}},"required":["type","sourceId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"test_vector2","description":"Binding kind: an injected synthetic {x,y} value for a 'vector2'-valueType action (InputManager.injectVector2/getVector2) — the \"injected test input\" backend named in F2, built in F1 as the typed Vector2 value model's testable source."},"sourceId":{"type":"string","description":"Names the injected test source this binding reads (InputManager.injectVector2)."},"deadzone":{"description":"Radial deadzone magnitude applied to the injected raw {x,y} before combine (default 0 — no deadzone). Vectors whose magnitude is below it read as {0,0}; at/above it, direction is preserved and magnitude rescales the same way the scalar deadzone does, then the result is clamped to the unit circle (magnitude <= 1).","type":"number"}},"required":["type","sourceId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"test_pointer_delta","description":"Binding kind: an injected synthetic per-frame {x,y} delta for a 'pointerDelta'-valueType action (InputManager.injectPointerDelta/getPointerDelta) — the \"injected test input\" backend named in F2. No deadzone (deltas are not deadzoned)."},"sourceId":{"type":"string","description":"Names the injected test source this binding reads (InputManager.injectPointerDelta)."}},"required":["type","sourceId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"test_pointer_position","description":"Binding kind: an injected synthetic absolute {x,y} position for a 'pointerPosition'-valueType action (InputManager.injectPointerPosition/getPointerPosition) — the \"injected test input\" backend named in F2."},"sourceId":{"type":"string","description":"Names the injected test source this binding reads (InputManager.injectPointerPosition)."}},"required":["type","sourceId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"touch_button","description":"Binding kind: a virtual on-screen button for a 'digital' action (InputManager.setTouchButton/isPressed) — edge-tracked (isJustPressed/isJustReleased) the same way a real mouse/keyboard button is."},"sourceId":{"type":"string","description":"Names the virtual control zone this binding reads (InputManager.setTouchButton) — a touch-UI-chosen id, not a real device index."}},"required":["type","sourceId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"touch_stick","description":"Binding kind: a virtual on-screen analog stick for a 'vector2' action (InputManager.setTouchStick/getVector2) — radial-deadzoned + unit-circle-clamped the same way a real gamepad stick is."},"sourceId":{"type":"string","description":"Names the virtual control zone this binding reads (InputManager.setTouchStick) — a touch-UI-chosen id, not a real device index."},"deadzone":{"description":"Radial deadzone magnitude applied to the raw {x,y} before combine (default 0 — no deadzone).","type":"number"}},"required":["type","sourceId"],"additionalProperties":false}]},"description":"Bindings that all trigger/feed this action. Digital actions combine via OR (any one binding satisfied is enough). Scalar actions combine via max-magnitude across contributing bindings (ties keep the first-listed binding). Vector2 actions combine by summing contributing {x,y} values then clamping to the unit circle. PointerDelta actions sum contributing deltas. PointerPosition actions use the most-recently-written contributing source (last-write-wins)."}},"required":["valueType","bindings"],"additionalProperties":false},"propertyNames":{"type":"string"}} Named actions, each with a list of bindings (InputManager.loadMap)
# $.actions{key} object no none {"additionalProperties":false} Missing source description
# $.actions{key}.valueType enum (5) yes "digital" {"enum":["digital","scalar","vector2","pointerDelta","pointerPosition"]} This action's declared value shape (F1, spec §12). 'digital' (boolean, with pressed/justPressed/justReleased edges) is the default when omitted, matching every action authored before F1. 'scalar' is a single deadzone-rescaled float axis. 'vector2' is a radial-deadzoned, unit-circle-normalized {x,y}. 'pointerDelta' is a per-frame {x,y} movement delta, summed across sources. 'pointerPosition' is an absolute {x,y}, last-write-wins across sources. InputManager enforces this at read time: reading an action through the wrong typed getter (e.g. getScalar on a 'digital' action) throws.
# $.actions{key}.bindings array yes none none Bindings that all trigger/feed this action. Digital actions combine via OR (any one binding satisfied is enough). Scalar actions combine via max-magnitude across contributing bindings (ties keep the first-listed binding). Vector2 actions combine by summing contributing {x,y} values then clamping to the unit circle. PointerDelta actions sum contributing deltas. PointerPosition actions use the most-recently-written contributing source (last-write-wins).
# $.actions{key}.bindings[] oneOf (12) yes none none Missing source description
# $.actions{key}.bindings[]oneOf[0] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[0] const "key" yes none {"const":"key"} Binding kind: a keyboard key (KeyboardEvent.code)
# $.actions{key}.bindings[].codeoneOf[0] string yes none none KeyboardEvent.code value, e.g. "KeyW", "Space", "ArrowUp"
# $.actions{key}.bindings[]oneOf[1] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[1] const "mouse_button" yes none {"const":"mouse_button"} Binding kind: a mouse button
# $.actions{key}.bindings[].buttononeOf[1] number yes none none MouseEvent.button index (0 = left, 1 = middle, 2 = right)
# $.actions{key}.bindings[]oneOf[2] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[2] const "mouse_move" yes none {"const":"mouse_move"} Binding kind: raw mouse movement (F2, spec §12 "Complete Device Backends"). Feeds a 'pointerDelta'-valueType action with the raw accumulated mouse delta (no deadzone), and can also feed a 'vector2'-valueType action (the same delta, radial-deadzoned + unit-circle-clamped via `deadzone`).
# $.actions{key}.bindings[].deadzoneoneOf[2] number no none none Radial deadzone magnitude applied only when this binding feeds a 'vector2'-valueType action (default 0 — no deadzone; ignored for 'pointerDelta' reads, which are never deadzoned).
# $.actions{key}.bindings[]oneOf[3] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[3] const "gamepad_button" yes none {"const":"gamepad_button"} Binding kind: a gamepad face/shoulder button
# $.actions{key}.bindings[].buttononeOf[3] number yes none none Standard Gamepad API button index
# $.actions{key}.bindings[]oneOf[4] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[4] const "gamepad_axis" yes none {"const":"gamepad_axis"} Binding kind: a single thresholded gamepad axis
# $.actions{key}.bindings[].axisoneOf[4] number yes none none Standard Gamepad API axis index
# $.actions{key}.bindings[].directiononeOf[4] enum (2) yes none {"enum":["positive","negative"]} Which side of the deadzone counts as "pressed"
# $.actions{key}.bindings[].deadzoneoneOf[4] number no none none Deadzone magnitude (default 0.15 if omitted)
# $.actions{key}.bindings[]oneOf[5] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[5] const "gamepad_axis_pair" yes none {"const":"gamepad_axis_pair"} Binding kind: a coupled (x, y) gamepad axis pair, e.g. a stick used as a 2D vector (look/aim/movement) (F2, spec §12 "Complete Device Backends"). Feeds a 'vector2'-valueType action: (xAxis, yAxis) read together, radial-deadzoned + unit-circle-clamped the same way a real analog stick is.
# $.actions{key}.bindings[].xAxisoneOf[5] number yes none none Standard Gamepad API axis index for the X component
# $.actions{key}.bindings[].yAxisoneOf[5] number yes none none Standard Gamepad API axis index for the Y component
# $.actions{key}.bindings[].deadzoneoneOf[5] number no none none Deadzone magnitude (default 0.15 if omitted)
# $.actions{key}.bindings[]oneOf[6] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[6] const "test_axis" yes none {"const":"test_axis"} Binding kind: an injected synthetic scalar value for a 'scalar'-valueType action (InputManager.injectAxis/getScalar) — the "injected test input" backend named in F2, built in F1 as the typed scalar value model's testable source.
# $.actions{key}.bindings[].sourceIdoneOf[6] string yes none none Names the injected test source this binding reads (InputManager.injectAxis).
# $.actions{key}.bindings[].deadzoneoneOf[6] number no none none 1D deadzone magnitude applied to the injected raw value before combine (default 0 — no deadzone). Values below it read as 0; values at/above it rescale from 0 (at the deadzone edge) to ±1 (at |raw| = 1), sign preserved.
# $.actions{key}.bindings[]oneOf[7] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[7] const "test_vector2" yes none {"const":"test_vector2"} Binding kind: an injected synthetic {x,y} value for a 'vector2'-valueType action (InputManager.injectVector2/getVector2) — the "injected test input" backend named in F2, built in F1 as the typed Vector2 value model's testable source.
# $.actions{key}.bindings[].sourceIdoneOf[7] string yes none none Names the injected test source this binding reads (InputManager.injectVector2).
# $.actions{key}.bindings[].deadzoneoneOf[7] number no none none Radial deadzone magnitude applied to the injected raw {x,y} before combine (default 0 — no deadzone). Vectors whose magnitude is below it read as {0,0}; at/above it, direction is preserved and magnitude rescales the same way the scalar deadzone does, then the result is clamped to the unit circle (magnitude <= 1).
# $.actions{key}.bindings[]oneOf[8] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[8] const "test_pointer_delta" yes none {"const":"test_pointer_delta"} Binding kind: an injected synthetic per-frame {x,y} delta for a 'pointerDelta'-valueType action (InputManager.injectPointerDelta/getPointerDelta) — the "injected test input" backend named in F2. No deadzone (deltas are not deadzoned).
# $.actions{key}.bindings[].sourceIdoneOf[8] string yes none none Names the injected test source this binding reads (InputManager.injectPointerDelta).
# $.actions{key}.bindings[]oneOf[9] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[9] const "test_pointer_position" yes none {"const":"test_pointer_position"} Binding kind: an injected synthetic absolute {x,y} position for a 'pointerPosition'-valueType action (InputManager.injectPointerPosition/getPointerPosition) — the "injected test input" backend named in F2.
# $.actions{key}.bindings[].sourceIdoneOf[9] string yes none none Names the injected test source this binding reads (InputManager.injectPointerPosition).
# $.actions{key}.bindings[]oneOf[10] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[10] const "touch_button" yes none {"const":"touch_button"} Binding kind: a virtual on-screen button for a 'digital' action (InputManager.setTouchButton/isPressed) — edge-tracked (isJustPressed/isJustReleased) the same way a real mouse/keyboard button is.
# $.actions{key}.bindings[].sourceIdoneOf[10] string yes none none Names the virtual control zone this binding reads (InputManager.setTouchButton) — a touch-UI-chosen id, not a real device index.
# $.actions{key}.bindings[]oneOf[11] object yes none {"additionalProperties":false} Missing source description
# $.actions{key}.bindings[].typeoneOf[11] const "touch_stick" yes none {"const":"touch_stick"} Binding kind: a virtual on-screen analog stick for a 'vector2' action (InputManager.setTouchStick/getVector2) — radial-deadzoned + unit-circle-clamped the same way a real gamepad stick is.
# $.actions{key}.bindings[].sourceIdoneOf[11] string yes none none Names the virtual control zone this binding reads (InputManager.setTouchStick) — a touch-UI-chosen id, not a real device index.
# $.actions{key}.bindings[].deadzoneoneOf[11] number no none none Radial deadzone magnitude applied to the raw {x,y} before combine (default 0 — no deadzone).