@forgeax/engine-input 0.1.33 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/action-state.ts","../src/gamepad-frame.ts","../src/gesture-recognizer.ts","../src/ui-ownership.ts","../src/virtual-joystick.ts","../src/browser-backend.ts","../src/input-snapshot.ts","../src/canvas-input-boundary.ts","../src/composite-backend.ts","../src/frame-start-scan-system.ts","../src/plugin-service.ts"],"names":["a","b"],"mappings":"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","file":"index.mjs","sourcesContent":["// action-state.ts — action mapping pure-function module for forgeax-engine.\n//\n// Derives per-frame ActionState[] from an InputBackendSample and an InputMap.\n// Zero ECS/DOM dependencies; fully node-testable.\n//\n// charter awareness:\n// P3 explicit failure — unmapped action names return empty signal, never throw\n// P4 consistent abstraction — consumer only sees action name, never device\n\nimport type { GamepadAxisIndex, GamepadButtonIndex, InputBackendSample } from './input-snapshot';\n\n// ─── Types ───────────────────────────────────────────────────────\n\n/**\n * Closed 4-member discriminant union for mapping raw input sources to actions.\n * The `type` field is the discriminant; consumers switch on it with no `default`\n * branch (AC-08b: TypeScript checks exhaustiveness at compile time).\n */\nexport type ActionBinding =\n | { readonly type: 'key'; readonly key: string }\n | { readonly type: 'mouseButton'; readonly button: 0 | 1 | 2 }\n | { readonly type: 'gamepadButton'; readonly button: GamepadButtonIndex }\n | {\n readonly type: 'gamepadAxis';\n readonly axis: GamepadAxisIndex;\n /**\n * Sign applied to the raw axis value before aggregation.\n * - Omitted: contributes |value| (trigger semantics, e.g. right trigger on axis 2).\n * - `1`: contributes max(0, value) (positive direction).\n * - `-1`: contributes max(0, -value) (negative direction, e.g. left stick).\n */\n readonly sign?: 1 | -1;\n };\n\n/**\n * An action definition in the InputMap: a semantic name + one or more bindings\n * to raw input sources, plus an optional per-action deadzone override.\n */\nexport interface ActionConfig {\n /** Semantic action name (e.g. 'jump', 'moveRight'). Referenced by snap.action(name). */\n readonly action: string;\n /** Raw input bindings that contribute to this action. Aggregated via OR/MAX. */\n readonly bindings: readonly ActionBinding[];\n /**\n * Per-action deadzone applied to analog strength remapping.\n * Default: 0.2 (Godot prior-art, F2). Analog values with |raw| < deadzone\n * produce strength=0. Values >= deadzone are linearly remapped into [0,1].\n */\n readonly deadzone?: number;\n}\n\n/**\n * Per-frame derived action state. Returned by deriveActionStates(); consumed\n * by snap.action(name) readpoints. All fields are frame-frozen (AC-11).\n */\nexport interface ActionState {\n readonly action: string;\n /** true when ANY binding contributes a press (OR aggregation). */\n readonly pressed: boolean;\n /**\n * true only on the frame when pressed transitions false→true.\n * One-frame lifetime; held state does not re-fire (AC-03).\n */\n readonly justPressed: boolean;\n /**\n * true only on the frame when pressed transitions true→false.\n * One-frame lifetime (AC-03).\n */\n readonly justReleased: boolean;\n /**\n * Deadzone-remapped analog strength in [0, 1]. Digital press → 1.0.\n * Analog values < deadzone → 0. Aggregate: MAX across bindings.\n */\n readonly strength: number;\n /**\n * Raw un-deadzoned magnitude in [0, 1]. Used by getVector (which applies its\n * own single radial deadzone to avoid per-axis deadzone stacking, F2).\n * Aggregate: MAX across bindings.\n */\n readonly raw: number;\n}\n\n// ─── Constants ───────────────────────────────────────────────────\n\n/**\n * Resource key for the immutable InputMap (ActionConfig[]) inserted into\n * the World. Canvas-form createApp does this automatically; assemble-form\n * hosts insert it directly (D-7).\n */\nexport const INPUT_MAP_KEY = 'InputMap';\n\n/** Default per-action deadzone (Godot prior-art, F2). */\nconst DEFAULT_DEADZONE = 0.2;\n\n// ─── Helpers ─────────────────────────────────────────────────────\n\n/**\n * Inverse lerp: maps a value from [a, b] to [0, 1] linearly.\n * Returns 0 when val <= a, 1 when val >= b.\n */\nfunction inverseLerp(a: number, b: number, val: number): number {\n if (val <= a) return 0;\n if (val >= b) return 1;\n return (val - a) / (b - a);\n}\n\n/**\n * Deadzone remap: maps |raw| from [deadzone, 1] to [0, 1].\n * |raw| < deadzone → 0. |raw| >= deadzone → inverse_lerp(deadzone, 1, |raw|).\n */\nfunction applyDeadzone(rawAbs: number, deadzone: number): number {\n return rawAbs < deadzone ? 0 : inverseLerp(deadzone, 1, rawAbs);\n}\n\n/**\n * Extract the raw contribution from a single binding against the sample.\n * Returns { rawAbs: number, pressed: boolean }.\n *\n * - Digital types (key/mouseButton/gamepadButton): rawAbs = 1.0 if pressed, 0 otherwise.\n * - Analog type (gamepadAxis): rawAbs = max(0, |value| or max(0, value*sign)).\n * For gamepadAxis, aggregates across ALL connected standardMapping slots (D-9).\n */\nfunction bindingContribution(\n binding: ActionBinding,\n sample: InputBackendSample,\n): { rawAbs: number; pressed: boolean } {\n switch (binding.type) {\n case 'key': {\n const down = sample.downKeys.has(binding.key);\n return { rawAbs: down ? 1.0 : 0, pressed: down };\n }\n case 'mouseButton': {\n const down = sample.buttons[binding.button] === true;\n return { rawAbs: down ? 1.0 : 0, pressed: down };\n }\n case 'gamepadButton': {\n // D-9: aggregate across ALL connected standardMapping slots.\n const slots = sample.gamepads ?? [];\n let anyPressed = false;\n for (const slot of slots) {\n if (!slot.standardMapping) continue;\n if (slot.pressed.has(binding.button)) {\n anyPressed = true;\n break;\n }\n }\n return { rawAbs: anyPressed ? 1.0 : 0, pressed: anyPressed };\n }\n case 'gamepadAxis': {\n // D-9: aggregate across ALL connected standardMapping slots (MAX).\n const slots = sample.gamepads ?? [];\n let maxRawAbs = 0;\n for (const slot of slots) {\n if (!slot.standardMapping) continue;\n const rawAxis = slot.axes[binding.axis];\n const sign = binding.sign;\n if (sign === undefined) {\n // Trigger semantics: contribute |value|\n const abs = Math.abs(rawAxis);\n if (abs > maxRawAbs) maxRawAbs = abs;\n } else if (sign === 1) {\n const v = Math.max(0, rawAxis);\n if (v > maxRawAbs) maxRawAbs = v;\n } else {\n // sign === -1\n const v = Math.max(0, -rawAxis);\n if (v > maxRawAbs) maxRawAbs = v;\n }\n }\n return { rawAbs: maxRawAbs, pressed: false };\n }\n }\n}\n\n// ─── deriveActionStates ──────────────────────────────────────────\n\n/**\n * Derive per-frame action states from a backend sample and an InputMap.\n *\n * Pure function with no side effects. Called once per frame by the\n * frame-start scan system. The result is frozen into the InputSnapshot\n * so all snap.action() calls in the same frame see identical state (AC-11).\n *\n * @param sample - One frame's raw input backend sample (POD).\n * @param inputMap - ActionConfig array; duplicate action names → last-wins (D-8).\n * @param prevActionStates - Previous frame's action states for edge diff\n * (justPressed/justReleased derivation). Omitted on the first frame or\n * when actions are not being tracked across frames.\n * @returns ActionState[] with one entry per action name in inputMap (last-wins dedup).\n */\nexport function deriveActionStates(\n sample: InputBackendSample,\n inputMap: readonly ActionConfig[],\n prevActionStates?: readonly ActionState[],\n): ActionState[] {\n // D-8: last-wins dedup — later configs overwrite earlier for same action name.\n const deduped = new Map<string, ActionConfig>();\n for (const config of inputMap) {\n deduped.set(config.action, config);\n }\n\n // Build prev lookup for edge diff.\n const prevByAction = new Map<string, boolean>();\n if (prevActionStates) {\n for (const s of prevActionStates) {\n prevByAction.set(s.action, s.pressed);\n }\n }\n\n const results: ActionState[] = [];\n\n for (const config of deduped.values()) {\n const deadzone = config.deadzone ?? DEFAULT_DEADZONE;\n\n // Aggregate across all bindings: OR for pressed, MAX for strength/raw.\n let aggregatedPressed = false;\n let aggregatedStrength = 0;\n let aggregatedRaw = 0;\n\n for (const binding of config.bindings) {\n const { rawAbs } = bindingContribution(binding, sample);\n\n // Update raw: MAX aggregation.\n if (rawAbs > aggregatedRaw) aggregatedRaw = rawAbs;\n\n // Update pressed: need to consider analog deadzone threshold.\n if (rawAbs >= deadzone) {\n aggregatedPressed = true;\n const str = applyDeadzone(rawAbs, deadzone);\n if (str > aggregatedStrength) aggregatedStrength = str;\n }\n\n // Digital sources already contribute 1.0/0 rawAbs.\n // For digital, rawAbs=1.0 >= deadzone(0.2) → pressed=true, strength=applyDeadzone(1.0,0.2)=1.0.\n }\n\n // Edge detection: justPressed / justReleased from prev frame's pressed state.\n const prevPressed = prevByAction.get(config.action) ?? false;\n const justPressed = aggregatedPressed && !prevPressed;\n const justReleased = sample.focusReset !== true && !aggregatedPressed && prevPressed;\n\n results.push({\n action: config.action,\n pressed: aggregatedPressed,\n justPressed,\n justReleased,\n strength: aggregatedStrength,\n raw: aggregatedRaw,\n });\n }\n\n return results;\n}\n\n// ─── getAxis / getVector ───────────────────────────────────────────\n\n/**\n * Options for getVector deadzone override.\n */\nexport interface GetVectorOptions {\n /**\n * Override the default radial deadzone. When omitted, the deadzone is\n * computed as the average of the 4 per-action deadzones.\n */\n readonly deadzone?: number;\n}\n\n/**\n * Compose a 1D axis value from two opposing actions.\n *\n * Returns `strength(pos) - strength(neg)`, range [-1, 1].\n *\n * - Both registered: combines normally.\n * - One unregistered (E-3): contributes 0.\n * - Neither registered: returns 0.\n * - Same action for both ends (E-12): always 0.\n *\n * @param inputMap - Input map (ActionConfig[]), used to look up per-action deadzone for getVector default.\n * @param actionStates - Derived action states (from deriveActionStates).\n * @param neg - Action name for the negative direction (e.g. 'moveLeft').\n * @param pos - Action name for the positive direction (e.g. 'moveRight').\n */\nexport function getAxis(\n _inputMap: readonly ActionConfig[],\n actionStates: readonly ActionState[],\n neg: string,\n pos: string,\n): number {\n const posState = actionStates.find((s) => s.action === pos);\n const negState = actionStates.find((s) => s.action === neg);\n const posStrength = posState?.strength ?? 0;\n const negStrength = negState?.strength ?? 0;\n if (neg === pos) return 0;\n return posStrength - negStrength;\n}\n\n/**\n * Compose a 2D vector from four directional actions using a single radial\n * deadzone (Godot input.cpp three-branch formula, F2).\n *\n * Reads `raw` (not `strength`) from actionStates to avoid per-axis deadzone\n * stacking into a square deadzone. Applies one radial deadzone:\n *\n * - length <= deadzone → (0, 0)\n * - length > 1 → vector / length (clamp to unit circle)\n * - otherwise → vector * inverse_lerp(deadzone, 1, length) / length\n *\n * Default deadzone = average of the 4 actions' per-action deadzones.\n * `opts.deadzone` overrides it.\n *\n * @param inputMap - Input map, used for per-action deadzone lookup.\n * @param actionStates - Derived action states.\n * @param negX - Action name for negative X (e.g. 'moveLeft').\n * @param posX - Action name for positive X (e.g. 'moveRight').\n * @param negY - Action name for negative Y (e.g. 'moveUp').\n * @param posY - Action name for positive Y (e.g. 'moveDown').\n * @param opts - Optional override (deadzone).\n */\nexport function getVector(\n inputMap: readonly ActionConfig[],\n actionStates: readonly ActionState[],\n negX: string,\n posX: string,\n negY: string,\n posY: string,\n opts?: GetVectorOptions,\n): { readonly x: number; readonly y: number } {\n // Look up raw values (not strength!) for each directional action.\n // getVector uses raw to avoid per-action deadzone stacking into a square\n // deadzone (F2: Godot getVector applies a SINGLE radial deadzone).\n const posXState = actionStates.find((s) => s.action === posX);\n const negXState = actionStates.find((s) => s.action === negX);\n const posYState = actionStates.find((s) => s.action === posY);\n const negYState = actionStates.find((s) => s.action === negY);\n\n const x = (posXState?.raw ?? 0) - (negXState?.raw ?? 0);\n const y = (posYState?.raw ?? 0) - (negYState?.raw ?? 0);\n\n // Compute radial deadzone.\n // Default = average of the 4 per-action deadzones, using only registered actions.\n const deadzone = opts?.deadzone ?? computeAverageDeadzone(inputMap, negX, posX, negY, posY);\n\n const length = Math.sqrt(x * x + y * y);\n\n // Three-branch formula (Godot input.cpp, F2):\n if (length <= deadzone) {\n // Below deadzone → zero vector (deadzone applied).\n return { x: 0, y: 0 };\n }\n if (length > 1) {\n // Clamp to unit circle.\n return { x: x / length, y: y / length };\n }\n // Intermediate zone: smoothly remap from deadzone→1 to 0→unit.\n // vec * inverse_lerp(deadzone, 1, length) / length\n const factor = inverseLerp(deadzone, 1, length) / length;\n return { x: x * factor, y: y * factor };\n}\n\n/**\n * Compute the average deadzone for 4 action names from the input map.\n * Actions not registered contribute DEFAULT_DEADZONE.\n */\nfunction computeAverageDeadzone(\n inputMap: readonly ActionConfig[],\n negX: string,\n posX: string,\n negY: string,\n posY: string,\n): number {\n const map = new Map<string, number>();\n for (const c of inputMap) {\n map.set(c.action, c.deadzone ?? DEFAULT_DEADZONE);\n }\n const dzNegX = map.get(negX) ?? DEFAULT_DEADZONE;\n const dzPosX = map.get(posX) ?? DEFAULT_DEADZONE;\n const dzNegY = map.get(negY) ?? DEFAULT_DEADZONE;\n const dzPosY = map.get(posY) ?? DEFAULT_DEADZONE;\n return (dzNegX + dzPosX + dzNegY + dzPosY) / 4;\n}\n","// gamepad-frame.ts -- pure functions for per-frame gamepad diff from raw\n// navigator.getGamepads() output. No DOM dependency; only called by\n// browser-backend.ts @internal.\n//\n// D-1: edge diff (justPressed / justReleased) derived via set-delta from\n// prev vs cur pressed sets — same pattern as Bevy button_input.rs.\n// D-1: slot diff (connect / disconnect) derived via set difference from\n// prev vs cur slot index sets.\n// OOS-4: no deadzone applied — axes pass through raw.\n//\n// M3 D-1 (option A): non-standard-layout gamepads are normalized at the\n// acquisition layer. When a caller-supplied remapLookup returns SDL\n// gamecontrollerdb.txt mapping tokens for the gamepad's id, raw HID\n// button/axis indices are re-projected onto the standard layout and the\n// slot is reported with standardMapping=true. No lookup / no match keeps\n// the Feat1 empty-signal behaviour (graceful degradation).\n\nimport type { MappingTokens } from './controller-db';\nimport type { GamepadSlotSample } from './input-snapshot';\n\n/**\n * Minimal raw Gamepad shape from browser API (no DOM types here).\n *\n * M3 F-2 seam fix: `id` mirrors the browser `Gamepad.id` string so the\n * remap lookup can derive the SDL GUID keyed by device identity (not by\n * slot index, which is unstable across reconnects).\n */\nexport interface RawGamepadStub {\n readonly index: number;\n readonly id: string;\n readonly connected: boolean;\n readonly mapping: string;\n readonly buttons: readonly { readonly value: number; readonly pressed: boolean }[];\n readonly axes: readonly number[];\n}\n\n/**\n * Standard layout button count (17: 0-16) and axis count (4: 0-3).\n * Non-standard gamepads without a DB match report standardMapping=false\n * and empty readpoints.\n */\nconst STANDARD_BUTTON_COUNT = 17;\n\n/**\n * SDL logical name -> standard-layout button index (W3C Gamepad standard\n * mapping, KB source section 4.3). `guide` occupies the optional 17th slot.\n */\nconst STANDARD_BUTTON_INDEX: Readonly<Record<string, number>> = {\n a: 0,\n b: 1,\n x: 2,\n y: 3,\n leftshoulder: 4,\n rightshoulder: 5,\n lefttrigger: 6,\n righttrigger: 7,\n back: 8,\n start: 9,\n leftstick: 10,\n rightstick: 11,\n dpup: 12,\n dpdown: 13,\n dpleft: 14,\n dpright: 15,\n guide: 16,\n};\n\n/** SDL logical name -> standard-layout axis index (KB source section 4.3). */\nconst STANDARD_AXIS_INDEX: Readonly<Record<string, number>> = {\n leftx: 0,\n lefty: 1,\n rightx: 2,\n righty: 3,\n};\n\n/** Analog trigger threshold: a trigger mapped to an axis counts as pressed above this. */\nconst TRIGGER_PRESS_THRESHOLD = 0.5;\n\ninterface RemappedReadpoints {\n readonly pressed: Set<number>;\n readonly buttonValues: Map<number, number>;\n readonly axes: [number, number, number, number];\n}\n\n/**\n * Re-project a non-standard raw gamepad onto the standard layout using SDL\n * mapping tokens. Browser getGamepads() exposes only buttons[] and axes[]\n * (no hats), so hat tokens (dpad-as-hat) cannot be resolved from raw data\n * and are skipped — a documented graceful degradation for the rare hat-only\n * dpad devices under the web Gamepad API.\n */\nfunction remapToStandardLayout(gp: RawGamepadStub, tokens: MappingTokens): RemappedReadpoints {\n const pressed = new Set<number>();\n const buttonValues = new Map<number, number>();\n const axes: [number, number, number, number] = [0, 0, 0, 0];\n\n for (const [name, token] of Object.entries(tokens)) {\n const stdButton = STANDARD_BUTTON_INDEX[name];\n const stdAxis = STANDARD_AXIS_INDEX[name];\n\n if (stdButton !== undefined) {\n if (token.kind === 'button') {\n const raw = gp.buttons[token.index];\n if (raw) {\n buttonValues.set(stdButton, raw.value);\n if (raw.pressed) pressed.add(stdButton);\n }\n } else if (token.kind === 'axis') {\n // Trigger (or button) mapped to a raw axis: value = raw axis reading.\n const value = gp.axes[token.index] ?? 0;\n buttonValues.set(stdButton, value);\n if (value > TRIGGER_PRESS_THRESHOLD) pressed.add(stdButton);\n }\n // hat -> button (dpad): no hat source in the browser API; skip.\n continue;\n }\n\n if (stdAxis !== undefined && token.kind === 'axis') {\n const raw = gp.axes[token.index] ?? 0;\n axes[stdAxis] = token.half === '-' ? -raw : raw;\n }\n }\n\n return { pressed, buttonValues, axes };\n}\n\n/** Build an empty-signal slot sample (non-standard-no-match / disconnected). */\nfunction emptySlot(index: number): GamepadSlotSample {\n return {\n index,\n standardMapping: false,\n pressed: new Set(),\n justPressed: new Set(),\n justReleased: new Set(),\n buttonValues: new Map(),\n axes: [0, 0, 0, 0],\n };\n}\n\n/** Derive justPressed / justReleased edge sets from prev vs cur pressed sets. */\nfunction edges(\n prevPressed: ReadonlySet<number>,\n curPressed: ReadonlySet<number>,\n): { justPressed: Set<number>; justReleased: Set<number> } {\n const justPressed = new Set<number>();\n const justReleased = new Set<number>();\n for (const b of curPressed) {\n if (!prevPressed.has(b)) justPressed.add(b);\n }\n for (const b of prevPressed) {\n if (!curPressed.has(b)) justReleased.add(b);\n }\n return { justPressed, justReleased };\n}\n\n/**\n * Diff prev vs cur frames for all gamepad slots. Returns a flat\n * GamepadSlotSample[] array keyed by gamepad.index.\n *\n * - Standard-mapping slots produce GamepadSlotSample with edge sets filled\n * from prev vs cur pressed-set delta.\n * - Non-standard slots: when `remapLookup` returns mapping tokens for the\n * gamepad id, raw HID indices are re-projected onto the standard layout\n * and the slot reports standardMapping=true (D-1 semantic redefinition).\n * With no lookup or no match, the slot reports standardMapping=false with\n * empty readpoints and connected=true (Feat1 behaviour, AC-04).\n * - Disconnected slots (in prev but not in cur) produce a slot with\n * standardMapping=false and all readpoints empty.\n * - Null entries in the browser getGamepads() array are skipped by the\n * caller before calling this function.\n *\n * @param remapLookup - Optional acquisition-layer normalizer. Given a\n * browser Gamepad.id, returns SDL mapping tokens or null. Only consulted\n * for non-standard-mapping gamepads (D-1 option A).\n */\nexport function diffGamepadFrame(\n prev: ReadonlyMap<number, GamepadSlotSample>,\n curGamepads: readonly RawGamepadStub[],\n remapLookup?: (gamepadId: string) => MappingTokens | null,\n): GamepadSlotSample[] {\n const results: GamepadSlotSample[] = [];\n const prevIndices = new Set(prev.keys());\n const curIndices = new Set<number>();\n\n for (const gp of curGamepads) {\n curIndices.add(gp.index);\n const prevPressed = prev.get(gp.index)?.pressed ?? new Set<number>();\n results.push(\n gp.mapping === 'standard'\n ? diffStandardSlot(gp, prevPressed)\n : diffNonStandardSlot(gp, prevPressed, remapLookup),\n );\n }\n\n // Disconnected slots: emit empty-signal entries for slots that were in prev\n // but not in cur, so the snapshot reader reports connected=false.\n for (const idx of prevIndices) {\n if (!curIndices.has(idx)) {\n results.push(emptySlot(idx));\n }\n }\n\n return results;\n}\n\n/** Diff a standard-mapping gamepad slot: raw indices pass through 1:1. */\nfunction diffStandardSlot(gp: RawGamepadStub, prevPressed: ReadonlySet<number>): GamepadSlotSample {\n const curPressed = new Set<number>();\n const buttonValues = new Map<number, number>();\n const btnCount = Math.min(gp.buttons.length, STANDARD_BUTTON_COUNT);\n for (let b = 0; b < btnCount; b++) {\n const btn = gp.buttons[b];\n if (!btn) continue;\n buttonValues.set(b, btn.value);\n if (btn.pressed) curPressed.add(b);\n }\n const { justPressed, justReleased } = edges(prevPressed, curPressed);\n // Axes: raw values, no deadzone (OOS-4).\n const axes: [number, number, number, number] = [\n gp.axes[0] ?? 0,\n gp.axes[1] ?? 0,\n gp.axes[2] ?? 0,\n gp.axes[3] ?? 0,\n ];\n return {\n index: gp.index,\n standardMapping: true,\n pressed: curPressed,\n justPressed,\n justReleased,\n buttonValues,\n axes,\n };\n}\n\n/**\n * Diff a non-standard-mapping gamepad slot (D-1 option A): attempt an\n * acquisition-layer remap via the SDL DB. No lookup / no match falls back\n * to the Feat1 empty signal with connected=true (AC-04).\n */\nfunction diffNonStandardSlot(\n gp: RawGamepadStub,\n prevPressed: ReadonlySet<number>,\n remapLookup?: (gamepadId: string) => MappingTokens | null,\n): GamepadSlotSample {\n const tokens = remapLookup ? remapLookup(gp.id) : null;\n if (!tokens) return emptySlot(gp.index);\n const { pressed, buttonValues, axes } = remapToStandardLayout(gp, tokens);\n const { justPressed, justReleased } = edges(prevPressed, pressed);\n return {\n index: gp.index,\n standardMapping: true,\n pressed,\n justPressed,\n justReleased,\n buttonValues,\n axes,\n };\n}\n","// gesture-recognizer.ts -- pure-function gesture state machines for\n// forgeax-engine input (M5). Zero DOM / ECS dependencies: node-testable.\n//\n// charter awareness:\n// C-3 (single legal cross-frame state holder) -- the recognizer owns the\n// only sanctioned cross-frame gesture state. The browser backend stores\n// a `RecognizerState` in its closure (alongside prevGamepadFrame /\n// pointerMap / vjBindState) and threads it through `processGestureFrame`\n// every `sample()`. This module never mutates its inputs; it returns a\n// fresh `newState` the producer must store for the next frame.\n// D-3 clock decoupling -- all timers advance off the injected `now`\n// value, NOT off pointer-event arrival. An idle frame (empty phase\n// queue) still advances long-press timing, so recognition is decoupled\n// from event frequency (AC-16). The F-1 falsification test proves an\n// event-frequency-coupled impl fails.\n// D-4 dual channel -- returns continuous values (`gestureState`:\n// pinchScale / rotationAngle) plus a one-frame lifecycle event list\n// (`gestureEvents`). The backend forwards these as the optional\n// `gestures?` / `gestureEvents?` sample fields (D-4 / F1 precedent).\n// D-10 thresholds -- long-press 500ms + slop 10px, double-tap 350ms +\n// 10px, swipe 0.5 px/ms over a 100ms window; exported as constants.\n// D-11 pinch/rotate -- lock the earliest two pointers, ignore a third;\n// 2->1 emits end + freezes continuous values; a fresh pair emits begin\n// and resets to identity (1.0 / 0).\n\nimport type { PointerPhaseEvent, PointerType } from './input-snapshot';\n\n// D-10 threshold defaults (LayaAir + Godot prior-art, plan-strategy section 2).\nexport const LONG_PRESS_DURATION_MS = 500;\nexport const LONG_PRESS_SLOP = 10;\nexport const DOUBLE_TAP_INTERVAL_MS = 350;\nexport const DOUBLE_TAP_DISTANCE = 10;\nexport const SWIPE_VELOCITY_THRESHOLD = 0.5;\nexport const SWIPE_WINDOW_MS = 100;\n\n/** Swipe direction taken from the dominant displacement axis (D-10). */\nconst SWIPE_DIRECTIONS = ['left', 'right', 'up', 'down'] as const;\nexport type SwipeDirection = (typeof SWIPE_DIRECTIONS)[number];\n\n/**\n * Continuous gesture values read each frame via `snap.gesture` (D-4).\n * Identity when no gesture is active or after a cancel/reset (AC-12):\n * pinchScale = 1.0, rotationAngle = 0.\n */\nexport interface GestureState {\n readonly pinchScale: number;\n readonly rotationAngle: number;\n}\n\n/**\n * Closed discriminant union of gesture lifecycle + instantaneous events\n * (AC-13). One-frame lifecycle: an event appears in exactly one frame's\n * `gestureEvents`. Every member carries `pointerType` (narrowed union,\n * AC-19) so consumers can exhaustively switch on gesture kind AND device\n * type without a default branch.\n */\nexport type GestureEvent =\n | {\n readonly kind: 'pinch-begin';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'pinch-end';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'pinch-cancel';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'rotate-begin';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'rotate-end';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'rotate-cancel';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'swipe';\n readonly pointerId: number;\n readonly direction: SwipeDirection;\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'long-press';\n readonly pointerId: number;\n readonly x: number;\n readonly y: number;\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'double-tap';\n readonly pointerId: number;\n readonly x: number;\n readonly y: number;\n readonly pointerType: PointerType;\n readonly timestamp: number;\n };\n\n/** Live position + device type for a pointer (subset of the backend pointerMap entry). */\nexport interface RecognizerPointer {\n readonly x: number;\n readonly y: number;\n readonly pointerType: PointerType;\n}\n\n/** Locked dual-finger tracker for pinch + rotate (D-11). */\nexport interface PinchRotateTracker {\n readonly pointerA: number;\n readonly pointerB: number;\n readonly initialDistance: number;\n /** Previous frame's raw atan2 angle; rotation accumulates frame deltas (D-11). */\n readonly lastAngle: number;\n readonly pointerType: PointerType;\n}\n\n/** Per-pointer long-press arming state (D-10). */\nexport interface LongPressTracker {\n readonly downTime: number;\n readonly x: number;\n readonly y: number;\n readonly pointerType: PointerType;\n readonly armed: boolean;\n readonly fired: boolean;\n}\n\n/** Timestamped position sample for swipe velocity (D-10, 100ms window). */\nexport interface SwipeSample {\n readonly t: number;\n readonly x: number;\n readonly y: number;\n}\n\n/** Last recorded tap for double-tap window matching (D-10). */\nexport interface TapRecord {\n readonly time: number;\n readonly x: number;\n readonly y: number;\n}\n\n/**\n * The single legal cross-frame gesture state (C-3). Immutable: each\n * `processGestureFrame` returns a fresh copy; the producer stores it for\n * the next frame. `gesture` is the current continuous value read by\n * `snap.gesture` -- live during pinch, frozen after a 2->1 end, identity\n * after cancel/reset or when no gesture ever activated.\n */\nexport interface RecognizerState {\n readonly pinch: PinchRotateTracker | null;\n readonly gesture: GestureState;\n readonly longPresses: ReadonlyMap<number, LongPressTracker>;\n readonly lastTap: TapRecord | null;\n readonly swipeHistory: ReadonlyMap<number, readonly SwipeSample[]>;\n}\n\n/** Result of processing one frame of phase events (D-4 dual channel). */\nexport interface GestureFrameResult {\n readonly newState: RecognizerState;\n readonly gestureState: GestureState;\n readonly gestureEvents: readonly GestureEvent[];\n}\n\n/** Identity continuous value (AC-12): no scale, no rotation. */\nexport const IDENTITY_GESTURE: GestureState = Object.freeze({ pinchScale: 1, rotationAngle: 0 });\n\n/** Fresh recognizer state with no active gestures. */\nexport function createRecognizerState(): RecognizerState {\n return {\n pinch: null,\n gesture: IDENTITY_GESTURE,\n longPresses: new Map(),\n lastTap: null,\n swipeHistory: new Map(),\n };\n}\n\n// ─── pure math helpers ───────────────────────────────────────────────\n\nfunction distance(ax: number, ay: number, bx: number, by: number): number {\n return Math.hypot(bx - ax, by - ay);\n}\n\nfunction angleOf(ax: number, ay: number, bx: number, by: number): number {\n return Math.atan2(by - ay, bx - ax);\n}\n\n/** Wrap an angle to (-PI, PI] so accumulated rotation never jumps a full turn. */\nfunction normalizeAngle(a: number): number {\n let r = a;\n while (r > Math.PI) r -= 2 * Math.PI;\n while (r <= -Math.PI) r += 2 * Math.PI;\n return r;\n}\n\nfunction dominantDirection(dx: number, dy: number): SwipeDirection {\n if (Math.abs(dx) >= Math.abs(dy)) return dx >= 0 ? SWIPE_DIRECTIONS[1] : SWIPE_DIRECTIONS[0];\n // Screen space: +y points down.\n return dy >= 0 ? SWIPE_DIRECTIONS[3] : SWIPE_DIRECTIONS[2];\n}\n\n/**\n * AC-19 real consumption path: exhaustive switch on `PointerType` with no\n * default branch. Every gesture event's `pointerType` flows through here at\n * construction, so adding a 4th `PointerType` member fails to compile\n * (the function would then be able to return `undefined`, violating its\n * `PointerType` return type). This is the sanctioned AC-19 consumption\n * proof required by plan-strategy section 7 (M5 boundary).\n */\nfunction narrowGesturePointerType(pt: PointerType): PointerType {\n switch (pt) {\n case 'mouse':\n return 'mouse';\n case 'pen':\n return 'pen';\n case 'touch':\n return 'touch';\n }\n}\n\n// ─── mutable per-frame working context ───────────────────────────────\n\ninterface WorkContext {\n pinch: PinchRotateTracker | null;\n gesture: { pinchScale: number; rotationAngle: number };\n longPresses: Map<number, LongPressTracker>;\n lastTap: TapRecord | null;\n swipeHistory: Map<number, SwipeSample[]>;\n events: GestureEvent[];\n}\n\nfunction emitPinchLifecycle(\n ctx: WorkContext,\n phase: 'begin' | 'end' | 'cancel',\n tracker: PinchRotateTracker,\n now: number,\n): void {\n const pointerIds: readonly [number, number] = [tracker.pointerA, tracker.pointerB];\n const pointerType = narrowGesturePointerType(tracker.pointerType);\n ctx.events.push({ kind: `pinch-${phase}`, pointerIds, pointerType, timestamp: now });\n ctx.events.push({ kind: `rotate-${phase}`, pointerIds, pointerType, timestamp: now });\n}\n\nfunction handleDown(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n // Arm a long-press timer + start a swipe velocity window + tap start.\n ctx.longPresses.set(ev.pointerId, {\n downTime: now,\n x: ev.x,\n y: ev.y,\n pointerType: ev.pointerType,\n armed: true,\n fired: false,\n });\n ctx.swipeHistory.set(ev.pointerId, [{ t: now, x: ev.x, y: ev.y }]);\n}\n\nfunction handleMove(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n // Disarm the long-press if the finger strays beyond slop (D-10).\n const lp = ctx.longPresses.get(ev.pointerId);\n if (lp?.armed && distance(lp.x, lp.y, ev.x, ev.y) > LONG_PRESS_SLOP) {\n ctx.longPresses.set(ev.pointerId, { ...lp, armed: false });\n }\n // Append to the swipe velocity window, pruning samples outside it.\n const hist = ctx.swipeHistory.get(ev.pointerId);\n if (hist) {\n hist.push({ t: now, x: ev.x, y: ev.y });\n pruneSwipeWindow(hist, now);\n }\n}\n\nfunction pruneSwipeWindow(hist: SwipeSample[], now: number): void {\n const cutoff = now - SWIPE_WINDOW_MS;\n // Keep at least the last sample so an up always has a reference point.\n while (hist.length > 1 && hist[0] !== undefined && hist[0].t < cutoff) {\n hist.shift();\n }\n}\n\nfunction detectSwipe(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n const hist = ctx.swipeHistory.get(ev.pointerId);\n if (!hist || hist.length === 0) return;\n const cutoff = now - SWIPE_WINDOW_MS;\n const oldest = hist.find((s) => s.t >= cutoff) ?? hist[0];\n if (!oldest) return;\n const dt = now - oldest.t;\n if (dt <= 0) return;\n const dist = distance(oldest.x, oldest.y, ev.x, ev.y);\n if (dist / dt < SWIPE_VELOCITY_THRESHOLD) return;\n ctx.events.push({\n kind: 'swipe',\n pointerId: ev.pointerId,\n direction: dominantDirection(ev.x - oldest.x, ev.y - oldest.y),\n pointerType: narrowGesturePointerType(ev.pointerType),\n timestamp: now,\n });\n}\n\nfunction detectDoubleTap(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n const prev = ctx.lastTap;\n const withinTime = prev !== null && now - prev.time <= DOUBLE_TAP_INTERVAL_MS;\n const withinDist = prev !== null && distance(prev.x, prev.y, ev.x, ev.y) <= DOUBLE_TAP_DISTANCE;\n if (prev !== null && withinTime && withinDist) {\n ctx.events.push({\n kind: 'double-tap',\n pointerId: ev.pointerId,\n x: ev.x,\n y: ev.y,\n pointerType: narrowGesturePointerType(ev.pointerType),\n timestamp: now,\n });\n ctx.lastTap = null; // consumed; a 3rd tap starts a fresh pair\n return;\n }\n ctx.lastTap = { time: now, x: ev.x, y: ev.y };\n}\n\nfunction endPinchIfMember(\n ctx: WorkContext,\n pointerId: number,\n phase: 'end' | 'cancel',\n now: number,\n): void {\n const pinch = ctx.pinch;\n if (!pinch || (pinch.pointerA !== pointerId && pinch.pointerB !== pointerId)) return;\n emitPinchLifecycle(ctx, phase, pinch, now);\n ctx.pinch = null;\n if (phase === 'cancel') {\n // Cancel resets to identity (AC-18); end (2->1) freezes the last value (D-11).\n ctx.gesture = { pinchScale: 1, rotationAngle: 0 };\n }\n}\n\nfunction handleUp(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n detectSwipe(ctx, ev, now);\n detectDoubleTap(ctx, ev, now);\n ctx.longPresses.delete(ev.pointerId);\n ctx.swipeHistory.delete(ev.pointerId);\n endPinchIfMember(ctx, ev.pointerId, 'end', now);\n}\n\nfunction handleCancel(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n ctx.longPresses.delete(ev.pointerId);\n ctx.swipeHistory.delete(ev.pointerId);\n endPinchIfMember(ctx, ev.pointerId, 'cancel', now);\n}\n\nfunction tryLockPair(\n ctx: WorkContext,\n pointerMap: ReadonlyMap<number, RecognizerPointer>,\n now: number,\n): void {\n if (ctx.pinch !== null || pointerMap.size < 2) return;\n // D-11: lock the earliest two pointers by ascending pointerId; a later\n // (third+) finger is ignored while the pair holds.\n const ids = [...pointerMap.keys()].sort((a, b) => a - b);\n const idA = ids[0];\n const idB = ids[1];\n if (idA === undefined || idB === undefined) return;\n const a = pointerMap.get(idA);\n const b = pointerMap.get(idB);\n if (!a || !b) return;\n ctx.pinch = {\n pointerA: idA,\n pointerB: idB,\n initialDistance: distance(a.x, a.y, b.x, b.y) || 1,\n lastAngle: angleOf(a.x, a.y, b.x, b.y),\n pointerType: a.pointerType,\n };\n ctx.gesture = { pinchScale: 1, rotationAngle: 0 };\n emitPinchLifecycle(ctx, 'begin', ctx.pinch, now);\n}\n\nfunction updatePinchContinuous(\n ctx: WorkContext,\n pointerMap: ReadonlyMap<number, RecognizerPointer>,\n): void {\n const pinch = ctx.pinch;\n if (!pinch) return;\n const a = pointerMap.get(pinch.pointerA);\n const b = pointerMap.get(pinch.pointerB);\n if (!a || !b) return; // a member briefly absent: keep the last value\n const curDist = distance(a.x, a.y, b.x, b.y);\n const curAngle = angleOf(a.x, a.y, b.x, b.y);\n const delta = normalizeAngle(curAngle - pinch.lastAngle);\n ctx.gesture = {\n pinchScale: curDist / pinch.initialDistance,\n rotationAngle: ctx.gesture.rotationAngle + delta,\n };\n ctx.pinch = { ...pinch, lastAngle: curAngle };\n}\n\nfunction fireLongPresses(\n ctx: WorkContext,\n pointerMap: ReadonlyMap<number, RecognizerPointer>,\n now: number,\n): void {\n const pinch = ctx.pinch;\n for (const [id, lp] of ctx.longPresses) {\n if (!lp.armed || lp.fired) continue;\n if (now - lp.downTime < LONG_PRESS_DURATION_MS) continue;\n if (!pointerMap.has(id)) continue; // finger must still be down\n // A finger locked into an active pinch pair is committed to the dual\n // gesture and must not also fire a long-press (D-11 dual-finger lock).\n if (pinch && (pinch.pointerA === id || pinch.pointerB === id)) continue;\n ctx.events.push({\n kind: 'long-press',\n pointerId: id,\n x: lp.x,\n y: lp.y,\n pointerType: narrowGesturePointerType(lp.pointerType),\n timestamp: now,\n });\n ctx.longPresses.set(id, { ...lp, fired: true });\n }\n}\n\n/**\n * Process one frame of pointer phase events, advancing all timers off\n * `now`, and return the new state + continuous values + one-frame event\n * list (D-4). Never mutates its inputs.\n */\nexport function processGestureFrame(\n phaseQueue: readonly PointerPhaseEvent[],\n pointerMap: ReadonlyMap<number, RecognizerPointer>,\n prevState: RecognizerState,\n now: number,\n): GestureFrameResult {\n const ctx: WorkContext = {\n pinch: prevState.pinch,\n gesture: { ...prevState.gesture },\n longPresses: new Map(prevState.longPresses),\n lastTap: prevState.lastTap,\n swipeHistory: cloneSwipeHistory(prevState.swipeHistory),\n events: [],\n };\n\n for (const ev of phaseQueue) {\n switch (ev.phase) {\n case 'down':\n handleDown(ctx, ev, now);\n break;\n case 'move':\n handleMove(ctx, ev, now);\n break;\n case 'up':\n handleUp(ctx, ev, now);\n break;\n case 'cancel':\n handleCancel(ctx, ev, now);\n break;\n }\n }\n\n tryLockPair(ctx, pointerMap, now);\n updatePinchContinuous(ctx, pointerMap);\n fireLongPresses(ctx, pointerMap, now);\n\n const gesture: GestureState = Object.freeze({\n pinchScale: ctx.gesture.pinchScale,\n rotationAngle: ctx.gesture.rotationAngle,\n });\n const newState: RecognizerState = {\n pinch: ctx.pinch,\n gesture,\n longPresses: ctx.longPresses,\n lastTap: ctx.lastTap,\n swipeHistory: ctx.swipeHistory,\n };\n return { newState, gestureState: gesture, gestureEvents: ctx.events };\n}\n\nfunction cloneSwipeHistory(\n src: ReadonlyMap<number, readonly SwipeSample[]>,\n): Map<number, SwipeSample[]> {\n const out = new Map<number, SwipeSample[]>();\n for (const [id, samples] of src) out.set(id, [...samples]);\n return out;\n}\n","/** Event-path ownership and lifecycle reset primitives for browser hosts. */\n\nexport interface UiOwnershipResult {\n readonly owned: boolean;\n readonly source: 'composed-path' | 'target-fallback' | 'unknown';\n}\n\nexport interface UiInputResetBoundaryOptions {\n readonly clear: () => void;\n readonly signal?: AbortSignal;\n}\n\nexport interface UiInputResetBoundary {\n readonly reset: () => void;\n readonly dispose: () => void;\n}\n\nfunction contains(root: Node, value: EventTarget | null): boolean {\n const NodeCtor = globalThis.Node;\n return NodeCtor && value instanceof NodeCtor ? value === root || root.contains(value) : false;\n}\n\nexport function resolveUiOwnership(event: Event, host: Node): UiOwnershipResult {\n const path = event.composedPath;\n if (typeof path === 'function') {\n const composed = path.call(event);\n return {\n owned:\n composed.some((item) => contains(host, item)) ||\n (composed.length === 0 && contains(host, event.target)),\n source: composed.length === 0 ? 'target-fallback' : 'composed-path',\n };\n }\n if ('target' in event) {\n return { owned: contains(host, event.target), source: 'target-fallback' };\n }\n return { owned: false, source: 'unknown' };\n}\n\nexport function isUiOwnedEvent(event: Event, host: Node): boolean {\n return resolveUiOwnership(event, host).owned;\n}\n\nexport function createUiInputResetBoundary(\n options: UiInputResetBoundaryOptions,\n): UiInputResetBoundary {\n let disposed = false;\n const reset = (): void => {\n if (!disposed) options.clear();\n };\n const onAbort = (): void => reset();\n options.signal?.addEventListener('abort', onAbort, { once: true });\n return {\n reset,\n dispose: () => {\n if (disposed) return;\n disposed = true;\n options.signal?.removeEventListener('abort', onAbort);\n },\n };\n}\n","// virtual-joystick.ts -- pure-function virtual joystick derivation (M3).\n//\n// No DOM dependency; backend closure holds per-joystick bindState\n// and calls deriveVirtualAxes each sample() frame.\n//\n// @internal -- only the browser backend calls these functions; the\n// barrel does not re-export them.\n\nimport type { VirtualAxisSample, VirtualJoystickConfig } from './input-snapshot';\n\n/**\n * Per-joystick binding state. The backend closure owns a\n * Map<string, BindState> keyed by joystick config name.\n */\nexport interface BindState {\n /** bound pointerId, or undefined if unbound */\n pointerId?: number | undefined;\n /** origin in canvas pixels (anchor for fixed, first-touch for floating) */\n originX: number;\n originY: number;\n}\n\nfunction computeVec(\n ptrX: number,\n ptrY: number,\n originX: number,\n originY: number,\n radius: number,\n deadzone: number,\n): { x: number; y: number } {\n const rawX = (ptrX - originX) / radius;\n const rawY = (ptrY - originY) / radius;\n const mag = Math.sqrt(rawX * rawX + rawY * rawY);\n if (mag < deadzone) return { x: 0, y: 0 };\n if (mag > 1) {\n // Clamp to unit vector: normalize direction, magnitude = 1.\n return { x: rawX / mag, y: rawY / mag };\n }\n return { x: rawX, y: rawY };\n}\n\n/**\n * Derive one frame of virtual axis outputs from live pointer state and\n * per-joystick binding state.\n *\n * Pure function: no DOM access. The backend closure is the SSOT for\n * per-joystick state; binding + origin selection happens in\n * browser-backend.ts onPointerDown. This function only reads bindState\n * and computes per-frame vectors.\n *\n * Unbound joysticks always produce the zero vector.\n *\n * @param configs - configured virtual joysticks\n * @param pointerMap - live pointer positions keyed by pointerId\n * @param bindState - per-joystick binding state (read-only)\n * @returns one VirtualAxisSample per configured joystick\n */\nexport function deriveVirtualAxes(\n configs: readonly VirtualJoystickConfig[],\n pointerMap: Map<number, { readonly x: number; readonly y: number }>,\n bindState: Map<string, BindState>,\n): VirtualAxisSample[] {\n const results: VirtualAxisSample[] = [];\n\n for (const cfg of configs) {\n const bs = bindState.get(cfg.name);\n\n if (bs?.pointerId !== undefined) {\n // Bound: compute vector from current pointer position.\n const ptr = pointerMap.get(bs.pointerId);\n if (ptr) {\n const vec = computeVec(ptr.x, ptr.y, bs.originX, bs.originY, cfg.radius, cfg.deadzone);\n results.push({ name: cfg.name, x: vec.x, y: vec.y });\n } else {\n // Pointer disappeared (up/cancel handled by backend unbind,\n // but this guards against pointer removal without unbind).\n bs.pointerId = undefined;\n results.push({ name: cfg.name, x: 0, y: 0 });\n }\n } else {\n // Unbound: zero vector. Binding is the backend's responsibility.\n results.push({ name: cfg.name, x: 0, y: 0 });\n }\n }\n\n return results;\n}\n\n/**\n * Unbind a joystick when its bound pointer goes up or is cancelled.\n * Sets pointerId to undefined; the next deriveVirtualAxes call will\n * produce a zero vector for the unbound joystick.\n */\nexport function handleVirtualJoystickUnbind(\n bindState: Map<string, BindState>,\n pointerId: number,\n): void {\n for (const bs of bindState.values()) {\n if (bs.pointerId === pointerId) {\n bs.pointerId = undefined;\n }\n }\n}\n","// browser-backend.ts -- DOM PointerLock + keyboard / mouse listener producer.\n//\n// charter awareness:\n// F2 minimal surface -- exposes only `attachBrowserInputBackend(canvas)`\n// returning a `(): void` detach handle; PointerLock + listener wiring\n// is internal (plan OOS-1 explicit -- not part of the user-facing\n// surface)\n// P3 explicit failure -- detach is part of the contract; double-detach\n// is a no-op (idempotent)\n// P4 consistent abstraction -- the snapshot consumer does not see\n// PointerLock state machine or `movementX/Y` units; only\n// `mouse.movementDelta`\n// P5 producer/consumer split -- this file is the only DOM-touching\n// surface in the package; everything else operates on the\n// `InputBackend` protocol (see input-snapshot.ts)\n//\n// Note: the actual PointerLock pump runs in a real browser; node-based\n// vitest unit tests inject fake backends through the `InputBackend`\n// protocol. The browser-mode coverage of this file is the M2b layer\n// (plan-strategy section 5.4 reason for the 70% floor).\n\nimport type { ControllerDb, MappingTokens } from './controller-db';\nimport { diffGamepadFrame, type RawGamepadStub } from './gamepad-frame';\nimport {\n createRecognizerState,\n type GestureEvent,\n type GestureState,\n processGestureFrame,\n type RecognizerPointer,\n type RecognizerState,\n} from './gesture-recognizer';\nimport type {\n Capabilities,\n GamepadSlotSample,\n InputBackend,\n InputBackendSample,\n PointerPhaseEvent,\n PointerSample,\n PointerType,\n VirtualAxisSample,\n VirtualJoystickConfig,\n} from './input-snapshot';\nimport { isUiOwnedEvent } from './ui-ownership';\nimport { type BindState, deriveVirtualAxes, handleVirtualJoystickUnbind } from './virtual-joystick';\n\n// D-5: normalize W3C PointerEvent.pointerType to the canonical 3-literal union.\n// The spec allows '' when device type is undetectable; we map it to 'mouse' so\n// the snapshot consumers (action matchers, gesture recognizers) can exhaustively\n// switch on PointerType without a default branch (AC-19).\nexport function coercePointerType(raw: string): PointerType {\n if (raw === 'pen') return 'pen';\n if (raw === 'touch') return 'touch';\n return 'mouse';\n}\n\n/**\n * Options accepted by `attachBrowserInputBackend`.\n */\nexport interface BrowserInputBackendOptions {\n /** Optional host-owned UI root. Events in this root never reach gameplay. */\n readonly uiRoot?: Node;\n /**\n * Optional document handle (testing override). Defaults to `document`.\n * Plan-strategy section 9 row 7 (`document.hasFocus()` semantics)\n * relies on this to decide whether the up-edge set should be cleared\n * when focus is lost.\n */\n readonly document?: Document;\n /**\n * Optional window handle (testing override). Defaults to `window`.\n * Used to attach key listeners (capturing focus loss) without\n * requiring the canvas itself to receive keyboard events.\n */\n readonly window?: Window;\n /**\n * Neutral gate for the auto PointerLock-on-click. When provided and it\n * returns false, the click handler skips `requestPointerLock()` — the host\n * decides whether a click should capture the cursor right now. Defaults to\n * always-locking (returns true), so the standalone game runtime keeps its\n * MVP behaviour unchanged. This predicate is deliberately host-opaque: the\n * backend never learns WHY locking is (dis)allowed — it only asks. A host\n * that mounts this canvas in a non-game context (e.g. an editor viewport\n * that owns the cursor for orbit/pick) supplies a predicate that returns\n * false there. The input package carries zero knowledge of those contexts.\n */\n readonly pointerLockAllowed?: () => boolean;\n /**\n * Optional navigator handle (testing override). Defaults to\n * `globalThis.navigator`. Used to poll `navigator.getGamepads()` each\n * frame. Mirrors the `document`/`window` override pattern.\n */\n readonly navigator?: { getGamepads?(): (Gamepad | null)[] };\n /**\n * Optional virtual joystick configurations (M3). When provided, the\n * backend auto-binds the first pointerdown within each config's region\n * and derives per-frame VirtualAxisSample outputs via deriveVirtualAxes.\n */\n readonly virtualJoysticks?: readonly VirtualJoystickConfig[];\n /**\n * Optional SDL controller DB text loader (M3 D-13 test injection). When\n * omitted, the backend dynamic-imports the vendored 554KB DB from\n * `@forgeax/engine-input/controller-db-data` on first sight of a\n * non-standard gamepad (D-2 lazy-load: the 554KB never sits in the\n * default path). Tests inject a synthetic DB string to avoid loading the\n * real vendored file. Returns the raw gamecontrollerdb.txt contents.\n */\n readonly loadControllerDb?: () => Promise<string>;\n /**\n * Optional monotonic clock (M5 D-3 test injection). Defaults to\n * `() => performance.now()`. The gesture recognizer advances all timers\n * (long-press duration, double-tap / swipe windows) off this clock, NOT\n * off pointer-event arrival, so recognition stays decoupled from event\n * frequency (AC-16). Tests inject a fake clock for deterministic timing,\n * mirroring the `document` / `window` / `navigator` override pattern.\n */\n readonly now?: () => number;\n /**\n * Optional lock provider (D-2). When provided, pointer-lock requests\n * route through requestLock() / exitLock() instead of the W3C\n * requestPointerLock / exitPointerLock API. The backend remains\n * host-opaque -- it never learns whether the provider wraps Tauri\n * native-grab, postMessage, or any other mechanism.\n */\n readonly lockProvider?: PointerLockProvider;\n /**\n * Optional callback for lock request failures (D-4). When W3C\n * requestPointerLock rejects or lockProvider.requestLock/exitLock\n * throws/rejects, the backend calls this with a detail object.\n * Without this callback, failures are silently caught (backward\n * compatible but contrary to charter P3).\n */\n readonly onLockError?: (detail: { path: 'w3c' | 'provider'; cause: unknown }) => void;\n}\n\n/**\n * Lock provider interface (D-2). A host injects this to replace the\n * W3C Pointer Lock API path. requestLock() may return void (fire-and-forget,\n * D-7 optimistic placement) or Promise<void> (awaitable). exitLock() is\n * called when the backend needs to release the lock (ESC / blur / detach /\n * setPointerLockAllowed(false)).\n */\nexport interface PointerLockProvider {\n /**\n * Request pointer lock. The backend optimistically sets providerLocked=true\n * when this is called (D-7). On throw/reject, the backend calls onLockError\n * and rolls back providerLocked.\n */\n requestLock(): void | Promise<void>;\n /** Release pointer lock. */\n exitLock(): void;\n}\n\n/**\n * Attach DOM listeners (keydown / keyup / mousedown / mouseup /\n * pointerlockchange / mousemove inside lock / blur) to `canvas` and the\n * surrounding window. Returns a `detach` callable that:\n *\n * - removes all listeners\n * - exits PointerLock if currently locked\n * - drops every internal accumulator\n *\n * The returned object also implements the `InputBackend` protocol -- the\n * runtime inserts it under `INPUT_BACKEND_KEY` and adds the\n * `InputFrameStartScan` system, which reads it back each tick.\n * Calling `detach()` and the protocol's `detach()` are equivalent\n * (idempotent; double-detach is safe -- charter P3).\n */\nexport function attachBrowserInputBackend(\n canvas: HTMLCanvasElement,\n options: BrowserInputBackendOptions = {},\n): (() => void) & { backend: InputBackend } {\n const doc = options.document ?? globalThis.document;\n const win = options.window ?? globalThis.window;\n\n const heldKeys = new Set<string>();\n const upEdges = new Set<string>();\n const heldCodes = new Set<string>();\n const upCodeEdges = new Set<string>();\n const pressedKeys = new Set<string>();\n const pressedCodes = new Set<string>();\n const buttons: [boolean, boolean, boolean] = [false, false, false];\n const pressedButtons: [boolean, boolean, boolean] = [false, false, false];\n const releasedButtons: [boolean, boolean, boolean] = [false, false, false];\n let mvx = 0;\n let mvy = 0;\n let wheelAccum = 0;\n let detached = false;\n\n const isUiEvent = (event: Event): boolean =>\n options.uiRoot !== undefined && isUiOwnedEvent(event, options.uiRoot);\n\n // w6: merged pointer-lock state tracking (D-1).\n // w3cLocked is driven by document-level pointerlockchange events,\n // isolated per-instance by comparing pointerLockElement === this canvas.\n let w3cLocked = false;\n // providerLocked is set optimistically when lockProvider.requestLock()\n // is called (D-7); cleared by exitLock() or on rejection.\n let providerLocked = false;\n // gameGate is a command-set boolean (setPointerLockAllowed), default true.\n let gameGate = true;\n\n function emitLockError(path: 'w3c' | 'provider', cause: unknown): void {\n try {\n options.onLockError?.({ path, cause });\n } catch {\n // Lock diagnostics are observational; a throwing host callback must not\n // create a second unhandled rejection from the browser Promise path.\n }\n }\n\n // w8 (D-1/D-3): release the provider lock idempotently. Calls the injected\n // exitLock (routing any throw to onLockError as { path: 'provider' }) and\n // clears providerLocked unconditionally. Shared by every provider-release\n // site (ESC, blur, setPointerLockAllowed(false), detach) so the release\n // semantics live in one place.\n function releaseProviderLock(): void {\n if (providerLocked && options.lockProvider?.exitLock) {\n try {\n options.lockProvider.exitLock();\n } catch (err: unknown) {\n emitLockError('provider', err);\n }\n }\n providerLocked = false;\n }\n\n // D-4: capability detected once at attach time.\n const nav =\n options.navigator ?? (globalThis as { navigator?: { getGamepads?(): unknown } }).navigator;\n const gamepadAvailable = typeof nav?.getGamepads === 'function';\n const pointerAvailable = typeof globalThis.PointerEvent !== 'undefined';\n const caps: Capabilities = { gamepad: gamepadAvailable, pointer: pointerAvailable };\n\n // D-1: prevGamepadFrame is the only cross-frame state holder for gamepad diff.\n // Stored in backend closure; diffGamepadFrame compares prev vs cur each sample().\n let prevGamepadFrame = new Map<number, GamepadSlotSample>();\n // Focus loss discards the old physical frame. The first successful sample\n // afterwards establishes a new baseline instead of turning a still-held\n // button into a synthetic justPressed edge.\n let gamepadBaselinePending = false;\n let focusResetPending = false;\n\n // M3 D-2 lazy-load state. The SDL DB (554KB) is loaded once, on first sight\n // of a non-standard gamepad, then cached here. `controllerDb` stays\n // undefined until the async load resolves; frames before that keep the\n // Feat1 empty signal (graceful degradation). `dbLoadStarted` prevents\n // re-triggering the load on every frame while the promise is pending.\n let controllerDb: ControllerDb | undefined;\n let dbLoadStarted = false;\n // Per-id GUID resolution cache (avoids re-parsing the same Gamepad.id).\n const guidCache = new Map<string, string | undefined>();\n\n // M3 D-13: the DB parser + GUID helpers live in the pure controller-db\n // module. They are dynamic-imported alongside the data so neither the\n // parser nor the 554KB vendored text enters the main-entry bundle.\n let controllerDbApi:\n | {\n parseControllerDb: (txt: string) => ControllerDb;\n extractGuidFromGamepadId: (id: string) => string | undefined;\n selectBestMappingEntry: (\n db: ControllerDb,\n guid: string,\n platform: string | undefined,\n ) => { readonly tokens: MappingTokens } | undefined;\n platformFromUserAgent: (ua: string) => string | undefined;\n }\n | undefined;\n\n function kickOffDbLoad(): void {\n if (dbLoadStarted) return;\n dbLoadStarted = true;\n const loadApi = controllerDbApi\n ? Promise.resolve(controllerDbApi)\n : import('@forgeax/engine-input/controller-db').then((m) => {\n controllerDbApi = m;\n return m;\n });\n const loadText = options.loadControllerDb\n ? options.loadControllerDb()\n : import('@forgeax/engine-input/controller-db-data').then((m) => m.loadBundledControllerDb());\n Promise.all([loadApi, loadText])\n .then(([api, txt]) => {\n controllerDb = api.parseControllerDb(txt);\n })\n .catch(() => {\n // Load failed (offline chunk / bad text): keep the Feat1 empty\n // signal. Reset so a later frame may retry.\n dbLoadStarted = false;\n });\n }\n\n // Acquisition-layer remap lookup passed to diffGamepadFrame. Returns the\n // standard-layout mapping tokens for a Gamepad.id, or null when the DB is\n // not yet loaded / the GUID is unextractable / no DB entry matches.\n function remapLookup(gamepadId: string): MappingTokens | null {\n if (!controllerDb || !controllerDbApi) return null;\n let guid = guidCache.get(gamepadId);\n if (!guidCache.has(gamepadId)) {\n guid = controllerDbApi.extractGuidFromGamepadId(gamepadId);\n guidCache.set(gamepadId, guid);\n }\n if (!guid) return null;\n const ua =\n typeof globalThis.navigator?.userAgent === 'string' ? globalThis.navigator.userAgent : '';\n const platform = controllerDbApi.platformFromUserAgent(ua);\n const entry = controllerDbApi.selectBestMappingEntry(controllerDb, guid, platform);\n return entry ? entry.tokens : null;\n }\n\n // w15: pointer map (pointerId → live position), phase queue (one-frame lifecycle),\n // and per-pointer previous position for cross-frame delta.\n const pointerMap = new Map<\n number,\n {\n x: number;\n y: number;\n pressure: number;\n pointerType: PointerType;\n prevX: number;\n prevY: number;\n }\n >();\n const phaseQueue: PointerPhaseEvent[] = [];\n let mouseX: number | undefined;\n let mouseY: number | undefined;\n\n // w21: virtual joystick binding state (per-joystick name → BindState).\n const vjConfigs = options.virtualJoysticks ?? [];\n const vjBindState = new Map<string, BindState>();\n\n // M5 D-3/D-4: gesture recognizer cross-frame state lives in this closure\n // (C-3: the only sanctioned cross-frame gesture holder, alongside\n // prevGamepadFrame / pointerMap / vjBindState). `now` is injectable for\n // deterministic test timing; production uses performance.now().\n const now = options.now ?? (() => performance.now());\n let recognizerState: RecognizerState = createRecognizerState();\n\n // DPR coordinate helpers. computePointerCoords applies the standard DPR-correct\n // canvas-pixel formula; falls back to clientX/clientY when getBoundingClientRect\n // is missing (fake canvas in unit tests).\n function computePointerCoords(ev: PointerEvent): { x: number; y: number } {\n const rect = canvas.getBoundingClientRect?.();\n if (!rect) return { x: ev.clientX, y: ev.clientY };\n const scaleX = canvas.width / rect.width;\n const scaleY = canvas.height / rect.height;\n return {\n x: (ev.clientX - rect.left) * scaleX,\n y: (ev.clientY - rect.top) * scaleY,\n };\n }\n\n function isFocused(): boolean {\n // `document.hasFocus()` indicates whether the tab is foreground;\n // when unfocused we suppress up-edges so stale releases do not fire\n // after alt-tabbing back (section 9 row 7).\n return typeof doc?.hasFocus === 'function' ? doc.hasFocus() : true;\n }\n\n function onKeyDown(ev: KeyboardEvent): void {\n if (isUiEvent(ev)) {\n clear();\n return;\n }\n if (!heldKeys.has(ev.key)) pressedKeys.add(ev.key);\n heldKeys.add(ev.key);\n if (ev.code) {\n if (!heldCodes.has(ev.code)) pressedCodes.add(ev.code);\n heldCodes.add(ev.code);\n }\n // w8 (D-1): ESC releases provider lock (W3C path handles ESC via browser\n // pointerlockchange). Only acts when providerLocked is true.\n if (ev.key === 'Escape' && providerLocked) {\n releaseProviderLock();\n }\n }\n function onKeyUp(ev: KeyboardEvent): void {\n if (isUiEvent(ev)) return;\n heldKeys.delete(ev.key);\n if (isFocused()) {\n upEdges.add(ev.key);\n }\n if (ev.code) {\n heldCodes.delete(ev.code);\n if (isFocused()) upCodeEdges.add(ev.code);\n }\n }\n function onPointerDown(ev: PointerEvent): void {\n if (isUiEvent(ev)) {\n clear();\n return;\n }\n // Only mouse-type pointers affect the mouse button cluster (D-3).\n if (ev.pointerType === 'mouse') {\n if (ev.button === 0 || ev.button === 1 || ev.button === 2) {\n if (!buttons[ev.button]) pressedButtons[ev.button] = true;\n buttons[ev.button] = true;\n }\n }\n // D-5: setPointerCapture for coherent pointer event dispatching — but NOT\n // while pointer lock is active. Pointer capture and pointer lock are mutually\n // exclusive (W3C): setPointerCapture throws InvalidStateError when the element\n // already holds the lock. Under lock the cursor is confined and every pointer\n // event already targets the locked element, so capture is redundant anyway.\n // The try/catch is belt-and-suspenders for the race where lock/capture state\n // flips between the pointerlockchange event and this handler.\n if (!w3cLocked && !providerLocked && typeof canvas.setPointerCapture === 'function') {\n try {\n canvas.setPointerCapture(ev.pointerId);\n } catch {\n /* capture illegal in the current pointer state (e.g. just-acquired lock) — safe to skip */\n }\n }\n // Track pointer in map for multi-pointer + delta (w15).\n const coords = computePointerCoords(ev);\n if (ev.pointerType === 'mouse') {\n mouseX = coords.x;\n mouseY = coords.y;\n }\n pointerMap.set(ev.pointerId, {\n x: coords.x,\n y: coords.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n prevX: coords.x,\n prevY: coords.y,\n });\n phaseQueue.push({\n pointerId: ev.pointerId,\n phase: 'down',\n x: coords.x,\n y: coords.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n });\n // w21: virtual joystick auto-bind -- first config whose region contains\n // the pointerdown position, if not already bound to another pointer.\n if (vjConfigs.length > 0) {\n for (const cfg of vjConfigs) {\n const { region } = cfg;\n if (\n coords.x >= region.x &&\n coords.x <= region.x + region.width &&\n coords.y >= region.y &&\n coords.y <= region.y + region.height\n ) {\n const existing = vjBindState.get(cfg.name);\n if (!existing?.pointerId) {\n const originX =\n cfg.mode === 'fixed' ? (cfg.anchor?.x ?? region.x + region.width / 2) : coords.x;\n const originY =\n cfg.mode === 'fixed' ? (cfg.anchor?.y ?? region.y + region.height / 2) : coords.y;\n if (existing) {\n existing.pointerId = ev.pointerId;\n existing.originX = originX;\n existing.originY = originY;\n } else {\n vjBindState.set(cfg.name, { pointerId: ev.pointerId, originX, originY });\n }\n // Only bind the first matching config per pointerdown.\n break;\n }\n }\n }\n }\n }\n function onPointerUp(ev: PointerEvent): void {\n if (isUiEvent(ev)) return;\n if (ev.pointerType === 'mouse') {\n if (ev.button === 0 || ev.button === 1 || ev.button === 2) {\n if (buttons[ev.button]) releasedButtons[ev.button] = true;\n buttons[ev.button] = false;\n }\n }\n const entry = pointerMap.get(ev.pointerId);\n if (entry) {\n phaseQueue.push({\n pointerId: ev.pointerId,\n phase: 'up',\n x: entry.x,\n y: entry.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n });\n pointerMap.delete(ev.pointerId);\n }\n // w21: unbind virtual joystick bound to this pointer.\n if (vjBindState.size > 0) {\n handleVirtualJoystickUnbind(vjBindState, ev.pointerId);\n }\n }\n function onPointerMove(ev: PointerEvent): void {\n if (isUiEvent(ev)) return;\n // D-3: movementDelta from pointermove (PointerEvent extends MouseEvent).\n if (ev.pointerType === 'mouse') {\n mvx += ev.movementX;\n mvy += ev.movementY;\n }\n // Update live position; prevX/prevY NOT updated here (AC-09: prev only\n // snapshots at sample() time, preventing Bevy #12442 zero-delta bug).\n const coords = computePointerCoords(ev);\n if (ev.pointerType === 'mouse') {\n mouseX = coords.x;\n mouseY = coords.y;\n }\n const entry = pointerMap.get(ev.pointerId);\n if (entry) {\n entry.x = coords.x;\n entry.y = coords.y;\n entry.pressure = ev.pressure;\n phaseQueue.push({\n pointerId: ev.pointerId,\n phase: 'move',\n x: coords.x,\n y: coords.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n });\n }\n }\n function onPointerCancel(ev: PointerEvent): void {\n if (isUiEvent(ev)) return;\n const entry = pointerMap.get(ev.pointerId);\n if (entry) {\n phaseQueue.push({\n pointerId: ev.pointerId,\n phase: 'cancel',\n x: entry.x,\n y: entry.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n });\n pointerMap.delete(ev.pointerId);\n }\n // w21: unbind virtual joystick on pointer cancel.\n if (vjBindState.size > 0) {\n handleVirtualJoystickUnbind(vjBindState, ev.pointerId);\n }\n }\n function onVisibilityChange(): void {\n if (doc.visibilityState === 'hidden') {\n onBlur();\n }\n }\n function onWheel(ev: WheelEvent): void {\n if (isUiEvent(ev)) {\n clear();\n return;\n }\n // plan-strategy D-5 sign-discrete normalization: collapse `WheelEvent`\n // across the three `deltaMode` units (PIXEL / LINE / PAGE) by taking\n // `Math.sign(deltaY)` per event. Trade-off documented at the\n // InputSnapshot.mouse.wheelDelta JSDoc + plan-strategy R-7.\n const dy = ev.deltaY;\n if (typeof dy === 'number' && dy !== 0) {\n wheelAccum += dy > 0 ? 1 : -1;\n }\n }\n function onBlur(): void {\n // A standalone backend preserves its current-frame cancellation semantics.\n // A host control boundary calls clear() separately on the same blur event so\n // no state crosses a lease; the source itself still emits cancellation to its\n // sole consumer as it did before ownership routing existed.\n upEdges.clear();\n upCodeEdges.clear();\n pressedKeys.clear();\n pressedCodes.clear();\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n heldKeys.clear();\n heldCodes.clear();\n buttons[0] = false;\n buttons[1] = false;\n buttons[2] = false;\n mvx = 0;\n mvy = 0;\n wheelAccum = 0;\n // Pointer lock is not allowed to survive a focus boundary. Publish the\n // unlocked state synchronously; pointerlockchange may arrive later (or\n // be suppressed by the browser while the document is hidden).\n if (typeof doc.exitPointerLock === 'function' && doc.pointerLockElement === canvas) {\n doc.exitPointerLock();\n }\n w3cLocked = false;\n releaseProviderLock();\n if (pointerMap.size > 0) {\n for (const [id, entry] of pointerMap) {\n phaseQueue.push({\n pointerId: id,\n phase: 'cancel',\n x: entry.x,\n y: entry.y,\n pressure: entry.pressure,\n pointerType: entry.pointerType,\n });\n }\n pointerMap.clear();\n }\n prevGamepadFrame.clear();\n gamepadBaselinePending = true;\n focusResetPending = true;\n vjBindState.clear();\n }\n\n // Use try-blocks: jsdom / fake canvases passed by tests may lack\n // `addEventListener`. We probe and skip silently to keep the unit-test\n // surface workable (charter P3: detach must always succeed even if\n // attach was a partial wiring).\n const safeAdd = <K extends string>(\n target: { addEventListener?: (k: K, h: EventListener) => void } | undefined,\n kind: K,\n handler: EventListener,\n ): void => {\n target?.addEventListener?.(kind, handler);\n };\n const safeRemove = <K extends string>(\n target: { removeEventListener?: (k: K, h: EventListener) => void } | undefined,\n kind: K,\n handler: EventListener,\n ): void => {\n target?.removeEventListener?.(kind, handler);\n };\n\n safeAdd(win, 'keydown', onKeyDown as EventListener);\n safeAdd(win, 'keyup', onKeyUp as EventListener);\n safeAdd(win, 'blur', onBlur as EventListener);\n safeAdd(canvas, 'pointerdown', onPointerDown as EventListener);\n safeAdd(canvas, 'pointerup', onPointerUp as EventListener);\n safeAdd(canvas, 'pointermove', onPointerMove as EventListener);\n safeAdd(canvas, 'pointercancel', onPointerCancel as EventListener);\n safeAdd(canvas, 'wheel', onWheel as EventListener);\n safeAdd(doc, 'visibilitychange', onVisibilityChange as EventListener);\n\n // w6 (D-1): track W3C pointer-lock state via document-level pointerlockchange.\n // Per-instance isolation: only update w3cLocked when pointerLockElement matches\n // this backend's canvas. A native unlock is also a lifecycle boundary: browsers\n // do not all pair an OS focus transition with a DOM blur event, so clear the\n // physical frame when an owned lock exits after being acquired.\n function onPointerLockChange(): void {\n const wasLocked = w3cLocked;\n w3cLocked = doc.pointerLockElement === canvas;\n if (wasLocked && !w3cLocked && !providerLocked) onBlur();\n }\n safeAdd(doc, 'pointerlockchange', onPointerLockChange as EventListener);\n\n function onPointerLockError(event: Event): void {\n emitLockError('w3c', event);\n }\n safeAdd(doc, 'pointerlockerror', onPointerLockError as EventListener);\n\n // PointerLock entry must be triggered by user activation (W3C requires\n // a click / keydown handler to call `requestPointerLock()`). The MVP\n // wires a click listener on the canvas as the activation surface;\n // OOS-1 keeps any explicit \"request lock\" / \"exit lock\" surface out\n // of the snapshot itself.\n // D-5: touch-action:none on the canvas so the browser does not interpret\n // touch gestures (scroll/pinch/zoom) and deprioritizes pointer events.\n // Presence-detect .style (fake canvas in unit tests may lack it).\n let _prevTouchAction: string | undefined;\n if (canvas.style) {\n _prevTouchAction = canvas.style.touchAction;\n canvas.style.touchAction = 'none';\n }\n\n function onCanvasClick(): void {\n // D-3: dual gate synthesis -- gameGate (command-set by template) AND\n // hostPredicate (per-click evaluated by host). Both must pass to proceed.\n if (!gameGate) return;\n // Host gate: when the host says \"not now\" (e.g. an editor viewport that owns\n // the cursor outside the play-game quadrant) skip the lock entirely. Default\n // is always-allow, so the standalone game runtime is unchanged.\n if (options.pointerLockAllowed && !options.pointerLockAllowed()) return;\n // D-2 / D-7: lockProvider path takes priority over W3C.\n if (options.lockProvider) {\n providerLocked = true; // D-7 optimistic placement\n try {\n const result = options.lockProvider.requestLock();\n if (result && typeof (result as Promise<void>).catch === 'function') {\n (result as Promise<void>).catch((cause: unknown) => {\n providerLocked = false;\n emitLockError('provider', cause);\n });\n }\n } catch (cause: unknown) {\n // Synchronous throw from requestLock.\n providerLocked = false;\n emitLockError('provider', cause);\n }\n return;\n }\n\n // W3C path: standard requestPointerLock.\n const fn = canvas.requestPointerLock;\n if (typeof fn !== 'function') return;\n try {\n const r = fn.call(canvas) as unknown;\n if (r && typeof (r as Promise<void>).catch === 'function') {\n (r as Promise<void>).catch((cause: unknown) => {\n emitLockError('w3c', cause);\n });\n }\n } catch (cause: unknown) {\n emitLockError('w3c', cause);\n }\n }\n safeAdd(canvas, 'click', onCanvasClick as EventListener);\n\n function sample(): InputBackendSample {\n // D-1: gamepad edge diff derived inside sample() — the only\n // cross-frame state holder. getGamepads() is polled once per frame;\n // null-padded arrays use gamepad.index as slot key.\n let gamepads: GamepadSlotSample[] | undefined;\n if (gamepadAvailable) {\n try {\n const rawGamepads = (nav.getGamepads?.() ?? []) as (RawGamepadStub | null)[];\n const valid: RawGamepadStub[] = [];\n let hasNonStandard = false;\n for (const gp of rawGamepads) {\n if (!gp?.connected) continue;\n valid.push(gp);\n if (gp.mapping !== 'standard') hasNonStandard = true;\n }\n // M3 D-2 / C-5: only a real non-standard gamepad triggers the DB\n // load. Standard pads never pull in the 554KB DB.\n if (hasNonStandard) kickOffDbLoad();\n gamepads = diffGamepadFrame(prevGamepadFrame, valid, remapLookup);\n if (gamepadBaselinePending) {\n gamepads = gamepads.map((slot) => ({\n ...slot,\n justPressed: new Set<number>(),\n justReleased: new Set<number>(),\n }));\n gamepadBaselinePending = false;\n }\n // Store this frame's state for next frame's diff.\n const nextFrame = new Map<number, GamepadSlotSample>();\n for (const slot of gamepads) {\n // Only store currently-connected slots for the next diff.\n // Disconnected slots (standardMapping=false, pressed=empty)\n // are not stored; they won't appear in next frame's prev.\n if (slot.pressed.size > 0 || slot.standardMapping) {\n nextFrame.set(slot.index, slot);\n }\n }\n prevGamepadFrame = nextFrame;\n } catch {\n // getGamepads() threw — treat as if no gamepad API.\n // AC-05: API unstable environment does not crash.\n }\n }\n\n // w15: freeze pointer map → PointerSample[] with cross-frame delta.\n // Delta = current frozen position − previous frozen position (AC-09).\n let pointers: PointerSample[] | undefined;\n if (pointerMap.size > 0) {\n pointers = [];\n for (const [id, entry] of pointerMap) {\n const deltaX = entry.x - entry.prevX;\n const deltaY = entry.y - entry.prevY;\n pointers.push({\n pointerId: id,\n x: entry.x,\n y: entry.y,\n pressure: entry.pressure,\n pointerType: entry.pointerType,\n active: true,\n delta: Object.freeze({ x: deltaX, y: deltaY }),\n });\n // Update prev position for next frame's delta (D-1 frame-end freeze).\n entry.prevX = entry.x;\n entry.prevY = entry.y;\n }\n }\n\n // w15: snapshot the phase queue for this frame.\n const pointerEvents: PointerPhaseEvent[] | undefined =\n phaseQueue.length > 0 ? [...phaseQueue] : undefined;\n\n // w21: derive virtual joystick axes from live pointer positions.\n let virtualAxes: VirtualAxisSample[] | undefined;\n if (vjConfigs.length > 0) {\n virtualAxes = deriveVirtualAxes(vjConfigs, pointerMap, vjBindState);\n }\n\n // M5 D-4: run the gesture recognizer over this frame's phase queue BEFORE\n // it is drained below. onBlur / pointercancel pushed cancel phases into\n // the same queue, so the recognizer naturally resets active gestures +\n // emits cancel events (AC-18) without a separate reset path. All timers\n // advance off `now()` (D-3), decoupled from event frequency (AC-16).\n const gestureResult = processGestureFrame(\n phaseQueue,\n pointerMap as ReadonlyMap<number, RecognizerPointer>,\n recognizerState,\n now(),\n );\n recognizerState = gestureResult.newState;\n // Emit optional fields only when there is gesture signal to carry: an\n // active/frozen continuous value (non-identity) or lifecycle events.\n const gestureEvents: readonly GestureEvent[] | undefined =\n gestureResult.gestureEvents.length > 0 ? gestureResult.gestureEvents : undefined;\n const gs = gestureResult.gestureState;\n const gestures: GestureState | undefined =\n gs.pinchScale !== 1 || gs.rotationAngle !== 0 ? gs : undefined;\n\n const out: InputBackendSample = {\n downKeys: new Set(heldKeys),\n upKeys: new Set(upEdges),\n downCodes: new Set(heldCodes),\n upCodes: new Set(upCodeEdges),\n pressedKeys: new Set(pressedKeys),\n pressedCodes: new Set(pressedCodes),\n buttons: [buttons[0], buttons[1], buttons[2]] as readonly [boolean, boolean, boolean],\n pressedButtons: [pressedButtons[0], pressedButtons[1], pressedButtons[2]] as readonly [\n boolean,\n boolean,\n boolean,\n ],\n releasedButtons: [releasedButtons[0], releasedButtons[1], releasedButtons[2]] as readonly [\n boolean,\n boolean,\n boolean,\n ],\n movementX: mvx,\n movementY: mvy,\n ...(mouseX !== undefined && mouseY !== undefined ? { mouseX, mouseY } : {}),\n wheelDelta: wheelAccum,\n focused: isFocused(),\n capabilities: caps,\n pointerLocked: w3cLocked || providerLocked,\n ...(gamepads ? { gamepads } : {}),\n ...(pointers ? { pointers } : {}),\n ...(pointerEvents ? { pointerEvents } : {}),\n ...(virtualAxes ? { virtualAxes } : {}),\n ...(gestures ? { gestures } : {}),\n ...(gestureEvents ? { gestureEvents } : {}),\n ...(focusResetPending ? { focusReset: true } : {}),\n };\n // Reset per-frame accumulators (movement delta + key edges + wheel notches + phase queue).\n upEdges.clear();\n upCodeEdges.clear();\n pressedKeys.clear();\n pressedCodes.clear();\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n mvx = 0;\n mvy = 0;\n wheelAccum = 0;\n phaseQueue.length = 0;\n focusResetPending = false;\n return out;\n }\n\n // w8 (D-3): command-set game gate for pointer-lock. set(false) immediately\n // releases any active lock on both W3C and provider paths.\n function setPointerLockAllowed(allowed: boolean): void {\n gameGate = allowed;\n if (!allowed) {\n // W3C path: exit pointer-lock if currently locked on this canvas.\n if (typeof doc.exitPointerLock === 'function' && doc.pointerLockElement === canvas) {\n doc.exitPointerLock();\n }\n // Provider path: call exitLock and clear providerLocked.\n releaseProviderLock();\n }\n }\n\n function clear(): void {\n heldKeys.clear();\n upEdges.clear();\n pressedKeys.clear();\n heldCodes.clear();\n upCodeEdges.clear();\n pressedCodes.clear();\n pointerMap.clear();\n phaseQueue.length = 0;\n prevGamepadFrame.clear();\n vjBindState.clear();\n recognizerState = createRecognizerState();\n buttons[0] = false;\n buttons[1] = false;\n buttons[2] = false;\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n mvx = 0;\n mvy = 0;\n wheelAccum = 0;\n if (typeof doc?.exitPointerLock === 'function' && doc.pointerLockElement === canvas) {\n doc.exitPointerLock();\n }\n // `pointerlockchange` is asynchronous. The boundary must nevertheless\n // publish an unlocked frame immediately after revocation.\n w3cLocked = false;\n releaseProviderLock();\n }\n\n function detach(): void {\n if (detached) return;\n detached = true;\n safeRemove(win, 'keydown', onKeyDown as EventListener);\n safeRemove(win, 'keyup', onKeyUp as EventListener);\n safeRemove(win, 'blur', onBlur as EventListener);\n safeRemove(canvas, 'pointerdown', onPointerDown as EventListener);\n safeRemove(canvas, 'pointerup', onPointerUp as EventListener);\n safeRemove(canvas, 'pointermove', onPointerMove as EventListener);\n safeRemove(canvas, 'pointercancel', onPointerCancel as EventListener);\n safeRemove(canvas, 'wheel', onWheel as EventListener);\n safeRemove(doc, 'visibilitychange', onVisibilityChange as EventListener);\n safeRemove(doc, 'pointerlockchange', onPointerLockChange as EventListener);\n safeRemove(doc, 'pointerlockerror', onPointerLockError as EventListener);\n safeRemove(canvas, 'click', onCanvasClick as EventListener);\n clear();\n // D-5: restore original touch-action value.\n if (canvas.style && _prevTouchAction !== undefined) {\n canvas.style.touchAction = _prevTouchAction;\n }\n }\n\n const backend: InputBackend = { sample, clear, detach, setPointerLockAllowed };\n\n // Returned callable doubles as the InputBackend (detach + sample). AI\n // users see one symbol with both shapes, mirroring the\n // produces-detach-and-protocol convention of `effect`-style libraries.\n const handle = Object.assign(detach, { backend });\n return handle;\n}\n","// input-snapshot.ts -- frozen frame-start input snapshot Resource for\n// forgeax-engine. Multi-device surface (keyboard + mouse + gamepad + pointer +\n// virtualAxis) — each cluster is a frozen reader on the per-frame Sample.\n//\n// charter awareness:\n// F1 single-entry indexability -- barrel exports all types; IDE autocomplete\n// reaches the full surface from one import\n// F2 minimal surface -- each device cluster exposes only its natural\n// readpoints; no phantom methods or modal parameters\n// P3 explicit failure -- no thrown errors from accessor methods; absent\n// keys / pre-start state / disconnected slots / unsupported devices\n// all report `false` / `0` / zero-vector (the empty signal IS the\n// signal). `mouse.button(i)` / `gamepad.button(b)` parameters are\n// literal unions so out-of-range indices are TS compile errors rather\n// than runtime bounds-clamps.\n// P4 consistent abstraction -- the snapshot hides the producer\n// (browser listener wiring + gamepad polling) entirely; consumers read\n// via the `InputSnapshot` Resource regardless of backend\n// P5 producer/consumer split -- the InputBackend protocol decouples\n// the producer from the snapshot; `frame-start-scan-system.ts` is the\n// bridge that calls `backend.sample()` and writes the Resource\n\nimport type { ActionConfig, ActionState, GetVectorOptions } from './action-state';\nimport { getAxis, getVector } from './action-state';\nimport type { GestureEvent, GestureState } from './gesture-recognizer';\nimport { IDENTITY_GESTURE } from './gesture-recognizer';\n\n// D-5 / AC-19: pointerType is narrowed from string to a 3-literal union.\n// The W3C Pointer Events spec allows '' when the device type cannot be\n// detected; coercion maps '' to 'mouse' at the producer, so the snapshot\n// only ever sees one of these three canonical values.\nexport type PointerType = 'mouse' | 'pen' | 'touch';\n\n/** Standard-layout gamepad button index (0-16 per W3C Gamepad spec). */\nexport type GamepadButtonIndex =\n | 0\n | 1\n | 2\n | 3\n | 4\n | 5\n | 6\n | 7\n | 8\n | 9\n | 10\n | 11\n | 12\n | 13\n | 14\n | 15\n | 16;\n\n/** Standard-layout gamepad axis index (0-3 per W3C Gamepad spec). */\nexport type GamepadAxisIndex = 0 | 1 | 2 | 3;\n\n/** W3C MouseEvent.button index (0=primary, 1=auxiliary, 2=secondary). */\nexport type MouseButtonIndex = 0 | 1 | 2;\n\n/** Per-slot gamepad frame data produced by `sample()`. */\nexport interface GamepadSlotSample {\n readonly index: number;\n /**\n * True when the browser reports a standard mapping OR the SDL controller\n * DB has normalized a non-standard layout at the acquisition layer (M3\n * D-1 redefinition). The Feat1 meaning (\"browser-reported standard\n * mapping only\") is widened here: a non-standard pad whose GUID matches\n * gamecontrollerdb.txt is re-projected onto the standard layout and\n * reported as standardMapping=true, so bindings and direct reads see a\n * uniform standard button/axis space. A non-standard pad with no DB match\n * (or before the DB has loaded) keeps standardMapping=false + empty\n * readpoints (graceful degradation).\n */\n readonly standardMapping: boolean;\n readonly pressed: ReadonlySet<number>;\n readonly justPressed: ReadonlySet<number>;\n readonly justReleased: ReadonlySet<number>;\n readonly buttonValues: ReadonlyMap<number, number>;\n readonly axes: readonly [number, number, number, number];\n}\n\n/** Per-pointer live state (active contacts tracked by pointerId).\n *\n * D-5 / E-10: `pointerType` is a 3-literal union. `'mouse'` is the default\n * placeholder for inactive pointers — when `active=false`, `pointerType` is\n * always `'mouse'`. The semantic \"no pointer\" is carried by the `active`\n * field, never by a sentinel string value.\n */\nexport interface PointerSample {\n readonly pointerId: number;\n readonly x: number;\n readonly y: number;\n readonly pressure: number;\n readonly pointerType: PointerType;\n readonly active: boolean;\n readonly delta: { readonly x: number; readonly y: number };\n}\n\n/** Per-frame phase event (down/move/up/cancel queue, one-frame lifecycle). */\nexport interface PointerPhaseEvent {\n readonly pointerId: number;\n readonly phase: 'down' | 'move' | 'up' | 'cancel';\n readonly x: number;\n readonly y: number;\n readonly pressure: number;\n readonly pointerType: PointerType;\n}\n\n/** Per-frame virtual axis output (named joystick derived from pointer input). */\nexport interface VirtualAxisSample {\n readonly name: string;\n readonly x: number;\n readonly y: number;\n}\n\n/**\n * Configuration for an on-screen virtual joystick (M3). Consumed by\n * attachBrowserInputBackend and passed through to deriveVirtualAxes.\n *\n * Fixed mode: origin is config.anchor (or region center if anchor omitted).\n * Floating mode: origin is the first pointerdown position within the region.\n */\nexport interface VirtualJoystickConfig {\n readonly name: string;\n readonly mode: 'fixed' | 'floating';\n /** Canvas-pixel region where touches are eligible to bind this joystick. */\n readonly region: {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n };\n /** Fixed-mode origin anchor. Defaults to region center when omitted. */\n readonly anchor?: { readonly x: number; readonly y: number } | undefined;\n /** Max drag radius in canvas pixels. Vector is clamped then normalized to radius. */\n readonly radius: number;\n /** Normalized deadzone (0..1). |vec| < deadzone → zero vector output. */\n readonly deadzone: number;\n}\n\n/** Capability snapshot (frozen at backend attach time). */\nexport interface Capabilities {\n readonly gamepad: boolean;\n readonly pointer: boolean;\n}\n\n/**\n * Frozen value-shape view exposed to user systems via the `InputSnapshot`\n * Resource. The methods are pure reads; calling them does not mutate any\n * accumulator (charter P3 -- no observable side effects from the accessor\n * surface). A fresh `InputSnapshot` instance is constructed by the\n * frame-start scan system once per `world.update()` and replaces the\n * previous Resource value.\n */\nexport interface InputSnapshot {\n /** Keyboard view (held state plus frame edges). */\n readonly keyboard: {\n /**\n * `true` while `key` is currently held. `key` matches the value the\n * backend records (KeyboardEvent.key for the browser backend). When\n * the key is not in the held set, returns `false` -- never throws\n * (charter P3: empty signal is the signal).\n */\n down(key: string): boolean;\n /** `true` for the first frame in which `key` becomes held. */\n justPressed(key: string): boolean;\n /**\n * `true` for one frame after the key was released (the up-edge). The\n * edge collapses on the following `world.update()`. `key` not in the\n * up-edge set returns `false`.\n */\n up(key: string): boolean;\n /** Code-key equivalent of `down`, using KeyboardEvent.code identity. */\n downCode(code: string): boolean;\n /** Code-key equivalent of `justPressed`. */\n justPressedCode(code: string): boolean;\n /** Code-key equivalent of `up`. */\n upCode(code: string): boolean;\n };\n /** Mouse view (charter F2 minimal surface: position + movementDelta + button + wheelDelta). */\n readonly mouse: {\n /**\n * Latest canvas-pixel cursor position. This is available during hover;\n * it does not require a button press or pointer capture. The position is\n * frozen with the rest of the frame-start snapshot.\n */\n readonly position: { readonly x: number; readonly y: number } | undefined;\n /**\n * PointerLock-style accumulated movement since the previous frame.\n * Value is frozen at frame-start; reading it does not clear the\n * accumulator. The next `world.update()` produces a fresh delta\n * (zero if no movement events arrived).\n */\n readonly movementDelta: { readonly x: number; readonly y: number };\n /**\n * Merged pointer-lock state: true when either W3C pointer-lock\n * (pointerLockElement === this backend's canvas) OR the lockProvider\n * path has engaged. Consumers read this to decide whether to consume\n * movementDelta for look/camera rotation. Required field, alongside\n * movementDelta -- both facts sit at the same attribute path for\n * single-point indexing (charter F1).\n */\n readonly pointerLocked: boolean;\n /**\n * `true` while the W3C MouseEvent.button slot `i` is held. `i` is\n * narrowed to the literal `0 | 1 | 2` so out-of-range indices are\n * rejected at compile time (charter P3 explicit failure: TS literal\n * narrowing replaces a runtime bounds-clamp).\n *\n * - 0 -- primary button (left)\n * - 1 -- auxiliary button (middle)\n * - 2 -- secondary button (right)\n */\n button(i: MouseButtonIndex): boolean;\n /** `true` for the first frame in which button `i` becomes held. */\n justPressed(i: MouseButtonIndex): boolean;\n /** `true` for the frame in which button `i` is released. */\n justReleased(i: MouseButtonIndex): boolean;\n /**\n * Discrete wheel notches accumulated since the previous frame.\n * Plan-strategy D-5 sign-discrete: each `WheelEvent` contributes\n * `Math.sign(event.deltaY)` to the per-frame accumulator regardless\n * of `deltaMode` (PIXEL / LINE / PAGE all collapse). Sign convention\n * follows W3C `WheelEvent.deltaY`: positive = scroll down / away\n * from user, negative = scroll up / toward user.\n *\n * Value is frozen at frame-start; reading it does not clear the\n * accumulator. The next `world.update()` produces a fresh delta\n * (zero when no wheel events arrived).\n *\n * Trade-off (plan-strategy R-7): trackpad high-resolution wheel\n * events collapse to one notch per event, losing sub-notch fidelity.\n * AI users who need analog magnitude must opt in via a future\n * unitful surface (OOS-7 ScrollSnapshot is the deferred shape).\n */\n readonly wheelDelta: number;\n };\n /**\n * Per-slot gamepad reader. Returns a reader object for the gamepad at\n * slot `i` regardless of connection state: disconnected or out-of-range\n * slots report `connected=false`, all button/axis readpoints return\n * `false`/`0` (charter P3 empty signal). The slot index is intentionally\n * not narrowed — platform slot counts vary, and bounds handling is a\n * runtime concern.\n */\n gamepad(i: number): {\n readonly connected: boolean;\n readonly standardMapping: boolean;\n button(b: GamepadButtonIndex): boolean;\n buttonValue(b: GamepadButtonIndex): number;\n justPressed(b: GamepadButtonIndex): boolean;\n justReleased(b: GamepadButtonIndex): boolean;\n axis(a: GamepadAxisIndex): number;\n };\n /**\n * Frozen capabilities snapshot, determined once at backend attach time.\n * Consumers use this to decide whether gamepad/pointer readpoints will\n * ever carry live data, without probing per-frame.\n */\n readonly capabilities: Capabilities;\n /**\n * Per-pointerId reader. Returns `{ active: true/false, x, y, pressure,\n * pointerType, delta }` for the given pointerId. Unknown pointerIds\n * return `{ active: false, ... }` without throwing.\n */\n pointer(\n id: number,\n ): PointerSample & { readonly delta: { readonly x: number; readonly y: number } };\n /**\n * Named virtual axis reader (joystick-derived). Returns `{ x, y }` for\n * the given joystick config name. Unknown names return the zero-vector\n * `{ x: 0, y: 0 }` without throwing.\n */\n virtualAxis(name: string): { readonly x: number; readonly y: number };\n /**\n * Per-frame phase event queue (down/move/up/cancel). One-frame\n * lifecycle; drained by `sample()` at frame end. Empty array when no\n * pointer events occurred this frame.\n */\n readonly pointerEvents: readonly PointerPhaseEvent[];\n /**\n * Continuous gesture values (pinch scale + rotation angle) for the\n * active dual-finger gesture. Returns the identity empty signal\n * (`pinchScale=1`, `rotationAngle=0`) when no gesture is active (AC-12);\n * an active gesture retains its value on idle frames (fingers held still\n * are not a gesture end). AC-11: reading the same frame's snapshot twice\n * returns the identical object.\n */\n readonly gesture: GestureState;\n /**\n * Per-frame gesture lifecycle + instantaneous event queue (begin / end /\n * cancel / swipe / long-press / double-tap). One-frame lifecycle, same\n * pattern as `pointerEvents` (charter P4). Empty array when no gesture\n * activity occurred this frame. Closed discriminant union (AC-13): a\n * consumer exhaustively switches on `kind` without a default branch.\n */\n readonly gestureEvents: readonly GestureEvent[];\n /**\n * Action mapping readpoint. Returns a frozen reader for the named action.\n * When `name` is registered in the InputMap, `isPressed()` / `justPressed()`\n * / `justReleased()` / `strength` reflect the derived state. Unregistered\n * action names return empty signal (false / 0 / false / false / 0) without\n * throwing (charter P3: empty signal is the signal). AC-11: calling\n * action() multiple times in the same frame returns identical values.\n */\n action(name: string): {\n readonly isPressed: () => boolean;\n readonly justPressed: () => boolean;\n readonly justReleased: () => boolean;\n readonly strength: number;\n };\n /**\n * Compose a 1D axis value from two opposing actions.\n *\n * Returns `strength(pos) - strength(neg)`, range [-1, 1].\n * Both registered: combines normally. One unregistered: contributes 0\n * (E-3). Same action for both ends: always 0 (E-12).\n *\n * @param neg - Action name for the negative direction (e.g. 'moveLeft').\n * @param pos - Action name for the positive direction (e.g. 'moveRight').\n */\n getAxis(neg: string, pos: string): number;\n /**\n * Compose a 2D vector from four directional actions with a single radial\n * deadzone (Godot input.cpp three-branch formula). Uses `raw` (not\n * `strength`) to avoid per-axis deadzone stacking into a square deadzone\n * (AC-06).\n *\n * @param negX - Action name for negative X (e.g. 'moveLeft').\n * @param posX - Action name for positive X (e.g. 'moveRight').\n * @param negY - Action name for negative Y (e.g. 'moveUp').\n * @param posY - Action name for positive Y (e.g. 'moveDown').\n * @param opts - Optional override (deadzone).\n */\n getVector(\n negX: string,\n posX: string,\n negY: string,\n posY: string,\n opts?: GetVectorOptions,\n ): { readonly x: number; readonly y: number };\n}\n\n/**\n * Backend protocol consumed by the frame-start scan system. The browser\n * implementation (`browser-backend.ts`) is the production producer;\n * tests inject fakes that emit synthetic samples.\n */\nexport interface InputBackend {\n /**\n * Produce one frame's worth of input data and reset the per-frame\n * accumulators (movement delta + edge sets). Held-key state and\n * held-button state survive across calls. Browser producers latch edge\n * transitions when events arrive, so a down+up sequence between two scans\n * remains observable instead of being lost to the held-state projection.\n *\n * Contract notes:\n * - `downKeys` is the held-key set as of the call (held across frames)\n * - `upKeys` is the release-edge set since the previous sample (cleared\n * after the call so the edge appears in exactly one frame)\n * - `buttons` is the held-button slot tuple `[b0, b1, b2]`\n * - `movementX` / `movementY` are the accumulated PointerLock delta\n * since the previous sample (cleared after the call)\n * - `focused` mirrors `document.hasFocus()` so the scan system can\n * suppress spurious up-edges across alt-tab transitions\n */\n sample(): InputBackendSample;\n /**\n * Command-set game gate for pointer-lock. When set to `false`, the\n * backend will not request pointer-lock on click AND will immediately\n * release any currently active lock (W3C path: `exitPointerLock`;\n * provider path: `exitLock()`). When `true` (default), pointer-lock\n * can be requested through the normal gate logic.\n *\n * Optional -- backends without pointer-lock support omit this method.\n */\n setPointerLockAllowed?(allowed: boolean): void;\n /**\n * Atomically discard acquired state without detaching listeners. A host calls\n * this when it revokes a control lease so held keys/buttons, contacts, frame\n * edges, deltas and pointer lock cannot bleed into a later consumer. Optional\n * keeps synthetic backends source-compatible.\n */\n clear?(): void;\n /** Detach DOM listeners; called when the engine shuts down. */\n detach(): void;\n}\n\n/** Snapshot value returned by `InputBackend.sample()` (POD). */\nexport interface InputBackendSample {\n readonly downKeys: ReadonlySet<string>;\n readonly upKeys: ReadonlySet<string>;\n /** Physical code identity (KeyboardEvent.code), when the producer has it. */\n readonly downCodes?: ReadonlySet<string>;\n /** One-frame physical code release edges, when the producer has them. */\n readonly upCodes?: ReadonlySet<string>;\n /** Logical key press edges latched since the previous frame-start scan. */\n readonly pressedKeys?: ReadonlySet<string>;\n /** Physical code press edges latched since the previous frame-start scan. */\n readonly pressedCodes?: ReadonlySet<string>;\n readonly buttons: readonly [boolean, boolean, boolean];\n /** Mouse button press edges latched since the previous frame-start scan. */\n readonly pressedButtons?: readonly [boolean, boolean, boolean];\n /** Mouse button release edges latched since the previous frame-start scan. */\n readonly releasedButtons?: readonly [boolean, boolean, boolean];\n readonly movementX: number;\n readonly movementY: number;\n /** Latest canvas-pixel mouse position; absent for non-pointer backends. */\n readonly mouseX?: number;\n readonly mouseY?: number;\n /**\n * Sign-discrete wheel notch accumulator since the previous sample\n * (plan-strategy D-5). Browser backend writes `Math.sign(deltaY)` per\n * `WheelEvent`; sample() drains the value and resets the producer\n * accumulator (mirrors movementX/Y semantics).\n */\n readonly wheelDelta: number;\n /** True for the first sample after blur/hidden state reset. */\n readonly focusReset?: boolean;\n readonly focused: boolean;\n /** M1+ gamepad per-slot frame data (optional — absent when backend lacks gamepad support). */\n readonly gamepads?: readonly GamepadSlotSample[];\n /** M1+ frozen capability snapshot (optional — absent for pre-M1 backends). */\n readonly capabilities?: Capabilities;\n /** M2+ active pointer contacts (optional — absent for keyboard-only backends). */\n readonly pointers?: readonly PointerSample[];\n /** M2+ per-frame phase event queue (optional — absent when no pointer events occurred). */\n readonly pointerEvents?: readonly PointerPhaseEvent[];\n /** M3+ virtual joystick axis outputs (optional — absent when no virtual joysticks configured). */\n readonly virtualAxes?: readonly VirtualAxisSample[];\n /** M5+ continuous gesture values (optional — absent when no gesture is active). */\n readonly gestures?: GestureState;\n /** M5+ per-frame gesture event queue (optional — absent when no gesture activity occurred). */\n readonly gestureEvents?: readonly GestureEvent[];\n /**\n * Merged pointer-lock state: true when either W3C pointer-lock is active\n * (pointerLockElement === this backend's canvas) OR the lockProvider path\n * has engaged (requestLock() was called and not yet released). Required\n * field -- always present, defaults to false when no lock is active.\n */\n readonly pointerLocked: boolean;\n}\n\n/** Build the neutral backend sample used before or outside an active consumer. */\nexport function createEmptyInputBackendSample(): InputBackendSample {\n return {\n downKeys: new Set<string>(),\n upKeys: new Set<string>(),\n buttons: [false, false, false],\n movementX: 0,\n movementY: 0,\n wheelDelta: 0,\n focused: true,\n pointerLocked: false,\n };\n}\n\n/**\n * Build an `InputSnapshot` from a backend sample. The returned object is\n * frozen on construction: `down/up/button` are bound to the closed-over\n * sets, and `movementDelta` is a frozen literal. Subsequent backend\n * activity does not bleed into the snapshot.\n */\nfunction emptyGamepadReader(): ReturnType<InputSnapshot['gamepad']> {\n return Object.freeze({\n connected: false,\n standardMapping: false,\n button(_b: GamepadButtonIndex): boolean {\n return false;\n },\n buttonValue(_b: GamepadButtonIndex): number {\n return 0;\n },\n justPressed(_b: GamepadButtonIndex): boolean {\n return false;\n },\n justReleased(_b: GamepadButtonIndex): boolean {\n return false;\n },\n axis(_a: GamepadAxisIndex): number {\n return 0;\n },\n });\n}\n\nfunction buildGamepadReader(slot: GamepadSlotSample): ReturnType<InputSnapshot['gamepad']> {\n if (!slot.standardMapping) {\n // AC-04: non-standard layout reports connected=true +\n // standardMapping=false + all readpoints empty signal.\n return Object.freeze({\n connected: true,\n standardMapping: false,\n button: emptyGamepadReader().button,\n buttonValue: emptyGamepadReader().buttonValue,\n justPressed: emptyGamepadReader().justPressed,\n justReleased: emptyGamepadReader().justReleased,\n axis: emptyGamepadReader().axis,\n });\n }\n return Object.freeze({\n connected: true,\n standardMapping: true,\n button(b: GamepadButtonIndex): boolean {\n return slot.pressed.has(b);\n },\n buttonValue(b: GamepadButtonIndex): number {\n return slot.buttonValues.get(b) ?? 0;\n },\n justPressed(b: GamepadButtonIndex): boolean {\n return slot.justPressed.has(b);\n },\n justReleased(b: GamepadButtonIndex): boolean {\n return slot.justReleased.has(b);\n },\n axis(a: GamepadAxisIndex): number {\n return slot.axes[a];\n },\n });\n}\n\n/**\n * Build an `InputSnapshot` from a backend sample.\n *\n * @param sample - One frame's raw input backend sample (POD).\n * @param actionStates - Optional per-frame derived action states from\n * deriveActionStates(). When provided, snap.action(name) returns mapped\n * values; when absent or empty, all action readpoints return empty signal\n * (charter P3: false/0, never throws). AC-11: actionStates is frozen into\n * the snapshot so same-frame re-reads return identical values.\n */\nexport function snapshotFromSample(\n sample: InputBackendSample,\n actionStates?: readonly ActionState[],\n inputMap?: readonly ActionConfig[],\n previousSnapshot?: InputSnapshot,\n): InputSnapshot {\n // structuralCopy: copying into local sets isolates the snapshot from\n // any later backend mutation (the browser backend reuses its internal\n // Set across frames). architecture-principles #2 derive: a Snapshot is\n // a derived view of the producer's state at one instant.\n const heldKeys = new Set<string>(sample.downKeys);\n const upEdges = new Set<string>(sample.upKeys);\n // Do not capture previousSnapshot in a callback: V8 can share that\n // context with the returned readers and retain the entire frame history.\n const justPressedKeys = new Set<string>(sample.pressedKeys);\n if (sample.pressedKeys === undefined) {\n for (const key of heldKeys) {\n if (!previousSnapshot?.keyboard.down(key)) justPressedKeys.add(key);\n }\n }\n const heldCodes = new Set<string>(sample.downCodes ?? []);\n const upCodeEdges = new Set<string>(sample.upCodes ?? []);\n const justPressedCodes = new Set<string>(sample.pressedCodes);\n if (sample.pressedCodes === undefined) {\n for (const code of heldCodes) {\n if (!previousSnapshot?.keyboard.downCode(code)) justPressedCodes.add(code);\n }\n }\n const buttons: readonly [boolean, boolean, boolean] = [\n sample.buttons[0],\n sample.buttons[1],\n sample.buttons[2],\n ];\n const justPressedButtons: readonly [boolean, boolean, boolean] =\n sample.pressedButtons === undefined\n ? [\n buttons[0] && (previousSnapshot === undefined || !previousSnapshot.mouse.button(0)),\n buttons[1] && (previousSnapshot === undefined || !previousSnapshot.mouse.button(1)),\n buttons[2] && (previousSnapshot === undefined || !previousSnapshot.mouse.button(2)),\n ]\n : [sample.pressedButtons[0], sample.pressedButtons[1], sample.pressedButtons[2]];\n const justReleasedButtons: readonly [boolean, boolean, boolean] =\n sample.releasedButtons === undefined\n ? [\n sample.focusReset !== true && previousSnapshot?.mouse.button(0) === true && !buttons[0],\n sample.focusReset !== true && previousSnapshot?.mouse.button(1) === true && !buttons[1],\n sample.focusReset !== true && previousSnapshot?.mouse.button(2) === true && !buttons[2],\n ]\n : [sample.releasedButtons[0], sample.releasedButtons[1], sample.releasedButtons[2]];\n const movementDelta = Object.freeze({ x: sample.movementX, y: sample.movementY });\n const mousePosition =\n sample.mouseX === undefined || sample.mouseY === undefined\n ? undefined\n : Object.freeze({ x: sample.mouseX, y: sample.mouseY });\n const wheelDelta = sample.wheelDelta;\n\n // D-9: use `??` empty-signal defaults for all new optional fields.\n const gamepadSlots: readonly GamepadSlotSample[] = sample.gamepads ?? [];\n const caps: Capabilities =\n sample.capabilities ?? Object.freeze({ gamepad: false, pointer: false });\n const pointerEvts: readonly PointerPhaseEvent[] = sample.pointerEvents ?? [];\n // D-4 / AC-12: no active gesture -> identity empty signal; gesture events\n // default to an empty one-frame queue (mirrors pointerEvents).\n const gesture: GestureState = sample.gestures ?? IDENTITY_GESTURE;\n const gestureEvts: readonly GestureEvent[] = sample.gestureEvents ?? [];\n // virtualAxes: consumed by M3 virtualAxis reader; stored as local for\n // the snapshot closure below.\n const _virtualAxes: readonly VirtualAxisSample[] = sample.virtualAxes ?? [];\n\n const virtualAxesMap = new Map<string, VirtualAxisSample>();\n for (const va of _virtualAxes) {\n virtualAxesMap.set(va.name, va);\n }\n\n // Build index→slot map so gamepad(i) looks up by slot.index, not array position.\n // The browser getGamepads() returns null-padded arrays where position IS the\n // index, but the diffGamepadFrame output is a sparse list keyed by .index.\n const gamepadSlotMap = new Map<number, GamepadSlotSample>();\n for (const slot of gamepadSlots) {\n gamepadSlotMap.set(slot.index, slot);\n }\n\n // Build action lookup map for snap.action(name) readpoint.\n const actionMap = new Map<string, ActionState>();\n if (actionStates) {\n for (const a of actionStates) {\n actionMap.set(a.action, a);\n }\n }\n\n function emptyActionReader(): ReturnType<InputSnapshot['action']> {\n return Object.freeze({\n isPressed: () => false,\n justPressed: () => false,\n justReleased: () => false,\n strength: 0,\n });\n }\n\n const snapshot: InputSnapshot = {\n keyboard: {\n down(key) {\n return heldKeys.has(key);\n },\n justPressed(key) {\n return justPressedKeys.has(key);\n },\n up(key) {\n return upEdges.has(key);\n },\n downCode(code) {\n return heldCodes.has(code);\n },\n justPressedCode(code) {\n return justPressedCodes.has(code);\n },\n upCode(code) {\n return upCodeEdges.has(code);\n },\n },\n mouse: {\n position: mousePosition,\n movementDelta,\n pointerLocked: sample.pointerLocked,\n button(i) {\n // i is narrowed to 0 | 1 | 2 by the type system; the runtime\n // index is therefore guaranteed to land in `buttons` (charter P3\n // -- no defensive fallback necessary because the type narrows the\n // input domain to the legal slots).\n return buttons[i] === true;\n },\n justPressed(i) {\n return justPressedButtons[i] === true;\n },\n justReleased(i) {\n return justReleasedButtons[i] === true;\n },\n wheelDelta,\n },\n gamepad(i) {\n const slot = gamepadSlotMap.get(i);\n if (!slot) return emptyGamepadReader();\n return buildGamepadReader(slot);\n },\n capabilities: caps,\n pointer(id) {\n const entry = (sample.pointers ?? []).find((p) => p.pointerId === id);\n if (!entry) {\n return Object.freeze({\n active: false,\n pointerId: -1,\n x: 0,\n y: 0,\n pressure: 0,\n pointerType: 'mouse' as PointerType,\n delta: Object.freeze({ x: 0, y: 0 }),\n });\n }\n return Object.freeze({\n ...entry,\n delta: Object.freeze({ x: entry.delta.x, y: entry.delta.y }),\n });\n },\n virtualAxis(name) {\n const va = virtualAxesMap.get(name);\n if (!va) return Object.freeze({ x: 0, y: 0 });\n return Object.freeze({ x: va.x, y: va.y });\n },\n action(name) {\n const s = actionMap.get(name);\n if (!s) return emptyActionReader();\n return Object.freeze({\n isPressed: () => s.pressed,\n justPressed: () => s.justPressed,\n justReleased: () => s.justReleased,\n strength: s.strength,\n });\n },\n getAxis(neg, pos) {\n if (!actionStates || !inputMap) return 0;\n return getAxis(inputMap, actionStates, neg, pos);\n },\n getVector(negX, posX, negY, posY, opts) {\n if (!actionStates || !inputMap) return { x: 0, y: 0 };\n return getVector(inputMap, actionStates, negX, posX, negY, posY, opts);\n },\n pointerEvents: pointerEvts,\n gesture,\n gestureEvents: gestureEvts,\n };\n (snapshot as unknown as Record<string, unknown>)._actionStates = actionStates;\n (snapshot as unknown as Record<string, unknown>)._inputMap = inputMap;\n return Object.freeze(snapshot);\n}\n\n/**\n * @internal Read previously derived action states from a snapshot for edge diff.\n * Used by the frame-start scan system (D-6: prev snapshot = edge baseline).\n */\nexport function readActionStatesForEdgeDiff(\n snap: InputSnapshot,\n): readonly ActionState[] | undefined {\n return (snap as unknown as { _actionStates?: readonly ActionState[] })._actionStates;\n}\n\n/**\n * Construct an empty snapshot for the pre-start window\n * (`engine.run()` has not yet attached a backend). Returns the full\n * multi-device shape as `snapshotFromSample`, with every accessor\n * returning `false` / `0` / zero-vector. AI users can put this into the\n * Resource store to satisfy `world.getResource('InputSnapshot')` calls\n * in fixtures or unit tests (charter P3: empty signal is the signal).\n * The underlying 7-field POD sample contract is unchanged (D-9).\n */\nexport function createInputSnapshot(): InputSnapshot {\n return snapshotFromSample(createEmptyInputBackendSample());\n}\n\n/** Stable Resource key for `world.insertResource` / `world.getResource`. */\nexport const INPUT_SNAPSHOT_RESOURCE_KEY = 'InputSnapshot';\n","// @forgeax/engine-input -- exclusive host-owned canvas input boundary.\n//\n// A physical canvas has one DOM acquisition backend. Hosts with two worlds (for\n// example editor + transient Play) route that one producer through these two\n// InputBackend views. This is exclusive ownership, deliberately separate from\n// synthetic/replay input composition.\n\nimport {\n createEmptyInputBackendSample,\n type InputBackend,\n type InputBackendSample,\n} from './input-snapshot';\nimport { isUiOwnedEvent } from './ui-ownership';\n\nexport interface CanvasInputBoundary {\n readonly editor: InputBackend;\n readonly game: InputBackend;\n owner(): 'editor' | 'game';\n grantGame(): void;\n revokeGame(): void;\n /** Clear the active consumer when an event originated in the host UI. */\n handleUiEvent(event: Event, host: Node): boolean;\n detach(): void;\n}\n\ntype CanvasInputOwner = ReturnType<CanvasInputBoundary['owner']>;\n\nexport function createCanvasInputBoundary(source: InputBackend): CanvasInputBoundary {\n let active: CanvasInputOwner = 'editor';\n let gamePointerLockAllowed = false;\n source.setPointerLockAllowed?.(false);\n\n const empty = (): InputBackendSample => createEmptyInputBackendSample();\n\n const clear = (): void => {\n source.clear?.();\n source.setPointerLockAllowed?.(false);\n };\n\n const routed = (consumer: CanvasInputOwner): InputBackend => ({\n sample: () => (consumer === active ? source.sample() : empty()),\n setPointerLockAllowed: (allowed) => {\n if (consumer === 'game') {\n gamePointerLockAllowed = allowed;\n source.setPointerLockAllowed?.(active === 'game' && allowed);\n } else {\n source.setPointerLockAllowed?.(false);\n }\n },\n clear: () => {\n if (consumer === active) clear();\n },\n detach: () => source.detach(),\n });\n\n const grantGame = (): void => {\n if (active === 'game') return;\n clear();\n active = 'game';\n source.setPointerLockAllowed?.(gamePointerLockAllowed);\n };\n\n const revokeGame = (): void => {\n clear();\n active = 'editor';\n };\n\n return {\n editor: routed('editor'),\n game: routed('game'),\n owner: () => active,\n grantGame,\n revokeGame,\n handleUiEvent: (event, host) => {\n if (!isUiOwnedEvent(event, host)) return false;\n clear();\n return true;\n },\n detach: () => source.detach(),\n };\n}\n","// @forgeax/engine-input -- CompositeInputBackend (synthetic-input decorator).\n//\n// PROBLEM. The scan system reads ONE `InputBackend` from `INPUT_BACKEND_KEY`\n// each frame. An AI / record-replay harness needs to feed synthetic input into\n// that same slot WITHOUT evicting the human's browser backend -- because a human\n// may take over at any instant (PIE two-world model + charter §8 human-as-final-\n// authority). Overwriting the resource locks the human out; wrapping it does not.\n//\n// SOLUTION. `makeCompositeBackend(inner)` returns an `InputBackend` that HOLDS\n// the human backend as `inner` and layers a programmatic injection surface\n// (`press` / `release` / `setButton` / `addMovement` / `addWheel`) on top. The\n// scan system stays variant-agnostic: it still calls `sample()` on one backend\n// (Depend-on-Abstractions -- the consumer never learns a composite exists).\n//\n// SIDE-EFFECT CONTRACT. `inner.sample()` DRAINS its per-frame accumulators\n// (up-edges, movement delta, wheel notches) on read, so the composite calls it\n// EXACTLY ONCE per `sample()` and drains its OWN injected accumulators in the\n// same pass. Field-by-field merge honoring each field's lifecycle:\n//\n// downKeys held across frames -> UNION(inner, injected.held)\n// upKeys lives one frame -> UNION; injected up-edge set drained here\n// buttons held tuple -> OR per slot\n// movementX/Y, wheelDelta -> SUM; injected side reset to 0 here\n// focused gates up-edge suppress -> inner.focused || injectionActive\n// pointerLocked -> inner (AI must not fabricate a lock)\n// optional (pointers/gamepads/...) -> pass through from inner untouched\n//\n// YIELD-TO-HUMAN (default on). A human-held key on `inner` suppresses only the\n// injected state for that SAME key in that frame. Other AI keys continue, so a\n// human can take a key without silencing unrelated synthetic input. This is the\n// structural realization of \"human wins\" without a global takeover policy.\n\nimport type { InputBackend, InputBackendSample } from './input-snapshot';\n\n/** Options controlling the composite merge policy. */\nexport interface CompositeBackendOptions {\n /**\n * When `true` (default), a key held on the inner (human) backend suppresses\n * injected state only for that same key in that frame. Set `false` for\n * record/replay or AI-solo scenarios where both sources should coexist even\n * on key overlap.\n */\n readonly yieldToHuman?: boolean;\n}\n\n/**\n * A composite backend: an `InputBackend` (drop-in for `INPUT_BACKEND_KEY`) plus\n * a programmatic injection surface. All injection is additive over the wrapped\n * human backend.\n */\nexport interface CompositeInputBackend extends InputBackend {\n /** Hold `key` down (mirrors a keydown). Idempotent. */\n press(key: string): void;\n /** Release `key` (mirrors a keyup); emits a one-frame up-edge on next sample. */\n release(key: string): void;\n /** Set an injected mouse-button slot (0/1/2) held-state. */\n setButton(slot: 0 | 1 | 2, down: boolean): void;\n /** Accumulate injected pointer-lock movement delta (drained on next sample). */\n addMovement(dx: number, dy: number): void;\n /** Accumulate injected wheel notches (drained on next sample). */\n addWheel(notches: number): void;\n /**\n * Drop all injected state and pending frame edges; currently-held keys/buttons\n * emit one clean release edge so a previously observed hold is closed.\n */\n clearInjected(): void;\n /** Open a fresh synthetic-input lease after a previous revoke boundary. */\n beginInjectedLease(): void;\n /** Revoke the current lease and fence later injections until reopened. */\n revokeInjectedLease(): void;\n /**\n * Create the one execution-scoped injection view. Creating a lease\n * invalidates every previously-created view; an invalid view remains a\n * no-op even after a later lease is opened.\n */\n createInjectedLease(): CompositeInputLease;\n /** Toggle the yield-to-human gate at runtime. */\n setYieldToHuman(yield_: boolean): void;\n}\n\n/**\n * Synthetic input exposed to one eval/execution. It deliberately has no\n * `beginInjectedLease` method: a script can release its own lease, but it\n * cannot reopen an old reference after the host has moved to another job.\n */\nexport interface CompositeInputLease extends InputBackend {\n press(key: string): void;\n release(key: string): void;\n setButton(slot: 0 | 1 | 2, down: boolean): void;\n addMovement(dx: number, dy: number): void;\n addWheel(notches: number): void;\n clearInjected(): void;\n revokeInjectedLease(): void;\n}\n\n// The public injection surface accepts either the logical KeyboardEvent.key\n// (`w`, ` `, `ArrowUp`) or the physical KeyboardEvent.code (`KeyW`, `Space`).\n// Keep both projections populated so code-first control drives games that read\n// either keyboard.down(...) or keyboard.downCode(...).\nconst CODE_TO_KEY: Readonly<Record<string, string>> = {\n Space: ' ',\n ShiftLeft: 'Shift',\n ShiftRight: 'Shift',\n ControlLeft: 'Control',\n ControlRight: 'Control',\n AltLeft: 'Alt',\n AltRight: 'Alt',\n MetaLeft: 'Meta',\n MetaRight: 'Meta',\n BracketLeft: '[',\n BracketRight: ']',\n Backslash: '\\\\',\n Semicolon: ';',\n Quote: \"'\",\n Comma: ',',\n Period: '.',\n Slash: '/',\n Minus: '-',\n Equal: '=',\n Backquote: '`',\n};\n\nfunction keyForCode(code: string): string | undefined {\n if (CODE_TO_KEY[code] !== undefined) return CODE_TO_KEY[code];\n if (/^Key[A-Z]$/.test(code)) return code.slice(3).toLowerCase();\n if (/^Digit[0-9]$/.test(code)) return code.slice(5);\n if (/^Numpad[0-9]$/.test(code)) return code.slice(6);\n if (/^F(?:[1-9]|1[0-2])$/.test(code)) return code;\n if (/^Arrow(?:Up|Down|Left|Right)$/.test(code)) return code;\n if (/^(?:Escape|Enter|Tab|Backspace|Delete|Home|End|PageUp|PageDown|Insert)$/.test(code))\n return code;\n return undefined;\n}\n\nfunction codeForKey(key: string): string | undefined {\n if (/^[a-zA-Z]$/.test(key)) return `Key${key.toUpperCase()}`;\n if (/^[0-9]$/.test(key)) return `Digit${key}`;\n if (key === ' ') return 'Space';\n if (\n /^(?:Arrow(?:Up|Down|Left|Right)|Escape|Enter|Tab|Backspace|Delete|Home|End|PageUp|PageDown|Insert)$/.test(\n key,\n )\n )\n return key;\n if (/^F(?:[1-9]|1[0-2])$/.test(key)) return key;\n const entry = Object.entries(CODE_TO_KEY).find(([, value]) => value === key);\n return entry?.[0];\n}\n\nfunction normalizeKey(value: string): { readonly key: string; readonly code: string | undefined } {\n const logical = keyForCode(value);\n return logical === undefined\n ? { key: value, code: codeForKey(value) }\n : { key: logical, code: value };\n}\n\nexport function makeCompositeBackend(\n inner: InputBackend,\n options?: CompositeBackendOptions,\n): CompositeInputBackend {\n let yieldToHuman = options?.yieldToHuman ?? true;\n let leaseRevoked = false;\n let leaseGeneration = 0;\n\n // Injected held-state (survives across frames).\n const heldKeys = new Set<string>();\n const heldCodes = new Set<string>();\n const buttons: [boolean, boolean, boolean] = [false, false, false];\n // Injected per-frame accumulators (drained on each sample()).\n const upEdges = new Set<string>();\n const upCodeEdges = new Set<string>();\n const pressedKeys = new Set<string>();\n const pressedCodes = new Set<string>();\n const pressedButtons: [boolean, boolean, boolean] = [false, false, false];\n const releasedButtons: [boolean, boolean, boolean] = [false, false, false];\n let mvx = 0;\n let mvy = 0;\n let wheel = 0;\n\n function injectionActive(): boolean {\n return (\n heldKeys.size > 0 ||\n heldCodes.size > 0 ||\n upEdges.size > 0 ||\n upCodeEdges.size > 0 ||\n pressedKeys.size > 0 ||\n pressedCodes.size > 0 ||\n buttons.some((b) => b) ||\n pressedButtons.some((b) => b) ||\n releasedButtons.some((b) => b)\n );\n }\n\n function sample(): InputBackendSample {\n // Call inner EXACTLY once -- it drains its own accumulators here.\n const base = inner.sample();\n\n // yield-to-human is PER-KEY: an injected key is suppressed only when the human\n // is holding the SAME key this frame. This is the minimal realization of\n // charter §8 (the human always wins a key they touch) WITHOUT the collateral of\n // a global gate — a human strafing D does not silence an AI holding W, so the\n // two genuinely coexist (that is the whole point of a composite; a caller who\n // wants \"human takes over everything\" can clearInjected() at the policy layer).\n // downKeys: union of human-held and injected-held, minus injected keys the human\n // is also pressing. A yielded injected release is likewise a no-op: emitting its\n // up-edge would incorrectly release the human-held key in the scan system.\n const downKeys = new Set(base.downKeys);\n const downCodes =\n base.downCodes === undefined && heldCodes.size === 0\n ? undefined\n : new Set(base.downCodes ?? []);\n for (const k of heldKeys) {\n const code = codeForKey(k);\n if (\n yieldToHuman &&\n (base.downKeys.has(k) || (code !== undefined && base.downCodes?.has(code) === true))\n )\n continue; // human owns this exact key\n downKeys.add(k);\n }\n for (const code of heldCodes) {\n const key = keyForCode(code);\n if (\n yieldToHuman &&\n (base.downCodes?.has(code) === true || (key !== undefined && base.downKeys.has(key)))\n )\n continue;\n downCodes?.add(code);\n }\n\n // upKeys: union of human up-edges and injected up-edges (one-frame life), except\n // injected edges for keys that the human still owns under the per-key yield gate.\n const mergedUp = new Set(base.upKeys);\n for (const k of upEdges) {\n const code = codeForKey(k);\n if (\n yieldToHuman &&\n (base.downKeys.has(k) || (code !== undefined && base.downCodes?.has(code) === true))\n )\n continue;\n mergedUp.add(k);\n }\n const mergedUpCodes =\n base.upCodes === undefined && upCodeEdges.size === 0\n ? undefined\n : new Set(base.upCodes ?? []);\n for (const code of upCodeEdges) {\n const key = keyForCode(code);\n if (\n yieldToHuman &&\n (base.downCodes?.has(code) === true || (key !== undefined && base.downKeys.has(key)))\n )\n continue;\n mergedUpCodes?.add(code);\n }\n\n const mergedPressed =\n base.pressedKeys === undefined && pressedKeys.size === 0\n ? undefined\n : new Set([...(base.pressedKeys ?? []), ...pressedKeys]);\n if (\n yieldToHuman &&\n (base.downKeys.size > 0 || (base.downCodes?.size ?? 0) > 0) &&\n mergedPressed !== undefined\n ) {\n for (const key of pressedKeys) {\n const code = codeForKey(key);\n if (base.downKeys.has(key) || (code !== undefined && base.downCodes?.has(code) === true))\n mergedPressed.delete(key);\n }\n }\n const mergedPressedCodes =\n base.pressedCodes === undefined && pressedCodes.size === 0\n ? undefined\n : new Set(base.pressedCodes ?? []);\n if (yieldToHuman && mergedPressedCodes !== undefined) {\n for (const code of pressedCodes) {\n const key = keyForCode(code);\n if (base.downCodes?.has(code) === true || (key !== undefined && base.downKeys.has(key)))\n mergedPressedCodes.delete(code);\n }\n }\n\n // buttons: OR per slot.\n const mergedButtons: readonly [boolean, boolean, boolean] = [\n base.buttons[0] || buttons[0],\n base.buttons[1] || buttons[1],\n base.buttons[2] || buttons[2],\n ];\n const mergedPressedButtons =\n base.pressedButtons === undefined && !pressedButtons.some(Boolean)\n ? undefined\n : ([\n (base.pressedButtons?.[0] ?? false) || pressedButtons[0],\n (base.pressedButtons?.[1] ?? false) || pressedButtons[1],\n (base.pressedButtons?.[2] ?? false) || pressedButtons[2],\n ] as const);\n const mergedReleasedButtons =\n base.releasedButtons === undefined && !releasedButtons.some(Boolean)\n ? undefined\n : ([\n (base.releasedButtons?.[0] ?? false) || releasedButtons[0],\n (base.releasedButtons?.[1] ?? false) || releasedButtons[1],\n (base.releasedButtons?.[2] ?? false) || releasedButtons[2],\n ] as const);\n\n // focused: keep true while WE are injecting, so the scan system does not\n // treat a headless/backgrounded tab (inner.focused === false) as a reason\n // to suppress our up-edges. Otherwise mirror inner.\n const focused = base.focused || injectionActive();\n\n const out: InputBackendSample = {\n ...base, // carry inner optional fields (pointers/gamepads/gestures/...) untouched\n downKeys,\n upKeys: mergedUp,\n ...(downCodes === undefined ? {} : { downCodes }),\n ...(mergedUpCodes === undefined ? {} : { upCodes: mergedUpCodes }),\n ...(mergedPressed === undefined ? {} : { pressedKeys: mergedPressed }),\n ...(mergedPressedCodes === undefined ? {} : { pressedCodes: mergedPressedCodes }),\n buttons: mergedButtons,\n ...(mergedPressedButtons === undefined ? {} : { pressedButtons: mergedPressedButtons }),\n ...(mergedReleasedButtons === undefined ? {} : { releasedButtons: mergedReleasedButtons }),\n movementX: base.movementX + mvx,\n movementY: base.movementY + mvy,\n wheelDelta: base.wheelDelta + wheel,\n focused,\n pointerLocked: base.pointerLocked, // AI never fabricates a lock\n };\n\n // Drain injected per-frame accumulators (mirrors inner's own drain).\n upEdges.clear();\n upCodeEdges.clear();\n pressedKeys.clear();\n pressedCodes.clear();\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n mvx = 0;\n mvy = 0;\n wheel = 0;\n\n return out;\n }\n\n // Only surface setPointerLockAllowed when the inner backend supports it, so\n // the optional method is truly absent (not `undefined`) under\n // exactOptionalPropertyTypes -- and forwards to the human backend when present.\n const lockGate: Pick<InputBackend, 'setPointerLockAllowed'> = inner.setPointerLockAllowed\n ? { setPointerLockAllowed: (allowed: boolean) => inner.setPointerLockAllowed?.(allowed) }\n : {};\n\n const clearInjected = (): void => {\n // Clearing is a lease boundary: discard every pending frame edge first,\n // then emit only the releases required to close state that was held\n // across the boundary. This prevents a press/release queued before a\n // revoke from becoming a ghost edge for the next consumer.\n upEdges.clear();\n upCodeEdges.clear();\n pressedKeys.clear();\n pressedCodes.clear();\n for (const k of heldKeys) upEdges.add(k);\n for (const code of heldCodes) upCodeEdges.add(code);\n heldKeys.clear();\n heldCodes.clear();\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n if (buttons[0]) releasedButtons[0] = true;\n if (buttons[1]) releasedButtons[1] = true;\n if (buttons[2]) releasedButtons[2] = true;\n buttons[0] = buttons[1] = buttons[2] = false;\n mvx = 0;\n mvy = 0;\n wheel = 0;\n };\n\n const beginInjectedLease = (): void => {\n // A new boundary must invalidate old references. Merely flipping a global\n // boolean would let an async script keep writing after a later job opens.\n leaseGeneration += 1;\n leaseRevoked = false;\n clearInjected();\n };\n const revokeInjectedLease = (): void => {\n leaseGeneration += 1;\n leaseRevoked = true;\n clearInjected();\n };\n\n const createInjectedLease = (): CompositeInputLease => {\n beginInjectedLease();\n const generation = leaseGeneration;\n const active = (): boolean => !leaseRevoked && generation === leaseGeneration;\n return {\n sample,\n detach: () => {},\n press(key) {\n if (!active()) return;\n const normalized = normalizeKey(key);\n if (!heldKeys.has(normalized.key)) pressedKeys.add(normalized.key);\n heldKeys.add(normalized.key);\n if (normalized.code !== undefined) {\n if (!heldCodes.has(normalized.code)) pressedCodes.add(normalized.code);\n heldCodes.add(normalized.code);\n }\n },\n release(key) {\n if (!active()) return;\n const normalized = normalizeKey(key);\n if (heldKeys.delete(normalized.key)) upEdges.add(normalized.key);\n if (normalized.code !== undefined && heldCodes.delete(normalized.code))\n upCodeEdges.add(normalized.code);\n },\n setButton(slot, down) {\n if (!active()) return;\n if (down && !buttons[slot]) pressedButtons[slot] = true;\n if (!down && buttons[slot]) releasedButtons[slot] = true;\n buttons[slot] = down;\n },\n addMovement(dx, dy) {\n if (!active()) return;\n mvx += dx;\n mvy += dy;\n },\n addWheel(notches) {\n if (!active()) return;\n wheel += notches;\n },\n clearInjected() {\n if (active()) clearInjected();\n },\n revokeInjectedLease() {\n if (active()) revokeInjectedLease();\n },\n };\n };\n\n return {\n sample,\n ...lockGate,\n // Teardown belongs to the human backend -- revoke the synthetic lease\n // first, then forward the physical listener teardown. `clear()` is also\n // exposed so an owner can revoke input without detaching the browser.\n clear: () => {\n clearInjected();\n inner.clear?.();\n },\n detach: () => {\n clearInjected();\n inner.detach();\n },\n\n press(key) {\n if (leaseRevoked) return;\n const normalized = normalizeKey(key);\n if (!heldKeys.has(normalized.key)) pressedKeys.add(normalized.key);\n heldKeys.add(normalized.key);\n if (normalized.code !== undefined) {\n if (!heldCodes.has(normalized.code)) pressedCodes.add(normalized.code);\n heldCodes.add(normalized.code);\n }\n },\n release(key) {\n if (leaseRevoked) return;\n const normalized = normalizeKey(key);\n if (heldKeys.delete(normalized.key)) upEdges.add(normalized.key); // held -> emit one up-edge\n if (normalized.code !== undefined && heldCodes.delete(normalized.code))\n upCodeEdges.add(normalized.code);\n },\n setButton(slot, down) {\n if (leaseRevoked) return;\n if (down && !buttons[slot]) pressedButtons[slot] = true;\n if (!down && buttons[slot]) releasedButtons[slot] = true;\n buttons[slot] = down;\n },\n addMovement(dx, dy) {\n if (leaseRevoked) return;\n mvx += dx;\n mvy += dy;\n },\n addWheel(notches) {\n if (leaseRevoked) return;\n wheel += notches;\n },\n clearInjected,\n beginInjectedLease,\n revokeInjectedLease,\n createInjectedLease,\n setYieldToHuman(yield_) {\n yieldToHuman = yield_;\n },\n };\n}\n","// frame-start-scan-system.ts -- bridges an `InputBackend` producer into\n// the `InputSnapshot` Resource consumed by user systems (charter P5).\n//\n// Plan-strategy section 2.10 D-5 locks the system to a frame-start position\n// in the schedule: user systems declare `after: ['input-frame-start-scan']`\n// to read the snapshot. The system itself holds zero queries; it only\n// pulls one sample from the backend and writes the Resource.\n//\n// The backend is supplied via the `InputBackend` World resource rather than a\n// captured closure. Resource reads remain explicit in the system body.\n\nimport { defineSystem, defineSystemSet, type SystemHandle } from '@forgeax/engine-ecs';\nimport {\n type ActionConfig,\n type ActionState,\n deriveActionStates,\n INPUT_MAP_KEY,\n} from './action-state';\nimport {\n INPUT_SNAPSHOT_RESOURCE_KEY,\n type InputBackend,\n type InputSnapshot,\n readActionStatesForEdgeDiff,\n snapshotFromSample,\n} from './input-snapshot';\n\n/**\n * Stable system name (locked by `frame-start-scan-system.test.ts`). User\n * systems reference it through `after: [FRAME_START_SCAN_SYSTEM_NAME]`\n * to ensure they observe the freshly written snapshot.\n */\nexport const FRAME_START_SCAN_SYSTEM_NAME = 'input-frame-start-scan';\nexport const InputSet = defineSystemSet({ name: 'input' });\n\n/**\n * Resource key under which the {@link InputBackend} producer is inserted\n * (M2 — full resource-ification, D-2 / D-7). The frame-start scan system\n * declares it in `resources`; the fn body reads it back via\n * `world.getResource(INPUT_BACKEND_KEY)`.\n *\n * Aligns with the `INPUT_SNAPSHOT_RESOURCE_KEY` naming. Consumers import the\n * constant rather than the bare string so a typo degrades to an import error\n * (charter P3).\n */\nexport const INPUT_BACKEND_KEY = 'InputBackend' as const;\n\n/**\n * The frame-start scan system token (M2 — full resource-ification, D-4).\n *\n * Module-level `defineSystem` with the real fn body — no factory, no closure.\n * Each `world.update()` tick:\n * 1. reads the {@link InputBackend} from `INPUT_BACKEND_KEY` and calls\n * `backend.sample()` once to atomically drain the per-frame accumulators\n * (movement delta plus key/code/button press and release edge sets);\n * 2. derives a fresh `InputSnapshot` via `snapshotFromSample`;\n * 3. writes it under `INPUT_SNAPSHOT_RESOURCE_KEY` via\n * `world.insertResource` -- idempotent overwrite, charter P4\n * consistent abstraction (consumers always read the same Resource key\n * regardless of which backend produced the sample).\n *\n * Labelled `'input'` (spec §6.2 label-anchor map).\n */\nexport const InputFrameStartScan: SystemHandle<readonly []> = defineSystem({\n name: FRAME_START_SCAN_SYSTEM_NAME,\n queries: [],\n fn: (world) => {\n const backend = world.getResource<InputBackend>(INPUT_BACKEND_KEY);\n const sample = backend.sample();\n\n // Action mapping: derive states from InputMap Resource + prev snapshot edges.\n // D-6: edge baseline reuses existing prev InputSnapshot Resource (Derive,\n // Don't Duplicate — zero new cross-frame state carrier).\n let actionStates: ReturnType<typeof deriveActionStates> | undefined;\n let inputMap: readonly ActionConfig[] | undefined;\n if (world.hasResource(INPUT_MAP_KEY)) {\n inputMap = world.getResource<readonly ActionConfig[]>(INPUT_MAP_KEY);\n // Read prev snapshot's internal action states for edge diff.\n // First frame: no prev snapshot → justPressed = pressed (same as Feat1 gamepad).\n let prevActionStates: readonly ActionState[] | undefined;\n if (world.hasResource(INPUT_SNAPSHOT_RESOURCE_KEY)) {\n const prevSnap = world.getResource<InputSnapshot>(INPUT_SNAPSHOT_RESOURCE_KEY);\n prevActionStates = readActionStatesForEdgeDiff(prevSnap);\n }\n actionStates = deriveActionStates(sample, inputMap, prevActionStates);\n }\n\n const previousSnapshot = world.hasResource(INPUT_SNAPSHOT_RESOURCE_KEY)\n ? world.getResource<InputSnapshot>(INPUT_SNAPSHOT_RESOURCE_KEY)\n : undefined;\n const snapshot = snapshotFromSample(sample, actionStates, inputMap, previousSnapshot);\n world.insertResource(INPUT_SNAPSHOT_RESOURCE_KEY, snapshot);\n },\n});\n","import type { Plugin } from '@forgeax/engine-plugin';\n\nimport type { InputBackend } from './input-snapshot';\n\ndeclare module '@forgeax/engine-plugin' {\n interface EngineContextServices {\n input?: InputBackend;\n }\n}\n\nexport function inputBackendPlugin(backend: InputBackend): Plugin {\n return {\n name: 'input-backend',\n provide: 'input',\n apply(ctx) {\n ctx.provide('input', backend);\n },\n };\n}\n\n/** Provide an App-acquired input backend and release its Host listeners with the Fiber. */\nexport function ownedInputBackendPlugin(backend: InputBackend, dispose: () => void): Plugin {\n return {\n name: 'input-backend',\n provide: 'input',\n apply(ctx) {\n ctx.provide('input', backend);\n ctx.effect(() => dispose, 'input/backend');\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/action-state.ts","../src/gamepad-frame.ts","../src/gesture-recognizer.ts","../src/input-snapshot.ts","../src/ui-ownership.ts","../src/virtual-joystick.ts","../src/browser-backend.ts","../src/canvas-input-boundary.ts","../src/composite-backend.ts","../src/frame-start-scan-system.ts","../src/plugin-service.ts"],"names":["a","b"],"mappings":"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","file":"index.mjs","sourcesContent":["// action-state.ts — action mapping pure-function module for forgeax-engine.\n//\n// Derives per-frame ActionState[] from an InputBackendSample and an InputMap.\n// Zero ECS/DOM dependencies; fully node-testable.\n//\n// charter awareness:\n// P3 explicit failure — unmapped action names return empty signal, never throw\n// P4 consistent abstraction — consumer only sees action name, never device\n\nimport type { GamepadAxisIndex, GamepadButtonIndex, InputBackendSample } from './input-snapshot';\n\n// ─── Types ───────────────────────────────────────────────────────\n\n/**\n * Closed 4-member discriminant union for mapping raw input sources to actions.\n * The `type` field is the discriminant; consumers switch on it with no `default`\n * branch (AC-08b: TypeScript checks exhaustiveness at compile time).\n */\nexport type ActionBinding =\n | { readonly type: 'key'; readonly key: string }\n | { readonly type: 'mouseButton'; readonly button: 0 | 1 | 2 }\n | { readonly type: 'gamepadButton'; readonly button: GamepadButtonIndex }\n | {\n readonly type: 'gamepadAxis';\n readonly axis: GamepadAxisIndex;\n /**\n * Sign applied to the raw axis value before aggregation.\n * - Omitted: contributes |value| (trigger semantics, e.g. right trigger on axis 2).\n * - `1`: contributes max(0, value) (positive direction).\n * - `-1`: contributes max(0, -value) (negative direction, e.g. left stick).\n */\n readonly sign?: 1 | -1;\n };\n\n/**\n * An action definition in the InputMap: a semantic name + one or more bindings\n * to raw input sources, plus an optional per-action deadzone override.\n */\nexport interface ActionConfig {\n /** Semantic action name (e.g. 'jump', 'moveRight'). Referenced by snap.action(name). */\n readonly action: string;\n /** Raw input bindings that contribute to this action. Aggregated via OR/MAX. */\n readonly bindings: readonly ActionBinding[];\n /**\n * Per-action deadzone applied to analog strength remapping.\n * Default: 0.2 (Godot prior-art, F2). Analog values with |raw| < deadzone\n * produce strength=0. Values >= deadzone are linearly remapped into [0,1].\n */\n readonly deadzone?: number;\n}\n\n/**\n * Per-frame derived action state. Returned by deriveActionStates(); consumed\n * by snap.action(name) readpoints. All fields are frame-frozen (AC-11).\n */\nexport interface ActionState {\n readonly action: string;\n /** true when ANY binding contributes a press (OR aggregation). */\n readonly pressed: boolean;\n /**\n * true only on the frame when pressed transitions false→true.\n * One-frame lifetime; held state does not re-fire (AC-03).\n */\n readonly justPressed: boolean;\n /**\n * true only on the frame when pressed transitions true→false.\n * One-frame lifetime (AC-03).\n */\n readonly justReleased: boolean;\n /**\n * Deadzone-remapped analog strength in [0, 1]. Digital press → 1.0.\n * Analog values < deadzone → 0. Aggregate: MAX across bindings.\n */\n readonly strength: number;\n /**\n * Raw un-deadzoned magnitude in [0, 1]. Used by getVector (which applies its\n * own single radial deadzone to avoid per-axis deadzone stacking, F2).\n * Aggregate: MAX across bindings.\n */\n readonly raw: number;\n}\n\n// ─── Constants ───────────────────────────────────────────────────\n\n/**\n * Resource key for the immutable InputMap (ActionConfig[]) inserted into\n * the World. Canvas-form createApp does this automatically; assemble-form\n * hosts insert it directly (D-7).\n */\nexport const INPUT_MAP_KEY = 'InputMap';\n\n/** Default per-action deadzone (Godot prior-art, F2). */\nconst DEFAULT_DEADZONE = 0.2;\n\n// ─── Helpers ─────────────────────────────────────────────────────\n\n/**\n * Inverse lerp: maps a value from [a, b] to [0, 1] linearly.\n * Returns 0 when val <= a, 1 when val >= b.\n */\nfunction inverseLerp(a: number, b: number, val: number): number {\n if (val <= a) return 0;\n if (val >= b) return 1;\n return (val - a) / (b - a);\n}\n\n/**\n * Deadzone remap: maps |raw| from [deadzone, 1] to [0, 1].\n * |raw| < deadzone → 0. |raw| >= deadzone → inverse_lerp(deadzone, 1, |raw|).\n */\nfunction applyDeadzone(rawAbs: number, deadzone: number): number {\n return rawAbs < deadzone ? 0 : inverseLerp(deadzone, 1, rawAbs);\n}\n\n/**\n * Extract the raw contribution from a single binding against the sample.\n * Returns { rawAbs: number, pressed: boolean }.\n *\n * - Digital types (key/mouseButton/gamepadButton): rawAbs = 1.0 if pressed, 0 otherwise.\n * - Analog type (gamepadAxis): rawAbs = max(0, |value| or max(0, value*sign)).\n * For gamepadAxis, aggregates across ALL connected standardMapping slots (D-9).\n */\nfunction bindingContribution(\n binding: ActionBinding,\n sample: InputBackendSample,\n): { rawAbs: number; pressed: boolean } {\n switch (binding.type) {\n case 'key': {\n const down = sample.downKeys.has(binding.key);\n return { rawAbs: down ? 1.0 : 0, pressed: down };\n }\n case 'mouseButton': {\n const down = sample.buttons[binding.button] === true;\n return { rawAbs: down ? 1.0 : 0, pressed: down };\n }\n case 'gamepadButton': {\n // D-9: aggregate across ALL connected standardMapping slots.\n const slots = sample.gamepads ?? [];\n let anyPressed = false;\n for (const slot of slots) {\n if (!slot.standardMapping) continue;\n if (slot.pressed.has(binding.button)) {\n anyPressed = true;\n break;\n }\n }\n return { rawAbs: anyPressed ? 1.0 : 0, pressed: anyPressed };\n }\n case 'gamepadAxis': {\n // D-9: aggregate across ALL connected standardMapping slots (MAX).\n const slots = sample.gamepads ?? [];\n let maxRawAbs = 0;\n for (const slot of slots) {\n if (!slot.standardMapping) continue;\n const rawAxis = slot.axes[binding.axis];\n const sign = binding.sign;\n if (sign === undefined) {\n // Trigger semantics: contribute |value|\n const abs = Math.abs(rawAxis);\n if (abs > maxRawAbs) maxRawAbs = abs;\n } else if (sign === 1) {\n const v = Math.max(0, rawAxis);\n if (v > maxRawAbs) maxRawAbs = v;\n } else {\n // sign === -1\n const v = Math.max(0, -rawAxis);\n if (v > maxRawAbs) maxRawAbs = v;\n }\n }\n return { rawAbs: maxRawAbs, pressed: false };\n }\n }\n}\n\n// ─── deriveActionStates ──────────────────────────────────────────\n\n/**\n * Derive per-frame action states from a backend sample and an InputMap.\n *\n * Pure function with no side effects. Called once per frame by the\n * frame-start scan system. The result is frozen into the InputSnapshot\n * so all snap.action() calls in the same frame see identical state (AC-11).\n *\n * @param sample - One frame's raw input backend sample (POD).\n * @param inputMap - ActionConfig array; duplicate action names → last-wins (D-8).\n * @param prevActionStates - Previous frame's action states for edge diff\n * (justPressed/justReleased derivation). Omitted on the first frame or\n * when actions are not being tracked across frames.\n * @returns ActionState[] with one entry per action name in inputMap (last-wins dedup).\n */\nexport function deriveActionStates(\n sample: InputBackendSample,\n inputMap: readonly ActionConfig[],\n prevActionStates?: readonly ActionState[],\n): ActionState[] {\n // D-8: last-wins dedup — later configs overwrite earlier for same action name.\n const deduped = new Map<string, ActionConfig>();\n for (const config of inputMap) {\n deduped.set(config.action, config);\n }\n\n // Build prev lookup for edge diff.\n const prevByAction = new Map<string, boolean>();\n if (prevActionStates) {\n for (const s of prevActionStates) {\n prevByAction.set(s.action, s.pressed);\n }\n }\n\n const results: ActionState[] = [];\n\n for (const config of deduped.values()) {\n const deadzone = config.deadzone ?? DEFAULT_DEADZONE;\n\n // Aggregate across all bindings: OR for pressed, MAX for strength/raw.\n let aggregatedPressed = false;\n let aggregatedStrength = 0;\n let aggregatedRaw = 0;\n\n for (const binding of config.bindings) {\n const { rawAbs } = bindingContribution(binding, sample);\n\n // Update raw: MAX aggregation.\n if (rawAbs > aggregatedRaw) aggregatedRaw = rawAbs;\n\n // Update pressed: need to consider analog deadzone threshold.\n if (rawAbs >= deadzone) {\n aggregatedPressed = true;\n const str = applyDeadzone(rawAbs, deadzone);\n if (str > aggregatedStrength) aggregatedStrength = str;\n }\n\n // Digital sources already contribute 1.0/0 rawAbs.\n // For digital, rawAbs=1.0 >= deadzone(0.2) → pressed=true, strength=applyDeadzone(1.0,0.2)=1.0.\n }\n\n // Edge detection: justPressed / justReleased from prev frame's pressed state.\n const prevPressed = prevByAction.get(config.action) ?? false;\n const justPressed = aggregatedPressed && !prevPressed;\n const justReleased = sample.focusReset !== true && !aggregatedPressed && prevPressed;\n\n results.push({\n action: config.action,\n pressed: aggregatedPressed,\n justPressed,\n justReleased,\n strength: aggregatedStrength,\n raw: aggregatedRaw,\n });\n }\n\n return results;\n}\n\n// ─── getAxis / getVector ───────────────────────────────────────────\n\n/**\n * Options for getVector deadzone override.\n */\nexport interface GetVectorOptions {\n /**\n * Override the default radial deadzone. When omitted, the deadzone is\n * computed as the average of the 4 per-action deadzones.\n */\n readonly deadzone?: number;\n}\n\n/**\n * Compose a 1D axis value from two opposing actions.\n *\n * Returns `strength(pos) - strength(neg)`, range [-1, 1].\n *\n * - Both registered: combines normally.\n * - One unregistered (E-3): contributes 0.\n * - Neither registered: returns 0.\n * - Same action for both ends (E-12): always 0.\n *\n * @param inputMap - Input map (ActionConfig[]), used to look up per-action deadzone for getVector default.\n * @param actionStates - Derived action states (from deriveActionStates).\n * @param neg - Action name for the negative direction (e.g. 'moveLeft').\n * @param pos - Action name for the positive direction (e.g. 'moveRight').\n */\nexport function getAxis(\n _inputMap: readonly ActionConfig[],\n actionStates: readonly ActionState[],\n neg: string,\n pos: string,\n): number {\n const posState = actionStates.find((s) => s.action === pos);\n const negState = actionStates.find((s) => s.action === neg);\n const posStrength = posState?.strength ?? 0;\n const negStrength = negState?.strength ?? 0;\n if (neg === pos) return 0;\n return posStrength - negStrength;\n}\n\n/**\n * Compose a 2D vector from four directional actions using a single radial\n * deadzone (Godot input.cpp three-branch formula, F2).\n *\n * Reads `raw` (not `strength`) from actionStates to avoid per-axis deadzone\n * stacking into a square deadzone. Applies one radial deadzone:\n *\n * - length <= deadzone → (0, 0)\n * - length > 1 → vector / length (clamp to unit circle)\n * - otherwise → vector * inverse_lerp(deadzone, 1, length) / length\n *\n * Default deadzone = average of the 4 actions' per-action deadzones.\n * `opts.deadzone` overrides it.\n *\n * @param inputMap - Input map, used for per-action deadzone lookup.\n * @param actionStates - Derived action states.\n * @param negX - Action name for negative X (e.g. 'moveLeft').\n * @param posX - Action name for positive X (e.g. 'moveRight').\n * @param negY - Action name for negative Y (e.g. 'moveUp').\n * @param posY - Action name for positive Y (e.g. 'moveDown').\n * @param opts - Optional override (deadzone).\n */\nexport function getVector(\n inputMap: readonly ActionConfig[],\n actionStates: readonly ActionState[],\n negX: string,\n posX: string,\n negY: string,\n posY: string,\n opts?: GetVectorOptions,\n): { readonly x: number; readonly y: number } {\n // Look up raw values (not strength!) for each directional action.\n // getVector uses raw to avoid per-action deadzone stacking into a square\n // deadzone (F2: Godot getVector applies a SINGLE radial deadzone).\n const posXState = actionStates.find((s) => s.action === posX);\n const negXState = actionStates.find((s) => s.action === negX);\n const posYState = actionStates.find((s) => s.action === posY);\n const negYState = actionStates.find((s) => s.action === negY);\n\n const x = (posXState?.raw ?? 0) - (negXState?.raw ?? 0);\n const y = (posYState?.raw ?? 0) - (negYState?.raw ?? 0);\n\n // Compute radial deadzone.\n // Default = average of the 4 per-action deadzones, using only registered actions.\n const deadzone = opts?.deadzone ?? computeAverageDeadzone(inputMap, negX, posX, negY, posY);\n\n const length = Math.sqrt(x * x + y * y);\n\n // Three-branch formula (Godot input.cpp, F2):\n if (length <= deadzone) {\n // Below deadzone → zero vector (deadzone applied).\n return { x: 0, y: 0 };\n }\n if (length > 1) {\n // Clamp to unit circle.\n return { x: x / length, y: y / length };\n }\n // Intermediate zone: smoothly remap from deadzone→1 to 0→unit.\n // vec * inverse_lerp(deadzone, 1, length) / length\n const factor = inverseLerp(deadzone, 1, length) / length;\n return { x: x * factor, y: y * factor };\n}\n\n/**\n * Compute the average deadzone for 4 action names from the input map.\n * Actions not registered contribute DEFAULT_DEADZONE.\n */\nfunction computeAverageDeadzone(\n inputMap: readonly ActionConfig[],\n negX: string,\n posX: string,\n negY: string,\n posY: string,\n): number {\n const map = new Map<string, number>();\n for (const c of inputMap) {\n map.set(c.action, c.deadzone ?? DEFAULT_DEADZONE);\n }\n const dzNegX = map.get(negX) ?? DEFAULT_DEADZONE;\n const dzPosX = map.get(posX) ?? DEFAULT_DEADZONE;\n const dzNegY = map.get(negY) ?? DEFAULT_DEADZONE;\n const dzPosY = map.get(posY) ?? DEFAULT_DEADZONE;\n return (dzNegX + dzPosX + dzNegY + dzPosY) / 4;\n}\n","// gamepad-frame.ts -- pure functions for per-frame gamepad diff from raw\n// navigator.getGamepads() output. No DOM dependency; only called by\n// browser-backend.ts @internal.\n//\n// D-1: edge diff (justPressed / justReleased) derived via set-delta from\n// prev vs cur pressed sets — same pattern as Bevy button_input.rs.\n// D-1: slot diff (connect / disconnect) derived via set difference from\n// prev vs cur slot index sets.\n// OOS-4: no deadzone applied — axes pass through raw.\n//\n// M3 D-1 (option A): non-standard-layout gamepads are normalized at the\n// acquisition layer. When a caller-supplied remapLookup returns SDL\n// gamecontrollerdb.txt mapping tokens for the gamepad's id, raw HID\n// button/axis indices are re-projected onto the standard layout and the\n// slot is reported with standardMapping=true. No lookup / no match keeps\n// the Feat1 empty-signal behaviour (graceful degradation).\n\nimport type { MappingTokens } from './controller-db';\nimport type { GamepadSlotSample } from './input-snapshot';\n\n/**\n * Minimal raw Gamepad shape from browser API (no DOM types here).\n *\n * M3 F-2 seam fix: `id` mirrors the browser `Gamepad.id` string so the\n * remap lookup can derive the SDL GUID keyed by device identity (not by\n * slot index, which is unstable across reconnects).\n */\nexport interface RawGamepadStub {\n readonly index: number;\n readonly id: string;\n readonly connected: boolean;\n readonly mapping: string;\n readonly buttons: readonly { readonly value: number; readonly pressed: boolean }[];\n readonly axes: readonly number[];\n}\n\n/**\n * Standard layout button count (17: 0-16) and axis count (4: 0-3).\n * Non-standard gamepads without a DB match report standardMapping=false\n * and empty readpoints.\n */\nconst STANDARD_BUTTON_COUNT = 17;\n\n/**\n * SDL logical name -> standard-layout button index (W3C Gamepad standard\n * mapping, KB source section 4.3). `guide` occupies the optional 17th slot.\n */\nconst STANDARD_BUTTON_INDEX: Readonly<Record<string, number>> = {\n a: 0,\n b: 1,\n x: 2,\n y: 3,\n leftshoulder: 4,\n rightshoulder: 5,\n lefttrigger: 6,\n righttrigger: 7,\n back: 8,\n start: 9,\n leftstick: 10,\n rightstick: 11,\n dpup: 12,\n dpdown: 13,\n dpleft: 14,\n dpright: 15,\n guide: 16,\n};\n\n/** SDL logical name -> standard-layout axis index (KB source section 4.3). */\nconst STANDARD_AXIS_INDEX: Readonly<Record<string, number>> = {\n leftx: 0,\n lefty: 1,\n rightx: 2,\n righty: 3,\n};\n\n/** Analog trigger threshold: a trigger mapped to an axis counts as pressed above this. */\nconst TRIGGER_PRESS_THRESHOLD = 0.5;\n\ninterface RemappedReadpoints {\n readonly pressed: Set<number>;\n readonly buttonValues: Map<number, number>;\n readonly axes: [number, number, number, number];\n}\n\n/**\n * Re-project a non-standard raw gamepad onto the standard layout using SDL\n * mapping tokens. Browser getGamepads() exposes only buttons[] and axes[]\n * (no hats), so hat tokens (dpad-as-hat) cannot be resolved from raw data\n * and are skipped — a documented graceful degradation for the rare hat-only\n * dpad devices under the web Gamepad API.\n */\nfunction remapToStandardLayout(gp: RawGamepadStub, tokens: MappingTokens): RemappedReadpoints {\n const pressed = new Set<number>();\n const buttonValues = new Map<number, number>();\n const axes: [number, number, number, number] = [0, 0, 0, 0];\n\n for (const [name, token] of Object.entries(tokens)) {\n const stdButton = STANDARD_BUTTON_INDEX[name];\n const stdAxis = STANDARD_AXIS_INDEX[name];\n\n if (stdButton !== undefined) {\n if (token.kind === 'button') {\n const raw = gp.buttons[token.index];\n if (raw) {\n buttonValues.set(stdButton, raw.value);\n if (raw.pressed) pressed.add(stdButton);\n }\n } else if (token.kind === 'axis') {\n // Trigger (or button) mapped to a raw axis: value = raw axis reading.\n const value = gp.axes[token.index] ?? 0;\n buttonValues.set(stdButton, value);\n if (value > TRIGGER_PRESS_THRESHOLD) pressed.add(stdButton);\n }\n // hat -> button (dpad): no hat source in the browser API; skip.\n continue;\n }\n\n if (stdAxis !== undefined && token.kind === 'axis') {\n const raw = gp.axes[token.index] ?? 0;\n axes[stdAxis] = token.half === '-' ? -raw : raw;\n }\n }\n\n return { pressed, buttonValues, axes };\n}\n\n/** Build an empty-signal slot sample (non-standard-no-match / disconnected). */\nfunction emptySlot(index: number): GamepadSlotSample {\n return {\n index,\n standardMapping: false,\n pressed: new Set(),\n justPressed: new Set(),\n justReleased: new Set(),\n buttonValues: new Map(),\n axes: [0, 0, 0, 0],\n };\n}\n\n/** Derive justPressed / justReleased edge sets from prev vs cur pressed sets. */\nfunction edges(\n prevPressed: ReadonlySet<number>,\n curPressed: ReadonlySet<number>,\n): { justPressed: Set<number>; justReleased: Set<number> } {\n const justPressed = new Set<number>();\n const justReleased = new Set<number>();\n for (const b of curPressed) {\n if (!prevPressed.has(b)) justPressed.add(b);\n }\n for (const b of prevPressed) {\n if (!curPressed.has(b)) justReleased.add(b);\n }\n return { justPressed, justReleased };\n}\n\n/**\n * Diff prev vs cur frames for all gamepad slots. Returns a flat\n * GamepadSlotSample[] array keyed by gamepad.index.\n *\n * - Standard-mapping slots produce GamepadSlotSample with edge sets filled\n * from prev vs cur pressed-set delta.\n * - Non-standard slots: when `remapLookup` returns mapping tokens for the\n * gamepad id, raw HID indices are re-projected onto the standard layout\n * and the slot reports standardMapping=true (D-1 semantic redefinition).\n * With no lookup or no match, the slot reports standardMapping=false with\n * empty readpoints and connected=true (Feat1 behaviour, AC-04).\n * - Disconnected slots (in prev but not in cur) produce a slot with\n * standardMapping=false and all readpoints empty.\n * - Null entries in the browser getGamepads() array are skipped by the\n * caller before calling this function.\n *\n * @param remapLookup - Optional acquisition-layer normalizer. Given a\n * browser Gamepad.id, returns SDL mapping tokens or null. Only consulted\n * for non-standard-mapping gamepads (D-1 option A).\n */\nexport function diffGamepadFrame(\n prev: ReadonlyMap<number, GamepadSlotSample>,\n curGamepads: readonly RawGamepadStub[],\n remapLookup?: (gamepadId: string) => MappingTokens | null,\n): GamepadSlotSample[] {\n const results: GamepadSlotSample[] = [];\n const prevIndices = new Set(prev.keys());\n const curIndices = new Set<number>();\n\n for (const gp of curGamepads) {\n curIndices.add(gp.index);\n const prevPressed = prev.get(gp.index)?.pressed ?? new Set<number>();\n results.push(\n gp.mapping === 'standard'\n ? diffStandardSlot(gp, prevPressed)\n : diffNonStandardSlot(gp, prevPressed, remapLookup),\n );\n }\n\n // Disconnected slots: emit empty-signal entries for slots that were in prev\n // but not in cur, so the snapshot reader reports connected=false.\n for (const idx of prevIndices) {\n if (!curIndices.has(idx)) {\n results.push(emptySlot(idx));\n }\n }\n\n return results;\n}\n\n/** Diff a standard-mapping gamepad slot: raw indices pass through 1:1. */\nfunction diffStandardSlot(gp: RawGamepadStub, prevPressed: ReadonlySet<number>): GamepadSlotSample {\n const curPressed = new Set<number>();\n const buttonValues = new Map<number, number>();\n const btnCount = Math.min(gp.buttons.length, STANDARD_BUTTON_COUNT);\n for (let b = 0; b < btnCount; b++) {\n const btn = gp.buttons[b];\n if (!btn) continue;\n buttonValues.set(b, btn.value);\n if (btn.pressed) curPressed.add(b);\n }\n const { justPressed, justReleased } = edges(prevPressed, curPressed);\n // Axes: raw values, no deadzone (OOS-4).\n const axes: [number, number, number, number] = [\n gp.axes[0] ?? 0,\n gp.axes[1] ?? 0,\n gp.axes[2] ?? 0,\n gp.axes[3] ?? 0,\n ];\n return {\n index: gp.index,\n standardMapping: true,\n pressed: curPressed,\n justPressed,\n justReleased,\n buttonValues,\n axes,\n };\n}\n\n/**\n * Diff a non-standard-mapping gamepad slot (D-1 option A): attempt an\n * acquisition-layer remap via the SDL DB. No lookup / no match falls back\n * to the Feat1 empty signal with connected=true (AC-04).\n */\nfunction diffNonStandardSlot(\n gp: RawGamepadStub,\n prevPressed: ReadonlySet<number>,\n remapLookup?: (gamepadId: string) => MappingTokens | null,\n): GamepadSlotSample {\n const tokens = remapLookup ? remapLookup(gp.id) : null;\n if (!tokens) return emptySlot(gp.index);\n const { pressed, buttonValues, axes } = remapToStandardLayout(gp, tokens);\n const { justPressed, justReleased } = edges(prevPressed, pressed);\n return {\n index: gp.index,\n standardMapping: true,\n pressed,\n justPressed,\n justReleased,\n buttonValues,\n axes,\n };\n}\n","// gesture-recognizer.ts -- pure-function gesture state machines for\n// forgeax-engine input (M5). Zero DOM / ECS dependencies: node-testable.\n//\n// charter awareness:\n// C-3 (single legal cross-frame state holder) -- the recognizer owns the\n// only sanctioned cross-frame gesture state. The browser backend stores\n// a `RecognizerState` in its closure (alongside prevGamepadFrame /\n// pointerMap / vjBindState) and threads it through `processGestureFrame`\n// every `sample()`. This module never mutates its inputs; it returns a\n// fresh `newState` the producer must store for the next frame.\n// D-3 clock decoupling -- all timers advance off the injected `now`\n// value, NOT off pointer-event arrival. An idle frame (empty phase\n// queue) still advances long-press timing, so recognition is decoupled\n// from event frequency (AC-16). The F-1 falsification test proves an\n// event-frequency-coupled impl fails.\n// D-4 dual channel -- returns continuous values (`gestureState`:\n// pinchScale / rotationAngle) plus a one-frame lifecycle event list\n// (`gestureEvents`). The backend forwards these as the optional\n// `gestures?` / `gestureEvents?` sample fields (D-4 / F1 precedent).\n// D-10 thresholds -- long-press 500ms + slop 10px, double-tap 350ms +\n// 10px, swipe 0.5 px/ms over a 100ms window; exported as constants.\n// D-11 pinch/rotate -- lock the earliest two pointers, ignore a third;\n// 2->1 emits end + freezes continuous values; a fresh pair emits begin\n// and resets to identity (1.0 / 0).\n\nimport type { PointerPhaseEvent, PointerType } from './input-snapshot';\n\n// D-10 threshold defaults (LayaAir + Godot prior-art, plan-strategy section 2).\nexport const LONG_PRESS_DURATION_MS = 500;\nexport const LONG_PRESS_SLOP = 10;\nexport const DOUBLE_TAP_INTERVAL_MS = 350;\nexport const DOUBLE_TAP_DISTANCE = 10;\nexport const SWIPE_VELOCITY_THRESHOLD = 0.5;\nexport const SWIPE_WINDOW_MS = 100;\n\n/** Swipe direction taken from the dominant displacement axis (D-10). */\nconst SWIPE_DIRECTIONS = ['left', 'right', 'up', 'down'] as const;\nexport type SwipeDirection = (typeof SWIPE_DIRECTIONS)[number];\n\n/**\n * Continuous gesture values read each frame via `snap.gesture` (D-4).\n * Identity when no gesture is active or after a cancel/reset (AC-12):\n * pinchScale = 1.0, rotationAngle = 0.\n */\nexport interface GestureState {\n readonly pinchScale: number;\n readonly rotationAngle: number;\n}\n\n/**\n * Closed discriminant union of gesture lifecycle + instantaneous events\n * (AC-13). One-frame lifecycle: an event appears in exactly one frame's\n * `gestureEvents`. Every member carries `pointerType` (narrowed union,\n * AC-19) so consumers can exhaustively switch on gesture kind AND device\n * type without a default branch.\n */\nexport type GestureEvent =\n | {\n readonly kind: 'pinch-begin';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'pinch-end';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'pinch-cancel';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'rotate-begin';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'rotate-end';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'rotate-cancel';\n readonly pointerIds: readonly [number, number];\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'swipe';\n readonly pointerId: number;\n readonly direction: SwipeDirection;\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'long-press';\n readonly pointerId: number;\n readonly x: number;\n readonly y: number;\n readonly pointerType: PointerType;\n readonly timestamp: number;\n }\n | {\n readonly kind: 'double-tap';\n readonly pointerId: number;\n readonly x: number;\n readonly y: number;\n readonly pointerType: PointerType;\n readonly timestamp: number;\n };\n\n/** Live position + device type for a pointer (subset of the backend pointerMap entry). */\nexport interface RecognizerPointer {\n readonly x: number;\n readonly y: number;\n readonly pointerType: PointerType;\n}\n\n/** Locked dual-finger tracker for pinch + rotate (D-11). */\nexport interface PinchRotateTracker {\n readonly pointerA: number;\n readonly pointerB: number;\n readonly initialDistance: number;\n /** Previous frame's raw atan2 angle; rotation accumulates frame deltas (D-11). */\n readonly lastAngle: number;\n readonly pointerType: PointerType;\n}\n\n/** Per-pointer long-press arming state (D-10). */\nexport interface LongPressTracker {\n readonly downTime: number;\n readonly x: number;\n readonly y: number;\n readonly pointerType: PointerType;\n readonly armed: boolean;\n readonly fired: boolean;\n}\n\n/** Timestamped position sample for swipe velocity (D-10, 100ms window). */\nexport interface SwipeSample {\n readonly t: number;\n readonly x: number;\n readonly y: number;\n}\n\n/** Last recorded tap for double-tap window matching (D-10). */\nexport interface TapRecord {\n readonly time: number;\n readonly x: number;\n readonly y: number;\n}\n\n/**\n * The single legal cross-frame gesture state (C-3). Immutable: each\n * `processGestureFrame` returns a fresh copy; the producer stores it for\n * the next frame. `gesture` is the current continuous value read by\n * `snap.gesture` -- live during pinch, frozen after a 2->1 end, identity\n * after cancel/reset or when no gesture ever activated.\n */\nexport interface RecognizerState {\n readonly pinch: PinchRotateTracker | null;\n readonly gesture: GestureState;\n readonly longPresses: ReadonlyMap<number, LongPressTracker>;\n readonly lastTap: TapRecord | null;\n readonly swipeHistory: ReadonlyMap<number, readonly SwipeSample[]>;\n}\n\n/** Result of processing one frame of phase events (D-4 dual channel). */\nexport interface GestureFrameResult {\n readonly newState: RecognizerState;\n readonly gestureState: GestureState;\n readonly gestureEvents: readonly GestureEvent[];\n}\n\n/** Identity continuous value (AC-12): no scale, no rotation. */\nexport const IDENTITY_GESTURE: GestureState = Object.freeze({ pinchScale: 1, rotationAngle: 0 });\n\n/** Fresh recognizer state with no active gestures. */\nexport function createRecognizerState(): RecognizerState {\n return {\n pinch: null,\n gesture: IDENTITY_GESTURE,\n longPresses: new Map(),\n lastTap: null,\n swipeHistory: new Map(),\n };\n}\n\n// ─── pure math helpers ───────────────────────────────────────────────\n\nfunction distance(ax: number, ay: number, bx: number, by: number): number {\n return Math.hypot(bx - ax, by - ay);\n}\n\nfunction angleOf(ax: number, ay: number, bx: number, by: number): number {\n return Math.atan2(by - ay, bx - ax);\n}\n\n/** Wrap an angle to (-PI, PI] so accumulated rotation never jumps a full turn. */\nfunction normalizeAngle(a: number): number {\n let r = a;\n while (r > Math.PI) r -= 2 * Math.PI;\n while (r <= -Math.PI) r += 2 * Math.PI;\n return r;\n}\n\nfunction dominantDirection(dx: number, dy: number): SwipeDirection {\n if (Math.abs(dx) >= Math.abs(dy)) return dx >= 0 ? SWIPE_DIRECTIONS[1] : SWIPE_DIRECTIONS[0];\n // Screen space: +y points down.\n return dy >= 0 ? SWIPE_DIRECTIONS[3] : SWIPE_DIRECTIONS[2];\n}\n\n/**\n * AC-19 real consumption path: exhaustive switch on `PointerType` with no\n * default branch. Every gesture event's `pointerType` flows through here at\n * construction, so adding a 4th `PointerType` member fails to compile\n * (the function would then be able to return `undefined`, violating its\n * `PointerType` return type). This is the sanctioned AC-19 consumption\n * proof required by plan-strategy section 7 (M5 boundary).\n */\nfunction narrowGesturePointerType(pt: PointerType): PointerType {\n switch (pt) {\n case 'mouse':\n return 'mouse';\n case 'pen':\n return 'pen';\n case 'touch':\n return 'touch';\n }\n}\n\n// ─── mutable per-frame working context ───────────────────────────────\n\ninterface WorkContext {\n pinch: PinchRotateTracker | null;\n gesture: { pinchScale: number; rotationAngle: number };\n longPresses: Map<number, LongPressTracker>;\n lastTap: TapRecord | null;\n swipeHistory: Map<number, SwipeSample[]>;\n events: GestureEvent[];\n}\n\nfunction emitPinchLifecycle(\n ctx: WorkContext,\n phase: 'begin' | 'end' | 'cancel',\n tracker: PinchRotateTracker,\n now: number,\n): void {\n const pointerIds: readonly [number, number] = [tracker.pointerA, tracker.pointerB];\n const pointerType = narrowGesturePointerType(tracker.pointerType);\n ctx.events.push({ kind: `pinch-${phase}`, pointerIds, pointerType, timestamp: now });\n ctx.events.push({ kind: `rotate-${phase}`, pointerIds, pointerType, timestamp: now });\n}\n\nfunction handleDown(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n // Arm a long-press timer + start a swipe velocity window + tap start.\n ctx.longPresses.set(ev.pointerId, {\n downTime: now,\n x: ev.x,\n y: ev.y,\n pointerType: ev.pointerType,\n armed: true,\n fired: false,\n });\n ctx.swipeHistory.set(ev.pointerId, [{ t: now, x: ev.x, y: ev.y }]);\n}\n\nfunction handleMove(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n // Disarm the long-press if the finger strays beyond slop (D-10).\n const lp = ctx.longPresses.get(ev.pointerId);\n if (lp?.armed && distance(lp.x, lp.y, ev.x, ev.y) > LONG_PRESS_SLOP) {\n ctx.longPresses.set(ev.pointerId, { ...lp, armed: false });\n }\n // Append to the swipe velocity window, pruning samples outside it.\n const hist = ctx.swipeHistory.get(ev.pointerId);\n if (hist) {\n hist.push({ t: now, x: ev.x, y: ev.y });\n pruneSwipeWindow(hist, now);\n }\n}\n\nfunction pruneSwipeWindow(hist: SwipeSample[], now: number): void {\n const cutoff = now - SWIPE_WINDOW_MS;\n // Keep at least the last sample so an up always has a reference point.\n while (hist.length > 1 && hist[0] !== undefined && hist[0].t < cutoff) {\n hist.shift();\n }\n}\n\nfunction detectSwipe(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n const hist = ctx.swipeHistory.get(ev.pointerId);\n if (!hist || hist.length === 0) return;\n const cutoff = now - SWIPE_WINDOW_MS;\n const oldest = hist.find((s) => s.t >= cutoff) ?? hist[0];\n if (!oldest) return;\n const dt = now - oldest.t;\n if (dt <= 0) return;\n const dist = distance(oldest.x, oldest.y, ev.x, ev.y);\n if (dist / dt < SWIPE_VELOCITY_THRESHOLD) return;\n ctx.events.push({\n kind: 'swipe',\n pointerId: ev.pointerId,\n direction: dominantDirection(ev.x - oldest.x, ev.y - oldest.y),\n pointerType: narrowGesturePointerType(ev.pointerType),\n timestamp: now,\n });\n}\n\nfunction detectDoubleTap(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n const prev = ctx.lastTap;\n const withinTime = prev !== null && now - prev.time <= DOUBLE_TAP_INTERVAL_MS;\n const withinDist = prev !== null && distance(prev.x, prev.y, ev.x, ev.y) <= DOUBLE_TAP_DISTANCE;\n if (prev !== null && withinTime && withinDist) {\n ctx.events.push({\n kind: 'double-tap',\n pointerId: ev.pointerId,\n x: ev.x,\n y: ev.y,\n pointerType: narrowGesturePointerType(ev.pointerType),\n timestamp: now,\n });\n ctx.lastTap = null; // consumed; a 3rd tap starts a fresh pair\n return;\n }\n ctx.lastTap = { time: now, x: ev.x, y: ev.y };\n}\n\nfunction endPinchIfMember(\n ctx: WorkContext,\n pointerId: number,\n phase: 'end' | 'cancel',\n now: number,\n): void {\n const pinch = ctx.pinch;\n if (!pinch || (pinch.pointerA !== pointerId && pinch.pointerB !== pointerId)) return;\n emitPinchLifecycle(ctx, phase, pinch, now);\n ctx.pinch = null;\n if (phase === 'cancel') {\n // Cancel resets to identity (AC-18); end (2->1) freezes the last value (D-11).\n ctx.gesture = { pinchScale: 1, rotationAngle: 0 };\n }\n}\n\nfunction handleUp(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n detectSwipe(ctx, ev, now);\n detectDoubleTap(ctx, ev, now);\n ctx.longPresses.delete(ev.pointerId);\n ctx.swipeHistory.delete(ev.pointerId);\n endPinchIfMember(ctx, ev.pointerId, 'end', now);\n}\n\nfunction handleCancel(ctx: WorkContext, ev: PointerPhaseEvent, now: number): void {\n ctx.longPresses.delete(ev.pointerId);\n ctx.swipeHistory.delete(ev.pointerId);\n endPinchIfMember(ctx, ev.pointerId, 'cancel', now);\n}\n\nfunction tryLockPair(\n ctx: WorkContext,\n pointerMap: ReadonlyMap<number, RecognizerPointer>,\n now: number,\n): void {\n if (ctx.pinch !== null || pointerMap.size < 2) return;\n // D-11: lock the earliest two pointers by ascending pointerId; a later\n // (third+) finger is ignored while the pair holds.\n const ids = [...pointerMap.keys()].sort((a, b) => a - b);\n const idA = ids[0];\n const idB = ids[1];\n if (idA === undefined || idB === undefined) return;\n const a = pointerMap.get(idA);\n const b = pointerMap.get(idB);\n if (!a || !b) return;\n ctx.pinch = {\n pointerA: idA,\n pointerB: idB,\n initialDistance: distance(a.x, a.y, b.x, b.y) || 1,\n lastAngle: angleOf(a.x, a.y, b.x, b.y),\n pointerType: a.pointerType,\n };\n ctx.gesture = { pinchScale: 1, rotationAngle: 0 };\n emitPinchLifecycle(ctx, 'begin', ctx.pinch, now);\n}\n\nfunction updatePinchContinuous(\n ctx: WorkContext,\n pointerMap: ReadonlyMap<number, RecognizerPointer>,\n): void {\n const pinch = ctx.pinch;\n if (!pinch) return;\n const a = pointerMap.get(pinch.pointerA);\n const b = pointerMap.get(pinch.pointerB);\n if (!a || !b) return; // a member briefly absent: keep the last value\n const curDist = distance(a.x, a.y, b.x, b.y);\n const curAngle = angleOf(a.x, a.y, b.x, b.y);\n const delta = normalizeAngle(curAngle - pinch.lastAngle);\n ctx.gesture = {\n pinchScale: curDist / pinch.initialDistance,\n rotationAngle: ctx.gesture.rotationAngle + delta,\n };\n ctx.pinch = { ...pinch, lastAngle: curAngle };\n}\n\nfunction fireLongPresses(\n ctx: WorkContext,\n pointerMap: ReadonlyMap<number, RecognizerPointer>,\n now: number,\n): void {\n const pinch = ctx.pinch;\n for (const [id, lp] of ctx.longPresses) {\n if (!lp.armed || lp.fired) continue;\n if (now - lp.downTime < LONG_PRESS_DURATION_MS) continue;\n if (!pointerMap.has(id)) continue; // finger must still be down\n // A finger locked into an active pinch pair is committed to the dual\n // gesture and must not also fire a long-press (D-11 dual-finger lock).\n if (pinch && (pinch.pointerA === id || pinch.pointerB === id)) continue;\n ctx.events.push({\n kind: 'long-press',\n pointerId: id,\n x: lp.x,\n y: lp.y,\n pointerType: narrowGesturePointerType(lp.pointerType),\n timestamp: now,\n });\n ctx.longPresses.set(id, { ...lp, fired: true });\n }\n}\n\n/**\n * Process one frame of pointer phase events, advancing all timers off\n * `now`, and return the new state + continuous values + one-frame event\n * list (D-4). Never mutates its inputs.\n */\nexport function processGestureFrame(\n phaseQueue: readonly PointerPhaseEvent[],\n pointerMap: ReadonlyMap<number, RecognizerPointer>,\n prevState: RecognizerState,\n now: number,\n): GestureFrameResult {\n const ctx: WorkContext = {\n pinch: prevState.pinch,\n gesture: { ...prevState.gesture },\n longPresses: new Map(prevState.longPresses),\n lastTap: prevState.lastTap,\n swipeHistory: cloneSwipeHistory(prevState.swipeHistory),\n events: [],\n };\n\n for (const ev of phaseQueue) {\n switch (ev.phase) {\n case 'down':\n handleDown(ctx, ev, now);\n break;\n case 'move':\n handleMove(ctx, ev, now);\n break;\n case 'up':\n handleUp(ctx, ev, now);\n break;\n case 'cancel':\n handleCancel(ctx, ev, now);\n break;\n }\n }\n\n tryLockPair(ctx, pointerMap, now);\n updatePinchContinuous(ctx, pointerMap);\n fireLongPresses(ctx, pointerMap, now);\n\n const gesture: GestureState = Object.freeze({\n pinchScale: ctx.gesture.pinchScale,\n rotationAngle: ctx.gesture.rotationAngle,\n });\n const newState: RecognizerState = {\n pinch: ctx.pinch,\n gesture,\n longPresses: ctx.longPresses,\n lastTap: ctx.lastTap,\n swipeHistory: ctx.swipeHistory,\n };\n return { newState, gestureState: gesture, gestureEvents: ctx.events };\n}\n\nfunction cloneSwipeHistory(\n src: ReadonlyMap<number, readonly SwipeSample[]>,\n): Map<number, SwipeSample[]> {\n const out = new Map<number, SwipeSample[]>();\n for (const [id, samples] of src) out.set(id, [...samples]);\n return out;\n}\n","// input-snapshot.ts -- frozen frame-start input snapshot Resource for\n// forgeax-engine. Multi-device surface (keyboard + mouse + gamepad + pointer +\n// virtualAxis) — each cluster is a frozen reader on the per-frame Sample.\n//\n// charter awareness:\n// F1 single-entry indexability -- barrel exports all types; IDE autocomplete\n// reaches the full surface from one import\n// F2 minimal surface -- each device cluster exposes only its natural\n// readpoints; no phantom methods or modal parameters\n// P3 explicit failure -- no thrown errors from accessor methods; absent\n// keys / pre-start state / disconnected slots / unsupported devices\n// all report `false` / `0` / zero-vector (the empty signal IS the\n// signal). `mouse.button(i)` / `gamepad.button(b)` parameters are\n// literal unions so out-of-range indices are TS compile errors rather\n// than runtime bounds-clamps.\n// P4 consistent abstraction -- the snapshot hides the producer\n// (browser listener wiring + gamepad polling) entirely; consumers read\n// via the `InputSnapshot` Resource regardless of backend\n// P5 producer/consumer split -- the InputBackend protocol decouples\n// the producer from the snapshot; `frame-start-scan-system.ts` is the\n// bridge that calls `backend.sample()` and writes the Resource\n\nimport type { ActionConfig, ActionState, GetVectorOptions } from './action-state';\nimport { getAxis, getVector } from './action-state';\nimport type { GestureEvent, GestureState } from './gesture-recognizer';\nimport { IDENTITY_GESTURE } from './gesture-recognizer';\n\n// D-5 / AC-19: pointerType is narrowed from string to a 3-literal union.\n// The W3C Pointer Events spec allows '' when the device type cannot be\n// detected; coercion maps '' to 'mouse' at the producer, so the snapshot\n// only ever sees one of these three canonical values.\nexport type PointerType = 'mouse' | 'pen' | 'touch';\n\n/** Standard-layout gamepad button index (0-16 per W3C Gamepad spec). */\nexport type GamepadButtonIndex =\n | 0\n | 1\n | 2\n | 3\n | 4\n | 5\n | 6\n | 7\n | 8\n | 9\n | 10\n | 11\n | 12\n | 13\n | 14\n | 15\n | 16;\n\n/** Standard-layout gamepad axis index (0-3 per W3C Gamepad spec). */\nexport type GamepadAxisIndex = 0 | 1 | 2 | 3;\n\n/** W3C MouseEvent.button index (0=primary, 1=auxiliary, 2=secondary). */\nexport type MouseButtonIndex = 0 | 1 | 2;\n\n/** Per-slot gamepad frame data produced by `sample()`. */\nexport interface GamepadSlotSample {\n readonly index: number;\n /**\n * True when the browser reports a standard mapping OR the SDL controller\n * DB has normalized a non-standard layout at the acquisition layer (M3\n * D-1 redefinition). The Feat1 meaning (\"browser-reported standard\n * mapping only\") is widened here: a non-standard pad whose GUID matches\n * gamecontrollerdb.txt is re-projected onto the standard layout and\n * reported as standardMapping=true, so bindings and direct reads see a\n * uniform standard button/axis space. A non-standard pad with no DB match\n * (or before the DB has loaded) keeps standardMapping=false + empty\n * readpoints (graceful degradation).\n */\n readonly standardMapping: boolean;\n readonly pressed: ReadonlySet<number>;\n readonly justPressed: ReadonlySet<number>;\n readonly justReleased: ReadonlySet<number>;\n readonly buttonValues: ReadonlyMap<number, number>;\n readonly axes: readonly [number, number, number, number];\n}\n\n/** Per-pointer live state (active contacts tracked by pointerId).\n *\n * D-5 / E-10: `pointerType` is a 3-literal union. `'mouse'` is the default\n * placeholder for inactive pointers — when `active=false`, `pointerType` is\n * always `'mouse'`. The semantic \"no pointer\" is carried by the `active`\n * field, never by a sentinel string value.\n */\nexport interface PointerSample {\n readonly pointerId: number;\n readonly x: number;\n readonly y: number;\n readonly pressure: number;\n readonly pointerType: PointerType;\n readonly active: boolean;\n readonly delta: { readonly x: number; readonly y: number };\n}\n\n/** Per-frame phase event (down/move/up/cancel queue, one-frame lifecycle). */\nexport interface PointerPhaseEvent {\n readonly pointerId: number;\n readonly phase: 'down' | 'move' | 'up' | 'cancel';\n readonly x: number;\n readonly y: number;\n readonly pressure: number;\n readonly pointerType: PointerType;\n}\n\n/** Per-frame virtual axis output (named joystick derived from pointer input). */\nexport interface VirtualAxisSample {\n readonly name: string;\n readonly x: number;\n readonly y: number;\n}\n\n/**\n * Configuration for an on-screen virtual joystick (M3). Consumed by\n * attachBrowserInputBackend and passed through to deriveVirtualAxes.\n *\n * Fixed mode: origin is config.anchor (or region center if anchor omitted).\n * Floating mode: origin is the first pointerdown position within the region.\n */\nexport interface VirtualJoystickConfig {\n readonly name: string;\n readonly mode: 'fixed' | 'floating';\n /** Canvas-pixel region where touches are eligible to bind this joystick. */\n readonly region: {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n };\n /** Fixed-mode origin anchor. Defaults to region center when omitted. */\n readonly anchor?: { readonly x: number; readonly y: number } | undefined;\n /** Max drag radius in canvas pixels. Vector is clamped then normalized to radius. */\n readonly radius: number;\n /** Normalized deadzone (0..1). |vec| < deadzone → zero vector output. */\n readonly deadzone: number;\n}\n\n/** Capability snapshot (frozen at backend attach time). */\nexport interface Capabilities {\n readonly gamepad: boolean;\n readonly pointer: boolean;\n}\n\n/**\n * Frozen value-shape view exposed to user systems via the `InputSnapshot`\n * Resource. The methods are pure reads; calling them does not mutate any\n * accumulator (charter P3 -- no observable side effects from the accessor\n * surface). A fresh `InputSnapshot` instance is constructed by the\n * frame-start scan system once per `world.update()` and replaces the\n * previous Resource value.\n */\nexport interface InputSnapshot {\n /** Keyboard view (held state plus frame edges). */\n readonly keyboard: {\n /**\n * `true` while `key` is currently held. `key` matches the value the\n * backend records (KeyboardEvent.key for the browser backend). When\n * the key is not in the held set, returns `false` -- never throws\n * (charter P3: empty signal is the signal).\n */\n down(key: string): boolean;\n /** `true` for the first frame in which `key` becomes held. */\n justPressed(key: string): boolean;\n /**\n * `true` for one frame after the key was released (the up-edge). The\n * edge collapses on the following `world.update()`. `key` not in the\n * up-edge set returns `false`.\n */\n up(key: string): boolean;\n /** Code-key equivalent of `down`, using KeyboardEvent.code identity. */\n downCode(code: string): boolean;\n /** Code-key equivalent of `justPressed`. */\n justPressedCode(code: string): boolean;\n /** Code-key equivalent of `up`. */\n upCode(code: string): boolean;\n };\n /** Mouse view (charter F2 minimal surface: position + movementDelta + button + wheelDelta). */\n readonly mouse: {\n /**\n * Latest canvas-pixel cursor position. This is available during hover;\n * it does not require a button press or pointer capture. The position is\n * frozen with the rest of the frame-start snapshot.\n */\n readonly position: { readonly x: number; readonly y: number } | undefined;\n /**\n * PointerLock-style accumulated movement since the previous frame.\n * Value is frozen at frame-start; reading it does not clear the\n * accumulator. The next `world.update()` produces a fresh delta\n * (zero if no movement events arrived).\n */\n readonly movementDelta: { readonly x: number; readonly y: number };\n /**\n * Merged pointer-lock state: true when either W3C pointer-lock\n * (pointerLockElement === this backend's canvas) OR the lockProvider\n * path has engaged. Consumers read this to decide whether to consume\n * movementDelta for look/camera rotation. Required field, alongside\n * movementDelta -- both facts sit at the same attribute path for\n * single-point indexing (charter F1).\n */\n readonly pointerLocked: boolean;\n /**\n * `true` while the W3C MouseEvent.button slot `i` is held. `i` is\n * narrowed to the literal `0 | 1 | 2` so out-of-range indices are\n * rejected at compile time (charter P3 explicit failure: TS literal\n * narrowing replaces a runtime bounds-clamp).\n *\n * - 0 -- primary button (left)\n * - 1 -- auxiliary button (middle)\n * - 2 -- secondary button (right)\n */\n button(i: MouseButtonIndex): boolean;\n /** `true` for the first frame in which button `i` becomes held. */\n justPressed(i: MouseButtonIndex): boolean;\n /** `true` for the frame in which button `i` is released. */\n justReleased(i: MouseButtonIndex): boolean;\n /**\n * Discrete wheel notches accumulated since the previous frame.\n * Plan-strategy D-5 sign-discrete: each `WheelEvent` contributes\n * `Math.sign(event.deltaY)` to the per-frame accumulator regardless\n * of `deltaMode` (PIXEL / LINE / PAGE all collapse). Sign convention\n * follows W3C `WheelEvent.deltaY`: positive = scroll down / away\n * from user, negative = scroll up / toward user.\n *\n * Value is frozen at frame-start; reading it does not clear the\n * accumulator. The next `world.update()` produces a fresh delta\n * (zero when no wheel events arrived).\n *\n * Trade-off (plan-strategy R-7): trackpad high-resolution wheel\n * events collapse to one notch per event, losing sub-notch fidelity.\n * AI users who need analog magnitude must opt in via a future\n * unitful surface (OOS-7 ScrollSnapshot is the deferred shape).\n */\n readonly wheelDelta: number;\n };\n /**\n * Per-slot gamepad reader. Returns a reader object for the gamepad at\n * slot `i` regardless of connection state: disconnected or out-of-range\n * slots report `connected=false`, all button/axis readpoints return\n * `false`/`0` (charter P3 empty signal). The slot index is intentionally\n * not narrowed — platform slot counts vary, and bounds handling is a\n * runtime concern.\n */\n gamepad(i: number): {\n readonly connected: boolean;\n readonly standardMapping: boolean;\n button(b: GamepadButtonIndex): boolean;\n buttonValue(b: GamepadButtonIndex): number;\n justPressed(b: GamepadButtonIndex): boolean;\n justReleased(b: GamepadButtonIndex): boolean;\n axis(a: GamepadAxisIndex): number;\n };\n /**\n * Frozen capabilities snapshot, determined once at backend attach time.\n * Consumers use this to decide whether gamepad/pointer readpoints will\n * ever carry live data, without probing per-frame.\n */\n readonly capabilities: Capabilities;\n /**\n * Per-pointerId reader. Returns `{ active: true/false, x, y, pressure,\n * pointerType, delta }` for the given pointerId. Unknown pointerIds\n * return `{ active: false, ... }` without throwing.\n */\n pointer(\n id: number,\n ): PointerSample & { readonly delta: { readonly x: number; readonly y: number } };\n /**\n * Named virtual axis reader (joystick-derived). Returns `{ x, y }` for\n * the given joystick config name. Unknown names return the zero-vector\n * `{ x: 0, y: 0 }` without throwing.\n */\n virtualAxis(name: string): { readonly x: number; readonly y: number };\n /**\n * Per-frame phase event queue (down/move/up/cancel). One-frame\n * lifecycle; drained by `sample()` at frame end. Empty array when no\n * pointer events occurred this frame.\n */\n readonly pointerEvents: readonly PointerPhaseEvent[];\n /**\n * Continuous gesture values (pinch scale + rotation angle) for the\n * active dual-finger gesture. Returns the identity empty signal\n * (`pinchScale=1`, `rotationAngle=0`) when no gesture is active (AC-12);\n * an active gesture retains its value on idle frames (fingers held still\n * are not a gesture end). AC-11: reading the same frame's snapshot twice\n * returns the identical object.\n */\n readonly gesture: GestureState;\n /**\n * Per-frame gesture lifecycle + instantaneous event queue (begin / end /\n * cancel / swipe / long-press / double-tap). One-frame lifecycle, same\n * pattern as `pointerEvents` (charter P4). Empty array when no gesture\n * activity occurred this frame. Closed discriminant union (AC-13): a\n * consumer exhaustively switches on `kind` without a default branch.\n */\n readonly gestureEvents: readonly GestureEvent[];\n /**\n * Action mapping readpoint. Returns a frozen reader for the named action.\n * When `name` is registered in the InputMap, `isPressed()` / `justPressed()`\n * / `justReleased()` / `strength` reflect the derived state. Unregistered\n * action names return empty signal (false / 0 / false / false / 0) without\n * throwing (charter P3: empty signal is the signal). AC-11: calling\n * action() multiple times in the same frame returns identical values.\n */\n action(name: string): {\n readonly isPressed: () => boolean;\n readonly justPressed: () => boolean;\n readonly justReleased: () => boolean;\n readonly strength: number;\n };\n /**\n * Compose a 1D axis value from two opposing actions.\n *\n * Returns `strength(pos) - strength(neg)`, range [-1, 1].\n * Both registered: combines normally. One unregistered: contributes 0\n * (E-3). Same action for both ends: always 0 (E-12).\n *\n * @param neg - Action name for the negative direction (e.g. 'moveLeft').\n * @param pos - Action name for the positive direction (e.g. 'moveRight').\n */\n getAxis(neg: string, pos: string): number;\n /**\n * Compose a 2D vector from four directional actions with a single radial\n * deadzone (Godot input.cpp three-branch formula). Uses `raw` (not\n * `strength`) to avoid per-axis deadzone stacking into a square deadzone\n * (AC-06).\n *\n * @param negX - Action name for negative X (e.g. 'moveLeft').\n * @param posX - Action name for positive X (e.g. 'moveRight').\n * @param negY - Action name for negative Y (e.g. 'moveUp').\n * @param posY - Action name for positive Y (e.g. 'moveDown').\n * @param opts - Optional override (deadzone).\n */\n getVector(\n negX: string,\n posX: string,\n negY: string,\n posY: string,\n opts?: GetVectorOptions,\n ): { readonly x: number; readonly y: number };\n}\n\n/**\n * Backend protocol consumed by the frame-start scan system. The browser\n * implementation (`browser-backend.ts`) is the production producer;\n * tests inject fakes that emit synthetic samples.\n */\nexport interface InputBackend {\n /**\n * Produce one frame's worth of input data and reset the per-frame\n * accumulators (movement delta + edge sets). Held-key state and\n * held-button state survive across calls. Browser producers latch edge\n * transitions when events arrive, so a down+up sequence between two scans\n * remains observable instead of being lost to the held-state projection.\n *\n * Contract notes:\n * - `downKeys` is the held-key set as of the call (held across frames)\n * - `upKeys` is the release-edge set since the previous sample (cleared\n * after the call so the edge appears in exactly one frame)\n * - `buttons` is the held-button slot tuple `[b0, b1, b2]`\n * - `movementX` / `movementY` are the accumulated PointerLock delta\n * since the previous sample (cleared after the call)\n * - `focused` mirrors `document.hasFocus()` so the scan system can\n * suppress spurious up-edges across alt-tab transitions\n */\n sample(): InputBackendSample;\n /**\n * Command-set game gate for pointer-lock. When set to `false`, the\n * backend will not request pointer-lock on click AND will immediately\n * release any currently active lock (W3C path: `exitPointerLock`;\n * provider path: `exitLock()`). When `true` (default), pointer-lock\n * can be requested through the normal gate logic.\n *\n * Optional -- backends without pointer-lock support omit this method.\n */\n setPointerLockAllowed?(allowed: boolean): void;\n /**\n * Gate physical/synthetic acquisition for a host lifecycle boundary. A\n * closed gate clears producer state and makes subsequent samples empty until\n * the gate is reopened; it is independent of pointer-lock policy.\n */\n setInputAllowed?(allowed: boolean): void;\n /**\n * Atomically discard acquired state without detaching listeners. A host calls\n * this when it revokes a control lease so held keys/buttons, contacts, frame\n * edges, deltas and pointer lock cannot bleed into a later consumer. Optional\n * keeps synthetic backends source-compatible.\n */\n clear?(): void;\n /** Detach DOM listeners; called when the engine shuts down. */\n detach(): void;\n}\n\n/** Snapshot value returned by `InputBackend.sample()` (POD). */\nexport interface InputBackendSample {\n readonly downKeys: ReadonlySet<string>;\n readonly upKeys: ReadonlySet<string>;\n /** Physical code identity (KeyboardEvent.code), when the producer has it. */\n readonly downCodes?: ReadonlySet<string>;\n /** One-frame physical code release edges, when the producer has them. */\n readonly upCodes?: ReadonlySet<string>;\n /** Logical key press edges latched since the previous frame-start scan. */\n readonly pressedKeys?: ReadonlySet<string>;\n /** Physical code press edges latched since the previous frame-start scan. */\n readonly pressedCodes?: ReadonlySet<string>;\n readonly buttons: readonly [boolean, boolean, boolean];\n /** Mouse button press edges latched since the previous frame-start scan. */\n readonly pressedButtons?: readonly [boolean, boolean, boolean];\n /** Mouse button release edges latched since the previous frame-start scan. */\n readonly releasedButtons?: readonly [boolean, boolean, boolean];\n readonly movementX: number;\n readonly movementY: number;\n /** Latest canvas-pixel mouse position; absent for non-pointer backends. */\n readonly mouseX?: number;\n readonly mouseY?: number;\n /**\n * Sign-discrete wheel notch accumulator since the previous sample\n * (plan-strategy D-5). Browser backend writes `Math.sign(deltaY)` per\n * `WheelEvent`; sample() drains the value and resets the producer\n * accumulator (mirrors movementX/Y semantics).\n */\n readonly wheelDelta: number;\n /** True for the first sample after blur/hidden state reset. */\n readonly focusReset?: boolean;\n readonly focused: boolean;\n /** M1+ gamepad per-slot frame data (optional — absent when backend lacks gamepad support). */\n readonly gamepads?: readonly GamepadSlotSample[];\n /** M1+ frozen capability snapshot (optional — absent for pre-M1 backends). */\n readonly capabilities?: Capabilities;\n /** M2+ active pointer contacts (optional — absent for keyboard-only backends). */\n readonly pointers?: readonly PointerSample[];\n /** M2+ per-frame phase event queue (optional — absent when no pointer events occurred). */\n readonly pointerEvents?: readonly PointerPhaseEvent[];\n /** M3+ virtual joystick axis outputs (optional — absent when no virtual joysticks configured). */\n readonly virtualAxes?: readonly VirtualAxisSample[];\n /** M5+ continuous gesture values (optional — absent when no gesture is active). */\n readonly gestures?: GestureState;\n /** M5+ per-frame gesture event queue (optional — absent when no gesture activity occurred). */\n readonly gestureEvents?: readonly GestureEvent[];\n /**\n * Merged pointer-lock state: true when either W3C pointer-lock is active\n * (pointerLockElement === this backend's canvas) OR the lockProvider path\n * has engaged (requestLock() was called and not yet released). Required\n * field -- always present, defaults to false when no lock is active.\n */\n readonly pointerLocked: boolean;\n}\n\n/** Build the neutral backend sample used before or outside an active consumer. */\nexport function createEmptyInputBackendSample(): InputBackendSample {\n return {\n downKeys: new Set<string>(),\n upKeys: new Set<string>(),\n buttons: [false, false, false],\n movementX: 0,\n movementY: 0,\n wheelDelta: 0,\n focused: true,\n pointerLocked: false,\n };\n}\n\n/**\n * Build an `InputSnapshot` from a backend sample. The returned object is\n * frozen on construction: `down/up/button` are bound to the closed-over\n * sets, and `movementDelta` is a frozen literal. Subsequent backend\n * activity does not bleed into the snapshot.\n */\nfunction emptyGamepadReader(): ReturnType<InputSnapshot['gamepad']> {\n return Object.freeze({\n connected: false,\n standardMapping: false,\n button(_b: GamepadButtonIndex): boolean {\n return false;\n },\n buttonValue(_b: GamepadButtonIndex): number {\n return 0;\n },\n justPressed(_b: GamepadButtonIndex): boolean {\n return false;\n },\n justReleased(_b: GamepadButtonIndex): boolean {\n return false;\n },\n axis(_a: GamepadAxisIndex): number {\n return 0;\n },\n });\n}\n\nfunction buildGamepadReader(slot: GamepadSlotSample): ReturnType<InputSnapshot['gamepad']> {\n if (!slot.standardMapping) {\n // AC-04: non-standard layout reports connected=true +\n // standardMapping=false + all readpoints empty signal.\n return Object.freeze({\n connected: true,\n standardMapping: false,\n button: emptyGamepadReader().button,\n buttonValue: emptyGamepadReader().buttonValue,\n justPressed: emptyGamepadReader().justPressed,\n justReleased: emptyGamepadReader().justReleased,\n axis: emptyGamepadReader().axis,\n });\n }\n return Object.freeze({\n connected: true,\n standardMapping: true,\n button(b: GamepadButtonIndex): boolean {\n return slot.pressed.has(b);\n },\n buttonValue(b: GamepadButtonIndex): number {\n return slot.buttonValues.get(b) ?? 0;\n },\n justPressed(b: GamepadButtonIndex): boolean {\n return slot.justPressed.has(b);\n },\n justReleased(b: GamepadButtonIndex): boolean {\n return slot.justReleased.has(b);\n },\n axis(a: GamepadAxisIndex): number {\n return slot.axes[a];\n },\n });\n}\n\n/**\n * Build an `InputSnapshot` from a backend sample.\n *\n * @param sample - One frame's raw input backend sample (POD).\n * @param actionStates - Optional per-frame derived action states from\n * deriveActionStates(). When provided, snap.action(name) returns mapped\n * values; when absent or empty, all action readpoints return empty signal\n * (charter P3: false/0, never throws). AC-11: actionStates is frozen into\n * the snapshot so same-frame re-reads return identical values.\n */\nexport function snapshotFromSample(\n sample: InputBackendSample,\n actionStates?: readonly ActionState[],\n inputMap?: readonly ActionConfig[],\n previousSnapshot?: InputSnapshot,\n): InputSnapshot {\n // structuralCopy: copying into local sets isolates the snapshot from\n // any later backend mutation (the browser backend reuses its internal\n // Set across frames). architecture-principles #2 derive: a Snapshot is\n // a derived view of the producer's state at one instant.\n const heldKeys = new Set<string>(sample.downKeys);\n const upEdges = new Set<string>(sample.upKeys);\n // Do not capture previousSnapshot in a callback: V8 can share that\n // context with the returned readers and retain the entire frame history.\n const justPressedKeys = new Set<string>(sample.pressedKeys);\n if (sample.pressedKeys === undefined) {\n for (const key of heldKeys) {\n if (!previousSnapshot?.keyboard.down(key)) justPressedKeys.add(key);\n }\n }\n const heldCodes = new Set<string>(sample.downCodes ?? []);\n const upCodeEdges = new Set<string>(sample.upCodes ?? []);\n const justPressedCodes = new Set<string>(sample.pressedCodes);\n if (sample.pressedCodes === undefined) {\n for (const code of heldCodes) {\n if (!previousSnapshot?.keyboard.downCode(code)) justPressedCodes.add(code);\n }\n }\n const buttons: readonly [boolean, boolean, boolean] = [\n sample.buttons[0],\n sample.buttons[1],\n sample.buttons[2],\n ];\n const justPressedButtons: readonly [boolean, boolean, boolean] =\n sample.pressedButtons === undefined\n ? [\n buttons[0] && (previousSnapshot === undefined || !previousSnapshot.mouse.button(0)),\n buttons[1] && (previousSnapshot === undefined || !previousSnapshot.mouse.button(1)),\n buttons[2] && (previousSnapshot === undefined || !previousSnapshot.mouse.button(2)),\n ]\n : [sample.pressedButtons[0], sample.pressedButtons[1], sample.pressedButtons[2]];\n const justReleasedButtons: readonly [boolean, boolean, boolean] =\n sample.releasedButtons === undefined\n ? [\n sample.focusReset !== true && previousSnapshot?.mouse.button(0) === true && !buttons[0],\n sample.focusReset !== true && previousSnapshot?.mouse.button(1) === true && !buttons[1],\n sample.focusReset !== true && previousSnapshot?.mouse.button(2) === true && !buttons[2],\n ]\n : [sample.releasedButtons[0], sample.releasedButtons[1], sample.releasedButtons[2]];\n const movementDelta = Object.freeze({ x: sample.movementX, y: sample.movementY });\n const mousePosition =\n sample.mouseX === undefined || sample.mouseY === undefined\n ? undefined\n : Object.freeze({ x: sample.mouseX, y: sample.mouseY });\n const wheelDelta = sample.wheelDelta;\n\n // D-9: use `??` empty-signal defaults for all new optional fields.\n const gamepadSlots: readonly GamepadSlotSample[] = sample.gamepads ?? [];\n const caps: Capabilities =\n sample.capabilities ?? Object.freeze({ gamepad: false, pointer: false });\n const pointerEvts: readonly PointerPhaseEvent[] = sample.pointerEvents ?? [];\n // D-4 / AC-12: no active gesture -> identity empty signal; gesture events\n // default to an empty one-frame queue (mirrors pointerEvents).\n const gesture: GestureState = sample.gestures ?? IDENTITY_GESTURE;\n const gestureEvts: readonly GestureEvent[] = sample.gestureEvents ?? [];\n // virtualAxes: consumed by M3 virtualAxis reader; stored as local for\n // the snapshot closure below.\n const _virtualAxes: readonly VirtualAxisSample[] = sample.virtualAxes ?? [];\n\n const virtualAxesMap = new Map<string, VirtualAxisSample>();\n for (const va of _virtualAxes) {\n virtualAxesMap.set(va.name, va);\n }\n\n // Build index→slot map so gamepad(i) looks up by slot.index, not array position.\n // The browser getGamepads() returns null-padded arrays where position IS the\n // index, but the diffGamepadFrame output is a sparse list keyed by .index.\n const gamepadSlotMap = new Map<number, GamepadSlotSample>();\n for (const slot of gamepadSlots) {\n gamepadSlotMap.set(slot.index, slot);\n }\n\n // Build action lookup map for snap.action(name) readpoint.\n const actionMap = new Map<string, ActionState>();\n if (actionStates) {\n for (const a of actionStates) {\n actionMap.set(a.action, a);\n }\n }\n\n function emptyActionReader(): ReturnType<InputSnapshot['action']> {\n return Object.freeze({\n isPressed: () => false,\n justPressed: () => false,\n justReleased: () => false,\n strength: 0,\n });\n }\n\n const snapshot: InputSnapshot = {\n keyboard: {\n down(key) {\n return heldKeys.has(key);\n },\n justPressed(key) {\n return justPressedKeys.has(key);\n },\n up(key) {\n return upEdges.has(key);\n },\n downCode(code) {\n return heldCodes.has(code);\n },\n justPressedCode(code) {\n return justPressedCodes.has(code);\n },\n upCode(code) {\n return upCodeEdges.has(code);\n },\n },\n mouse: {\n position: mousePosition,\n movementDelta,\n pointerLocked: sample.pointerLocked,\n button(i) {\n // i is narrowed to 0 | 1 | 2 by the type system; the runtime\n // index is therefore guaranteed to land in `buttons` (charter P3\n // -- no defensive fallback necessary because the type narrows the\n // input domain to the legal slots).\n return buttons[i] === true;\n },\n justPressed(i) {\n return justPressedButtons[i] === true;\n },\n justReleased(i) {\n return justReleasedButtons[i] === true;\n },\n wheelDelta,\n },\n gamepad(i) {\n const slot = gamepadSlotMap.get(i);\n if (!slot) return emptyGamepadReader();\n return buildGamepadReader(slot);\n },\n capabilities: caps,\n pointer(id) {\n const entry = (sample.pointers ?? []).find((p) => p.pointerId === id);\n if (!entry) {\n return Object.freeze({\n active: false,\n pointerId: -1,\n x: 0,\n y: 0,\n pressure: 0,\n pointerType: 'mouse' as PointerType,\n delta: Object.freeze({ x: 0, y: 0 }),\n });\n }\n return Object.freeze({\n ...entry,\n delta: Object.freeze({ x: entry.delta.x, y: entry.delta.y }),\n });\n },\n virtualAxis(name) {\n const va = virtualAxesMap.get(name);\n if (!va) return Object.freeze({ x: 0, y: 0 });\n return Object.freeze({ x: va.x, y: va.y });\n },\n action(name) {\n const s = actionMap.get(name);\n if (!s) return emptyActionReader();\n return Object.freeze({\n isPressed: () => s.pressed,\n justPressed: () => s.justPressed,\n justReleased: () => s.justReleased,\n strength: s.strength,\n });\n },\n getAxis(neg, pos) {\n if (!actionStates || !inputMap) return 0;\n return getAxis(inputMap, actionStates, neg, pos);\n },\n getVector(negX, posX, negY, posY, opts) {\n if (!actionStates || !inputMap) return { x: 0, y: 0 };\n return getVector(inputMap, actionStates, negX, posX, negY, posY, opts);\n },\n pointerEvents: pointerEvts,\n gesture,\n gestureEvents: gestureEvts,\n };\n (snapshot as unknown as Record<string, unknown>)._actionStates = actionStates;\n (snapshot as unknown as Record<string, unknown>)._inputMap = inputMap;\n return Object.freeze(snapshot);\n}\n\n/**\n * @internal Read previously derived action states from a snapshot for edge diff.\n * Used by the frame-start scan system (D-6: prev snapshot = edge baseline).\n */\nexport function readActionStatesForEdgeDiff(\n snap: InputSnapshot,\n): readonly ActionState[] | undefined {\n return (snap as unknown as { _actionStates?: readonly ActionState[] })._actionStates;\n}\n\n/**\n * Construct an empty snapshot for the pre-start window\n * (`engine.run()` has not yet attached a backend). Returns the full\n * multi-device shape as `snapshotFromSample`, with every accessor\n * returning `false` / `0` / zero-vector. AI users can put this into the\n * Resource store to satisfy `world.getResource('InputSnapshot')` calls\n * in fixtures or unit tests (charter P3: empty signal is the signal).\n * The underlying 7-field POD sample contract is unchanged (D-9).\n */\nexport function createInputSnapshot(): InputSnapshot {\n return snapshotFromSample(createEmptyInputBackendSample());\n}\n\n/** Stable Resource key for `world.insertResource` / `world.getResource`. */\nexport const INPUT_SNAPSHOT_RESOURCE_KEY = 'InputSnapshot';\n","/** Event-path ownership and lifecycle reset primitives for browser hosts. */\n\nexport interface UiOwnershipResult {\n readonly owned: boolean;\n readonly source: 'composed-path' | 'target-fallback' | 'unknown';\n}\n\nexport interface UiInputResetBoundaryOptions {\n readonly clear: () => void;\n readonly signal?: AbortSignal;\n}\n\nexport interface UiInputResetBoundary {\n readonly reset: () => void;\n readonly dispose: () => void;\n}\n\nfunction contains(root: Node, value: EventTarget | null): boolean {\n const NodeCtor = globalThis.Node;\n return NodeCtor && value instanceof NodeCtor ? value === root || root.contains(value) : false;\n}\n\nexport function resolveUiOwnership(event: Event, host: Node): UiOwnershipResult {\n const path = event.composedPath;\n if (typeof path === 'function') {\n const composed = path.call(event);\n return {\n owned:\n composed.some((item) => contains(host, item)) ||\n (composed.length === 0 && contains(host, event.target)),\n source: composed.length === 0 ? 'target-fallback' : 'composed-path',\n };\n }\n if ('target' in event) {\n return { owned: contains(host, event.target), source: 'target-fallback' };\n }\n return { owned: false, source: 'unknown' };\n}\n\nexport function isUiOwnedEvent(event: Event, host: Node): boolean {\n return resolveUiOwnership(event, host).owned;\n}\n\nexport function createUiInputResetBoundary(\n options: UiInputResetBoundaryOptions,\n): UiInputResetBoundary {\n let disposed = false;\n const reset = (): void => {\n if (!disposed) options.clear();\n };\n const onAbort = (): void => reset();\n options.signal?.addEventListener('abort', onAbort, { once: true });\n return {\n reset,\n dispose: () => {\n if (disposed) return;\n disposed = true;\n options.signal?.removeEventListener('abort', onAbort);\n },\n };\n}\n","// virtual-joystick.ts -- pure-function virtual joystick derivation (M3).\n//\n// No DOM dependency; backend closure holds per-joystick bindState\n// and calls deriveVirtualAxes each sample() frame.\n//\n// @internal -- only the browser backend calls these functions; the\n// barrel does not re-export them.\n\nimport type { VirtualAxisSample, VirtualJoystickConfig } from './input-snapshot';\n\n/**\n * Per-joystick binding state. The backend closure owns a\n * Map<string, BindState> keyed by joystick config name.\n */\nexport interface BindState {\n /** bound pointerId, or undefined if unbound */\n pointerId?: number | undefined;\n /** origin in canvas pixels (anchor for fixed, first-touch for floating) */\n originX: number;\n originY: number;\n}\n\nfunction computeVec(\n ptrX: number,\n ptrY: number,\n originX: number,\n originY: number,\n radius: number,\n deadzone: number,\n): { x: number; y: number } {\n const rawX = (ptrX - originX) / radius;\n const rawY = (ptrY - originY) / radius;\n const mag = Math.sqrt(rawX * rawX + rawY * rawY);\n if (mag < deadzone) return { x: 0, y: 0 };\n if (mag > 1) {\n // Clamp to unit vector: normalize direction, magnitude = 1.\n return { x: rawX / mag, y: rawY / mag };\n }\n return { x: rawX, y: rawY };\n}\n\n/**\n * Derive one frame of virtual axis outputs from live pointer state and\n * per-joystick binding state.\n *\n * Pure function: no DOM access. The backend closure is the SSOT for\n * per-joystick state; binding + origin selection happens in\n * browser-backend.ts onPointerDown. This function only reads bindState\n * and computes per-frame vectors.\n *\n * Unbound joysticks always produce the zero vector.\n *\n * @param configs - configured virtual joysticks\n * @param pointerMap - live pointer positions keyed by pointerId\n * @param bindState - per-joystick binding state (read-only)\n * @returns one VirtualAxisSample per configured joystick\n */\nexport function deriveVirtualAxes(\n configs: readonly VirtualJoystickConfig[],\n pointerMap: Map<number, { readonly x: number; readonly y: number }>,\n bindState: Map<string, BindState>,\n): VirtualAxisSample[] {\n const results: VirtualAxisSample[] = [];\n\n for (const cfg of configs) {\n const bs = bindState.get(cfg.name);\n\n if (bs?.pointerId !== undefined) {\n // Bound: compute vector from current pointer position.\n const ptr = pointerMap.get(bs.pointerId);\n if (ptr) {\n const vec = computeVec(ptr.x, ptr.y, bs.originX, bs.originY, cfg.radius, cfg.deadzone);\n results.push({ name: cfg.name, x: vec.x, y: vec.y });\n } else {\n // Pointer disappeared (up/cancel handled by backend unbind,\n // but this guards against pointer removal without unbind).\n bs.pointerId = undefined;\n results.push({ name: cfg.name, x: 0, y: 0 });\n }\n } else {\n // Unbound: zero vector. Binding is the backend's responsibility.\n results.push({ name: cfg.name, x: 0, y: 0 });\n }\n }\n\n return results;\n}\n\n/**\n * Unbind a joystick when its bound pointer goes up or is cancelled.\n * Sets pointerId to undefined; the next deriveVirtualAxes call will\n * produce a zero vector for the unbound joystick.\n */\nexport function handleVirtualJoystickUnbind(\n bindState: Map<string, BindState>,\n pointerId: number,\n): void {\n for (const bs of bindState.values()) {\n if (bs.pointerId === pointerId) {\n bs.pointerId = undefined;\n }\n }\n}\n","// browser-backend.ts -- DOM PointerLock + keyboard / mouse listener producer.\n//\n// charter awareness:\n// F2 minimal surface -- exposes only `attachBrowserInputBackend(canvas)`\n// returning a `(): void` detach handle; PointerLock + listener wiring\n// is internal (plan OOS-1 explicit -- not part of the user-facing\n// surface)\n// P3 explicit failure -- detach is part of the contract; double-detach\n// is a no-op (idempotent)\n// P4 consistent abstraction -- the snapshot consumer does not see\n// PointerLock state machine or `movementX/Y` units; only\n// `mouse.movementDelta`\n// P5 producer/consumer split -- this file is the only DOM-touching\n// surface in the package; everything else operates on the\n// `InputBackend` protocol (see input-snapshot.ts)\n//\n// Note: the actual PointerLock pump runs in a real browser; node-based\n// vitest unit tests inject fake backends through the `InputBackend`\n// protocol. The browser-mode coverage of this file is the M2b layer\n// (plan-strategy section 5.4 reason for the 70% floor).\n\nimport type { ControllerDb, MappingTokens } from './controller-db';\nimport { diffGamepadFrame, type RawGamepadStub } from './gamepad-frame';\nimport {\n createRecognizerState,\n type GestureEvent,\n type GestureState,\n processGestureFrame,\n type RecognizerPointer,\n type RecognizerState,\n} from './gesture-recognizer';\nimport type {\n Capabilities,\n GamepadSlotSample,\n InputBackend,\n InputBackendSample,\n PointerPhaseEvent,\n PointerSample,\n PointerType,\n VirtualAxisSample,\n VirtualJoystickConfig,\n} from './input-snapshot';\nimport { createEmptyInputBackendSample } from './input-snapshot';\nimport { isUiOwnedEvent } from './ui-ownership';\nimport { type BindState, deriveVirtualAxes, handleVirtualJoystickUnbind } from './virtual-joystick';\n\n// D-5: normalize W3C PointerEvent.pointerType to the canonical 3-literal union.\n// The spec allows '' when device type is undetectable; we map it to 'mouse' so\n// the snapshot consumers (action matchers, gesture recognizers) can exhaustively\n// switch on PointerType without a default branch (AC-19).\nexport function coercePointerType(raw: string): PointerType {\n if (raw === 'pen') return 'pen';\n if (raw === 'touch') return 'touch';\n return 'mouse';\n}\n\n/**\n * Options accepted by `attachBrowserInputBackend`.\n */\nexport interface BrowserInputBackendOptions {\n /** Optional host-owned UI root. Events in this root never reach gameplay. */\n readonly uiRoot?: Node;\n /**\n * Optional document handle (testing override). Defaults to `document`.\n * Plan-strategy section 9 row 7 (`document.hasFocus()` semantics)\n * relies on this to decide whether the up-edge set should be cleared\n * when focus is lost.\n */\n readonly document?: Document;\n /**\n * Optional window handle (testing override). Defaults to `window`.\n * Used to attach key listeners (capturing focus loss) without\n * requiring the canvas itself to receive keyboard events.\n */\n readonly window?: Window;\n /**\n * Neutral gate for the auto PointerLock-on-click. When provided and it\n * returns false, the click handler skips `requestPointerLock()` — the host\n * decides whether a click should capture the cursor right now. Defaults to\n * always-locking (returns true), so the standalone game runtime keeps its\n * MVP behaviour unchanged. This predicate is deliberately host-opaque: the\n * backend never learns WHY locking is (dis)allowed — it only asks. A host\n * that mounts this canvas in a non-game context (e.g. an editor viewport\n * that owns the cursor for orbit/pick) supplies a predicate that returns\n * false there. The input package carries zero knowledge of those contexts.\n */\n readonly pointerLockAllowed?: () => boolean;\n /**\n * Optional navigator handle (testing override). Defaults to\n * `globalThis.navigator`. Used to poll `navigator.getGamepads()` each\n * frame. Mirrors the `document`/`window` override pattern.\n */\n readonly navigator?: { getGamepads?(): (Gamepad | null)[] };\n /**\n * Optional virtual joystick configurations (M3). When provided, the\n * backend auto-binds the first pointerdown within each config's region\n * and derives per-frame VirtualAxisSample outputs via deriveVirtualAxes.\n */\n readonly virtualJoysticks?: readonly VirtualJoystickConfig[];\n /**\n * Optional SDL controller DB text loader (M3 D-13 test injection). When\n * omitted, the backend dynamic-imports the vendored 554KB DB from\n * `@forgeax/engine-input/controller-db-data` on first sight of a\n * non-standard gamepad (D-2 lazy-load: the 554KB never sits in the\n * default path). Tests inject a synthetic DB string to avoid loading the\n * real vendored file. Returns the raw gamecontrollerdb.txt contents.\n */\n readonly loadControllerDb?: () => Promise<string>;\n /**\n * Optional monotonic clock (M5 D-3 test injection). Defaults to\n * `() => performance.now()`. The gesture recognizer advances all timers\n * (long-press duration, double-tap / swipe windows) off this clock, NOT\n * off pointer-event arrival, so recognition stays decoupled from event\n * frequency (AC-16). Tests inject a fake clock for deterministic timing,\n * mirroring the `document` / `window` / `navigator` override pattern.\n */\n readonly now?: () => number;\n /**\n * Optional lock provider (D-2). When provided, pointer-lock requests\n * route through requestLock() / exitLock() instead of the W3C\n * requestPointerLock / exitPointerLock API. The backend remains\n * host-opaque -- it never learns whether the provider wraps Tauri\n * native-grab, postMessage, or any other mechanism.\n */\n readonly lockProvider?: PointerLockProvider;\n /**\n * Optional callback for lock request failures (D-4). When W3C\n * requestPointerLock rejects or lockProvider.requestLock/exitLock\n * throws/rejects, the backend calls this with a detail object.\n * Without this callback, failures are silently caught (backward\n * compatible but contrary to charter P3).\n */\n readonly onLockError?: (detail: { path: 'w3c' | 'provider'; cause: unknown }) => void;\n}\n\n/**\n * Lock provider interface (D-2). A host injects this to replace the\n * W3C Pointer Lock API path. requestLock() may return void (fire-and-forget,\n * D-7 optimistic placement) or Promise<void> (awaitable). exitLock() is\n * called when the backend needs to release the lock (ESC / blur / detach /\n * setPointerLockAllowed(false)).\n */\nexport interface PointerLockProvider {\n /**\n * Request pointer lock. The backend optimistically sets providerLocked=true\n * when this is called (D-7). On throw/reject, the backend calls onLockError\n * and rolls back providerLocked.\n */\n requestLock(): void | Promise<void>;\n /** Release pointer lock. */\n exitLock(): void;\n}\n\n/**\n * Attach DOM listeners (keydown / keyup / mousedown / mouseup /\n * pointerlockchange / mousemove inside lock / blur) to `canvas` and the\n * surrounding window. Returns a `detach` callable that:\n *\n * - removes all listeners\n * - exits PointerLock if currently locked\n * - drops every internal accumulator\n *\n * The returned object also implements the `InputBackend` protocol -- the\n * runtime inserts it under `INPUT_BACKEND_KEY` and adds the\n * `InputFrameStartScan` system, which reads it back each tick.\n * Calling `detach()` and the protocol's `detach()` are equivalent\n * (idempotent; double-detach is safe -- charter P3).\n */\nexport function attachBrowserInputBackend(\n canvas: HTMLCanvasElement,\n options: BrowserInputBackendOptions = {},\n): (() => void) & { backend: InputBackend } {\n const doc = options.document ?? globalThis.document;\n const win = options.window ?? globalThis.window;\n\n const heldKeys = new Set<string>();\n const upEdges = new Set<string>();\n const heldCodes = new Set<string>();\n const upCodeEdges = new Set<string>();\n const pressedKeys = new Set<string>();\n const pressedCodes = new Set<string>();\n const buttons: [boolean, boolean, boolean] = [false, false, false];\n const pressedButtons: [boolean, boolean, boolean] = [false, false, false];\n const releasedButtons: [boolean, boolean, boolean] = [false, false, false];\n let mvx = 0;\n let mvy = 0;\n let wheelAccum = 0;\n let detached = false;\n\n const isUiEvent = (event: Event): boolean =>\n options.uiRoot !== undefined && isUiOwnedEvent(event, options.uiRoot);\n\n // w6: merged pointer-lock state tracking (D-1).\n // w3cLocked is driven by document-level pointerlockchange events,\n // isolated per-instance by comparing pointerLockElement === this canvas.\n let w3cLocked = false;\n // providerLocked is set optimistically when lockProvider.requestLock()\n // is called (D-7); cleared by exitLock() or on rejection.\n let providerLocked = false;\n // gameGate is a command-set boolean (setPointerLockAllowed), default true.\n let gameGate = true;\n // Startup overlays and other host lifecycle boundaries gate acquisition at\n // the producer, so events cannot become stale gameplay input at the next\n // frame-start scan.\n let inputAllowed = true;\n\n function emitLockError(path: 'w3c' | 'provider', cause: unknown): void {\n try {\n options.onLockError?.({ path, cause });\n } catch {\n // Lock diagnostics are observational; a throwing host callback must not\n // create a second unhandled rejection from the browser Promise path.\n }\n }\n\n // w8 (D-1/D-3): release the provider lock idempotently. Calls the injected\n // exitLock (routing any throw to onLockError as { path: 'provider' }) and\n // clears providerLocked unconditionally. Shared by every provider-release\n // site (ESC, blur, setPointerLockAllowed(false), detach) so the release\n // semantics live in one place.\n function releaseProviderLock(): void {\n if (providerLocked && options.lockProvider?.exitLock) {\n try {\n options.lockProvider.exitLock();\n } catch (err: unknown) {\n emitLockError('provider', err);\n }\n }\n providerLocked = false;\n }\n\n // D-4: capability detected once at attach time.\n const nav =\n options.navigator ?? (globalThis as { navigator?: { getGamepads?(): unknown } }).navigator;\n const gamepadAvailable = typeof nav?.getGamepads === 'function';\n const pointerAvailable = typeof globalThis.PointerEvent !== 'undefined';\n const caps: Capabilities = { gamepad: gamepadAvailable, pointer: pointerAvailable };\n\n // D-1: prevGamepadFrame is the only cross-frame state holder for gamepad diff.\n // Stored in backend closure; diffGamepadFrame compares prev vs cur each sample().\n let prevGamepadFrame = new Map<number, GamepadSlotSample>();\n // Focus loss discards the old physical frame. The first successful sample\n // afterwards establishes a new baseline instead of turning a still-held\n // button into a synthetic justPressed edge.\n let gamepadBaselinePending = false;\n let focusResetPending = false;\n\n // M3 D-2 lazy-load state. The SDL DB (554KB) is loaded once, on first sight\n // of a non-standard gamepad, then cached here. `controllerDb` stays\n // undefined until the async load resolves; frames before that keep the\n // Feat1 empty signal (graceful degradation). `dbLoadStarted` prevents\n // re-triggering the load on every frame while the promise is pending.\n let controllerDb: ControllerDb | undefined;\n let dbLoadStarted = false;\n // Per-id GUID resolution cache (avoids re-parsing the same Gamepad.id).\n const guidCache = new Map<string, string | undefined>();\n\n // M3 D-13: the DB parser + GUID helpers live in the pure controller-db\n // module. They are dynamic-imported alongside the data so neither the\n // parser nor the 554KB vendored text enters the main-entry bundle.\n let controllerDbApi:\n | {\n parseControllerDb: (txt: string) => ControllerDb;\n extractGuidFromGamepadId: (id: string) => string | undefined;\n selectBestMappingEntry: (\n db: ControllerDb,\n guid: string,\n platform: string | undefined,\n ) => { readonly tokens: MappingTokens } | undefined;\n platformFromUserAgent: (ua: string) => string | undefined;\n }\n | undefined;\n\n function kickOffDbLoad(): void {\n if (dbLoadStarted) return;\n dbLoadStarted = true;\n const loadApi = controllerDbApi\n ? Promise.resolve(controllerDbApi)\n : import('@forgeax/engine-input/controller-db').then((m) => {\n controllerDbApi = m;\n return m;\n });\n const loadText = options.loadControllerDb\n ? options.loadControllerDb()\n : import('@forgeax/engine-input/controller-db-data').then((m) => m.loadBundledControllerDb());\n Promise.all([loadApi, loadText])\n .then(([api, txt]) => {\n controllerDb = api.parseControllerDb(txt);\n })\n .catch(() => {\n // Load failed (offline chunk / bad text): keep the Feat1 empty\n // signal. Reset so a later frame may retry.\n dbLoadStarted = false;\n });\n }\n\n // Acquisition-layer remap lookup passed to diffGamepadFrame. Returns the\n // standard-layout mapping tokens for a Gamepad.id, or null when the DB is\n // not yet loaded / the GUID is unextractable / no DB entry matches.\n function remapLookup(gamepadId: string): MappingTokens | null {\n if (!controllerDb || !controllerDbApi) return null;\n let guid = guidCache.get(gamepadId);\n if (!guidCache.has(gamepadId)) {\n guid = controllerDbApi.extractGuidFromGamepadId(gamepadId);\n guidCache.set(gamepadId, guid);\n }\n if (!guid) return null;\n const ua =\n typeof globalThis.navigator?.userAgent === 'string' ? globalThis.navigator.userAgent : '';\n const platform = controllerDbApi.platformFromUserAgent(ua);\n const entry = controllerDbApi.selectBestMappingEntry(controllerDb, guid, platform);\n return entry ? entry.tokens : null;\n }\n\n // w15: pointer map (pointerId → live position), phase queue (one-frame lifecycle),\n // and per-pointer previous position for cross-frame delta.\n const pointerMap = new Map<\n number,\n {\n x: number;\n y: number;\n pressure: number;\n pointerType: PointerType;\n prevX: number;\n prevY: number;\n }\n >();\n const phaseQueue: PointerPhaseEvent[] = [];\n let mouseX: number | undefined;\n let mouseY: number | undefined;\n\n // w21: virtual joystick binding state (per-joystick name → BindState).\n const vjConfigs = options.virtualJoysticks ?? [];\n const vjBindState = new Map<string, BindState>();\n\n // M5 D-3/D-4: gesture recognizer cross-frame state lives in this closure\n // (C-3: the only sanctioned cross-frame gesture holder, alongside\n // prevGamepadFrame / pointerMap / vjBindState). `now` is injectable for\n // deterministic test timing; production uses performance.now().\n const now = options.now ?? (() => performance.now());\n let recognizerState: RecognizerState = createRecognizerState();\n\n // DPR coordinate helpers. computePointerCoords applies the standard DPR-correct\n // canvas-pixel formula; falls back to clientX/clientY when getBoundingClientRect\n // is missing (fake canvas in unit tests).\n function computePointerCoords(ev: PointerEvent): { x: number; y: number } {\n const rect = canvas.getBoundingClientRect?.();\n if (!rect) return { x: ev.clientX, y: ev.clientY };\n const scaleX = canvas.width / rect.width;\n const scaleY = canvas.height / rect.height;\n return {\n x: (ev.clientX - rect.left) * scaleX,\n y: (ev.clientY - rect.top) * scaleY,\n };\n }\n\n function isFocused(): boolean {\n // `document.hasFocus()` indicates whether the tab is foreground;\n // when unfocused we suppress up-edges so stale releases do not fire\n // after alt-tabbing back (section 9 row 7).\n return typeof doc?.hasFocus === 'function' ? doc.hasFocus() : true;\n }\n\n function onKeyDown(ev: KeyboardEvent): void {\n if (!inputAllowed) return;\n if (isUiEvent(ev)) {\n clear();\n return;\n }\n if (!heldKeys.has(ev.key)) pressedKeys.add(ev.key);\n heldKeys.add(ev.key);\n if (ev.code) {\n if (!heldCodes.has(ev.code)) pressedCodes.add(ev.code);\n heldCodes.add(ev.code);\n }\n // w8 (D-1): ESC releases provider lock (W3C path handles ESC via browser\n // pointerlockchange). Only acts when providerLocked is true.\n if (ev.key === 'Escape' && providerLocked) {\n releaseProviderLock();\n }\n }\n function onKeyUp(ev: KeyboardEvent): void {\n if (!inputAllowed) return;\n if (isUiEvent(ev)) return;\n heldKeys.delete(ev.key);\n if (isFocused()) {\n upEdges.add(ev.key);\n }\n if (ev.code) {\n heldCodes.delete(ev.code);\n if (isFocused()) upCodeEdges.add(ev.code);\n }\n }\n function onPointerDown(ev: PointerEvent): void {\n if (!inputAllowed) return;\n if (isUiEvent(ev)) {\n clear();\n return;\n }\n // Only mouse-type pointers affect the mouse button cluster (D-3).\n if (ev.pointerType === 'mouse') {\n if (ev.button === 0 || ev.button === 1 || ev.button === 2) {\n if (!buttons[ev.button]) pressedButtons[ev.button] = true;\n buttons[ev.button] = true;\n }\n }\n // D-5: setPointerCapture for coherent pointer event dispatching — but NOT\n // while pointer lock is active. Pointer capture and pointer lock are mutually\n // exclusive (W3C): setPointerCapture throws InvalidStateError when the element\n // already holds the lock. Under lock the cursor is confined and every pointer\n // event already targets the locked element, so capture is redundant anyway.\n // The try/catch is belt-and-suspenders for the race where lock/capture state\n // flips between the pointerlockchange event and this handler.\n if (!w3cLocked && !providerLocked && typeof canvas.setPointerCapture === 'function') {\n try {\n canvas.setPointerCapture(ev.pointerId);\n } catch {\n /* capture illegal in the current pointer state (e.g. just-acquired lock) — safe to skip */\n }\n }\n // Track pointer in map for multi-pointer + delta (w15).\n const coords = computePointerCoords(ev);\n if (ev.pointerType === 'mouse') {\n mouseX = coords.x;\n mouseY = coords.y;\n }\n pointerMap.set(ev.pointerId, {\n x: coords.x,\n y: coords.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n prevX: coords.x,\n prevY: coords.y,\n });\n phaseQueue.push({\n pointerId: ev.pointerId,\n phase: 'down',\n x: coords.x,\n y: coords.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n });\n // w21: virtual joystick auto-bind -- first config whose region contains\n // the pointerdown position, if not already bound to another pointer.\n if (vjConfigs.length > 0) {\n for (const cfg of vjConfigs) {\n const { region } = cfg;\n if (\n coords.x >= region.x &&\n coords.x <= region.x + region.width &&\n coords.y >= region.y &&\n coords.y <= region.y + region.height\n ) {\n const existing = vjBindState.get(cfg.name);\n if (!existing?.pointerId) {\n const originX =\n cfg.mode === 'fixed' ? (cfg.anchor?.x ?? region.x + region.width / 2) : coords.x;\n const originY =\n cfg.mode === 'fixed' ? (cfg.anchor?.y ?? region.y + region.height / 2) : coords.y;\n if (existing) {\n existing.pointerId = ev.pointerId;\n existing.originX = originX;\n existing.originY = originY;\n } else {\n vjBindState.set(cfg.name, { pointerId: ev.pointerId, originX, originY });\n }\n // Only bind the first matching config per pointerdown.\n break;\n }\n }\n }\n }\n }\n function onPointerUp(ev: PointerEvent): void {\n if (!inputAllowed) return;\n if (isUiEvent(ev)) return;\n if (ev.pointerType === 'mouse') {\n if (ev.button === 0 || ev.button === 1 || ev.button === 2) {\n if (buttons[ev.button]) releasedButtons[ev.button] = true;\n buttons[ev.button] = false;\n }\n }\n const entry = pointerMap.get(ev.pointerId);\n if (entry) {\n phaseQueue.push({\n pointerId: ev.pointerId,\n phase: 'up',\n x: entry.x,\n y: entry.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n });\n pointerMap.delete(ev.pointerId);\n }\n // w21: unbind virtual joystick bound to this pointer.\n if (vjBindState.size > 0) {\n handleVirtualJoystickUnbind(vjBindState, ev.pointerId);\n }\n }\n function onPointerMove(ev: PointerEvent): void {\n if (!inputAllowed) return;\n if (isUiEvent(ev)) return;\n // D-3: movementDelta from pointermove (PointerEvent extends MouseEvent).\n if (ev.pointerType === 'mouse') {\n mvx += ev.movementX;\n mvy += ev.movementY;\n }\n // Update live position; prevX/prevY NOT updated here (AC-09: prev only\n // snapshots at sample() time, preventing Bevy #12442 zero-delta bug).\n const coords = computePointerCoords(ev);\n if (ev.pointerType === 'mouse') {\n mouseX = coords.x;\n mouseY = coords.y;\n }\n const entry = pointerMap.get(ev.pointerId);\n if (entry) {\n entry.x = coords.x;\n entry.y = coords.y;\n entry.pressure = ev.pressure;\n phaseQueue.push({\n pointerId: ev.pointerId,\n phase: 'move',\n x: coords.x,\n y: coords.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n });\n }\n }\n function onPointerCancel(ev: PointerEvent): void {\n if (!inputAllowed) return;\n if (isUiEvent(ev)) return;\n const entry = pointerMap.get(ev.pointerId);\n if (entry) {\n phaseQueue.push({\n pointerId: ev.pointerId,\n phase: 'cancel',\n x: entry.x,\n y: entry.y,\n pressure: ev.pressure,\n pointerType: coercePointerType(ev.pointerType),\n });\n pointerMap.delete(ev.pointerId);\n }\n // w21: unbind virtual joystick on pointer cancel.\n if (vjBindState.size > 0) {\n handleVirtualJoystickUnbind(vjBindState, ev.pointerId);\n }\n }\n function onVisibilityChange(): void {\n if (doc.visibilityState === 'hidden') {\n onBlur();\n }\n }\n function onWheel(ev: WheelEvent): void {\n if (!inputAllowed) return;\n if (isUiEvent(ev)) {\n clear();\n return;\n }\n // plan-strategy D-5 sign-discrete normalization: collapse `WheelEvent`\n // across the three `deltaMode` units (PIXEL / LINE / PAGE) by taking\n // `Math.sign(deltaY)` per event. Trade-off documented at the\n // InputSnapshot.mouse.wheelDelta JSDoc + plan-strategy R-7.\n const dy = ev.deltaY;\n if (typeof dy === 'number' && dy !== 0) {\n wheelAccum += dy > 0 ? 1 : -1;\n }\n }\n function onBlur(): void {\n // A standalone backend preserves its current-frame cancellation semantics.\n // A host control boundary calls clear() separately on the same blur event so\n // no state crosses a lease; the source itself still emits cancellation to its\n // sole consumer as it did before ownership routing existed.\n upEdges.clear();\n upCodeEdges.clear();\n pressedKeys.clear();\n pressedCodes.clear();\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n heldKeys.clear();\n heldCodes.clear();\n buttons[0] = false;\n buttons[1] = false;\n buttons[2] = false;\n mvx = 0;\n mvy = 0;\n wheelAccum = 0;\n // Pointer lock is not allowed to survive a focus boundary. Publish the\n // unlocked state synchronously; pointerlockchange may arrive later (or\n // be suppressed by the browser while the document is hidden).\n if (typeof doc.exitPointerLock === 'function' && doc.pointerLockElement === canvas) {\n doc.exitPointerLock();\n }\n w3cLocked = false;\n releaseProviderLock();\n if (pointerMap.size > 0) {\n for (const [id, entry] of pointerMap) {\n phaseQueue.push({\n pointerId: id,\n phase: 'cancel',\n x: entry.x,\n y: entry.y,\n pressure: entry.pressure,\n pointerType: entry.pointerType,\n });\n }\n pointerMap.clear();\n }\n prevGamepadFrame.clear();\n gamepadBaselinePending = true;\n focusResetPending = true;\n vjBindState.clear();\n }\n\n // Use try-blocks: jsdom / fake canvases passed by tests may lack\n // `addEventListener`. We probe and skip silently to keep the unit-test\n // surface workable (charter P3: detach must always succeed even if\n // attach was a partial wiring).\n const safeAdd = <K extends string>(\n target: { addEventListener?: (k: K, h: EventListener) => void } | undefined,\n kind: K,\n handler: EventListener,\n ): void => {\n target?.addEventListener?.(kind, handler);\n };\n const safeRemove = <K extends string>(\n target: { removeEventListener?: (k: K, h: EventListener) => void } | undefined,\n kind: K,\n handler: EventListener,\n ): void => {\n target?.removeEventListener?.(kind, handler);\n };\n\n safeAdd(win, 'keydown', onKeyDown as EventListener);\n safeAdd(win, 'keyup', onKeyUp as EventListener);\n safeAdd(win, 'blur', onBlur as EventListener);\n safeAdd(canvas, 'pointerdown', onPointerDown as EventListener);\n safeAdd(canvas, 'pointerup', onPointerUp as EventListener);\n safeAdd(canvas, 'pointermove', onPointerMove as EventListener);\n safeAdd(canvas, 'pointercancel', onPointerCancel as EventListener);\n safeAdd(canvas, 'wheel', onWheel as EventListener);\n safeAdd(doc, 'visibilitychange', onVisibilityChange as EventListener);\n\n // w6 (D-1): track W3C pointer-lock state via document-level pointerlockchange.\n // Per-instance isolation: only update w3cLocked when pointerLockElement matches\n // this backend's canvas. A native unlock is also a lifecycle boundary: browsers\n // do not all pair an OS focus transition with a DOM blur event, so clear the\n // physical frame when an owned lock exits after being acquired.\n function onPointerLockChange(): void {\n const wasLocked = w3cLocked;\n w3cLocked = doc.pointerLockElement === canvas;\n if (wasLocked && !w3cLocked && !providerLocked) onBlur();\n }\n safeAdd(doc, 'pointerlockchange', onPointerLockChange as EventListener);\n\n function onPointerLockError(event: Event): void {\n emitLockError('w3c', event);\n }\n safeAdd(doc, 'pointerlockerror', onPointerLockError as EventListener);\n\n // PointerLock entry must be triggered by user activation (W3C requires\n // a click / keydown handler to call `requestPointerLock()`). The MVP\n // wires a click listener on the canvas as the activation surface;\n // OOS-1 keeps any explicit \"request lock\" / \"exit lock\" surface out\n // of the snapshot itself.\n // D-5: touch-action:none on the canvas so the browser does not interpret\n // touch gestures (scroll/pinch/zoom) and deprioritizes pointer events.\n // Presence-detect .style (fake canvas in unit tests may lack it).\n let _prevTouchAction: string | undefined;\n if (canvas.style) {\n _prevTouchAction = canvas.style.touchAction;\n canvas.style.touchAction = 'none';\n }\n\n function onCanvasClick(): void {\n if (!inputAllowed) return;\n // D-3: dual gate synthesis -- gameGate (command-set by template) AND\n // hostPredicate (per-click evaluated by host). Both must pass to proceed.\n if (!gameGate) return;\n // Host gate: when the host says \"not now\" (e.g. an editor viewport that owns\n // the cursor outside the play-game quadrant) skip the lock entirely. Default\n // is always-allow, so the standalone game runtime is unchanged.\n if (options.pointerLockAllowed && !options.pointerLockAllowed()) return;\n // D-2 / D-7: lockProvider path takes priority over W3C.\n if (options.lockProvider) {\n providerLocked = true; // D-7 optimistic placement\n try {\n const result = options.lockProvider.requestLock();\n if (result && typeof (result as Promise<void>).catch === 'function') {\n (result as Promise<void>).catch((cause: unknown) => {\n providerLocked = false;\n emitLockError('provider', cause);\n });\n }\n } catch (cause: unknown) {\n // Synchronous throw from requestLock.\n providerLocked = false;\n emitLockError('provider', cause);\n }\n return;\n }\n\n // W3C path: standard requestPointerLock.\n const fn = canvas.requestPointerLock;\n if (typeof fn !== 'function') return;\n try {\n const r = fn.call(canvas) as unknown;\n if (r && typeof (r as Promise<void>).catch === 'function') {\n (r as Promise<void>).catch((cause: unknown) => {\n emitLockError('w3c', cause);\n });\n }\n } catch (cause: unknown) {\n emitLockError('w3c', cause);\n }\n }\n safeAdd(canvas, 'click', onCanvasClick as EventListener);\n\n function sample(): InputBackendSample {\n if (!inputAllowed) {\n clear();\n return createEmptyInputBackendSample();\n }\n // D-1: gamepad edge diff derived inside sample() — the only\n // cross-frame state holder. getGamepads() is polled once per frame;\n // null-padded arrays use gamepad.index as slot key.\n let gamepads: GamepadSlotSample[] | undefined;\n if (gamepadAvailable) {\n try {\n const rawGamepads = (nav.getGamepads?.() ?? []) as (RawGamepadStub | null)[];\n const valid: RawGamepadStub[] = [];\n let hasNonStandard = false;\n for (const gp of rawGamepads) {\n if (!gp?.connected) continue;\n valid.push(gp);\n if (gp.mapping !== 'standard') hasNonStandard = true;\n }\n // M3 D-2 / C-5: only a real non-standard gamepad triggers the DB\n // load. Standard pads never pull in the 554KB DB.\n if (hasNonStandard) kickOffDbLoad();\n gamepads = diffGamepadFrame(prevGamepadFrame, valid, remapLookup);\n if (gamepadBaselinePending) {\n gamepads = gamepads.map((slot) => ({\n ...slot,\n justPressed: new Set<number>(),\n justReleased: new Set<number>(),\n }));\n gamepadBaselinePending = false;\n }\n // Store this frame's state for next frame's diff.\n const nextFrame = new Map<number, GamepadSlotSample>();\n for (const slot of gamepads) {\n // Only store currently-connected slots for the next diff.\n // Disconnected slots (standardMapping=false, pressed=empty)\n // are not stored; they won't appear in next frame's prev.\n if (slot.pressed.size > 0 || slot.standardMapping) {\n nextFrame.set(slot.index, slot);\n }\n }\n prevGamepadFrame = nextFrame;\n } catch {\n // getGamepads() threw — treat as if no gamepad API.\n // AC-05: API unstable environment does not crash.\n }\n }\n\n // w15: freeze pointer map → PointerSample[] with cross-frame delta.\n // Delta = current frozen position − previous frozen position (AC-09).\n let pointers: PointerSample[] | undefined;\n if (pointerMap.size > 0) {\n pointers = [];\n for (const [id, entry] of pointerMap) {\n const deltaX = entry.x - entry.prevX;\n const deltaY = entry.y - entry.prevY;\n pointers.push({\n pointerId: id,\n x: entry.x,\n y: entry.y,\n pressure: entry.pressure,\n pointerType: entry.pointerType,\n active: true,\n delta: Object.freeze({ x: deltaX, y: deltaY }),\n });\n // Update prev position for next frame's delta (D-1 frame-end freeze).\n entry.prevX = entry.x;\n entry.prevY = entry.y;\n }\n }\n\n // w15: snapshot the phase queue for this frame.\n const pointerEvents: PointerPhaseEvent[] | undefined =\n phaseQueue.length > 0 ? [...phaseQueue] : undefined;\n\n // w21: derive virtual joystick axes from live pointer positions.\n let virtualAxes: VirtualAxisSample[] | undefined;\n if (vjConfigs.length > 0) {\n virtualAxes = deriveVirtualAxes(vjConfigs, pointerMap, vjBindState);\n }\n\n // M5 D-4: run the gesture recognizer over this frame's phase queue BEFORE\n // it is drained below. onBlur / pointercancel pushed cancel phases into\n // the same queue, so the recognizer naturally resets active gestures +\n // emits cancel events (AC-18) without a separate reset path. All timers\n // advance off `now()` (D-3), decoupled from event frequency (AC-16).\n const gestureResult = processGestureFrame(\n phaseQueue,\n pointerMap as ReadonlyMap<number, RecognizerPointer>,\n recognizerState,\n now(),\n );\n recognizerState = gestureResult.newState;\n // Emit optional fields only when there is gesture signal to carry: an\n // active/frozen continuous value (non-identity) or lifecycle events.\n const gestureEvents: readonly GestureEvent[] | undefined =\n gestureResult.gestureEvents.length > 0 ? gestureResult.gestureEvents : undefined;\n const gs = gestureResult.gestureState;\n const gestures: GestureState | undefined =\n gs.pinchScale !== 1 || gs.rotationAngle !== 0 ? gs : undefined;\n\n const out: InputBackendSample = {\n downKeys: new Set(heldKeys),\n upKeys: new Set(upEdges),\n downCodes: new Set(heldCodes),\n upCodes: new Set(upCodeEdges),\n pressedKeys: new Set(pressedKeys),\n pressedCodes: new Set(pressedCodes),\n buttons: [buttons[0], buttons[1], buttons[2]] as readonly [boolean, boolean, boolean],\n pressedButtons: [pressedButtons[0], pressedButtons[1], pressedButtons[2]] as readonly [\n boolean,\n boolean,\n boolean,\n ],\n releasedButtons: [releasedButtons[0], releasedButtons[1], releasedButtons[2]] as readonly [\n boolean,\n boolean,\n boolean,\n ],\n movementX: mvx,\n movementY: mvy,\n ...(mouseX !== undefined && mouseY !== undefined ? { mouseX, mouseY } : {}),\n wheelDelta: wheelAccum,\n focused: isFocused(),\n capabilities: caps,\n pointerLocked: w3cLocked || providerLocked,\n ...(gamepads ? { gamepads } : {}),\n ...(pointers ? { pointers } : {}),\n ...(pointerEvents ? { pointerEvents } : {}),\n ...(virtualAxes ? { virtualAxes } : {}),\n ...(gestures ? { gestures } : {}),\n ...(gestureEvents ? { gestureEvents } : {}),\n ...(focusResetPending ? { focusReset: true } : {}),\n };\n // Reset per-frame accumulators (movement delta + key edges + wheel notches + phase queue).\n upEdges.clear();\n upCodeEdges.clear();\n pressedKeys.clear();\n pressedCodes.clear();\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n mvx = 0;\n mvy = 0;\n wheelAccum = 0;\n phaseQueue.length = 0;\n focusResetPending = false;\n return out;\n }\n\n // w8 (D-3): command-set game gate for pointer-lock. set(false) immediately\n // releases any active lock on both W3C and provider paths.\n function setPointerLockAllowed(allowed: boolean): void {\n gameGate = allowed;\n if (!allowed) {\n // W3C path: exit pointer-lock if currently locked on this canvas.\n if (typeof doc.exitPointerLock === 'function' && doc.pointerLockElement === canvas) {\n doc.exitPointerLock();\n }\n // Provider path: call exitLock and clear providerLocked.\n releaseProviderLock();\n }\n }\n\n function setInputAllowed(allowed: boolean): void {\n inputAllowed = allowed;\n // Both closing and reopening are lease boundaries. Clearing on reopen\n // fences any event that raced the closed gate before the next scan.\n clear();\n }\n\n function clear(): void {\n heldKeys.clear();\n upEdges.clear();\n pressedKeys.clear();\n heldCodes.clear();\n upCodeEdges.clear();\n pressedCodes.clear();\n pointerMap.clear();\n phaseQueue.length = 0;\n prevGamepadFrame.clear();\n vjBindState.clear();\n recognizerState = createRecognizerState();\n buttons[0] = false;\n buttons[1] = false;\n buttons[2] = false;\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n mvx = 0;\n mvy = 0;\n wheelAccum = 0;\n if (typeof doc?.exitPointerLock === 'function' && doc.pointerLockElement === canvas) {\n doc.exitPointerLock();\n }\n // `pointerlockchange` is asynchronous. The boundary must nevertheless\n // publish an unlocked frame immediately after revocation.\n w3cLocked = false;\n releaseProviderLock();\n }\n\n function detach(): void {\n if (detached) return;\n detached = true;\n safeRemove(win, 'keydown', onKeyDown as EventListener);\n safeRemove(win, 'keyup', onKeyUp as EventListener);\n safeRemove(win, 'blur', onBlur as EventListener);\n safeRemove(canvas, 'pointerdown', onPointerDown as EventListener);\n safeRemove(canvas, 'pointerup', onPointerUp as EventListener);\n safeRemove(canvas, 'pointermove', onPointerMove as EventListener);\n safeRemove(canvas, 'pointercancel', onPointerCancel as EventListener);\n safeRemove(canvas, 'wheel', onWheel as EventListener);\n safeRemove(doc, 'visibilitychange', onVisibilityChange as EventListener);\n safeRemove(doc, 'pointerlockchange', onPointerLockChange as EventListener);\n safeRemove(doc, 'pointerlockerror', onPointerLockError as EventListener);\n safeRemove(canvas, 'click', onCanvasClick as EventListener);\n clear();\n // D-5: restore original touch-action value.\n if (canvas.style && _prevTouchAction !== undefined) {\n canvas.style.touchAction = _prevTouchAction;\n }\n }\n\n const backend: InputBackend = {\n sample,\n clear,\n detach,\n setPointerLockAllowed,\n setInputAllowed,\n };\n\n // Returned callable doubles as the InputBackend (detach + sample). AI\n // users see one symbol with both shapes, mirroring the\n // produces-detach-and-protocol convention of `effect`-style libraries.\n const handle = Object.assign(detach, { backend });\n return handle;\n}\n","// @forgeax/engine-input -- exclusive host-owned canvas input boundary.\n//\n// A physical canvas has one DOM acquisition backend. Hosts with two worlds (for\n// example editor + transient Play) route that one producer through these two\n// InputBackend views. This is exclusive ownership, deliberately separate from\n// synthetic/replay input composition.\n\nimport {\n createEmptyInputBackendSample,\n type InputBackend,\n type InputBackendSample,\n} from './input-snapshot';\nimport { isUiOwnedEvent } from './ui-ownership';\n\nexport interface CanvasInputBoundary {\n readonly editor: InputBackend;\n readonly game: InputBackend;\n owner(): 'editor' | 'game';\n grantGame(): void;\n revokeGame(): void;\n /** Clear the active consumer when an event originated in the host UI. */\n handleUiEvent(event: Event, host: Node): boolean;\n detach(): void;\n}\n\ntype CanvasInputOwner = ReturnType<CanvasInputBoundary['owner']>;\n\nexport function createCanvasInputBoundary(source: InputBackend): CanvasInputBoundary {\n let active: CanvasInputOwner = 'editor';\n let gamePointerLockAllowed = false;\n let editorInputAllowed = true;\n let gameInputAllowed = true;\n source.setPointerLockAllowed?.(false);\n\n const empty = (): InputBackendSample => createEmptyInputBackendSample();\n\n const clear = (): void => {\n source.clear?.();\n source.setPointerLockAllowed?.(false);\n };\n\n const routed = (consumer: CanvasInputOwner): InputBackend => ({\n sample: () => (consumer === active ? source.sample() : empty()),\n setPointerLockAllowed: (allowed) => {\n if (consumer === 'game') {\n gamePointerLockAllowed = allowed;\n source.setPointerLockAllowed?.(active === 'game' && allowed);\n } else {\n source.setPointerLockAllowed?.(false);\n }\n },\n setInputAllowed: (allowed) => {\n if (consumer === 'game') gameInputAllowed = allowed;\n else editorInputAllowed = allowed;\n source.setInputAllowed?.(active === 'game' ? gameInputAllowed : editorInputAllowed);\n },\n clear: () => {\n if (consumer === active) clear();\n },\n detach: () => source.detach(),\n });\n\n const grantGame = (): void => {\n if (active === 'game') return;\n clear();\n active = 'game';\n source.setPointerLockAllowed?.(gamePointerLockAllowed);\n source.setInputAllowed?.(gameInputAllowed);\n };\n\n const revokeGame = (): void => {\n clear();\n active = 'editor';\n source.setInputAllowed?.(editorInputAllowed);\n };\n\n return {\n editor: routed('editor'),\n game: routed('game'),\n owner: () => active,\n grantGame,\n revokeGame,\n handleUiEvent: (event, host) => {\n if (!isUiOwnedEvent(event, host)) return false;\n clear();\n return true;\n },\n detach: () => source.detach(),\n };\n}\n","// @forgeax/engine-input -- CompositeInputBackend (synthetic-input decorator).\n//\n// PROBLEM. The scan system reads ONE `InputBackend` from `INPUT_BACKEND_KEY`\n// each frame. An AI / record-replay harness needs to feed synthetic input into\n// that same slot WITHOUT evicting the human's browser backend -- because a human\n// may take over at any instant (PIE two-world model + charter §8 human-as-final-\n// authority). Overwriting the resource locks the human out; wrapping it does not.\n//\n// SOLUTION. `makeCompositeBackend(inner)` returns an `InputBackend` that HOLDS\n// the human backend as `inner` and layers a programmatic injection surface\n// (`press` / `release` / `setButton` / `addMovement` / `addWheel`) on top. The\n// scan system stays variant-agnostic: it still calls `sample()` on one backend\n// (Depend-on-Abstractions -- the consumer never learns a composite exists).\n//\n// SIDE-EFFECT CONTRACT. `inner.sample()` DRAINS its per-frame accumulators\n// (up-edges, movement delta, wheel notches) on read, so the composite calls it\n// EXACTLY ONCE per `sample()` and drains its OWN injected accumulators in the\n// same pass. Field-by-field merge honoring each field's lifecycle:\n//\n// downKeys held across frames -> UNION(inner, injected.held)\n// upKeys lives one frame -> UNION; injected up-edge set drained here\n// buttons held tuple -> OR per slot\n// movementX/Y, wheelDelta -> SUM; injected side reset to 0 here\n// focused gates up-edge suppress -> inner.focused || injectionActive\n// pointerLocked -> inner (AI must not fabricate a lock)\n// optional (pointers/gamepads/...) -> pass through from inner untouched\n//\n// YIELD-TO-HUMAN (default on). A human-held key on `inner` suppresses only the\n// injected state for that SAME key in that frame. Other AI keys continue, so a\n// human can take a key without silencing unrelated synthetic input. This is the\n// structural realization of \"human wins\" without a global takeover policy.\n\nimport type { InputBackend, InputBackendSample } from './input-snapshot';\n\n/** Options controlling the composite merge policy. */\nexport interface CompositeBackendOptions {\n /**\n * When `true` (default), a key held on the inner (human) backend suppresses\n * injected state only for that same key in that frame. Set `false` for\n * record/replay or AI-solo scenarios where both sources should coexist even\n * on key overlap.\n */\n readonly yieldToHuman?: boolean;\n}\n\n/**\n * A composite backend: an `InputBackend` (drop-in for `INPUT_BACKEND_KEY`) plus\n * a programmatic injection surface. All injection is additive over the wrapped\n * human backend.\n */\nexport interface CompositeInputBackend extends InputBackend {\n /** Hold `key` down (mirrors a keydown). Idempotent. */\n press(key: string): void;\n /** Release `key` (mirrors a keyup); emits a one-frame up-edge on next sample. */\n release(key: string): void;\n /** Set an injected mouse-button slot (0/1/2) held-state. */\n setButton(slot: 0 | 1 | 2, down: boolean): void;\n /** Accumulate injected pointer-lock movement delta (drained on next sample). */\n addMovement(dx: number, dy: number): void;\n /** Accumulate injected wheel notches (drained on next sample). */\n addWheel(notches: number): void;\n /**\n * Drop all injected state and pending frame edges; currently-held keys/buttons\n * emit one clean release edge so a previously observed hold is closed.\n */\n clearInjected(): void;\n /** Open a fresh synthetic-input lease after a previous revoke boundary. */\n beginInjectedLease(): void;\n /** Revoke the current lease and fence later injections until reopened. */\n revokeInjectedLease(): void;\n /**\n * Create the one execution-scoped injection view. Creating a lease\n * invalidates every previously-created view; an invalid view remains a\n * no-op even after a later lease is opened.\n */\n createInjectedLease(): CompositeInputLease;\n /** Toggle the yield-to-human gate at runtime. */\n setYieldToHuman(yield_: boolean): void;\n}\n\n/**\n * Synthetic input exposed to one eval/execution. It deliberately has no\n * `beginInjectedLease` method: a script can release its own lease, but it\n * cannot reopen an old reference after the host has moved to another job.\n */\nexport interface CompositeInputLease extends InputBackend {\n press(key: string): void;\n release(key: string): void;\n setButton(slot: 0 | 1 | 2, down: boolean): void;\n addMovement(dx: number, dy: number): void;\n addWheel(notches: number): void;\n clearInjected(): void;\n revokeInjectedLease(): void;\n}\n\n// The public injection surface accepts either the logical KeyboardEvent.key\n// (`w`, ` `, `ArrowUp`) or the physical KeyboardEvent.code (`KeyW`, `Space`).\n// Keep both projections populated so code-first control drives games that read\n// either keyboard.down(...) or keyboard.downCode(...).\nconst CODE_TO_KEY: Readonly<Record<string, string>> = {\n Space: ' ',\n ShiftLeft: 'Shift',\n ShiftRight: 'Shift',\n ControlLeft: 'Control',\n ControlRight: 'Control',\n AltLeft: 'Alt',\n AltRight: 'Alt',\n MetaLeft: 'Meta',\n MetaRight: 'Meta',\n BracketLeft: '[',\n BracketRight: ']',\n Backslash: '\\\\',\n Semicolon: ';',\n Quote: \"'\",\n Comma: ',',\n Period: '.',\n Slash: '/',\n Minus: '-',\n Equal: '=',\n Backquote: '`',\n};\n\nfunction keyForCode(code: string): string | undefined {\n if (CODE_TO_KEY[code] !== undefined) return CODE_TO_KEY[code];\n if (/^Key[A-Z]$/.test(code)) return code.slice(3).toLowerCase();\n if (/^Digit[0-9]$/.test(code)) return code.slice(5);\n if (/^Numpad[0-9]$/.test(code)) return code.slice(6);\n if (/^F(?:[1-9]|1[0-2])$/.test(code)) return code;\n if (/^Arrow(?:Up|Down|Left|Right)$/.test(code)) return code;\n if (/^(?:Escape|Enter|Tab|Backspace|Delete|Home|End|PageUp|PageDown|Insert)$/.test(code))\n return code;\n return undefined;\n}\n\nfunction codeForKey(key: string): string | undefined {\n if (/^[a-zA-Z]$/.test(key)) return `Key${key.toUpperCase()}`;\n if (/^[0-9]$/.test(key)) return `Digit${key}`;\n if (key === ' ') return 'Space';\n if (\n /^(?:Arrow(?:Up|Down|Left|Right)|Escape|Enter|Tab|Backspace|Delete|Home|End|PageUp|PageDown|Insert)$/.test(\n key,\n )\n )\n return key;\n if (/^F(?:[1-9]|1[0-2])$/.test(key)) return key;\n const entry = Object.entries(CODE_TO_KEY).find(([, value]) => value === key);\n return entry?.[0];\n}\n\nfunction normalizeKey(value: string): { readonly key: string; readonly code: string | undefined } {\n const logical = keyForCode(value);\n return logical === undefined\n ? { key: value, code: codeForKey(value) }\n : { key: logical, code: value };\n}\n\nexport function makeCompositeBackend(\n inner: InputBackend,\n options?: CompositeBackendOptions,\n): CompositeInputBackend {\n let yieldToHuman = options?.yieldToHuman ?? true;\n let inputAllowed = true;\n let leaseRevoked = false;\n let leaseGeneration = 0;\n\n // Injected held-state (survives across frames).\n const heldKeys = new Set<string>();\n const heldCodes = new Set<string>();\n const buttons: [boolean, boolean, boolean] = [false, false, false];\n // Injected per-frame accumulators (drained on each sample()).\n const upEdges = new Set<string>();\n const upCodeEdges = new Set<string>();\n const pressedKeys = new Set<string>();\n const pressedCodes = new Set<string>();\n const pressedButtons: [boolean, boolean, boolean] = [false, false, false];\n const releasedButtons: [boolean, boolean, boolean] = [false, false, false];\n let mvx = 0;\n let mvy = 0;\n let wheel = 0;\n\n function injectionActive(): boolean {\n return (\n heldKeys.size > 0 ||\n heldCodes.size > 0 ||\n upEdges.size > 0 ||\n upCodeEdges.size > 0 ||\n pressedKeys.size > 0 ||\n pressedCodes.size > 0 ||\n buttons.some((b) => b) ||\n pressedButtons.some((b) => b) ||\n releasedButtons.some((b) => b)\n );\n }\n\n function sample(): InputBackendSample {\n // Call inner EXACTLY once -- it drains its own accumulators here.\n const base = inner.sample();\n if (!inputAllowed) {\n clearInjected();\n return {\n ...base,\n downKeys: new Set(),\n upKeys: new Set(),\n downCodes: new Set(),\n upCodes: new Set(),\n pressedKeys: new Set(),\n pressedCodes: new Set(),\n buttons: [false, false, false],\n pressedButtons: [false, false, false],\n releasedButtons: [false, false, false],\n movementX: 0,\n movementY: 0,\n wheelDelta: 0,\n pointerLocked: false,\n };\n }\n\n // yield-to-human is PER-KEY: an injected key is suppressed only when the human\n // is holding the SAME key this frame. This is the minimal realization of\n // charter §8 (the human always wins a key they touch) WITHOUT the collateral of\n // a global gate — a human strafing D does not silence an AI holding W, so the\n // two genuinely coexist (that is the whole point of a composite; a caller who\n // wants \"human takes over everything\" can clearInjected() at the policy layer).\n // downKeys: union of human-held and injected-held, minus injected keys the human\n // is also pressing. A yielded injected release is likewise a no-op: emitting its\n // up-edge would incorrectly release the human-held key in the scan system.\n const downKeys = new Set(base.downKeys);\n const downCodes =\n base.downCodes === undefined && heldCodes.size === 0\n ? undefined\n : new Set(base.downCodes ?? []);\n for (const k of heldKeys) {\n const code = codeForKey(k);\n if (\n yieldToHuman &&\n (base.downKeys.has(k) || (code !== undefined && base.downCodes?.has(code) === true))\n )\n continue; // human owns this exact key\n downKeys.add(k);\n }\n for (const code of heldCodes) {\n const key = keyForCode(code);\n if (\n yieldToHuman &&\n (base.downCodes?.has(code) === true || (key !== undefined && base.downKeys.has(key)))\n )\n continue;\n downCodes?.add(code);\n }\n\n // upKeys: union of human up-edges and injected up-edges (one-frame life), except\n // injected edges for keys that the human still owns under the per-key yield gate.\n const mergedUp = new Set(base.upKeys);\n for (const k of upEdges) {\n const code = codeForKey(k);\n if (\n yieldToHuman &&\n (base.downKeys.has(k) || (code !== undefined && base.downCodes?.has(code) === true))\n )\n continue;\n mergedUp.add(k);\n }\n const mergedUpCodes =\n base.upCodes === undefined && upCodeEdges.size === 0\n ? undefined\n : new Set(base.upCodes ?? []);\n for (const code of upCodeEdges) {\n const key = keyForCode(code);\n if (\n yieldToHuman &&\n (base.downCodes?.has(code) === true || (key !== undefined && base.downKeys.has(key)))\n )\n continue;\n mergedUpCodes?.add(code);\n }\n\n const mergedPressed =\n base.pressedKeys === undefined && pressedKeys.size === 0\n ? undefined\n : new Set([...(base.pressedKeys ?? []), ...pressedKeys]);\n if (\n yieldToHuman &&\n (base.downKeys.size > 0 || (base.downCodes?.size ?? 0) > 0) &&\n mergedPressed !== undefined\n ) {\n for (const key of pressedKeys) {\n const code = codeForKey(key);\n if (base.downKeys.has(key) || (code !== undefined && base.downCodes?.has(code) === true))\n mergedPressed.delete(key);\n }\n }\n const mergedPressedCodes =\n base.pressedCodes === undefined && pressedCodes.size === 0\n ? undefined\n : new Set(base.pressedCodes ?? []);\n if (yieldToHuman && mergedPressedCodes !== undefined) {\n for (const code of pressedCodes) {\n const key = keyForCode(code);\n if (base.downCodes?.has(code) === true || (key !== undefined && base.downKeys.has(key)))\n mergedPressedCodes.delete(code);\n }\n }\n\n // buttons: OR per slot.\n const mergedButtons: readonly [boolean, boolean, boolean] = [\n base.buttons[0] || buttons[0],\n base.buttons[1] || buttons[1],\n base.buttons[2] || buttons[2],\n ];\n const mergedPressedButtons =\n base.pressedButtons === undefined && !pressedButtons.some(Boolean)\n ? undefined\n : ([\n (base.pressedButtons?.[0] ?? false) || pressedButtons[0],\n (base.pressedButtons?.[1] ?? false) || pressedButtons[1],\n (base.pressedButtons?.[2] ?? false) || pressedButtons[2],\n ] as const);\n const mergedReleasedButtons =\n base.releasedButtons === undefined && !releasedButtons.some(Boolean)\n ? undefined\n : ([\n (base.releasedButtons?.[0] ?? false) || releasedButtons[0],\n (base.releasedButtons?.[1] ?? false) || releasedButtons[1],\n (base.releasedButtons?.[2] ?? false) || releasedButtons[2],\n ] as const);\n\n // focused: keep true while WE are injecting, so the scan system does not\n // treat a headless/backgrounded tab (inner.focused === false) as a reason\n // to suppress our up-edges. Otherwise mirror inner.\n const focused = base.focused || injectionActive();\n\n const out: InputBackendSample = {\n ...base, // carry inner optional fields (pointers/gamepads/gestures/...) untouched\n downKeys,\n upKeys: mergedUp,\n ...(downCodes === undefined ? {} : { downCodes }),\n ...(mergedUpCodes === undefined ? {} : { upCodes: mergedUpCodes }),\n ...(mergedPressed === undefined ? {} : { pressedKeys: mergedPressed }),\n ...(mergedPressedCodes === undefined ? {} : { pressedCodes: mergedPressedCodes }),\n buttons: mergedButtons,\n ...(mergedPressedButtons === undefined ? {} : { pressedButtons: mergedPressedButtons }),\n ...(mergedReleasedButtons === undefined ? {} : { releasedButtons: mergedReleasedButtons }),\n movementX: base.movementX + mvx,\n movementY: base.movementY + mvy,\n wheelDelta: base.wheelDelta + wheel,\n focused,\n pointerLocked: base.pointerLocked, // AI never fabricates a lock\n };\n\n // Drain injected per-frame accumulators (mirrors inner's own drain).\n upEdges.clear();\n upCodeEdges.clear();\n pressedKeys.clear();\n pressedCodes.clear();\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n mvx = 0;\n mvy = 0;\n wheel = 0;\n\n return out;\n }\n\n // Only surface setPointerLockAllowed when the inner backend supports it, so\n // the optional method is truly absent (not `undefined`) under\n // exactOptionalPropertyTypes -- and forwards to the human backend when present.\n const lockGate: Pick<InputBackend, 'setPointerLockAllowed'> = inner.setPointerLockAllowed\n ? { setPointerLockAllowed: (allowed: boolean) => inner.setPointerLockAllowed?.(allowed) }\n : {};\n const inputGate: Pick<InputBackend, 'setInputAllowed'> = {\n setInputAllowed: (allowed: boolean) => {\n inputAllowed = allowed;\n inner.setInputAllowed?.(allowed);\n // Closing and reopening are both lease boundaries. Clear after either\n // transition so synthetic edges cannot cross a startup/input fence.\n clearInjected();\n },\n };\n\n const clearInjected = (): void => {\n // Clearing is a lease boundary: discard every pending frame edge first,\n // then emit only the releases required to close state that was held\n // across the boundary. This prevents a press/release queued before a\n // revoke from becoming a ghost edge for the next consumer.\n upEdges.clear();\n upCodeEdges.clear();\n pressedKeys.clear();\n pressedCodes.clear();\n for (const k of heldKeys) upEdges.add(k);\n for (const code of heldCodes) upCodeEdges.add(code);\n heldKeys.clear();\n heldCodes.clear();\n pressedButtons[0] = false;\n pressedButtons[1] = false;\n pressedButtons[2] = false;\n releasedButtons[0] = false;\n releasedButtons[1] = false;\n releasedButtons[2] = false;\n if (buttons[0]) releasedButtons[0] = true;\n if (buttons[1]) releasedButtons[1] = true;\n if (buttons[2]) releasedButtons[2] = true;\n buttons[0] = buttons[1] = buttons[2] = false;\n mvx = 0;\n mvy = 0;\n wheel = 0;\n };\n\n const beginInjectedLease = (): void => {\n // A new boundary must invalidate old references. Merely flipping a global\n // boolean would let an async script keep writing after a later job opens.\n leaseGeneration += 1;\n leaseRevoked = false;\n clearInjected();\n };\n const revokeInjectedLease = (): void => {\n leaseGeneration += 1;\n leaseRevoked = true;\n clearInjected();\n };\n\n const createInjectedLease = (): CompositeInputLease => {\n beginInjectedLease();\n const generation = leaseGeneration;\n const active = (): boolean => inputAllowed && !leaseRevoked && generation === leaseGeneration;\n return {\n sample,\n detach: () => {},\n press(key) {\n if (!active()) return;\n const normalized = normalizeKey(key);\n if (!heldKeys.has(normalized.key)) pressedKeys.add(normalized.key);\n heldKeys.add(normalized.key);\n if (normalized.code !== undefined) {\n if (!heldCodes.has(normalized.code)) pressedCodes.add(normalized.code);\n heldCodes.add(normalized.code);\n }\n },\n release(key) {\n if (!active()) return;\n const normalized = normalizeKey(key);\n if (heldKeys.delete(normalized.key)) upEdges.add(normalized.key);\n if (normalized.code !== undefined && heldCodes.delete(normalized.code))\n upCodeEdges.add(normalized.code);\n },\n setButton(slot, down) {\n if (!active()) return;\n if (down && !buttons[slot]) pressedButtons[slot] = true;\n if (!down && buttons[slot]) releasedButtons[slot] = true;\n buttons[slot] = down;\n },\n addMovement(dx, dy) {\n if (!active()) return;\n mvx += dx;\n mvy += dy;\n },\n addWheel(notches) {\n if (!active()) return;\n wheel += notches;\n },\n clearInjected() {\n if (active()) clearInjected();\n },\n revokeInjectedLease() {\n if (active()) revokeInjectedLease();\n },\n };\n };\n\n return {\n sample,\n ...lockGate,\n ...inputGate,\n // Teardown belongs to the human backend -- revoke the synthetic lease\n // first, then forward the physical listener teardown. `clear()` is also\n // exposed so an owner can revoke input without detaching the browser.\n clear: () => {\n clearInjected();\n inner.clear?.();\n },\n detach: () => {\n clearInjected();\n inner.detach();\n },\n\n press(key) {\n if (leaseRevoked || !inputAllowed) return;\n const normalized = normalizeKey(key);\n if (!heldKeys.has(normalized.key)) pressedKeys.add(normalized.key);\n heldKeys.add(normalized.key);\n if (normalized.code !== undefined) {\n if (!heldCodes.has(normalized.code)) pressedCodes.add(normalized.code);\n heldCodes.add(normalized.code);\n }\n },\n release(key) {\n if (leaseRevoked || !inputAllowed) return;\n const normalized = normalizeKey(key);\n if (heldKeys.delete(normalized.key)) upEdges.add(normalized.key); // held -> emit one up-edge\n if (normalized.code !== undefined && heldCodes.delete(normalized.code))\n upCodeEdges.add(normalized.code);\n },\n setButton(slot, down) {\n if (leaseRevoked || !inputAllowed) return;\n if (down && !buttons[slot]) pressedButtons[slot] = true;\n if (!down && buttons[slot]) releasedButtons[slot] = true;\n buttons[slot] = down;\n },\n addMovement(dx, dy) {\n if (leaseRevoked || !inputAllowed) return;\n mvx += dx;\n mvy += dy;\n },\n addWheel(notches) {\n if (leaseRevoked || !inputAllowed) return;\n wheel += notches;\n },\n clearInjected,\n beginInjectedLease,\n revokeInjectedLease,\n createInjectedLease,\n setYieldToHuman(yield_) {\n yieldToHuman = yield_;\n },\n };\n}\n","// frame-start-scan-system.ts -- bridges an `InputBackend` producer into\n// the `InputSnapshot` Resource consumed by user systems (charter P5).\n//\n// Plan-strategy section 2.10 D-5 locks the system to a frame-start position\n// in the schedule: user systems declare `after: ['input-frame-start-scan']`\n// to read the snapshot. The system itself holds zero queries; it only\n// pulls one sample from the backend and writes the Resource.\n//\n// The backend is supplied via the `InputBackend` World resource rather than a\n// captured closure. Resource reads remain explicit in the system body.\n\nimport { defineSystem, defineSystemSet, type SystemHandle } from '@forgeax/engine-ecs';\nimport {\n type ActionConfig,\n type ActionState,\n deriveActionStates,\n INPUT_MAP_KEY,\n} from './action-state';\nimport {\n INPUT_SNAPSHOT_RESOURCE_KEY,\n type InputBackend,\n type InputSnapshot,\n readActionStatesForEdgeDiff,\n snapshotFromSample,\n} from './input-snapshot';\n\n/**\n * Stable system name (locked by `frame-start-scan-system.test.ts`). User\n * systems reference it through `after: [FRAME_START_SCAN_SYSTEM_NAME]`\n * to ensure they observe the freshly written snapshot.\n */\nexport const FRAME_START_SCAN_SYSTEM_NAME = 'input-frame-start-scan';\nexport const InputSet = defineSystemSet({ name: 'input' });\n\n/**\n * Resource key under which the {@link InputBackend} producer is inserted\n * (M2 — full resource-ification, D-2 / D-7). The frame-start scan system\n * declares it in `resources`; the fn body reads it back via\n * `world.getResource(INPUT_BACKEND_KEY)`.\n *\n * Aligns with the `INPUT_SNAPSHOT_RESOURCE_KEY` naming. Consumers import the\n * constant rather than the bare string so a typo degrades to an import error\n * (charter P3).\n */\nexport const INPUT_BACKEND_KEY = 'InputBackend' as const;\n\n/**\n * The frame-start scan system token (M2 — full resource-ification, D-4).\n *\n * Module-level `defineSystem` with the real fn body — no factory, no closure.\n * Each `world.update()` tick:\n * 1. reads the {@link InputBackend} from `INPUT_BACKEND_KEY` and calls\n * `backend.sample()` once to atomically drain the per-frame accumulators\n * (movement delta plus key/code/button press and release edge sets);\n * 2. derives a fresh `InputSnapshot` via `snapshotFromSample`;\n * 3. writes it under `INPUT_SNAPSHOT_RESOURCE_KEY` via\n * `world.insertResource` -- idempotent overwrite, charter P4\n * consistent abstraction (consumers always read the same Resource key\n * regardless of which backend produced the sample).\n *\n * Labelled `'input'` (spec §6.2 label-anchor map).\n */\nexport const InputFrameStartScan: SystemHandle<readonly []> = defineSystem({\n name: FRAME_START_SCAN_SYSTEM_NAME,\n queries: [],\n fn: (world) => {\n const backend = world.getResource<InputBackend>(INPUT_BACKEND_KEY);\n const sample = backend.sample();\n\n // Action mapping: derive states from InputMap Resource + prev snapshot edges.\n // D-6: edge baseline reuses existing prev InputSnapshot Resource (Derive,\n // Don't Duplicate — zero new cross-frame state carrier).\n let actionStates: ReturnType<typeof deriveActionStates> | undefined;\n let inputMap: readonly ActionConfig[] | undefined;\n if (world.hasResource(INPUT_MAP_KEY)) {\n inputMap = world.getResource<readonly ActionConfig[]>(INPUT_MAP_KEY);\n // Read prev snapshot's internal action states for edge diff.\n // First frame: no prev snapshot → justPressed = pressed (same as Feat1 gamepad).\n let prevActionStates: readonly ActionState[] | undefined;\n if (world.hasResource(INPUT_SNAPSHOT_RESOURCE_KEY)) {\n const prevSnap = world.getResource<InputSnapshot>(INPUT_SNAPSHOT_RESOURCE_KEY);\n prevActionStates = readActionStatesForEdgeDiff(prevSnap);\n }\n actionStates = deriveActionStates(sample, inputMap, prevActionStates);\n }\n\n const previousSnapshot = world.hasResource(INPUT_SNAPSHOT_RESOURCE_KEY)\n ? world.getResource<InputSnapshot>(INPUT_SNAPSHOT_RESOURCE_KEY)\n : undefined;\n const snapshot = snapshotFromSample(sample, actionStates, inputMap, previousSnapshot);\n world.insertResource(INPUT_SNAPSHOT_RESOURCE_KEY, snapshot);\n },\n});\n","import type { Plugin } from '@forgeax/engine-plugin';\n\nimport type { InputBackend } from './input-snapshot';\n\ndeclare module '@forgeax/engine-plugin' {\n interface EngineContextServices {\n input?: InputBackend;\n }\n}\n\nexport function inputBackendPlugin(backend: InputBackend): Plugin {\n return {\n name: 'input-backend',\n provide: 'input',\n apply(ctx) {\n ctx.provide('input', backend);\n },\n };\n}\n\n/** Provide an App-acquired input backend and release its Host listeners with the Fiber. */\nexport function ownedInputBackendPlugin(backend: InputBackend, dispose: () => void): Plugin {\n return {\n name: 'input-backend',\n provide: 'input',\n apply(ctx) {\n ctx.provide('input', backend);\n ctx.effect(() => dispose, 'input/backend');\n },\n };\n}\n"]}