@yagejs/input 0.4.0 → 0.6.0
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.
- package/dist/api-BaItBbSe.d.cts +685 -0
- package/dist/api-BaItBbSe.d.ts +685 -0
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +1 -1
- package/dist/{chunk-CYWOKPMI.js → chunk-O2U7FZ7Q.js} +1 -1
- package/dist/chunk-O2U7FZ7Q.js.map +1 -0
- package/dist/index.cjs +1264 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1265 -108
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/api-CTGj55Rb.d.cts +0 -208
- package/dist/api-CTGj55Rb.d.ts +0 -208
- package/dist/chunk-CYWOKPMI.js.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/InputPlugin.ts","../src/InputManager.ts","../src/types.ts","../src/InputPollSystem.ts","../src/InputClearSystem.ts","../src/InputDebugContributor.ts","../src/keyDisplayNames.ts"],"sourcesContent":["export { InputPlugin } from \"./InputPlugin.js\";\nexport { InputManager } from \"./InputManager.js\";\nexport { getKeyDisplayName } from \"./keyDisplayNames.js\";\nexport { InputManagerKey } from \"./types.js\";\nexport type {\n InputConfig,\n ActionMapDefinition,\n InputConflictPolicy,\n RebindOptions,\n RebindResult,\n CameraLike,\n RendererLike,\n} from \"./types.js\";\n","import type { EngineContext, Plugin, SystemScheduler } from \"@yagejs/core\";\nimport { RendererAdapterKey } from \"@yagejs/core\";\nimport { DebugRegistryKey } from \"@yagejs/debug/api\";\nimport { InputManager } from \"./InputManager.js\";\nimport { InputManagerKey, type InputConfig } from \"./types.js\";\nimport { InputPollSystem } from \"./InputPollSystem.js\";\nimport { InputClearSystem } from \"./InputClearSystem.js\";\nimport { InputDebugContributor } from \"./InputDebugContributor.js\";\n\nconst MOUSE_BUTTON_MAP: Record<number, string> = {\n 0: \"MouseLeft\",\n 1: \"MouseMiddle\",\n 2: \"MouseRight\",\n};\n\n/** Input plugin — wires keyboard and pointer listeners, registers InputManager. */\nexport class InputPlugin implements Plugin {\n readonly name = \"input\";\n readonly version = \"2.0.0\";\n\n private readonly config: InputConfig;\n private manager!: InputManager;\n private context!: EngineContext;\n private cleanupFns: Array<() => void> = [];\n\n constructor(config?: InputConfig) {\n this.config = config ?? {};\n }\n\n install(context: EngineContext): void {\n this.context = context;\n this.manager = new InputManager();\n\n if (this.config.actions) {\n this.manager.setActionMap(this.config.actions);\n }\n\n if (this.config.groups) {\n this.manager.setGroups(this.config.groups);\n }\n\n // Default to the well-known RendererAdapterKey so the canonical renderer\n // is picked up with no config. `rendererKey` stays as an override for\n // custom/foreign renderers registered under a different key.\n const rendererKey = this.config.rendererKey ?? RendererAdapterKey;\n const renderer = context.tryResolve(rendererKey);\n const pointerTarget: EventTarget =\n this.config.target ?? renderer?.canvas ?? document;\n\n // Element used to convert clientX/clientY to element-relative coordinates.\n // When `canvasToVirtual` is available, it always expects canvas-origin\n // pixels — so prefer the canvas over a custom `config.target` (which may\n // be a wrapping element). Falls back to null if neither is available.\n const coordinateElement: Element | null =\n renderer?.canvas ??\n this.config.target ??\n null;\n\n // When the renderer exposes canvasToVirtual, route pointer coords through\n // it so they stay correct under responsive fit or custom virtual sizes.\n // Without it, raw canvas-relative CSS pixels are passed through unchanged\n // (works only when canvas CSS size == virtual size — the default).\n const mapPointer = (cssX: number, cssY: number): { x: number; y: number } =>\n renderer?.canvasToVirtual?.(cssX, cssY) ?? { x: cssX, y: cssY };\n\n const preventSet = new Set(this.config.preventDefaultKeys ?? []);\n\n // Keyboard listeners\n const onKeyDown = (e: Event): void => {\n const ke = e as KeyboardEvent;\n if (ke.repeat) return;\n if (preventSet.has(ke.code)) ke.preventDefault();\n this.manager._onKeyDown(ke.code);\n };\n const onKeyUp = (e: Event): void => {\n const ke = e as KeyboardEvent;\n if (preventSet.has(ke.code)) ke.preventDefault();\n this.manager._onKeyUp(ke.code);\n };\n window.addEventListener(\"keydown\", onKeyDown);\n window.addEventListener(\"keyup\", onKeyUp);\n this.cleanupFns.push(\n () => window.removeEventListener(\"keydown\", onKeyDown),\n () => window.removeEventListener(\"keyup\", onKeyUp),\n );\n\n // Pointer listeners — pointerdown on target, pointerup/move/cancel on window\n // so releases outside the target element are still captured\n const onPointerMove = (e: Event): void => {\n const pe = e as PointerEvent;\n let cssX: number;\n let cssY: number;\n if (coordinateElement) {\n const rect = coordinateElement.getBoundingClientRect();\n cssX = pe.clientX - rect.left;\n cssY = pe.clientY - rect.top;\n } else {\n cssX = pe.clientX;\n cssY = pe.clientY;\n }\n const mapped = mapPointer(cssX, cssY);\n this.manager._onPointerMove(mapped.x, mapped.y);\n };\n const onPointerDown = (e: Event): void => {\n const pe = e as PointerEvent;\n const button = pe.button as 0 | 1 | 2;\n if (button in MOUSE_BUTTON_MAP) {\n this.manager.firePointerDown(button);\n } else {\n this.manager._onPointerDown();\n }\n };\n const onPointerUp = (e: Event): void => {\n const pe = e as PointerEvent;\n const button = pe.button as 0 | 1 | 2;\n if (button in MOUSE_BUTTON_MAP) {\n this.manager.firePointerUp(button);\n } else {\n this.manager._onPointerUp();\n }\n };\n const onPointerCancel = (): void => {\n this.manager.clearPointerButtons();\n };\n\n pointerTarget.addEventListener(\"pointerdown\", onPointerDown);\n window.addEventListener(\"pointermove\", onPointerMove);\n window.addEventListener(\"pointerup\", onPointerUp);\n window.addEventListener(\"pointercancel\", onPointerCancel);\n this.cleanupFns.push(\n () => pointerTarget.removeEventListener(\"pointerdown\", onPointerDown),\n () => window.removeEventListener(\"pointermove\", onPointerMove),\n () => window.removeEventListener(\"pointerup\", onPointerUp),\n () => window.removeEventListener(\"pointercancel\", onPointerCancel),\n );\n\n context.register(InputManagerKey, this.manager);\n }\n\n registerSystems(scheduler: SystemScheduler): void {\n scheduler.add(new InputPollSystem());\n scheduler.add(new InputClearSystem());\n }\n\n onStart(): void {\n const registry = this.context.tryResolve(DebugRegistryKey);\n registry?.register(new InputDebugContributor(this.manager));\n }\n\n onDestroy(): void {\n for (const cleanup of this.cleanupFns) {\n cleanup();\n }\n this.cleanupFns.length = 0;\n }\n}\n","import { Vec2 } from \"@yagejs/core\";\nimport type {\n ActionMapDefinition,\n CameraLike,\n RebindOptions,\n RebindResult,\n} from \"./types.js\";\n\n/** Central input state manager. Resolved via DI with InputManagerKey. */\nexport class InputManager {\n private pressedKeys = new Set<string>();\n private justPressedKeys = new Set<string>();\n private justReleasedKeys = new Set<string>();\n private holdStart = new Map<string, number>();\n private syntheticPressedActions = new Set<string>();\n private syntheticActionStarts = new Map<string, number>();\n private actionMap = new Map<string, string[]>();\n private defaultBindings = new Map<string, string[]>();\n private groups = new Map<string, Set<string>>();\n private actionGroups = new Map<string, Set<string>>();\n private disabledGroups = new Set<string>();\n private pointerScreenPos = Vec2.ZERO;\n private pointerDownState = false;\n private pressedMouseButtons = new Set<number>();\n private gamepadButtons = new Map<number, boolean>();\n private gamepadAxes = new Map<number, number>();\n private camera: CameraLike | null = null;\n private elapsedMs = 0;\n private listenResolve: ((key: string | null) => void) | null = null;\n\n // -- Action-based queries --\n\n /** Whether any key mapped to this action is currently held. */\n isPressed(action: string): boolean {\n if (!this.isActionEnabled(action)) return false;\n return this.syntheticPressedActions.has(action) ||\n this.anyKeyInSet(action, this.pressedKeys);\n }\n\n /** Whether any key mapped to this action was pressed this frame. */\n isJustPressed(action: string): boolean {\n if (!this.isActionEnabled(action)) return false;\n return this.syntheticPressedActions.has(action) ||\n this.anyKeyInSet(action, this.justPressedKeys);\n }\n\n /** Whether any key mapped to this action was released this frame. */\n isJustReleased(action: string): boolean {\n if (!this.isActionEnabled(action)) return false;\n return this.anyKeyInSet(action, this.justReleasedKeys);\n }\n\n /** Returns true if any key bound to the action exists in the given set. */\n private anyKeyInSet(action: string, set: Set<string>): boolean {\n const keys = this.actionMap.get(action);\n if (!keys) return false;\n for (const key of keys) {\n if (set.has(key)) return true;\n }\n return false;\n }\n\n /** Milliseconds the action has been held. Returns 0 if not held. */\n getHoldDuration(action: string): number {\n if (!this.isActionEnabled(action)) return 0;\n const keys = this.actionMap.get(action);\n if (!keys && !this.syntheticPressedActions.has(action)) return 0;\n let maxDuration = 0;\n for (const key of keys ?? []) {\n const start = this.holdStart.get(key);\n if (start !== undefined) {\n maxDuration = Math.max(maxDuration, this.elapsedMs - start);\n }\n }\n const syntheticStart = this.syntheticActionStarts.get(action);\n if (syntheticStart !== undefined) {\n maxDuration = Math.max(maxDuration, this.elapsedMs - syntheticStart);\n }\n return maxDuration;\n }\n\n /** Whether the action has been held for at least `minTime` ms. */\n isHeldFor(action: string, minTime: number): boolean {\n return this.getHoldDuration(action) >= minTime;\n }\n\n // -- Axis helpers --\n\n /** Returns -1, 0, or 1 based on negative/positive action states. */\n getAxis(negative: string, positive: string): number {\n const neg = this.isPressed(negative) ? 1 : 0;\n const pos = this.isPressed(positive) ? 1 : 0;\n return pos - neg;\n }\n\n /** Returns a Vec2 from four directional actions. Not normalized. */\n getVector(\n left: string,\n right: string,\n up: string,\n down: string,\n ): Vec2 {\n const x = this.getAxis(left, right);\n const y = this.getAxis(up, down);\n return new Vec2(x, y);\n }\n\n // -- Pointer --\n\n /** Pointer position in world coordinates (via Camera), or screen coords if no camera. */\n getPointerPosition(): Vec2 {\n if (this.camera) {\n const w = this.camera.screenToWorld(\n this.pointerScreenPos.x,\n this.pointerScreenPos.y,\n );\n return new Vec2(w.x, w.y);\n }\n return this.pointerScreenPos;\n }\n\n /** Raw pointer position in screen coordinates. */\n getPointerScreenPosition(): Vec2 {\n return this.pointerScreenPos;\n }\n\n /** Whether any pointer button is currently held. */\n isPointerDown(): boolean {\n return this.pointerDownState;\n }\n\n // -- Runtime action map management --\n\n /** Replace the entire action map and store it as the default for {@link resetBindings}. */\n setActionMap(actions: ActionMapDefinition): void {\n this.actionMap.clear();\n this.defaultBindings.clear();\n for (const [action, keys] of Object.entries(actions)) {\n this.actionMap.set(action, [...keys]);\n this.defaultBindings.set(action, [...keys]);\n }\n }\n\n /** Add a key binding to an action. Creates the action if it doesn't exist. */\n bindKey(action: string, key: string): void {\n let keys = this.actionMap.get(action);\n if (!keys) {\n keys = [];\n this.actionMap.set(action, keys);\n }\n if (!keys.includes(key)) {\n keys.push(key);\n }\n }\n\n /** Remove a key binding from an action. */\n unbindKey(action: string, key: string): void {\n const keys = this.actionMap.get(action);\n if (!keys) return;\n const idx = keys.indexOf(key);\n if (idx !== -1) keys.splice(idx, 1);\n }\n\n // -- Binding queries --\n\n /** Returns the current key bindings for an action, or an empty array if unmapped. */\n getBindings(action: string): readonly string[] {\n return this.actionMap.get(action) ?? [];\n }\n\n /** Returns all action names that have the given key bound. */\n getActionsForKey(key: string): string[] {\n const result: string[] = [];\n for (const [action, keys] of this.actionMap) {\n if (keys.includes(key)) result.push(action);\n }\n return result;\n }\n\n // -- Rebinding --\n\n /**\n * Rebind a key to an action with optional conflict detection.\n * Conflicts are only detected between actions sharing at least one group.\n */\n rebind(action: string, key: string, opts?: RebindOptions): RebindResult {\n const conflict = opts?.conflict ?? \"reject\";\n const slot = opts?.slot;\n\n const conflictAction = this.findConflictInGroups(action, key);\n\n if (conflictAction && conflict === \"reject\") {\n return { ok: false, conflict: { action: conflictAction, key } };\n }\n\n if (conflictAction && conflict === \"replace\") {\n this.unbindKey(conflictAction, key);\n }\n\n let keys = this.actionMap.get(action);\n if (!keys) {\n keys = [];\n this.actionMap.set(action, keys);\n }\n\n // Remove existing occurrence to avoid duplicates, adjusting slot for the shift\n const existingIdx = keys.indexOf(key);\n let targetSlot = slot;\n if (targetSlot !== undefined && existingIdx !== -1 && existingIdx !== targetSlot) {\n keys.splice(existingIdx, 1);\n if (targetSlot > existingIdx) targetSlot--;\n }\n\n if (targetSlot !== undefined && targetSlot < keys.length) {\n keys[targetSlot] = key;\n } else if (!keys.includes(key)) {\n keys.push(key);\n }\n\n return { ok: true };\n }\n\n /**\n * Finds the first action that uses the given key AND shares at least one\n * group with the target action. Ungrouped actions never conflict.\n */\n private findConflictInGroups(action: string, key: string): string | null {\n const myGroups = this.actionGroups.get(action);\n if (!myGroups || myGroups.size === 0) return null;\n\n for (const [otherAction, otherKeys] of this.actionMap) {\n if (otherAction === action) continue;\n if (!otherKeys.includes(key)) continue;\n\n const otherGroups = this.actionGroups.get(otherAction);\n if (!otherGroups) continue;\n\n for (const g of myGroups) {\n if (otherGroups.has(g)) return otherAction;\n }\n }\n return null;\n }\n\n // -- Binding persistence --\n\n /** Reset bindings to defaults. If an action name is provided, only reset that action. */\n resetBindings(action?: string): void {\n if (action !== undefined) {\n const defaults = this.defaultBindings.get(action);\n if (defaults) {\n this.actionMap.set(action, [...defaults]);\n }\n } else {\n this.actionMap.clear();\n for (const [a, keys] of this.defaultBindings) {\n this.actionMap.set(a, [...keys]);\n }\n }\n }\n\n /** Export the current bindings as a plain object for serialization. */\n exportBindings(): ActionMapDefinition {\n const result: ActionMapDefinition = {};\n for (const [action, keys] of this.actionMap) {\n result[action] = [...keys];\n }\n return result;\n }\n\n /** Load bindings from a plain object. Resets to defaults first, then overlays the provided map. */\n loadBindings(map: ActionMapDefinition): void {\n this.resetBindings();\n for (const [action, keys] of Object.entries(map)) {\n this.actionMap.set(action, [...keys]);\n }\n }\n\n // -- Group management --\n\n /** Configure input groups. Group name -> array of action names. */\n setGroups(groups: Record<string, string[]>): void {\n this.groups.clear();\n this.actionGroups.clear();\n for (const [name, actions] of Object.entries(groups)) {\n this.groups.set(name, new Set(actions));\n for (const action of actions) {\n let set = this.actionGroups.get(action);\n if (!set) {\n set = new Set();\n this.actionGroups.set(action, set);\n }\n set.add(name);\n }\n }\n }\n\n /** Enable a group by name. */\n enableGroup(name: string): void {\n this.disabledGroups.delete(name);\n }\n\n /** Disable a group by name. Actions only in disabled groups become inactive. */\n disableGroup(name: string): void {\n this.disabledGroups.add(name);\n }\n\n /** Set exactly these groups as active; all others are disabled. */\n setActiveGroups(names: string[]): void {\n this.disabledGroups.clear();\n for (const group of this.groups.keys()) {\n if (!names.includes(group)) {\n this.disabledGroups.add(group);\n }\n }\n }\n\n /** Whether a group is currently enabled. Returns true for unknown group names. */\n isGroupEnabled(name: string): boolean {\n return !this.disabledGroups.has(name);\n }\n\n /** Get all configured group names. */\n getGroups(): string[] {\n return Array.from(this.groups.keys());\n }\n\n /** Get the action names belonging to a group. Returns empty array for unknown groups. */\n getGroupActions(name: string): readonly string[] {\n const set = this.groups.get(name);\n return set ? Array.from(set) : [];\n }\n\n /** Returns true if the action is ungrouped or any of its groups is enabled. */\n private isActionEnabled(action: string): boolean {\n const groupSet = this.actionGroups.get(action);\n if (!groupSet || groupSet.size === 0) return true;\n for (const group of groupSet) {\n if (!this.disabledGroups.has(group)) return true;\n }\n return false;\n }\n\n // -- Key listening --\n\n /** Returns a promise that resolves with the next key code pressed. Intercepts the key. */\n listenForNextKey(): Promise<string | null> {\n this.cancelListen();\n return new Promise<string | null>((resolve) => {\n this.listenResolve = resolve;\n });\n }\n\n /** Cancel an active {@link listenForNextKey}. Resolves the pending promise with `null`. */\n cancelListen(): void {\n if (this.listenResolve) {\n const resolve = this.listenResolve;\n this.listenResolve = null;\n resolve(null);\n }\n }\n\n /** Public wrapper for synthetic key-down injection. */\n fireKeyDown(code: string): void {\n this._onKeyDown(code);\n }\n\n /** Public wrapper for synthetic key-up injection. */\n fireKeyUp(code: string): void {\n this._onKeyUp(code);\n }\n\n /** Public wrapper for synthetic pointer movement. */\n firePointerMove(screenX: number, screenY: number): void {\n this._onPointerMove(screenX, screenY);\n }\n\n /** Public wrapper for synthetic pointer-button presses. */\n firePointerDown(button: 0 | 1 | 2 = 0): void {\n this._onPointerDown();\n this.pressedMouseButtons.add(button);\n\n if (button === 0) this._onKeyDown(\"MouseLeft\");\n if (button === 1) this._onKeyDown(\"MouseMiddle\");\n if (button === 2) this._onKeyDown(\"MouseRight\");\n }\n\n /** Public wrapper for synthetic pointer-button releases. */\n firePointerUp(button: 0 | 1 | 2 = 0): void {\n this.pressedMouseButtons.delete(button);\n this.pointerDownState = this.pressedMouseButtons.size > 0;\n if (!this.pointerDownState) {\n this._onPointerUp();\n }\n\n if (button === 0) this._onKeyUp(\"MouseLeft\");\n if (button === 1) this._onKeyUp(\"MouseMiddle\");\n if (button === 2) this._onKeyUp(\"MouseRight\");\n }\n\n /** Store synthetic gamepad button state. */\n fireGamepadButton(idx: number, pressed: boolean): void {\n this.gamepadButtons.set(idx, pressed);\n }\n\n /** Store synthetic gamepad axis state. */\n fireGamepadAxis(idx: number, value: number): void {\n this.gamepadAxes.set(idx, value);\n }\n\n /** Inject a one-frame synthetic action pulse. */\n fireAction(name: string): void {\n if (!this.actionMap.has(name)) {\n throw new Error(`InputManager.fireAction(): unknown action \"${name}\".`);\n }\n this.syntheticPressedActions.add(name);\n this.syntheticActionStarts.set(name, this.elapsedMs);\n }\n\n /** Release all synthetic and physical input state. */\n clearAll(): void {\n for (const code of [...this.pressedKeys]) {\n this._onKeyUp(code);\n }\n // Hard reset: synthetic releases generated above are intentionally\n // discarded. Callers want a clean slate, not a flurry of justReleased\n // pulses for downstream listeners.\n this.justPressedKeys.clear();\n this.justReleasedKeys.clear();\n this.holdStart.clear();\n this.syntheticPressedActions.clear();\n this.syntheticActionStarts.clear();\n this.pressedMouseButtons.clear();\n this.pointerDownState = false;\n this.gamepadButtons.clear();\n this.gamepadAxes.clear();\n }\n\n /** Release any pressed pointer buttons without touching keyboard state. */\n clearPointerButtons(): void {\n for (const button of [...this.pressedMouseButtons]) {\n if (button === 0) this._onKeyUp(\"MouseLeft\");\n if (button === 1) this._onKeyUp(\"MouseMiddle\");\n if (button === 2) this._onKeyUp(\"MouseRight\");\n }\n this.pressedMouseButtons.clear();\n this.pointerDownState = false;\n }\n\n /** Snapshot of current held input state for inspector tooling. */\n snapshotState(): {\n keys: string[];\n actions: string[];\n mouse: { x: number; y: number; buttons: number[]; down: boolean };\n gamepad: {\n buttons: number[];\n axes: Array<{ index: number; value: number }>;\n };\n } {\n const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0);\n const keys = [...this.pressedKeys].sort(cmp);\n const actions = this.getActionNames()\n .filter((action) => this.isPressed(action))\n .sort(cmp);\n const buttons = [...this.pressedMouseButtons].sort((a, b) => a - b);\n const pressedButtons = [...this.gamepadButtons.entries()]\n .filter(([, pressed]) => pressed)\n .map(([idx]) => idx)\n .sort((a, b) => a - b);\n const axes = [...this.gamepadAxes.entries()]\n .filter(([, value]) => value !== 0)\n .sort(([a], [b]) => a - b)\n .map(([index, value]) => ({ index, value }));\n\n return {\n keys,\n actions,\n mouse: {\n x: this.pointerScreenPos.x,\n y: this.pointerScreenPos.y,\n buttons,\n down: this.pointerDownState,\n },\n gamepad: {\n buttons: pressedButtons,\n axes,\n },\n };\n }\n\n // -- Internal methods (called by InputPlugin / Systems) --\n\n /** @internal */\n _onKeyDown(code: string): void {\n if (this.listenResolve) {\n const resolve = this.listenResolve;\n this.listenResolve = null;\n resolve(code);\n return;\n }\n if (!this.pressedKeys.has(code)) {\n this.pressedKeys.add(code);\n this.justPressedKeys.add(code);\n this.holdStart.set(code, this.elapsedMs);\n }\n }\n\n /** @internal */\n _onKeyUp(code: string): void {\n if (this.pressedKeys.has(code)) {\n this.pressedKeys.delete(code);\n this.justReleasedKeys.add(code);\n this.holdStart.delete(code);\n }\n }\n\n /** @internal */\n _onPointerMove(screenX: number, screenY: number): void {\n this.pointerScreenPos = new Vec2(screenX, screenY);\n }\n\n /** @internal */\n _onPointerDown(): void {\n this.pointerDownState = true;\n }\n\n /** @internal */\n _onPointerUp(): void {\n this.pointerDownState = false;\n }\n\n /** @internal Clear per-frame justPressed/justReleased flags. */\n _clearFrameState(): void {\n this.justPressedKeys.clear();\n this.justReleasedKeys.clear();\n this.syntheticPressedActions.clear();\n this.syntheticActionStarts.clear();\n }\n\n /** Set camera for pointer world-coord conversion. */\n setCamera(camera: CameraLike): void {\n this.camera = camera;\n }\n\n /** Clear the camera reference (e.g. on scene exit). */\n clearCamera(): void {\n this.camera = null;\n }\n\n /** Get all configured action names. */\n getActionNames(): string[] {\n return Array.from(this.actionMap.keys());\n }\n\n /** @internal Advance the elapsed game-time clock. Called by InputPollSystem. */\n _advanceTime(dtMs: number): void {\n this.elapsedMs += dtMs;\n }\n}\n","import { ServiceKey } from \"@yagejs/core\";\nimport type { RendererAdapter } from \"@yagejs/core\";\nimport type { InputManager } from \"./InputManager.js\";\n\n/** Service key for the InputManager. */\nexport const InputManagerKey = new ServiceKey<InputManager>(\"inputManager\");\n\n/** Minimal camera surface needed by InputManager for pointer world-coord conversion. */\nexport interface CameraLike {\n screenToWorld(screenX: number, screenY: number): { x: number; y: number };\n}\n\n/**\n * Minimal renderer surface needed by InputPlugin for canvas access and\n * coordinate mapping. Alias of the cross-package `RendererAdapter` contract.\n */\nexport type RendererLike = RendererAdapter;\n\n/** Configuration for the InputPlugin. */\nexport interface InputConfig {\n /** Target element for pointer events (default: canvas from renderer, or document). */\n target?: HTMLElement;\n /** Action map: action name -> array of physical key codes. */\n actions?: ActionMapDefinition;\n /** Input groups: group name -> array of action names belonging to it. */\n groups?: Record<string, string[]>;\n /** Key codes to call preventDefault() on (default: none). */\n preventDefaultKeys?: string[];\n /**\n * Optional override for the renderer service key. When omitted, InputPlugin\n * auto-resolves `RendererAdapterKey` — the canonical `@yagejs/renderer`\n * plugin registers itself under that key, so pointer events target its\n * canvas and coordinates route through `canvasToVirtual` out of the box.\n * Set this only if you ship a custom renderer registered under a different\n * key.\n */\n rendererKey?: ServiceKey<RendererAdapter>;\n}\n\n/** Maps action names to arrays of physical key codes. */\nexport type ActionMapDefinition = Record<string, string[]>;\n\n/** How to handle a conflict when rebinding a key already used by another action in the same group. */\nexport type InputConflictPolicy = \"replace\" | \"keep-both\" | \"reject\";\n\n/** Options for {@link InputManager.rebind}. */\nexport interface RebindOptions {\n /** Index of the binding slot to replace. Appends if the slot does not exist. */\n slot?: number;\n /** How to resolve conflicts with other actions in the same group(s). Default: `\"reject\"`. */\n conflict?: InputConflictPolicy;\n}\n\n/** Result of a {@link InputManager.rebind} call. */\nexport interface RebindResult {\n /** Whether the rebind succeeded. */\n ok: boolean;\n /** Present when `ok` is false due to a conflict with `conflict: \"reject\"`. */\n conflict?: { action: string; key: string };\n}\n","import { System, Phase } from \"@yagejs/core\";\nimport { InputManagerKey } from \"./types.js\";\n\n/**\n * Runs at the start of each frame (EarlyUpdate, priority -100).\n * Advances the input elapsed clock. Gamepad polling will be added here later.\n */\nexport class InputPollSystem extends System {\n readonly phase = Phase.EarlyUpdate;\n readonly priority = -100;\n\n update(dt: number): void {\n this.use(InputManagerKey)._advanceTime(dt);\n }\n}\n","import { System, Phase } from \"@yagejs/core\";\nimport { InputManagerKey } from \"./types.js\";\n\n/**\n * Runs at the end of each frame (EndOfFrame, priority 9000).\n * Clears per-frame justPressed/justReleased flags.\n */\nexport class InputClearSystem extends System {\n readonly phase = Phase.EndOfFrame;\n readonly priority = 9000;\n\n update(): void {\n this.use(InputManagerKey)._clearFrameState();\n }\n}\n","import type {\n DebugContributor,\n WorldDebugApi,\n HudDebugApi,\n} from \"@yagejs/debug/api\";\nimport type { InputManager } from \"./InputManager.js\";\n\nconst CROSSHAIR_SIZE = 10;\nconst CROSSHAIR_COLOR = 0xff00ff;\n\n/** Debug contributor that shows pressed actions and pointer position. */\nexport class InputDebugContributor implements DebugContributor {\n readonly name = \"input\";\n readonly flags = [\"actions\", \"pointer\"] as const;\n\n constructor(private readonly manager: InputManager) {}\n\n drawWorld(api: WorldDebugApi): void {\n if (!api.isFlagEnabled(\"pointer\")) return;\n\n const pos = this.manager.getPointerPosition();\n const g = api.acquireGraphics();\n if (!g) return;\n\n const size = CROSSHAIR_SIZE / api.cameraZoom;\n const lineWidth = 1 / api.cameraZoom;\n g.moveTo(pos.x - size, pos.y)\n .lineTo(pos.x + size, pos.y)\n .moveTo(pos.x, pos.y - size)\n .lineTo(pos.x, pos.y + size)\n .stroke({ width: lineWidth, color: CROSSHAIR_COLOR });\n }\n\n drawHud(api: HudDebugApi): void {\n if (!api.isFlagEnabled(\"actions\")) return;\n\n const pressed = this.manager\n .getActionNames()\n .filter((action) => this.manager.isPressed(action));\n\n const label = pressed.length > 0 ? pressed.join(\", \") : \"(none)\";\n api.addLine(`Input: ${label}`);\n\n const groups = this.manager.getGroups();\n if (groups.length > 0) {\n const disabled = groups.filter((g) => !this.manager.isGroupEnabled(g));\n if (disabled.length > 0) {\n api.addLine(`Disabled groups: ${disabled.join(\", \")}`);\n }\n }\n }\n}\n","const KEY_DISPLAY_NAMES: Record<string, string> = {\n // Letters\n KeyA: \"A\",\n KeyB: \"B\",\n KeyC: \"C\",\n KeyD: \"D\",\n KeyE: \"E\",\n KeyF: \"F\",\n KeyG: \"G\",\n KeyH: \"H\",\n KeyI: \"I\",\n KeyJ: \"J\",\n KeyK: \"K\",\n KeyL: \"L\",\n KeyM: \"M\",\n KeyN: \"N\",\n KeyO: \"O\",\n KeyP: \"P\",\n KeyQ: \"Q\",\n KeyR: \"R\",\n KeyS: \"S\",\n KeyT: \"T\",\n KeyU: \"U\",\n KeyV: \"V\",\n KeyW: \"W\",\n KeyX: \"X\",\n KeyY: \"Y\",\n KeyZ: \"Z\",\n\n // Digits\n Digit0: \"0\",\n Digit1: \"1\",\n Digit2: \"2\",\n Digit3: \"3\",\n Digit4: \"4\",\n Digit5: \"5\",\n Digit6: \"6\",\n Digit7: \"7\",\n Digit8: \"8\",\n Digit9: \"9\",\n\n // Function keys\n F1: \"F1\",\n F2: \"F2\",\n F3: \"F3\",\n F4: \"F4\",\n F5: \"F5\",\n F6: \"F6\",\n F7: \"F7\",\n F8: \"F8\",\n F9: \"F9\",\n F10: \"F10\",\n F11: \"F11\",\n F12: \"F12\",\n\n // Modifiers\n ShiftLeft: \"Left Shift\",\n ShiftRight: \"Right Shift\",\n ControlLeft: \"Left Ctrl\",\n ControlRight: \"Right Ctrl\",\n AltLeft: \"Left Alt\",\n AltRight: \"Right Alt\",\n MetaLeft: \"Left Meta\",\n MetaRight: \"Right Meta\",\n\n // Arrows\n ArrowUp: \"Up\",\n ArrowDown: \"Down\",\n ArrowLeft: \"Left\",\n ArrowRight: \"Right\",\n\n // Common keys\n Space: \"Space\",\n Enter: \"Enter\",\n Escape: \"Esc\",\n Tab: \"Tab\",\n Backspace: \"Backspace\",\n Delete: \"Delete\",\n Insert: \"Insert\",\n Home: \"Home\",\n End: \"End\",\n PageUp: \"Page Up\",\n PageDown: \"Page Down\",\n CapsLock: \"Caps Lock\",\n NumLock: \"Num Lock\",\n ScrollLock: \"Scroll Lock\",\n PrintScreen: \"Print Screen\",\n Pause: \"Pause\",\n ContextMenu: \"Menu\",\n\n // Punctuation / symbols\n Backquote: \"`\",\n Minus: \"-\",\n Equal: \"=\",\n BracketLeft: \"[\",\n BracketRight: \"]\",\n Backslash: \"\\\\\",\n Semicolon: \";\",\n Quote: \"'\",\n Comma: \",\",\n Period: \".\",\n Slash: \"/\",\n\n // Numpad\n Numpad0: \"Numpad 0\",\n Numpad1: \"Numpad 1\",\n Numpad2: \"Numpad 2\",\n Numpad3: \"Numpad 3\",\n Numpad4: \"Numpad 4\",\n Numpad5: \"Numpad 5\",\n Numpad6: \"Numpad 6\",\n Numpad7: \"Numpad 7\",\n Numpad8: \"Numpad 8\",\n Numpad9: \"Numpad 9\",\n NumpadAdd: \"Numpad +\",\n NumpadSubtract: \"Numpad -\",\n NumpadMultiply: \"Numpad *\",\n NumpadDivide: \"Numpad /\",\n NumpadDecimal: \"Numpad .\",\n NumpadEnter: \"Numpad Enter\",\n\n // Mouse buttons (synthetic codes from InputPlugin)\n MouseLeft: \"Left Click\",\n MouseMiddle: \"Middle Click\",\n MouseRight: \"Right Click\",\n};\n\n/** Returns a human-readable display name for a `KeyboardEvent.code` or mouse key string. */\nexport function getKeyDisplayName(code: string): string {\n return KEY_DISPLAY_NAMES[code] ?? code;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,IAAAA,eAAmC;AACnC,iBAAiC;;;ACFjC,kBAAqB;AASd,IAAM,eAAN,MAAmB;AAAA,EAT1B,OAS0B;AAAA;AAAA;AAAA,EAChB,cAAc,oBAAI,IAAY;AAAA,EAC9B,kBAAkB,oBAAI,IAAY;AAAA,EAClC,mBAAmB,oBAAI,IAAY;AAAA,EACnC,YAAY,oBAAI,IAAoB;AAAA,EACpC,0BAA0B,oBAAI,IAAY;AAAA,EAC1C,wBAAwB,oBAAI,IAAoB;AAAA,EAChD,YAAY,oBAAI,IAAsB;AAAA,EACtC,kBAAkB,oBAAI,IAAsB;AAAA,EAC5C,SAAS,oBAAI,IAAyB;AAAA,EACtC,eAAe,oBAAI,IAAyB;AAAA,EAC5C,iBAAiB,oBAAI,IAAY;AAAA,EACjC,mBAAmB,iBAAK;AAAA,EACxB,mBAAmB;AAAA,EACnB,sBAAsB,oBAAI,IAAY;AAAA,EACtC,iBAAiB,oBAAI,IAAqB;AAAA,EAC1C,cAAc,oBAAI,IAAoB;AAAA,EACtC,SAA4B;AAAA,EAC5B,YAAY;AAAA,EACZ,gBAAuD;AAAA;AAAA;AAAA,EAK/D,UAAU,QAAyB;AACjC,QAAI,CAAC,KAAK,gBAAgB,MAAM,EAAG,QAAO;AAC1C,WAAO,KAAK,wBAAwB,IAAI,MAAM,KAC5C,KAAK,YAAY,QAAQ,KAAK,WAAW;AAAA,EAC7C;AAAA;AAAA,EAGA,cAAc,QAAyB;AACrC,QAAI,CAAC,KAAK,gBAAgB,MAAM,EAAG,QAAO;AAC1C,WAAO,KAAK,wBAAwB,IAAI,MAAM,KAC5C,KAAK,YAAY,QAAQ,KAAK,eAAe;AAAA,EACjD;AAAA;AAAA,EAGA,eAAe,QAAyB;AACtC,QAAI,CAAC,KAAK,gBAAgB,MAAM,EAAG,QAAO;AAC1C,WAAO,KAAK,YAAY,QAAQ,KAAK,gBAAgB;AAAA,EACvD;AAAA;AAAA,EAGQ,YAAY,QAAgB,KAA2B;AAC7D,UAAM,OAAO,KAAK,UAAU,IAAI,MAAM;AACtC,QAAI,CAAC,KAAM,QAAO;AAClB,eAAW,OAAO,MAAM;AACtB,UAAI,IAAI,IAAI,GAAG,EAAG,QAAO;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,gBAAgB,QAAwB;AACtC,QAAI,CAAC,KAAK,gBAAgB,MAAM,EAAG,QAAO;AAC1C,UAAM,OAAO,KAAK,UAAU,IAAI,MAAM;AACtC,QAAI,CAAC,QAAQ,CAAC,KAAK,wBAAwB,IAAI,MAAM,EAAG,QAAO;AAC/D,QAAI,cAAc;AAClB,eAAW,OAAO,QAAQ,CAAC,GAAG;AAC5B,YAAM,QAAQ,KAAK,UAAU,IAAI,GAAG;AACpC,UAAI,UAAU,QAAW;AACvB,sBAAc,KAAK,IAAI,aAAa,KAAK,YAAY,KAAK;AAAA,MAC5D;AAAA,IACF;AACA,UAAM,iBAAiB,KAAK,sBAAsB,IAAI,MAAM;AAC5D,QAAI,mBAAmB,QAAW;AAChC,oBAAc,KAAK,IAAI,aAAa,KAAK,YAAY,cAAc;AAAA,IACrE;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,UAAU,QAAgB,SAA0B;AAClD,WAAO,KAAK,gBAAgB,MAAM,KAAK;AAAA,EACzC;AAAA;AAAA;AAAA,EAKA,QAAQ,UAAkB,UAA0B;AAClD,UAAM,MAAM,KAAK,UAAU,QAAQ,IAAI,IAAI;AAC3C,UAAM,MAAM,KAAK,UAAU,QAAQ,IAAI,IAAI;AAC3C,WAAO,MAAM;AAAA,EACf;AAAA;AAAA,EAGA,UACE,MACA,OACA,IACA,MACM;AACN,UAAM,IAAI,KAAK,QAAQ,MAAM,KAAK;AAClC,UAAM,IAAI,KAAK,QAAQ,IAAI,IAAI;AAC/B,WAAO,IAAI,iBAAK,GAAG,CAAC;AAAA,EACtB;AAAA;AAAA;AAAA,EAKA,qBAA2B;AACzB,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,KAAK,OAAO;AAAA,QACpB,KAAK,iBAAiB;AAAA,QACtB,KAAK,iBAAiB;AAAA,MACxB;AACA,aAAO,IAAI,iBAAK,EAAE,GAAG,EAAE,CAAC;AAAA,IAC1B;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,2BAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,gBAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA,EAKA,aAAa,SAAoC;AAC/C,SAAK,UAAU,MAAM;AACrB,SAAK,gBAAgB,MAAM;AAC3B,eAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,OAAO,GAAG;AACpD,WAAK,UAAU,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC;AACpC,WAAK,gBAAgB,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA,EAGA,QAAQ,QAAgB,KAAmB;AACzC,QAAI,OAAO,KAAK,UAAU,IAAI,MAAM;AACpC,QAAI,CAAC,MAAM;AACT,aAAO,CAAC;AACR,WAAK,UAAU,IAAI,QAAQ,IAAI;AAAA,IACjC;AACA,QAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,WAAK,KAAK,GAAG;AAAA,IACf;AAAA,EACF;AAAA;AAAA,EAGA,UAAU,QAAgB,KAAmB;AAC3C,UAAM,OAAO,KAAK,UAAU,IAAI,MAAM;AACtC,QAAI,CAAC,KAAM;AACX,UAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,QAAI,QAAQ,GAAI,MAAK,OAAO,KAAK,CAAC;AAAA,EACpC;AAAA;AAAA;AAAA,EAKA,YAAY,QAAmC;AAC7C,WAAO,KAAK,UAAU,IAAI,MAAM,KAAK,CAAC;AAAA,EACxC;AAAA;AAAA,EAGA,iBAAiB,KAAuB;AACtC,UAAM,SAAmB,CAAC;AAC1B,eAAW,CAAC,QAAQ,IAAI,KAAK,KAAK,WAAW;AAC3C,UAAI,KAAK,SAAS,GAAG,EAAG,QAAO,KAAK,MAAM;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,QAAgB,KAAa,MAAoC;AACtE,UAAM,WAAW,MAAM,YAAY;AACnC,UAAM,OAAO,MAAM;AAEnB,UAAM,iBAAiB,KAAK,qBAAqB,QAAQ,GAAG;AAE5D,QAAI,kBAAkB,aAAa,UAAU;AAC3C,aAAO,EAAE,IAAI,OAAO,UAAU,EAAE,QAAQ,gBAAgB,IAAI,EAAE;AAAA,IAChE;AAEA,QAAI,kBAAkB,aAAa,WAAW;AAC5C,WAAK,UAAU,gBAAgB,GAAG;AAAA,IACpC;AAEA,QAAI,OAAO,KAAK,UAAU,IAAI,MAAM;AACpC,QAAI,CAAC,MAAM;AACT,aAAO,CAAC;AACR,WAAK,UAAU,IAAI,QAAQ,IAAI;AAAA,IACjC;AAGA,UAAM,cAAc,KAAK,QAAQ,GAAG;AACpC,QAAI,aAAa;AACjB,QAAI,eAAe,UAAa,gBAAgB,MAAM,gBAAgB,YAAY;AAChF,WAAK,OAAO,aAAa,CAAC;AAC1B,UAAI,aAAa,YAAa;AAAA,IAChC;AAEA,QAAI,eAAe,UAAa,aAAa,KAAK,QAAQ;AACxD,WAAK,UAAU,IAAI;AAAA,IACrB,WAAW,CAAC,KAAK,SAAS,GAAG,GAAG;AAC9B,WAAK,KAAK,GAAG;AAAA,IACf;AAEA,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,QAAgB,KAA4B;AACvE,UAAM,WAAW,KAAK,aAAa,IAAI,MAAM;AAC7C,QAAI,CAAC,YAAY,SAAS,SAAS,EAAG,QAAO;AAE7C,eAAW,CAAC,aAAa,SAAS,KAAK,KAAK,WAAW;AACrD,UAAI,gBAAgB,OAAQ;AAC5B,UAAI,CAAC,UAAU,SAAS,GAAG,EAAG;AAE9B,YAAM,cAAc,KAAK,aAAa,IAAI,WAAW;AACrD,UAAI,CAAC,YAAa;AAElB,iBAAW,KAAK,UAAU;AACxB,YAAI,YAAY,IAAI,CAAC,EAAG,QAAO;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAKA,cAAc,QAAuB;AACnC,QAAI,WAAW,QAAW;AACxB,YAAM,WAAW,KAAK,gBAAgB,IAAI,MAAM;AAChD,UAAI,UAAU;AACZ,aAAK,UAAU,IAAI,QAAQ,CAAC,GAAG,QAAQ,CAAC;AAAA,MAC1C;AAAA,IACF,OAAO;AACL,WAAK,UAAU,MAAM;AACrB,iBAAW,CAAC,GAAG,IAAI,KAAK,KAAK,iBAAiB;AAC5C,aAAK,UAAU,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,iBAAsC;AACpC,UAAM,SAA8B,CAAC;AACrC,eAAW,CAAC,QAAQ,IAAI,KAAK,KAAK,WAAW;AAC3C,aAAO,MAAM,IAAI,CAAC,GAAG,IAAI;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,KAAgC;AAC3C,SAAK,cAAc;AACnB,eAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,GAAG,GAAG;AAChD,WAAK,UAAU,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,UAAU,QAAwC;AAChD,SAAK,OAAO,MAAM;AAClB,SAAK,aAAa,MAAM;AACxB,eAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,MAAM,GAAG;AACpD,WAAK,OAAO,IAAI,MAAM,IAAI,IAAI,OAAO,CAAC;AACtC,iBAAW,UAAU,SAAS;AAC5B,YAAI,MAAM,KAAK,aAAa,IAAI,MAAM;AACtC,YAAI,CAAC,KAAK;AACR,gBAAM,oBAAI,IAAI;AACd,eAAK,aAAa,IAAI,QAAQ,GAAG;AAAA,QACnC;AACA,YAAI,IAAI,IAAI;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,YAAY,MAAoB;AAC9B,SAAK,eAAe,OAAO,IAAI;AAAA,EACjC;AAAA;AAAA,EAGA,aAAa,MAAoB;AAC/B,SAAK,eAAe,IAAI,IAAI;AAAA,EAC9B;AAAA;AAAA,EAGA,gBAAgB,OAAuB;AACrC,SAAK,eAAe,MAAM;AAC1B,eAAW,SAAS,KAAK,OAAO,KAAK,GAAG;AACtC,UAAI,CAAC,MAAM,SAAS,KAAK,GAAG;AAC1B,aAAK,eAAe,IAAI,KAAK;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,eAAe,MAAuB;AACpC,WAAO,CAAC,KAAK,eAAe,IAAI,IAAI;AAAA,EACtC;AAAA;AAAA,EAGA,YAAsB;AACpB,WAAO,MAAM,KAAK,KAAK,OAAO,KAAK,CAAC;AAAA,EACtC;AAAA;AAAA,EAGA,gBAAgB,MAAiC;AAC/C,UAAM,MAAM,KAAK,OAAO,IAAI,IAAI;AAChC,WAAO,MAAM,MAAM,KAAK,GAAG,IAAI,CAAC;AAAA,EAClC;AAAA;AAAA,EAGQ,gBAAgB,QAAyB;AAC/C,UAAM,WAAW,KAAK,aAAa,IAAI,MAAM;AAC7C,QAAI,CAAC,YAAY,SAAS,SAAS,EAAG,QAAO;AAC7C,eAAW,SAAS,UAAU;AAC5B,UAAI,CAAC,KAAK,eAAe,IAAI,KAAK,EAAG,QAAO;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAKA,mBAA2C;AACzC,SAAK,aAAa;AAClB,WAAO,IAAI,QAAuB,CAAC,YAAY;AAC7C,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,eAAqB;AACnB,QAAI,KAAK,eAAe;AACtB,YAAM,UAAU,KAAK;AACrB,WAAK,gBAAgB;AACrB,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AAAA;AAAA,EAGA,YAAY,MAAoB;AAC9B,SAAK,WAAW,IAAI;AAAA,EACtB;AAAA;AAAA,EAGA,UAAU,MAAoB;AAC5B,SAAK,SAAS,IAAI;AAAA,EACpB;AAAA;AAAA,EAGA,gBAAgB,SAAiB,SAAuB;AACtD,SAAK,eAAe,SAAS,OAAO;AAAA,EACtC;AAAA;AAAA,EAGA,gBAAgB,SAAoB,GAAS;AAC3C,SAAK,eAAe;AACpB,SAAK,oBAAoB,IAAI,MAAM;AAEnC,QAAI,WAAW,EAAG,MAAK,WAAW,WAAW;AAC7C,QAAI,WAAW,EAAG,MAAK,WAAW,aAAa;AAC/C,QAAI,WAAW,EAAG,MAAK,WAAW,YAAY;AAAA,EAChD;AAAA;AAAA,EAGA,cAAc,SAAoB,GAAS;AACzC,SAAK,oBAAoB,OAAO,MAAM;AACtC,SAAK,mBAAmB,KAAK,oBAAoB,OAAO;AACxD,QAAI,CAAC,KAAK,kBAAkB;AAC1B,WAAK,aAAa;AAAA,IACpB;AAEA,QAAI,WAAW,EAAG,MAAK,SAAS,WAAW;AAC3C,QAAI,WAAW,EAAG,MAAK,SAAS,aAAa;AAC7C,QAAI,WAAW,EAAG,MAAK,SAAS,YAAY;AAAA,EAC9C;AAAA;AAAA,EAGA,kBAAkB,KAAa,SAAwB;AACrD,SAAK,eAAe,IAAI,KAAK,OAAO;AAAA,EACtC;AAAA;AAAA,EAGA,gBAAgB,KAAa,OAAqB;AAChD,SAAK,YAAY,IAAI,KAAK,KAAK;AAAA,EACjC;AAAA;AAAA,EAGA,WAAW,MAAoB;AAC7B,QAAI,CAAC,KAAK,UAAU,IAAI,IAAI,GAAG;AAC7B,YAAM,IAAI,MAAM,8CAA8C,IAAI,IAAI;AAAA,IACxE;AACA,SAAK,wBAAwB,IAAI,IAAI;AACrC,SAAK,sBAAsB,IAAI,MAAM,KAAK,SAAS;AAAA,EACrD;AAAA;AAAA,EAGA,WAAiB;AACf,eAAW,QAAQ,CAAC,GAAG,KAAK,WAAW,GAAG;AACxC,WAAK,SAAS,IAAI;AAAA,IACpB;AAIA,SAAK,gBAAgB,MAAM;AAC3B,SAAK,iBAAiB,MAAM;AAC5B,SAAK,UAAU,MAAM;AACrB,SAAK,wBAAwB,MAAM;AACnC,SAAK,sBAAsB,MAAM;AACjC,SAAK,oBAAoB,MAAM;AAC/B,SAAK,mBAAmB;AACxB,SAAK,eAAe,MAAM;AAC1B,SAAK,YAAY,MAAM;AAAA,EACzB;AAAA;AAAA,EAGA,sBAA4B;AAC1B,eAAW,UAAU,CAAC,GAAG,KAAK,mBAAmB,GAAG;AAClD,UAAI,WAAW,EAAG,MAAK,SAAS,WAAW;AAC3C,UAAI,WAAW,EAAG,MAAK,SAAS,aAAa;AAC7C,UAAI,WAAW,EAAG,MAAK,SAAS,YAAY;AAAA,IAC9C;AACA,SAAK,oBAAoB,MAAM;AAC/B,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,gBAQE;AACA,UAAM,MAAM,wBAAC,GAAW,MAAe,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,GAApD;AACZ,UAAM,OAAO,CAAC,GAAG,KAAK,WAAW,EAAE,KAAK,GAAG;AAC3C,UAAM,UAAU,KAAK,eAAe,EACjC,OAAO,CAAC,WAAW,KAAK,UAAU,MAAM,CAAC,EACzC,KAAK,GAAG;AACX,UAAM,UAAU,CAAC,GAAG,KAAK,mBAAmB,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAClE,UAAM,iBAAiB,CAAC,GAAG,KAAK,eAAe,QAAQ,CAAC,EACrD,OAAO,CAAC,CAAC,EAAE,OAAO,MAAM,OAAO,EAC/B,IAAI,CAAC,CAAC,GAAG,MAAM,GAAG,EAClB,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACvB,UAAM,OAAO,CAAC,GAAG,KAAK,YAAY,QAAQ,CAAC,EACxC,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,CAAC,EACjC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,EACxB,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,EAAE,OAAO,MAAM,EAAE;AAE7C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,OAAO;AAAA,QACL,GAAG,KAAK,iBAAiB;AAAA,QACzB,GAAG,KAAK,iBAAiB;AAAA,QACzB;AAAA,QACA,MAAM,KAAK;AAAA,MACb;AAAA,MACA,SAAS;AAAA,QACP,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,WAAW,MAAoB;AAC7B,QAAI,KAAK,eAAe;AACtB,YAAM,UAAU,KAAK;AACrB,WAAK,gBAAgB;AACrB,cAAQ,IAAI;AACZ;AAAA,IACF;AACA,QAAI,CAAC,KAAK,YAAY,IAAI,IAAI,GAAG;AAC/B,WAAK,YAAY,IAAI,IAAI;AACzB,WAAK,gBAAgB,IAAI,IAAI;AAC7B,WAAK,UAAU,IAAI,MAAM,KAAK,SAAS;AAAA,IACzC;AAAA,EACF;AAAA;AAAA,EAGA,SAAS,MAAoB;AAC3B,QAAI,KAAK,YAAY,IAAI,IAAI,GAAG;AAC9B,WAAK,YAAY,OAAO,IAAI;AAC5B,WAAK,iBAAiB,IAAI,IAAI;AAC9B,WAAK,UAAU,OAAO,IAAI;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA,EAGA,eAAe,SAAiB,SAAuB;AACrD,SAAK,mBAAmB,IAAI,iBAAK,SAAS,OAAO;AAAA,EACnD;AAAA;AAAA,EAGA,iBAAuB;AACrB,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,eAAqB;AACnB,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,mBAAyB;AACvB,SAAK,gBAAgB,MAAM;AAC3B,SAAK,iBAAiB,MAAM;AAC5B,SAAK,wBAAwB,MAAM;AACnC,SAAK,sBAAsB,MAAM;AAAA,EACnC;AAAA;AAAA,EAGA,UAAU,QAA0B;AAClC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA,EAGA,cAAoB;AAClB,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA,EAGA,iBAA2B;AACzB,WAAO,MAAM,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,EACzC;AAAA;AAAA,EAGA,aAAa,MAAoB;AAC/B,SAAK,aAAa;AAAA,EACpB;AACF;;;AC9iBA,IAAAC,eAA2B;AAKpB,IAAM,kBAAkB,IAAI,wBAAyB,cAAc;;;ACL1E,IAAAC,eAA8B;AAOvB,IAAM,kBAAN,cAA8B,oBAAO;AAAA,EAP5C,OAO4C;AAAA;AAAA;AAAA,EACjC,QAAQ,mBAAM;AAAA,EACd,WAAW;AAAA,EAEpB,OAAO,IAAkB;AACvB,SAAK,IAAI,eAAe,EAAE,aAAa,EAAE;AAAA,EAC3C;AACF;;;ACdA,IAAAC,eAA8B;AAOvB,IAAM,mBAAN,cAA+B,oBAAO;AAAA,EAP7C,OAO6C;AAAA;AAAA;AAAA,EAClC,QAAQ,mBAAM;AAAA,EACd,WAAW;AAAA,EAEpB,SAAe;AACb,SAAK,IAAI,eAAe,EAAE,iBAAiB;AAAA,EAC7C;AACF;;;ACPA,IAAM,iBAAiB;AACvB,IAAM,kBAAkB;AAGjB,IAAM,wBAAN,MAAwD;AAAA,EAI7D,YAA6B,SAAuB;AAAvB;AAAA,EAAwB;AAAA,EAAxB;AAAA,EAf/B,OAW+D;AAAA;AAAA;AAAA,EACpD,OAAO;AAAA,EACP,QAAQ,CAAC,WAAW,SAAS;AAAA,EAItC,UAAU,KAA0B;AAClC,QAAI,CAAC,IAAI,cAAc,SAAS,EAAG;AAEnC,UAAM,MAAM,KAAK,QAAQ,mBAAmB;AAC5C,UAAM,IAAI,IAAI,gBAAgB;AAC9B,QAAI,CAAC,EAAG;AAER,UAAM,OAAO,iBAAiB,IAAI;AAClC,UAAM,YAAY,IAAI,IAAI;AAC1B,MAAE,OAAO,IAAI,IAAI,MAAM,IAAI,CAAC,EACzB,OAAO,IAAI,IAAI,MAAM,IAAI,CAAC,EAC1B,OAAO,IAAI,GAAG,IAAI,IAAI,IAAI,EAC1B,OAAO,IAAI,GAAG,IAAI,IAAI,IAAI,EAC1B,OAAO,EAAE,OAAO,WAAW,OAAO,gBAAgB,CAAC;AAAA,EACxD;AAAA,EAEA,QAAQ,KAAwB;AAC9B,QAAI,CAAC,IAAI,cAAc,SAAS,EAAG;AAEnC,UAAM,UAAU,KAAK,QAClB,eAAe,EACf,OAAO,CAAC,WAAW,KAAK,QAAQ,UAAU,MAAM,CAAC;AAEpD,UAAM,QAAQ,QAAQ,SAAS,IAAI,QAAQ,KAAK,IAAI,IAAI;AACxD,QAAI,QAAQ,UAAU,KAAK,EAAE;AAE7B,UAAM,SAAS,KAAK,QAAQ,UAAU;AACtC,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,WAAW,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,QAAQ,eAAe,CAAC,CAAC;AACrE,UAAI,SAAS,SAAS,GAAG;AACvB,YAAI,QAAQ,oBAAoB,SAAS,KAAK,IAAI,CAAC,EAAE;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AACF;;;AL1CA,IAAM,mBAA2C;AAAA,EAC/C,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAGO,IAAM,cAAN,MAAoC;AAAA,EAhB3C,OAgB2C;AAAA;AAAA;AAAA,EAChC,OAAO;AAAA,EACP,UAAU;AAAA,EAEF;AAAA,EACT;AAAA,EACA;AAAA,EACA,aAAgC,CAAC;AAAA,EAEzC,YAAY,QAAsB;AAChC,SAAK,SAAS,UAAU,CAAC;AAAA,EAC3B;AAAA,EAEA,QAAQ,SAA8B;AACpC,SAAK,UAAU;AACf,SAAK,UAAU,IAAI,aAAa;AAEhC,QAAI,KAAK,OAAO,SAAS;AACvB,WAAK,QAAQ,aAAa,KAAK,OAAO,OAAO;AAAA,IAC/C;AAEA,QAAI,KAAK,OAAO,QAAQ;AACtB,WAAK,QAAQ,UAAU,KAAK,OAAO,MAAM;AAAA,IAC3C;AAKA,UAAM,cAAc,KAAK,OAAO,eAAe;AAC/C,UAAM,WAAW,QAAQ,WAAW,WAAW;AAC/C,UAAM,gBACJ,KAAK,OAAO,UAAU,UAAU,UAAU;AAM5C,UAAM,oBACJ,UAAU,UACV,KAAK,OAAO,UACZ;AAMF,UAAM,aAAa,wBAAC,MAAc,SAChC,UAAU,kBAAkB,MAAM,IAAI,KAAK,EAAE,GAAG,MAAM,GAAG,KAAK,GAD7C;AAGnB,UAAM,aAAa,IAAI,IAAI,KAAK,OAAO,sBAAsB,CAAC,CAAC;AAG/D,UAAM,YAAY,wBAAC,MAAmB;AACpC,YAAM,KAAK;AACX,UAAI,GAAG,OAAQ;AACf,UAAI,WAAW,IAAI,GAAG,IAAI,EAAG,IAAG,eAAe;AAC/C,WAAK,QAAQ,WAAW,GAAG,IAAI;AAAA,IACjC,GALkB;AAMlB,UAAM,UAAU,wBAAC,MAAmB;AAClC,YAAM,KAAK;AACX,UAAI,WAAW,IAAI,GAAG,IAAI,EAAG,IAAG,eAAe;AAC/C,WAAK,QAAQ,SAAS,GAAG,IAAI;AAAA,IAC/B,GAJgB;AAKhB,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,iBAAiB,SAAS,OAAO;AACxC,SAAK,WAAW;AAAA,MACd,MAAM,OAAO,oBAAoB,WAAW,SAAS;AAAA,MACrD,MAAM,OAAO,oBAAoB,SAAS,OAAO;AAAA,IACnD;AAIA,UAAM,gBAAgB,wBAAC,MAAmB;AACxC,YAAM,KAAK;AACX,UAAI;AACJ,UAAI;AACJ,UAAI,mBAAmB;AACrB,cAAM,OAAO,kBAAkB,sBAAsB;AACrD,eAAO,GAAG,UAAU,KAAK;AACzB,eAAO,GAAG,UAAU,KAAK;AAAA,MAC3B,OAAO;AACL,eAAO,GAAG;AACV,eAAO,GAAG;AAAA,MACZ;AACA,YAAM,SAAS,WAAW,MAAM,IAAI;AACpC,WAAK,QAAQ,eAAe,OAAO,GAAG,OAAO,CAAC;AAAA,IAChD,GAdsB;AAetB,UAAM,gBAAgB,wBAAC,MAAmB;AACxC,YAAM,KAAK;AACX,YAAM,SAAS,GAAG;AAClB,UAAI,UAAU,kBAAkB;AAC9B,aAAK,QAAQ,gBAAgB,MAAM;AAAA,MACrC,OAAO;AACL,aAAK,QAAQ,eAAe;AAAA,MAC9B;AAAA,IACF,GARsB;AAStB,UAAM,cAAc,wBAAC,MAAmB;AACtC,YAAM,KAAK;AACX,YAAM,SAAS,GAAG;AAClB,UAAI,UAAU,kBAAkB;AAC9B,aAAK,QAAQ,cAAc,MAAM;AAAA,MACnC,OAAO;AACL,aAAK,QAAQ,aAAa;AAAA,MAC5B;AAAA,IACF,GARoB;AASpB,UAAM,kBAAkB,6BAAY;AAClC,WAAK,QAAQ,oBAAoB;AAAA,IACnC,GAFwB;AAIxB,kBAAc,iBAAiB,eAAe,aAAa;AAC3D,WAAO,iBAAiB,eAAe,aAAa;AACpD,WAAO,iBAAiB,aAAa,WAAW;AAChD,WAAO,iBAAiB,iBAAiB,eAAe;AACxD,SAAK,WAAW;AAAA,MACd,MAAM,cAAc,oBAAoB,eAAe,aAAa;AAAA,MACpE,MAAM,OAAO,oBAAoB,eAAe,aAAa;AAAA,MAC7D,MAAM,OAAO,oBAAoB,aAAa,WAAW;AAAA,MACzD,MAAM,OAAO,oBAAoB,iBAAiB,eAAe;AAAA,IACnE;AAEA,YAAQ,SAAS,iBAAiB,KAAK,OAAO;AAAA,EAChD;AAAA,EAEA,gBAAgB,WAAkC;AAChD,cAAU,IAAI,IAAI,gBAAgB,CAAC;AACnC,cAAU,IAAI,IAAI,iBAAiB,CAAC;AAAA,EACtC;AAAA,EAEA,UAAgB;AACd,UAAM,WAAW,KAAK,QAAQ,WAAW,2BAAgB;AACzD,cAAU,SAAS,IAAI,sBAAsB,KAAK,OAAO,CAAC;AAAA,EAC5D;AAAA,EAEA,YAAkB;AAChB,eAAW,WAAW,KAAK,YAAY;AACrC,cAAQ;AAAA,IACV;AACA,SAAK,WAAW,SAAS;AAAA,EAC3B;AACF;;;AM3JA,IAAM,oBAA4C;AAAA;AAAA,EAEhD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA;AAAA,EAGN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA;AAAA,EAGR,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA;AAAA,EAGL,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,cAAc;AAAA,EACd,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA;AAAA,EAGX,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA;AAAA,EAGZ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,OAAO;AAAA,EACP,aAAa;AAAA;AAAA,EAGb,WAAW;AAAA,EACX,OAAO;AAAA,EACP,OAAO;AAAA,EACP,aAAa;AAAA,EACb,cAAc;AAAA,EACd,WAAW;AAAA,EACX,WAAW;AAAA,EACX,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA;AAAA,EAGP,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,eAAe;AAAA,EACf,aAAa;AAAA;AAAA,EAGb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,YAAY;AACd;AAGO,SAAS,kBAAkB,MAAsB;AACtD,SAAO,kBAAkB,IAAI,KAAK;AACpC;AAFgB;","names":["import_core","import_core","import_core","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/InputPlugin.ts","../src/InputManager.ts","../src/types.ts","../src/InputPollSystem.ts","../src/InputClearSystem.ts","../src/InputDebugContributor.ts","../src/keyDisplayNames.ts"],"sourcesContent":["export { InputPlugin } from \"./InputPlugin.js\";\nexport { InputManager } from \"./InputManager.js\";\nexport { getKeyDisplayName } from \"./keyDisplayNames.js\";\nexport { InputManagerKey } from \"./types.js\";\nexport type {\n InputConfig,\n ActionMapDefinition,\n InputConflictPolicy,\n RebindOptions,\n RebindResult,\n CameraLike,\n RendererLike,\n GamepadInfo,\n GamepadAxisKey,\n PointerInfo,\n PointerType,\n} from \"./types.js\";\n","import type { EngineContext, Plugin, SystemScheduler } from \"@yagejs/core\";\nimport { RendererAdapterKey } from \"@yagejs/core\";\nimport { DebugRegistryKey } from \"@yagejs/debug/api\";\nimport { InputManager } from \"./InputManager.js\";\nimport {\n InputManagerKey,\n type InputConfig,\n type PointerEventInfo,\n type PointerType,\n} from \"./types.js\";\nimport { InputPollSystem } from \"./InputPollSystem.js\";\nimport { InputClearSystem } from \"./InputClearSystem.js\";\nimport { InputDebugContributor } from \"./InputDebugContributor.js\";\n\n/** Input plugin — wires keyboard and pointer listeners, registers InputManager. */\nexport class InputPlugin implements Plugin {\n readonly name = \"input\";\n readonly version = \"2.0.0\";\n\n private readonly config: InputConfig;\n private manager!: InputManager;\n private context!: EngineContext;\n private cleanupFns: Array<() => void> = [];\n\n constructor(config?: InputConfig) {\n this.config = config ?? {};\n }\n\n install(context: EngineContext): void {\n this.context = context;\n this.manager = new InputManager();\n\n if (this.config.actions) {\n this.manager.setActionMap(this.config.actions);\n }\n\n if (this.config.groups) {\n this.manager.setGroups(this.config.groups);\n }\n\n if (this.config.deadzones) {\n this.manager.setDeadzones(this.config.deadzones);\n }\n\n if (this.config.triggerThreshold !== undefined) {\n this.manager.setTriggerThreshold(this.config.triggerThreshold);\n }\n\n if (this.config.pollGamepads === false) {\n this.manager.setPollingEnabled(false);\n }\n\n // Default to the well-known RendererAdapterKey so the canonical renderer\n // is picked up with no config. `rendererKey` stays as an override for\n // custom/foreign renderers registered under a different key.\n const rendererKey = this.config.rendererKey ?? RendererAdapterKey;\n const renderer = context.tryResolve(rendererKey);\n const pointerTarget: EventTarget =\n this.config.target ?? renderer?.canvas ?? document;\n\n // Stash the renderer adapter so the manager's drain step can call its\n // optional `hitTestUI(x, y)` for the UI auto-consume fallback.\n this.manager._setRenderer(renderer ?? null);\n\n // Element used to convert clientX/clientY to element-relative coordinates.\n // When `canvasToVirtual` is available, it always expects canvas-origin\n // pixels — so prefer the canvas over a custom `config.target` (which may\n // be a wrapping element). Falls back to null if neither is available.\n const coordinateElement: Element | null =\n renderer?.canvas ??\n this.config.target ??\n null;\n\n // When the renderer exposes canvasToVirtual, route pointer coords through\n // it so they stay correct under responsive fit or custom virtual sizes.\n // Without it, raw canvas-relative CSS pixels are passed through unchanged\n // (works only when canvas CSS size == virtual size — the default).\n const mapPointer = (cssX: number, cssY: number): { x: number; y: number } =>\n renderer?.canvasToVirtual?.(cssX, cssY) ?? { x: cssX, y: cssY };\n\n const preventSet = new Set(this.config.preventDefaultKeys ?? []);\n\n // Keyboard listeners. DOM events enqueue onto the input manager's buffer\n // and apply at the next `Phase.EarlyUpdate` drain — so any listener that\n // wants to claim the event (`consumePointer`, hit-test fallback, etc.) has\n // a chance to run before action-map edges fire.\n const onKeyDown = (e: Event): void => {\n const ke = e as KeyboardEvent;\n if (ke.repeat) return;\n if (preventSet.has(ke.code)) ke.preventDefault();\n this.manager._enqueueKeyDown(ke.code);\n };\n const onKeyUp = (e: Event): void => {\n const ke = e as KeyboardEvent;\n if (preventSet.has(ke.code)) ke.preventDefault();\n this.manager._enqueueKeyUp(ke.code);\n };\n window.addEventListener(\"keydown\", onKeyDown);\n window.addEventListener(\"keyup\", onKeyUp);\n this.cleanupFns.push(\n () => window.removeEventListener(\"keydown\", onKeyDown),\n () => window.removeEventListener(\"keyup\", onKeyUp),\n );\n\n // Pointer listeners — pointerdown on target, pointerup/move/cancel on window\n // so releases outside the target element are still captured.\n const buildInfo = (pe: PointerEvent): PointerEventInfo => {\n let cssX: number;\n let cssY: number;\n if (coordinateElement) {\n const rect = coordinateElement.getBoundingClientRect();\n cssX = pe.clientX - rect.left;\n cssY = pe.clientY - rect.top;\n } else {\n cssX = pe.clientX;\n cssY = pe.clientY;\n }\n const mapped = mapPointer(cssX, cssY);\n // Browsers occasionally emit empty `pointerType` for unusual devices.\n // Fall back to `\"mouse\"` so downstream code never sees an invalid string.\n const rawType = pe.pointerType;\n const type: PointerType =\n rawType === \"touch\" || rawType === \"pen\" ? rawType : \"mouse\";\n return {\n id: pe.pointerId,\n screenX: mapped.x,\n screenY: mapped.y,\n type,\n isPrimary: pe.isPrimary,\n button: pe.button,\n };\n };\n const onPointerMove = (e: Event): void => {\n this.manager._enqueuePointerMove(buildInfo(e as PointerEvent));\n };\n const onPointerDown = (e: Event): void => {\n this.manager._enqueuePointerDown(buildInfo(e as PointerEvent));\n };\n const onPointerUp = (e: Event): void => {\n this.manager._enqueuePointerUp(buildInfo(e as PointerEvent));\n };\n const onPointerCancel = (e: Event): void => {\n const pe = e as PointerEvent;\n this.manager._enqueuePointerCancel(pe.pointerId);\n };\n // `pointerleave` covers the hover lifecycle for pen / touch pointers that\n // never receive a `pointerdown` (a stylus floating over the tablet, then\n // pulled away). Without this, the manager would accumulate undead entries\n // in `getPointers()` for every hover session. Mouse pointers ignore leave\n // by design — `_applyPointerCancel` skips removal for `type === \"mouse\"`.\n const onPointerLeave = (e: Event): void => {\n const pe = e as PointerEvent;\n this.manager._enqueuePointerCancel(pe.pointerId);\n };\n\n pointerTarget.addEventListener(\"pointerdown\", onPointerDown);\n window.addEventListener(\"pointermove\", onPointerMove);\n window.addEventListener(\"pointerup\", onPointerUp);\n window.addEventListener(\"pointercancel\", onPointerCancel);\n pointerTarget.addEventListener(\"pointerleave\", onPointerLeave);\n this.cleanupFns.push(\n () => pointerTarget.removeEventListener(\"pointerdown\", onPointerDown),\n () => window.removeEventListener(\"pointermove\", onPointerMove),\n () => window.removeEventListener(\"pointerup\", onPointerUp),\n () => window.removeEventListener(\"pointercancel\", onPointerCancel),\n () => pointerTarget.removeEventListener(\"pointerleave\", onPointerLeave),\n );\n\n // Scroll wheel — fires `WheelUp/Down/Left/Right` action-map edges (one\n // frame each) and notifies any `onWheel` subscribers with raw deltas.\n const wheelInvertY = this.config.wheelInvertY === true;\n const preventDefaultWheel = this.config.preventDefaultWheel === true;\n const onWheel = (e: Event): void => {\n const we = e as WheelEvent;\n if (preventDefaultWheel) we.preventDefault();\n const dy = wheelInvertY ? -we.deltaY : we.deltaY;\n this.manager._enqueueWheel(we.deltaX, dy);\n };\n pointerTarget.addEventListener(\n \"wheel\",\n onWheel,\n preventDefaultWheel ? { passive: false } : undefined,\n );\n this.cleanupFns.push(() =>\n pointerTarget.removeEventListener(\"wheel\", onWheel),\n );\n\n // Gamepad connect/disconnect — note: browsers gate this behind a first\n // button press, so a freshly-plugged pad won't fire until the user acts.\n const onGamepadConnected = (e: Event): void => {\n const ge = e as GamepadEvent;\n if (!ge.gamepad) return;\n this.manager._onGamepadConnected({\n index: ge.gamepad.index,\n id: ge.gamepad.id,\n });\n };\n const onGamepadDisconnected = (e: Event): void => {\n const ge = e as GamepadEvent;\n if (!ge.gamepad) return;\n this.manager._onGamepadDisconnected({\n index: ge.gamepad.index,\n id: ge.gamepad.id,\n });\n };\n window.addEventListener(\"gamepadconnected\", onGamepadConnected);\n window.addEventListener(\"gamepaddisconnected\", onGamepadDisconnected);\n this.cleanupFns.push(\n () => window.removeEventListener(\"gamepadconnected\", onGamepadConnected),\n () =>\n window.removeEventListener(\"gamepaddisconnected\", onGamepadDisconnected),\n );\n\n // When the tab hides, `navigator.getGamepads()` returns stale data and a\n // touch held at the moment of hide may never receive its `pointerup`\n // (Android notification shade, iOS app switcher). Force-release both so\n // they don't appear stuck on return.\n if (typeof document !== \"undefined\") {\n const onVisibilityChange = (): void => {\n if (document.visibilityState === \"hidden\") {\n this.manager._releaseAllGamepadState();\n this.manager.clearPointerButtons();\n }\n };\n document.addEventListener(\"visibilitychange\", onVisibilityChange);\n this.cleanupFns.push(() =>\n document.removeEventListener(\"visibilitychange\", onVisibilityChange),\n );\n }\n\n context.register(InputManagerKey, this.manager);\n }\n\n registerSystems(scheduler: SystemScheduler): void {\n scheduler.add(new InputPollSystem());\n scheduler.add(new InputClearSystem());\n }\n\n onStart(): void {\n const registry = this.context.tryResolve(DebugRegistryKey);\n registry?.register(new InputDebugContributor(this.manager));\n }\n\n onDestroy(): void {\n for (const cleanup of this.cleanupFns) {\n cleanup();\n }\n this.cleanupFns.length = 0;\n }\n}\n","import { Vec2 } from \"@yagejs/core\";\nimport type { RendererAdapter } from \"@yagejs/core\";\nimport type {\n ActionMapDefinition,\n CameraLike,\n GamepadAxisKey,\n GamepadInfo,\n PointerEventInfo,\n PointerInfo,\n PointerType,\n RebindOptions,\n RebindResult,\n} from \"./types.js\";\n\n/** Action-map codes for the three primary mouse buttons, indexed by button. */\nconst MOUSE_BUTTON_CODES = [\"MouseLeft\", \"MouseMiddle\", \"MouseRight\"] as const;\n\n/** Mutable internal pointer record. Exposed externally as the read-only {@link PointerInfo}. */\ninterface MutablePointerInfo {\n id: number;\n screenPos: Vec2;\n type: PointerType;\n isPrimary: boolean;\n buttons: Set<number>;\n isDown: boolean;\n}\n\n/**\n * DOM-originated input events buffered between the browser dispatch tick and\n * the next `InputPollSystem` drain at `Phase.EarlyUpdate`. Synthetic injection\n * (`fireKeyDown`, `firePointerDown`, etc.) bypasses the queue and applies state\n * synchronously through `_apply*` to keep test ergonomics intact.\n */\ntype BufferedInputEvent =\n | { kind: \"keyDown\"; code: string }\n | { kind: \"keyUp\"; code: string }\n | { kind: \"pointerDown\"; info: PointerEventInfo }\n | { kind: \"pointerUp\"; info: PointerEventInfo }\n | { kind: \"pointerCancel\"; id: number }\n | { kind: \"wheel\"; dx: number; dy: number };\n\n/** Standard-mapping button codes, indexed by W3C button position. */\nconst STANDARD_BUTTON_CODES = [\n \"GamepadA\",\n \"GamepadB\",\n \"GamepadX\",\n \"GamepadY\",\n \"GamepadLB\",\n \"GamepadRB\",\n \"GamepadLT\",\n \"GamepadRT\",\n \"GamepadSelect\",\n \"GamepadStart\",\n \"GamepadLeftStick\",\n \"GamepadRightStick\",\n \"GamepadDPadUp\",\n \"GamepadDPadDown\",\n \"GamepadDPadLeft\",\n \"GamepadDPadRight\",\n \"GamepadHome\",\n] as const;\n\nconst TRIGGER_LEFT_INDEX = 6;\nconst TRIGGER_RIGHT_INDEX = 7;\n\nconst STICK_AXIS_KEYS: Record<\n \"left\" | \"right\",\n { x: GamepadAxisKey; y: GamepadAxisKey }\n> = {\n left: { x: \"leftX\", y: \"leftY\" },\n right: { x: \"rightX\", y: \"rightY\" },\n};\n\nconst TRIGGER_AXIS_KEYS: Record<\"left\" | \"right\", GamepadAxisKey> = {\n left: \"leftTrigger\",\n right: \"rightTrigger\",\n};\n\n/** Standard-mapping axis indices map to semantic axis keys. */\nconst STANDARD_AXIS_KEYS: readonly GamepadAxisKey[] = [\n \"leftX\",\n \"leftY\",\n \"rightX\",\n \"rightY\",\n];\n\n/** Central input state manager. Resolved via DI with InputManagerKey. */\nexport class InputManager {\n private pressedKeys = new Set<string>();\n private justPressedKeys = new Set<string>();\n private justReleasedKeys = new Set<string>();\n private holdStart = new Map<string, number>();\n private syntheticPressedActions = new Set<string>();\n private syntheticActionStarts = new Map<string, number>();\n private actionMap = new Map<string, string[]>();\n private defaultBindings = new Map<string, string[]>();\n private groups = new Map<string, Set<string>>();\n private actionGroups = new Map<string, Set<string>>();\n private disabledGroups = new Set<string>();\n /** Tracked pointers keyed by `pointerId`. Mouse persists; touch/pen removed on up/cancel. */\n private pointers = new Map<number, MutablePointerInfo>();\n /** Id of the pointer the browser last marked `isPrimary`, or `null` when none are tracked. */\n private primaryPointerId: number | null = null;\n /**\n * Aggregate \"any pointer has this button held\" cache. The action-map codes\n * `MouseLeft`/`MouseMiddle`/`MouseRight` are driven from edges into/out of this\n * set so two simultaneous taps holding button 0 do not double-fire.\n * Consumed pointers are excluded from the aggregate so UI-claimed presses\n * never propagate to gameplay actions.\n */\n private mouseButtonAggregate = new Set<number>();\n /**\n * Pointers marked as \"claimed\" via {@link consumePointer} (or auto-claimed by\n * the renderer's UI hit-test fallback). Lifetime is per-pointer-event-cycle:\n * cleared when the pointer's last button releases (drained `pointerUp`) or on\n * `pointercancel`.\n */\n private consumedPointers = new Set<number>();\n /** Wheel-edge gate flipped by {@link consumeWheel}. Cleared at end of frame. */\n private consumedWheelThisFrame = false;\n /** Buffered DOM-originated events awaiting drain at `Phase.EarlyUpdate`. */\n private inputQueue: BufferedInputEvent[] = [];\n /**\n * Renderer reference for the optional `hitTestUI(x, y)` lookup. Stashed by\n * {@link _setRenderer} during `InputPlugin.install` so the drain step can\n * read it cheaply each frame.\n */\n private renderer: RendererAdapter | null = null;\n private pointerDownListeners: Array<(info: PointerInfo) => void> = [];\n private pointerUpListeners: Array<(info: PointerInfo) => void> = [];\n private pointerMoveListeners: Array<(info: PointerInfo) => void> = [];\n private keyDownListenersAny: Array<(code: string) => void> = [];\n private keyUpListenersAny: Array<(code: string) => void> = [];\n private keyDownListeners = new Map<string, Array<(code: string) => void>>();\n private keyUpListeners = new Map<string, Array<(code: string) => void>>();\n private actionListeners = new Map<string, Array<(name: string) => void>>();\n private actionReleasedListeners = new Map<\n string,\n Array<(name: string) => void>\n >();\n private wheelListeners: Array<(dx: number, dy: number) => void> = [];\n /** Real-pad axis values keyed by `${padIndex}:${axisKey}`. */\n private gamepadAxisState = new Map<string, number>();\n /** Synthetic axis values for fireGamepadAxis injection (test path). */\n private syntheticAxisState = new Map<GamepadAxisKey, number>();\n /** \"Any pad\" aggregate of currently-pressed gamepad codes. */\n private lastButtonState = new Map<string, boolean>();\n /** Per-pad \"anything happening\" flag, used to detect rising-edge activity for active-pad promotion. */\n private lastPadActivity = new Map<number, boolean>();\n /** Pads currently known to the engine (populated via events or polling). */\n private connectedPads = new Map<number, GamepadInfo>();\n /** Index of the pad whose analog input is read by default. `null` when no pad is connected. */\n private activePadIndex: number | null = null;\n private gamepadConnectListeners: Array<(info: GamepadInfo) => void> = [];\n private gamepadDisconnectListeners: Array<(info: GamepadInfo) => void> = [];\n private activePadListeners: Array<(info: GamepadInfo | null) => void> = [];\n private stickDeadzone = 0.15;\n private triggerDeadzone = 0.05;\n private triggerThreshold = 0.5;\n private pollingEnabled = true;\n private camera: CameraLike | null = null;\n private elapsedMs = 0;\n private listenResolve: ((key: string | null) => void) | null = null;\n\n // -- Action-based queries --\n\n /** Whether any key mapped to this action is currently held. */\n isPressed(action: string): boolean {\n if (!this.isActionEnabled(action)) return false;\n return this.syntheticPressedActions.has(action) ||\n this.anyKeyInSet(action, this.pressedKeys);\n }\n\n /** Whether any key mapped to this action was pressed this frame. */\n isJustPressed(action: string): boolean {\n if (!this.isActionEnabled(action)) return false;\n return this.syntheticPressedActions.has(action) ||\n this.anyKeyInSet(action, this.justPressedKeys);\n }\n\n /** Whether any key mapped to this action was released this frame. */\n isJustReleased(action: string): boolean {\n if (!this.isActionEnabled(action)) return false;\n return this.anyKeyInSet(action, this.justReleasedKeys);\n }\n\n /** Returns true if any key bound to the action exists in the given set. */\n private anyKeyInSet(action: string, set: Set<string>): boolean {\n const keys = this.actionMap.get(action);\n if (!keys) return false;\n for (const key of keys) {\n if (set.has(key)) return true;\n }\n return false;\n }\n\n /** Milliseconds the action has been held. Returns 0 if not held. */\n getHoldDuration(action: string): number {\n if (!this.isActionEnabled(action)) return 0;\n const keys = this.actionMap.get(action);\n if (!keys && !this.syntheticPressedActions.has(action)) return 0;\n let maxDuration = 0;\n for (const key of keys ?? []) {\n const start = this.holdStart.get(key);\n if (start !== undefined) {\n maxDuration = Math.max(maxDuration, this.elapsedMs - start);\n }\n }\n const syntheticStart = this.syntheticActionStarts.get(action);\n if (syntheticStart !== undefined) {\n maxDuration = Math.max(maxDuration, this.elapsedMs - syntheticStart);\n }\n return maxDuration;\n }\n\n /** Whether the action has been held for at least `minTime` ms. */\n isHeldFor(action: string, minTime: number): boolean {\n return this.getHoldDuration(action) >= minTime;\n }\n\n // -- Axis helpers --\n\n /** Returns -1, 0, or 1 based on negative/positive action states. */\n getAxis(negative: string, positive: string): number {\n const neg = this.isPressed(negative) ? 1 : 0;\n const pos = this.isPressed(positive) ? 1 : 0;\n return pos - neg;\n }\n\n /** Returns a Vec2 from four directional actions. Not normalized. */\n getVector(\n left: string,\n right: string,\n up: string,\n down: string,\n ): Vec2 {\n const x = this.getAxis(left, right);\n const y = this.getAxis(up, down);\n return new Vec2(x, y);\n }\n\n // -- Pointer --\n\n /**\n * Primary pointer's position in world coordinates (via Camera), or screen\n * coords if no camera. Returns `Vec2.ZERO` when no pointer is tracked.\n *\n * For multi-pointer access (touch UIs etc.) iterate {@link getPointers} and\n * convert each `screenPos` via the camera as needed.\n */\n getPointerPosition(): Vec2 {\n const primary = this.getPrimaryPointer();\n if (!primary) return Vec2.ZERO;\n if (this.camera) {\n const w = this.camera.screenToWorld(primary.screenPos.x, primary.screenPos.y);\n return new Vec2(w.x, w.y);\n }\n return primary.screenPos;\n }\n\n /** Primary pointer's raw position in screen coordinates, or `Vec2.ZERO` when no pointer is tracked. */\n getPointerScreenPosition(): Vec2 {\n const primary = this.getPrimaryPointer();\n return primary ? primary.screenPos : Vec2.ZERO;\n }\n\n /** Whether the primary pointer has any button held. */\n isPointerDown(): boolean {\n const primary = this.getPrimaryPointer();\n return primary ? primary.isDown : false;\n }\n\n /** All currently-tracked pointers (one per active mouse, pen, or finger). */\n getPointers(): readonly PointerInfo[] {\n const out: PointerInfo[] = [];\n for (const p of this.pointers.values()) {\n out.push(this.toPointerInfo(p));\n }\n return out;\n }\n\n /** Direct lookup by `pointerId`, or `undefined` if no pointer with that id is tracked. */\n getPointer(id: number): PointerInfo | undefined {\n const p = this.pointers.get(id);\n return p ? this.toPointerInfo(p) : undefined;\n }\n\n /**\n * Defensive snapshot of a tracked pointer. The runtime `MutablePointerInfo`\n * holds a real `Set` for `buttons` — even though the `PointerInfo` type\n * declares `ReadonlySet`, JS doesn't enforce that at runtime, so we copy the\n * set on every public read. `Vec2` is convention-immutable across YAGE, so\n * we share the same instance.\n */\n private toPointerInfo(pointer: MutablePointerInfo): PointerInfo {\n return {\n id: pointer.id,\n screenPos: pointer.screenPos,\n type: pointer.type,\n isPrimary: pointer.isPrimary,\n buttons: new Set(pointer.buttons),\n isDown: pointer.isDown,\n };\n }\n\n /**\n * Subscribe to pointer-down events (button transitions from up → down on a\n * tracked pointer). Returns a disposer that detaches the listener.\n */\n onPointerDown(fn: (info: PointerInfo) => void): () => void {\n this.pointerDownListeners.push(fn);\n return () => {\n const idx = this.pointerDownListeners.indexOf(fn);\n if (idx !== -1) this.pointerDownListeners.splice(idx, 1);\n };\n }\n\n /**\n * Subscribe to pointer-up events (button transitions from down → up, plus\n * touch / pen lifecycle ends and `pointercancel`). Returns a disposer.\n */\n onPointerUp(fn: (info: PointerInfo) => void): () => void {\n this.pointerUpListeners.push(fn);\n return () => {\n const idx = this.pointerUpListeners.indexOf(fn);\n if (idx !== -1) this.pointerUpListeners.splice(idx, 1);\n };\n }\n\n /** Subscribe to pointer-move events. Returns a disposer. */\n onPointerMove(fn: (info: PointerInfo) => void): () => void {\n this.pointerMoveListeners.push(fn);\n return () => {\n const idx = this.pointerMoveListeners.indexOf(fn);\n if (idx !== -1) this.pointerMoveListeners.splice(idx, 1);\n };\n }\n\n // -- Consume primitives --\n\n /**\n * Mark a pointer as claimed for the rest of its event cycle (down → up).\n * Subsequent action-map edges for this pointer (e.g. the `MouseLeft` edge a\n * `pointerdown` would normally fire) are suppressed; `onPointerDown/Up/Move`\n * listeners still fire because they are explicit user opt-ins.\n *\n * The mark clears automatically when the pointer's last button releases or\n * on `pointercancel`. Call from a Pixi `pointerdown` handler that wants to\n * own the event: `manager.consumePointer(e.pointerId)`.\n */\n consumePointer(id: number): void {\n this.consumedPointers.add(id);\n }\n\n /** Whether the pointer is currently marked consumed. */\n isPointerConsumed(id: number): boolean {\n return this.consumedPointers.has(id);\n }\n\n /**\n * Suppress wheel action-map edges (`WheelUp/Down/Left/Right`) for the rest\n * of the current frame. `onWheel` listeners still fire.\n */\n consumeWheel(): void {\n this.consumedWheelThisFrame = true;\n }\n\n // -- Listener parity (keys, actions, wheel) --\n\n /**\n * Subscribe to key-down events. Pass a code (e.g. `\"Space\"`, `\"GamepadA\"`)\n * to filter, or `\"*\"` for all keys. The listener fires on the same edge\n * `isJustPressed` reports — for DOM-originated events that's the next\n * `Phase.EarlyUpdate` after the browser dispatches; for synthetic injection\n * (`fireKeyDown`) it's synchronous. Returns a disposer.\n */\n onKeyDown(code: string, fn: (code: string) => void): () => void {\n if (code === \"*\") {\n this.keyDownListenersAny.push(fn);\n return () => {\n const idx = this.keyDownListenersAny.indexOf(fn);\n if (idx !== -1) this.keyDownListenersAny.splice(idx, 1);\n };\n }\n let arr = this.keyDownListeners.get(code);\n if (!arr) {\n arr = [];\n this.keyDownListeners.set(code, arr);\n }\n arr.push(fn);\n return () => {\n const list = this.keyDownListeners.get(code);\n if (!list) return;\n const idx = list.indexOf(fn);\n if (idx !== -1) list.splice(idx, 1);\n };\n }\n\n /** Subscribe to key-up events. See {@link onKeyDown}. */\n onKeyUp(code: string, fn: (code: string) => void): () => void {\n if (code === \"*\") {\n this.keyUpListenersAny.push(fn);\n return () => {\n const idx = this.keyUpListenersAny.indexOf(fn);\n if (idx !== -1) this.keyUpListenersAny.splice(idx, 1);\n };\n }\n let arr = this.keyUpListeners.get(code);\n if (!arr) {\n arr = [];\n this.keyUpListeners.set(code, arr);\n }\n arr.push(fn);\n return () => {\n const list = this.keyUpListeners.get(code);\n if (!list) return;\n const idx = list.indexOf(fn);\n if (idx !== -1) list.splice(idx, 1);\n };\n }\n\n /**\n * Subscribe to action press edges (rising edge of any key bound to the\n * action). Fires once per press. Returns a disposer.\n */\n onAction(name: string, fn: (name: string) => void): () => void {\n let arr = this.actionListeners.get(name);\n if (!arr) {\n arr = [];\n this.actionListeners.set(name, arr);\n }\n arr.push(fn);\n return () => {\n const list = this.actionListeners.get(name);\n if (!list) return;\n const idx = list.indexOf(fn);\n if (idx !== -1) list.splice(idx, 1);\n };\n }\n\n /** Subscribe to action release edges. Returns a disposer. */\n onActionReleased(name: string, fn: (name: string) => void): () => void {\n let arr = this.actionReleasedListeners.get(name);\n if (!arr) {\n arr = [];\n this.actionReleasedListeners.set(name, arr);\n }\n arr.push(fn);\n return () => {\n const list = this.actionReleasedListeners.get(name);\n if (!list) return;\n const idx = list.indexOf(fn);\n if (idx !== -1) list.splice(idx, 1);\n };\n }\n\n /**\n * Subscribe to scroll-wheel events. Receives raw `deltaX`/`deltaY` (already\n * sign-flipped by `InputConfig.wheelInvertY` if set). Fires regardless of\n * {@link consumeWheel} — it only gates action edges. Returns a disposer.\n */\n onWheel(fn: (dx: number, dy: number) => void): () => void {\n this.wheelListeners.push(fn);\n return () => {\n const idx = this.wheelListeners.indexOf(fn);\n if (idx !== -1) this.wheelListeners.splice(idx, 1);\n };\n }\n\n private getPrimaryPointer(): MutablePointerInfo | null {\n if (this.primaryPointerId === null) return null;\n return this.pointers.get(this.primaryPointerId) ?? null;\n }\n\n // -- Runtime action map management --\n\n /** Replace the entire action map and store it as the default for {@link resetBindings}. */\n setActionMap(actions: ActionMapDefinition): void {\n this.actionMap.clear();\n this.defaultBindings.clear();\n for (const [action, keys] of Object.entries(actions)) {\n this.actionMap.set(action, [...keys]);\n this.defaultBindings.set(action, [...keys]);\n }\n }\n\n /** Add a key binding to an action. Creates the action if it doesn't exist. */\n bindKey(action: string, key: string): void {\n let keys = this.actionMap.get(action);\n if (!keys) {\n keys = [];\n this.actionMap.set(action, keys);\n }\n if (!keys.includes(key)) {\n keys.push(key);\n }\n }\n\n /** Remove a key binding from an action. */\n unbindKey(action: string, key: string): void {\n const keys = this.actionMap.get(action);\n if (!keys) return;\n const idx = keys.indexOf(key);\n if (idx !== -1) keys.splice(idx, 1);\n }\n\n // -- Binding queries --\n\n /** Returns the current key bindings for an action, or an empty array if unmapped. */\n getBindings(action: string): readonly string[] {\n return this.actionMap.get(action) ?? [];\n }\n\n /** Returns all action names that have the given key bound. */\n getActionsForKey(key: string): string[] {\n const result: string[] = [];\n for (const [action, keys] of this.actionMap) {\n if (keys.includes(key)) result.push(action);\n }\n return result;\n }\n\n // -- Rebinding --\n\n /**\n * Rebind a key to an action with optional conflict detection.\n * Conflicts are only detected between actions sharing at least one group.\n */\n rebind(action: string, key: string, opts?: RebindOptions): RebindResult {\n const conflict = opts?.conflict ?? \"reject\";\n const slot = opts?.slot;\n\n const conflictAction = this.findConflictInGroups(action, key);\n\n if (conflictAction && conflict === \"reject\") {\n return { ok: false, conflict: { action: conflictAction, key } };\n }\n\n if (conflictAction && conflict === \"replace\") {\n this.unbindKey(conflictAction, key);\n }\n\n let keys = this.actionMap.get(action);\n if (!keys) {\n keys = [];\n this.actionMap.set(action, keys);\n }\n\n // Remove existing occurrence to avoid duplicates, adjusting slot for the shift\n const existingIdx = keys.indexOf(key);\n let targetSlot = slot;\n if (targetSlot !== undefined && existingIdx !== -1 && existingIdx !== targetSlot) {\n keys.splice(existingIdx, 1);\n if (targetSlot > existingIdx) targetSlot--;\n }\n\n if (targetSlot !== undefined && targetSlot < keys.length) {\n keys[targetSlot] = key;\n } else if (!keys.includes(key)) {\n keys.push(key);\n }\n\n return { ok: true };\n }\n\n /**\n * Finds the first action that uses the given key AND shares at least one\n * group with the target action. Ungrouped actions never conflict.\n */\n private findConflictInGroups(action: string, key: string): string | null {\n const myGroups = this.actionGroups.get(action);\n if (!myGroups || myGroups.size === 0) return null;\n\n for (const [otherAction, otherKeys] of this.actionMap) {\n if (otherAction === action) continue;\n if (!otherKeys.includes(key)) continue;\n\n const otherGroups = this.actionGroups.get(otherAction);\n if (!otherGroups) continue;\n\n for (const g of myGroups) {\n if (otherGroups.has(g)) return otherAction;\n }\n }\n return null;\n }\n\n // -- Binding persistence --\n\n /** Reset bindings to defaults. If an action name is provided, only reset that action. */\n resetBindings(action?: string): void {\n if (action !== undefined) {\n const defaults = this.defaultBindings.get(action);\n if (defaults) {\n this.actionMap.set(action, [...defaults]);\n }\n } else {\n this.actionMap.clear();\n for (const [a, keys] of this.defaultBindings) {\n this.actionMap.set(a, [...keys]);\n }\n }\n }\n\n /** Export the current bindings as a plain object for serialization. */\n exportBindings(): ActionMapDefinition {\n const result: ActionMapDefinition = {};\n for (const [action, keys] of this.actionMap) {\n result[action] = [...keys];\n }\n return result;\n }\n\n /** Load bindings from a plain object. Resets to defaults first, then overlays the provided map. */\n loadBindings(map: ActionMapDefinition): void {\n this.resetBindings();\n for (const [action, keys] of Object.entries(map)) {\n this.actionMap.set(action, [...keys]);\n }\n }\n\n // -- Group management --\n\n /** Configure input groups. Group name -> array of action names. */\n setGroups(groups: Record<string, string[]>): void {\n this.groups.clear();\n this.actionGroups.clear();\n for (const [name, actions] of Object.entries(groups)) {\n this.groups.set(name, new Set(actions));\n for (const action of actions) {\n let set = this.actionGroups.get(action);\n if (!set) {\n set = new Set();\n this.actionGroups.set(action, set);\n }\n set.add(name);\n }\n }\n }\n\n /** Enable a group by name. */\n enableGroup(name: string): void {\n this.disabledGroups.delete(name);\n }\n\n /** Disable a group by name. Actions only in disabled groups become inactive. */\n disableGroup(name: string): void {\n this.disabledGroups.add(name);\n }\n\n /** Set exactly these groups as active; all others are disabled. */\n setActiveGroups(names: string[]): void {\n this.disabledGroups.clear();\n for (const group of this.groups.keys()) {\n if (!names.includes(group)) {\n this.disabledGroups.add(group);\n }\n }\n }\n\n /** Whether a group is currently enabled. Returns true for unknown group names. */\n isGroupEnabled(name: string): boolean {\n return !this.disabledGroups.has(name);\n }\n\n /** Get all configured group names. */\n getGroups(): string[] {\n return Array.from(this.groups.keys());\n }\n\n /** Get the action names belonging to a group. Returns empty array for unknown groups. */\n getGroupActions(name: string): readonly string[] {\n const set = this.groups.get(name);\n return set ? Array.from(set) : [];\n }\n\n /** Returns true if the action is ungrouped or any of its groups is enabled. */\n private isActionEnabled(action: string): boolean {\n const groupSet = this.actionGroups.get(action);\n if (!groupSet || groupSet.size === 0) return true;\n for (const group of groupSet) {\n if (!this.disabledGroups.has(group)) return true;\n }\n return false;\n }\n\n // -- Key listening --\n\n /** Returns a promise that resolves with the next key code pressed. Intercepts the key. */\n listenForNextKey(): Promise<string | null> {\n this.cancelListen();\n return new Promise<string | null>((resolve) => {\n this.listenResolve = resolve;\n });\n }\n\n /** Cancel an active {@link listenForNextKey}. Resolves the pending promise with `null`. */\n cancelListen(): void {\n if (this.listenResolve) {\n const resolve = this.listenResolve;\n this.listenResolve = null;\n resolve(null);\n }\n }\n\n /** Public wrapper for synthetic key-down injection. Applies sync. */\n fireKeyDown(code: string): void {\n this._applyKeyDown(code);\n }\n\n /** Public wrapper for synthetic key-up injection. Applies sync. */\n fireKeyUp(code: string): void {\n this._applyKeyUp(code);\n }\n\n /**\n * Public wrapper for synthetic pointer movement. Defaults to the primary\n * mouse pointer (`id: 1`, `type: \"mouse\"`); pass `opts` to drive a specific\n * touch / pen pointer.\n */\n firePointerMove(\n screenX: number,\n screenY: number,\n opts?: { id?: number; type?: PointerType; isPrimary?: boolean },\n ): void {\n this._applyPointerMove(this.makeSyntheticInfo(screenX, screenY, -1, opts));\n }\n\n /**\n * Public wrapper for synthetic pointer-button presses. Defaults to button 0\n * on the primary mouse pointer. Pass `opts` for touch / pen / non-primary\n * pointers (e.g. `{ id: 5, type: \"touch\", isPrimary: false }`).\n */\n firePointerDown(\n button: 0 | 1 | 2 = 0,\n opts?: { id?: number; type?: PointerType; isPrimary?: boolean },\n ): void {\n const id = opts?.id ?? 1;\n const existing = this.pointers.get(id);\n this._applyPointerDown(\n this.makeSyntheticInfo(\n existing?.screenPos.x ?? 0,\n existing?.screenPos.y ?? 0,\n button,\n opts,\n ),\n );\n }\n\n /** Public wrapper for synthetic pointer-button releases. */\n firePointerUp(\n button: 0 | 1 | 2 = 0,\n opts?: { id?: number },\n ): void {\n const id = opts?.id ?? 1;\n const existing = this.pointers.get(id);\n const info: PointerEventInfo = {\n id,\n screenX: existing?.screenPos.x ?? 0,\n screenY: existing?.screenPos.y ?? 0,\n type: existing?.type ?? \"mouse\",\n isPrimary: existing?.isPrimary ?? id === 1,\n button,\n };\n this._applyPointerUp(info);\n }\n\n /** Public wrapper for synthetic wheel input. Applies sync, including\n * action edges and `onWheel` listener notification — matching the DOM path\n * so tests and inspector probes drive the full surface. */\n fireWheel(dx: number, dy: number): void {\n for (const fn of [...this.wheelListeners]) fn(dx, dy);\n this.applyWheelEdges(dx, dy);\n }\n\n private makeSyntheticInfo(\n screenX: number,\n screenY: number,\n button: number,\n opts?: { id?: number; type?: PointerType; isPrimary?: boolean },\n ): PointerEventInfo {\n const id = opts?.id ?? 1;\n return {\n id,\n screenX,\n screenY,\n type: opts?.type ?? \"mouse\",\n isPrimary: opts?.isPrimary ?? id === 1,\n button,\n };\n }\n\n /**\n * Inject a synthetic gamepad button edge. Routes through the same internal\n * path as real polling, so action queries (`isPressed`, `isJustPressed`),\n * `listenForNextKey`, and rebinding all see the synthetic input.\n *\n * `code` should be a gamepad code string (e.g. `\"GamepadA\"`, `\"GamepadLT\"`).\n * Used by inspector probes / deterministic tests in lieu of real polling.\n */\n fireGamepadButton(code: string, pressed: boolean): void {\n const wasPressed = this.lastButtonState.get(code) ?? false;\n if (pressed && !wasPressed) {\n this._applyKeyDown(code);\n this.lastButtonState.set(code, true);\n } else if (!pressed && wasPressed) {\n this._applyKeyUp(code);\n this.lastButtonState.delete(code);\n }\n }\n\n /**\n * Inject a synthetic gamepad axis value. Stored separately from real-pad\n * axis state and consulted by `getStick` / `getTrigger` only when no real\n * pad is active — matching how a test fixture would use the API.\n *\n * Trigger axes additionally emit `GamepadLT`/`GamepadRT` button edges when\n * crossing `triggerThreshold`, mirroring real-pad polling so synthetic\n * inspector probes drive `isPressed` the same way as physical hardware.\n */\n fireGamepadAxis(side: GamepadAxisKey, value: number): void {\n const safe = Number.isFinite(value) ? value : 0;\n this.syntheticAxisState.set(side, safe);\n if (side === \"leftTrigger\") {\n this.fireGamepadButton(\"GamepadLT\", safe >= this.triggerThreshold);\n } else if (side === \"rightTrigger\") {\n this.fireGamepadButton(\"GamepadRT\", safe >= this.triggerThreshold);\n }\n }\n\n // -- Gamepad analog API --\n\n /**\n * Returns the deadzoned, magnitude-clamped stick vector for the given side.\n *\n * By default reads from the active pad (the most recently used controller,\n * or the first connected one if nothing has been used yet). Pass\n * `{ pad: index }` to read from a specific pad — useful for couch-co-op\n * where each player's controller is addressed explicitly.\n *\n * Falls back to synthetic injection (`fireGamepadAxis`) when no pad is\n * active — that's the test/probe path.\n */\n getStick(side: \"left\" | \"right\", opts?: { pad?: number }): Vec2 {\n const { x: xKey, y: yKey } = STICK_AXIS_KEYS[side];\n const padIdx = opts?.pad !== undefined ? opts.pad : this.activePadIndex;\n let x: number;\n let y: number;\n if (padIdx !== null) {\n x = this.gamepadAxisState.get(`${padIdx}:${xKey}`) ?? 0;\n y = this.gamepadAxisState.get(`${padIdx}:${yKey}`) ?? 0;\n } else {\n x = this.syntheticAxisState.get(xKey) ?? 0;\n y = this.syntheticAxisState.get(yKey) ?? 0;\n }\n const mag = Math.hypot(x, y);\n if (mag < this.stickDeadzone) return Vec2.ZERO;\n // Guards the deadzone:0 case — `mag === 0` slips past the deadzone check\n // when the deadzone is disabled, and dividing by zero would yield NaN.\n if (mag === 0) return Vec2.ZERO;\n const adjustedMag = Math.min(\n 1,\n (mag - this.stickDeadzone) / (1 - this.stickDeadzone),\n );\n return new Vec2((x / mag) * adjustedMag, (y / mag) * adjustedMag);\n }\n\n /**\n * Returns the deadzoned trigger value (0..1) for the given side.\n * Reads from the active pad by default; use `{ pad: index }` for explicit\n * per-pad reads. Falls back to synthetic state when no pad is active.\n */\n getTrigger(side: \"left\" | \"right\", opts?: { pad?: number }): number {\n const key = TRIGGER_AXIS_KEYS[side];\n const padIdx = opts?.pad !== undefined ? opts.pad : this.activePadIndex;\n const v =\n padIdx !== null\n ? (this.gamepadAxisState.get(`${padIdx}:${key}`) ?? 0)\n : (this.syntheticAxisState.get(key) ?? 0);\n if (v < this.triggerDeadzone) return 0;\n return Math.min(1, (v - this.triggerDeadzone) / (1 - this.triggerDeadzone));\n }\n\n // -- Gamepad enumeration / events --\n\n /**\n * Synchronously poll `navigator.getGamepads()` for currently-connected pads.\n * Use this rather than the cached event-driven list when you need ground\n * truth — `gamepadconnected` doesn't fire until the user presses a button.\n */\n gamepads(): readonly GamepadInfo[] {\n if (\n typeof navigator === \"undefined\" ||\n typeof navigator.getGamepads !== \"function\"\n ) {\n return [];\n }\n const result: GamepadInfo[] = [];\n for (const pad of navigator.getGamepads()) {\n if (pad) result.push({ index: pad.index, id: pad.id });\n }\n return result;\n }\n\n /**\n * Subscribe to gamepad-connected events. Replays currently-known pads\n * synchronously so callers don't need a separate `gamepads()` call.\n * Returns a disposer.\n */\n onGamepadConnected(fn: (info: GamepadInfo) => void): () => void {\n this.gamepadConnectListeners.push(fn);\n for (const info of this.connectedPads.values()) fn(info);\n return () => {\n const idx = this.gamepadConnectListeners.indexOf(fn);\n if (idx !== -1) this.gamepadConnectListeners.splice(idx, 1);\n };\n }\n\n /** Subscribe to gamepad-disconnected events. Returns a disposer. */\n onGamepadDisconnected(fn: (info: GamepadInfo) => void): () => void {\n this.gamepadDisconnectListeners.push(fn);\n return () => {\n const idx = this.gamepadDisconnectListeners.indexOf(fn);\n if (idx !== -1) this.gamepadDisconnectListeners.splice(idx, 1);\n };\n }\n\n // -- Active pad --\n\n /**\n * The pad whose analog input is read by default. Auto-promotes on input\n * activity (button press or stick/trigger above deadzone) and on first\n * connect. Returns `null` when no pad is connected.\n */\n getActivePad(): GamepadInfo | null {\n if (this.activePadIndex === null) return null;\n return this.connectedPads.get(this.activePadIndex) ?? null;\n }\n\n /**\n * Manually set the active pad. Index must match a currently connected pad\n * — pass an unknown index and the call is a no-op. Pass `null` to clear\n * (analog reads will fall back to synthetic state if any).\n */\n setActivePad(index: number | null): void {\n if (index !== null && !this.connectedPads.has(index)) return;\n this.setActivePadInternal(index);\n }\n\n /**\n * Subscribe to active-pad changes. Replays the current active pad\n * synchronously on subscribe so callers get the present state without a\n * separate `getActivePad()` call. Returns a disposer.\n */\n onActivePadChanged(\n fn: (info: GamepadInfo | null) => void,\n ): () => void {\n this.activePadListeners.push(fn);\n fn(this.getActivePad());\n return () => {\n const idx = this.activePadListeners.indexOf(fn);\n if (idx !== -1) this.activePadListeners.splice(idx, 1);\n };\n }\n\n private setActivePadInternal(index: number | null): void {\n if (this.activePadIndex === index) return;\n this.activePadIndex = index;\n const info = this.getActivePad();\n for (const fn of this.activePadListeners) fn(info);\n }\n\n // -- Gamepad runtime config --\n\n /** Enable or disable real gamepad polling. Synthetic injection still works when disabled. */\n setPollingEnabled(enabled: boolean): void {\n this.pollingEnabled = enabled;\n }\n\n /** Whether real gamepad polling is currently enabled. */\n isPollingEnabled(): boolean {\n return this.pollingEnabled;\n }\n\n /**\n * Update analog deadzones at runtime. Either field may be omitted.\n * Values are clamped to `[0, 0.999]` — capping below 1 keeps the rescaling\n * denominator non-zero. Non-finite values are ignored.\n */\n setDeadzones(opts: { stick?: number; trigger?: number }): void {\n if (opts.stick !== undefined && Number.isFinite(opts.stick)) {\n this.stickDeadzone = Math.max(0, Math.min(0.999, opts.stick));\n }\n if (opts.trigger !== undefined && Number.isFinite(opts.trigger)) {\n this.triggerDeadzone = Math.max(0, Math.min(0.999, opts.trigger));\n }\n }\n\n /**\n * Set the trigger button-edge threshold (default 0.5). Clamped to `[0, 1]`;\n * non-finite values are ignored.\n */\n setTriggerThreshold(value: number): void {\n if (!Number.isFinite(value)) return;\n this.triggerThreshold = Math.max(0, Math.min(1, value));\n }\n\n // -- Internal: polling and connect/disconnect plumbing --\n\n /**\n * @internal Force-release held gamepad buttons and clear real-pad analog\n * snapshots. Used on tab-hide (where `navigator.getGamepads()` returns\n * stale data) and on disconnect when polling is paused. Synthetic axes\n * live in their own field, so they're untouched.\n */\n _releaseAllGamepadState(): void {\n for (const code of [...this.lastButtonState.keys()]) {\n this._applyKeyUp(code);\n }\n this.lastButtonState.clear();\n this.gamepadAxisState.clear();\n this.lastPadActivity.clear();\n }\n\n /** @internal Called by InputPlugin from `gamepadconnected` event or by\n * polling when discovering a previously-unknown pad. Idempotent. */\n _onGamepadConnected(info: GamepadInfo): void {\n if (this.connectedPads.has(info.index)) return;\n this.connectedPads.set(info.index, info);\n // First pad to connect auto-promotes — single-player \"just works\" with\n // no setActivePad call required.\n if (this.activePadIndex === null) {\n this.setActivePadInternal(info.index);\n }\n for (const fn of this.gamepadConnectListeners) fn(info);\n }\n\n /** @internal Called by InputPlugin from `gamepaddisconnected` event or by\n * polling when a pad vanishes silently. Idempotent. */\n _onGamepadDisconnected(info: GamepadInfo): void {\n if (!this.connectedPads.has(info.index)) return;\n this.connectedPads.delete(info.index);\n // Drop per-pad state for the departed pad.\n for (const key of [...this.gamepadAxisState.keys()]) {\n if (key.startsWith(`${info.index}:`)) this.gamepadAxisState.delete(key);\n }\n this.lastPadActivity.delete(info.index);\n // If the departed pad was active, demote and pick the first remaining\n // connected pad (or null) so analog reads keep working without API calls.\n if (this.activePadIndex === info.index) {\n const next = this.connectedPads.keys().next();\n this.setActivePadInternal(next.done ? null : next.value);\n }\n // Re-aggregate held buttons against remaining pads. We can't recursively\n // call `_pollGamepads` because the disconnect detection there is what got\n // us here — instead reconcile button state inline against the current\n // navigator snapshot.\n if (\n this.pollingEnabled &&\n typeof navigator !== \"undefined\" &&\n typeof navigator.getGamepads === \"function\"\n ) {\n this.reconcileButtonStateAcrossPads(navigator.getGamepads());\n } else {\n this._releaseAllGamepadState();\n }\n for (const fn of this.gamepadDisconnectListeners) fn(info);\n }\n\n /**\n * @internal Poll real gamepads via `navigator.getGamepads()` and emit\n * key-down/key-up edges for any aggregate state changes. Called by\n * `InputPollSystem` once per frame.\n */\n _pollGamepads(): void {\n if (\n typeof navigator === \"undefined\" ||\n typeof navigator.getGamepads !== \"function\"\n ) {\n return;\n }\n const pads = navigator.getGamepads();\n\n // 1. Reconcile pad presence. The browser's `gamepadconnected` event is\n // gated behind first user input, so polling discovers already-plugged\n // pads. The matching `gamepaddisconnected` is also unreliable when the\n // tab backgrounds — polling reconciles vanished pads too.\n const liveIndices = new Set<number>();\n for (const pad of pads) {\n if (!pad) continue;\n liveIndices.add(pad.index);\n if (!this.connectedPads.has(pad.index)) {\n this._onGamepadConnected({ index: pad.index, id: pad.id });\n }\n }\n for (const [, info] of [...this.connectedPads]) {\n if (!liveIndices.has(info.index)) {\n this._onGamepadDisconnected(info);\n }\n }\n\n // 2. Defensive axis-state cleanup for any stale entries the disconnect\n // path missed (e.g. partial state during prior frames).\n for (const key of [...this.gamepadAxisState.keys()]) {\n const colon = key.indexOf(\":\");\n if (colon === -1) continue;\n const idx = Number.parseInt(key.slice(0, colon), 10);\n if (!liveIndices.has(idx)) this.gamepadAxisState.delete(key);\n }\n\n // 3. Refresh per-pad axis state and compute current activity. Activity\n // is captured into a map first so the promotion decision can consider\n // all pads together (not in iteration order).\n const currentActivity = new Map<number, boolean>();\n for (const pad of pads) {\n if (!pad) continue;\n const standard = pad.mapping === \"standard\";\n if (standard) {\n for (let axIdx = 0; axIdx < STANDARD_AXIS_KEYS.length; axIdx++) {\n const axisKey = STANDARD_AXIS_KEYS[axIdx];\n if (!axisKey) continue;\n const raw = pad.axes[axIdx] ?? 0;\n this.gamepadAxisState.set(\n `${pad.index}:${axisKey}`,\n Number.isFinite(raw) ? raw : 0,\n );\n }\n const lt = pad.buttons[TRIGGER_LEFT_INDEX]?.value ?? 0;\n const rt = pad.buttons[TRIGGER_RIGHT_INDEX]?.value ?? 0;\n this.gamepadAxisState.set(\n `${pad.index}:leftTrigger`,\n Number.isFinite(lt) ? lt : 0,\n );\n this.gamepadAxisState.set(\n `${pad.index}:rightTrigger`,\n Number.isFinite(rt) ? rt : 0,\n );\n }\n currentActivity.set(pad.index, this.padHasActivity(pad));\n }\n\n // 4. Auto-promotion. The active pad's own activity protects it — we\n // only promote when active is idle, so couch-co-op players don't steal\n // each other's slot mid-press. Among rising-edge candidates we pick the\n // first one in iteration order (deterministic; arbitrary in practice).\n const activeStillActive =\n this.activePadIndex !== null &&\n (currentActivity.get(this.activePadIndex) ?? false);\n if (!activeStillActive) {\n for (const [padIdx, isActive] of currentActivity) {\n const wasActive = this.lastPadActivity.get(padIdx) ?? false;\n if (isActive && !wasActive && padIdx !== this.activePadIndex) {\n this.setActivePadInternal(padIdx);\n break;\n }\n }\n }\n for (const [padIdx, isActive] of currentActivity) {\n this.lastPadActivity.set(padIdx, isActive);\n }\n\n // 5. Reconcile button state across all pads (any-pad action map).\n this.reconcileButtonStateAcrossPads(pads);\n }\n\n /** Whether a pad has any input that should claim active-pad ownership. */\n private padHasActivity(pad: Gamepad): boolean {\n for (const btn of pad.buttons) {\n if (btn?.pressed) return true;\n }\n if (pad.mapping === \"standard\") {\n const lx = pad.axes[0] ?? 0;\n const ly = pad.axes[1] ?? 0;\n const rx = pad.axes[2] ?? 0;\n const ry = pad.axes[3] ?? 0;\n if (Math.hypot(lx, ly) > this.stickDeadzone) return true;\n if (Math.hypot(rx, ry) > this.stickDeadzone) return true;\n const lt = pad.buttons[TRIGGER_LEFT_INDEX]?.value ?? 0;\n const rt = pad.buttons[TRIGGER_RIGHT_INDEX]?.value ?? 0;\n if (lt > this.triggerDeadzone) return true;\n if (rt > this.triggerDeadzone) return true;\n }\n return false;\n }\n\n /**\n * Aggregate \"any pad pressed\" per code across the supplied pad list and\n * emit `_applyKeyDown`/`_applyKeyUp` edges. `lastButtonState` is updated\n * unconditionally so listen-mode interception doesn't cause held-button\n * re-fires on subsequent frames.\n */\n private reconcileButtonStateAcrossPads(\n pads: ReadonlyArray<Gamepad | null>,\n ): void {\n const codePressed = new Map<string, boolean>();\n for (const pad of pads) {\n if (!pad) continue;\n const standard = pad.mapping === \"standard\";\n const buttons = pad.buttons;\n for (let btnIdx = 0; btnIdx < buttons.length; btnIdx++) {\n const btn = buttons[btnIdx];\n if (!btn) continue;\n const standardCode =\n standard && btnIdx < STANDARD_BUTTON_CODES.length\n ? STANDARD_BUTTON_CODES[btnIdx]\n : undefined;\n const code = standardCode ?? `GamepadButton${btnIdx}`;\n const isTrigger =\n standard &&\n (btnIdx === TRIGGER_LEFT_INDEX || btnIdx === TRIGGER_RIGHT_INDEX);\n const isDown = isTrigger ? btn.value >= this.triggerThreshold : btn.pressed;\n if (isDown) codePressed.set(code, true);\n }\n }\n\n const allCodes = new Set<string>([\n ...this.lastButtonState.keys(),\n ...codePressed.keys(),\n ]);\n for (const code of allCodes) {\n const wasPressed = this.lastButtonState.get(code) ?? false;\n const isPressed = codePressed.get(code) ?? false;\n if (isPressed && !wasPressed) {\n this._applyKeyDown(code);\n } else if (!isPressed && wasPressed) {\n this._applyKeyUp(code);\n }\n if (isPressed) {\n this.lastButtonState.set(code, true);\n } else {\n this.lastButtonState.delete(code);\n }\n }\n }\n\n /** Inject a one-frame synthetic action pulse. */\n fireAction(name: string): void {\n if (!this.actionMap.has(name)) {\n throw new Error(`InputManager.fireAction(): unknown action \"${name}\".`);\n }\n this.syntheticPressedActions.add(name);\n this.syntheticActionStarts.set(name, this.elapsedMs);\n this.notifyActionListeners(this.actionListeners, name);\n }\n\n /** Release all synthetic and physical input state. */\n clearAll(): void {\n for (const code of [...this.pressedKeys]) {\n this._applyKeyUp(code);\n }\n // Hard reset: synthetic releases generated above are intentionally\n // discarded. Callers want a clean slate, not a flurry of justReleased\n // pulses for downstream listeners.\n this.justPressedKeys.clear();\n this.justReleasedKeys.clear();\n this.holdStart.clear();\n this.syntheticPressedActions.clear();\n this.syntheticActionStarts.clear();\n this.pointers.clear();\n this.primaryPointerId = null;\n this.mouseButtonAggregate.clear();\n this.consumedPointers.clear();\n this.consumedWheelThisFrame = false;\n this.inputQueue.length = 0;\n this.lastButtonState.clear();\n this.gamepadAxisState.clear();\n this.syntheticAxisState.clear();\n this.lastPadActivity.clear();\n }\n\n /**\n * Drop all tracked pointers and release the aggregate `MouseLeft/Middle/Right`\n * codes without touching keyboard or gamepad state. Useful for window-blur\n * / page-hide handling.\n */\n clearPointerButtons(): void {\n for (const button of [...this.mouseButtonAggregate]) {\n const code = MOUSE_BUTTON_CODES[button];\n if (code) this._applyKeyUp(code);\n }\n this.mouseButtonAggregate.clear();\n this.pointers.clear();\n this.primaryPointerId = null;\n this.consumedPointers.clear();\n // Discard any pointer events that arrived before tab-hide drained.\n this.inputQueue = this.inputQueue.filter(\n (e) =>\n e.kind !== \"pointerDown\" &&\n e.kind !== \"pointerUp\" &&\n e.kind !== \"pointerCancel\",\n );\n }\n\n /** Snapshot of current held input state for inspector tooling. */\n snapshotState(): {\n keys: string[];\n actions: string[];\n mouse: { x: number; y: number; buttons: number[]; down: boolean };\n pointers: Array<{\n id: number;\n x: number;\n y: number;\n type: PointerType;\n isPrimary: boolean;\n buttons: number[];\n down: boolean;\n }>;\n gamepad: {\n buttons: string[];\n axes: Array<{ key: string; value: number }>;\n };\n } {\n const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0);\n const keys = [...this.pressedKeys].sort(cmp);\n const nonGamepadKeys = keys.filter((k) => !k.startsWith(\"Gamepad\"));\n const gamepadButtons = keys.filter((k) => k.startsWith(\"Gamepad\"));\n const actions = this.getActionNames()\n .filter((action) => this.isPressed(action))\n .sort(cmp);\n const aggregateButtons = [...this.mouseButtonAggregate].sort((a, b) => a - b);\n const pointers = [...this.pointers.values()]\n .sort((a, b) => a.id - b.id)\n .map((p) => ({\n id: p.id,\n x: p.screenPos.x,\n y: p.screenPos.y,\n type: p.type,\n isPrimary: p.isPrimary,\n buttons: [...p.buttons].sort((a, b) => a - b),\n down: p.isDown,\n }));\n const primary = this.getPrimaryPointer();\n const realAxes = [...this.gamepadAxisState.entries()]\n .filter(([, value]) => Math.abs(value) > 0.001)\n .map(([key, value]) => ({ key, value }));\n const syntheticAxes = [...this.syntheticAxisState.entries()]\n .filter(([, value]) => Math.abs(value) > 0.001)\n .map(([key, value]) => ({ key: `synthetic:${key}`, value }));\n const axes = [...realAxes, ...syntheticAxes].sort((a, b) => cmp(a.key, b.key));\n\n return {\n keys: nonGamepadKeys,\n actions,\n mouse: {\n x: primary?.screenPos.x ?? 0,\n y: primary?.screenPos.y ?? 0,\n buttons: aggregateButtons,\n down: this.mouseButtonAggregate.size > 0,\n },\n pointers,\n gamepad: {\n buttons: gamepadButtons,\n axes,\n },\n };\n }\n\n // -- Internal: DOM-handler enqueue path --\n\n /**\n * @internal Stash the renderer adapter so the drain step can call its\n * optional `hitTestUI(x, y)` for the auto-consume fallback. Called by\n * `InputPlugin.install`.\n */\n _setRenderer(renderer: RendererAdapter | null): void {\n this.renderer = renderer;\n }\n\n /** @internal */\n _enqueueKeyDown(code: string): void {\n this.inputQueue.push({ kind: \"keyDown\", code });\n }\n\n /** @internal */\n _enqueueKeyUp(code: string): void {\n this.inputQueue.push({ kind: \"keyUp\", code });\n }\n\n /**\n * @internal Sync portion: upsert the pointer entry (existence, screenPos,\n * type, isPrimary, primaryPointerId) and notify pointerMoveListeners so\n * pointer-tracking UIs see live cursor positions. Move events do not carry\n * action-map edges, so they are not queued.\n */\n _enqueuePointerMove(info: PointerEventInfo): void {\n const pointer = this.upsertPointer(info);\n pointer.screenPos = new Vec2(info.screenX, info.screenY);\n this.notifyPointerListeners(this.pointerMoveListeners, pointer);\n }\n\n /**\n * @internal Sync portion: upsert pointer (existence, screenPos, type,\n * isPrimary, primaryPointerId) and notify pointerDownListeners. Button\n * mutation, action-map edges, and mouse-aggregate emit are deferred to the\n * next drain at `Phase.EarlyUpdate` so {@link consumePointer} (or the\n * renderer's UI hit-test) can suppress them, AND so a same-frame\n * down+up that arrives before drain still produces the correct\n * `MouseLeft` press/release edges (recomputing aggregate from live state\n * after sync mutation would silently drop the transient transition).\n *\n * Listeners therefore observe `pointer.buttons` BEFORE this event's edge is\n * applied. That's a documented tradeoff: the canonical event-button info\n * is in the `FederatedPointerEvent` / `PointerEvent` the user's Pixi\n * handler already receives, so the lossy `info.buttons` view rarely\n * matters in practice.\n */\n _enqueuePointerDown(info: PointerEventInfo): void {\n const pointer = this.upsertPointer(info);\n pointer.screenPos = new Vec2(info.screenX, info.screenY);\n this.notifyPointerListeners(this.pointerDownListeners, pointer);\n this.inputQueue.push({ kind: \"pointerDown\", info });\n }\n\n /** @internal */\n _enqueuePointerUp(info: PointerEventInfo): void {\n const pointer = this.upsertPointer(info);\n pointer.screenPos = new Vec2(info.screenX, info.screenY);\n this.notifyPointerListeners(this.pointerUpListeners, pointer);\n this.inputQueue.push({ kind: \"pointerUp\", info });\n }\n\n /** @internal */\n _enqueuePointerCancel(id: number): void {\n const pointer = this.pointers.get(id);\n if (pointer) {\n this.notifyPointerListeners(this.pointerUpListeners, pointer);\n }\n this.inputQueue.push({ kind: \"pointerCancel\", id });\n }\n\n /** @internal */\n _enqueueWheel(dx: number, dy: number): void {\n // Notify wheel listeners synchronously — they're explicit user opt-ins.\n for (const fn of [...this.wheelListeners]) fn(dx, dy);\n this.inputQueue.push({ kind: \"wheel\", dx, dy });\n }\n\n /**\n * @internal Drain queued DOM events at `Phase.EarlyUpdate`. Each event\n * applies its deferred state (button mutations, action-map edges,\n * mouse-aggregate transitions). Consumed pointers are excluded from the\n * mouse aggregate so UI-claimed presses do not propagate to gameplay\n * actions. The renderer's optional `hitTestUI(x, y)` auto-claims a pointer\n * whose `pointerdown` lands on a UI-marked container.\n */\n _drainInputQueue(): void {\n if (this.inputQueue.length === 0) return;\n const queue = this.inputQueue;\n this.inputQueue = [];\n for (const event of queue) {\n switch (event.kind) {\n case \"keyDown\":\n this._applyKeyDown(event.code);\n break;\n case \"keyUp\":\n this._applyKeyUp(event.code);\n break;\n case \"pointerDown\":\n this.drainPointerDown(event.info);\n break;\n case \"pointerUp\":\n this.drainPointerUp(event.info);\n break;\n case \"pointerCancel\":\n this.drainPointerCancel(event.id);\n break;\n case \"wheel\":\n this.applyWheelEdges(event.dx, event.dy);\n break;\n }\n }\n }\n\n private drainPointerDown(info: PointerEventInfo): void {\n // Auto-consume on UI hit. Skipped if explicitly already consumed (the\n // primitive `consumePointer` won — no need to re-check) so handler code\n // stays authoritative.\n if (\n !this.consumedPointers.has(info.id) &&\n this.renderer?.hitTestUI?.(info.screenX, info.screenY)\n ) {\n this.consumedPointers.add(info.id);\n }\n const pointer = this.pointers.get(info.id);\n if (!pointer) return;\n if (info.button >= 0 && info.button <= 2) {\n pointer.buttons.add(info.button);\n pointer.isDown = true;\n this.recomputeMouseAggregate(info.button);\n } else {\n pointer.isDown = pointer.buttons.size > 0;\n }\n }\n\n private drainPointerUp(info: PointerEventInfo): void {\n const pointer = this.pointers.get(info.id);\n if (!pointer) return;\n if (info.button >= 0 && info.button <= 2) {\n pointer.buttons.delete(info.button);\n this.recomputeMouseAggregate(info.button);\n }\n pointer.isDown = pointer.buttons.size > 0;\n if (!pointer.isDown) {\n // End of event cycle — clear the consume mark so the next press starts\n // unmarked. Touch / pen pointers also vanish here (mouse persists for\n // hover queries; the browser does not emit a separate \"leave\").\n this.consumedPointers.delete(info.id);\n if (pointer.type !== \"mouse\") {\n this.removePointer(pointer.id);\n }\n }\n }\n\n private drainPointerCancel(id: number): void {\n const pointer = this.pointers.get(id);\n if (!pointer) return;\n const heldButtons = [...pointer.buttons];\n pointer.buttons.clear();\n pointer.isDown = false;\n for (const button of heldButtons) {\n this.recomputeMouseAggregate(button);\n }\n this.consumedPointers.delete(id);\n if (pointer.type !== \"mouse\") {\n this.removePointer(id);\n }\n }\n\n private applyWheelEdges(dx: number, dy: number): void {\n if (this.consumedWheelThisFrame) return;\n // Wheel codes appear as one-frame `justPressed` edges that never enter\n // `pressedKeys` — scrolling is not a held state, just discrete ticks.\n if (Math.abs(dy) > 0.001) {\n const code = dy < 0 ? \"WheelUp\" : \"WheelDown\";\n this.fireOneFrameEdge(code);\n }\n if (Math.abs(dx) > 0.001) {\n const code = dx < 0 ? \"WheelLeft\" : \"WheelRight\";\n this.fireOneFrameEdge(code);\n }\n }\n\n /**\n * Add a code to `justPressedKeys` without entering `pressedKeys`. Used for\n * discrete edges (wheel ticks) that are never \"held\". Listeners and\n * `listenForNextKey` still fire as usual.\n */\n private fireOneFrameEdge(code: string): void {\n if (this.listenResolve) {\n const resolve = this.listenResolve;\n this.listenResolve = null;\n resolve(code);\n return;\n }\n this.justPressedKeys.add(code);\n this.notifyKeyListeners(this.keyDownListeners, this.keyDownListenersAny, code);\n for (const action of this.actionsForCode(code)) {\n this.notifyActionListeners(this.actionListeners, action);\n }\n }\n\n // -- Internal: synthetic / sync apply path --\n\n /**\n * @internal Synthetic key-down. DOM-originated events must use\n * {@link _enqueueKeyDown} so `consumePointer` and the UI hit-test fallback\n * have a chance to run before action edges fire.\n */\n _applyKeyDown(code: string): void {\n if (this.listenResolve) {\n const resolve = this.listenResolve;\n this.listenResolve = null;\n resolve(code);\n return;\n }\n if (!this.pressedKeys.has(code)) {\n this.pressedKeys.add(code);\n this.justPressedKeys.add(code);\n this.holdStart.set(code, this.elapsedMs);\n this.notifyKeyListeners(this.keyDownListeners, this.keyDownListenersAny, code);\n for (const action of this.actionsForCode(code)) {\n this.notifyActionListeners(this.actionListeners, action);\n }\n }\n }\n\n /**\n * @internal Synthetic key-up. DOM-originated events must use\n * {@link _enqueueKeyUp}.\n */\n _applyKeyUp(code: string): void {\n if (this.pressedKeys.has(code)) {\n this.pressedKeys.delete(code);\n this.justReleasedKeys.add(code);\n this.holdStart.delete(code);\n this.notifyKeyListeners(this.keyUpListeners, this.keyUpListenersAny, code);\n for (const action of this.actionsForCode(code)) {\n this.notifyActionListeners(this.actionReleasedListeners, action);\n }\n }\n }\n\n /**\n * @internal Synthetic pointer move. DOM-originated events must use\n * {@link _enqueuePointerMove}.\n */\n _applyPointerMove(info: PointerEventInfo): void {\n const pointer = this.upsertPointer(info);\n pointer.screenPos = new Vec2(info.screenX, info.screenY);\n this.notifyPointerListeners(this.pointerMoveListeners, pointer);\n }\n\n /**\n * @internal Synthetic pointer down. DOM-originated events must use\n * {@link _enqueuePointerDown}. This applies all state (button mutation,\n * mouse-aggregate emit, listener notify) synchronously.\n */\n _applyPointerDown(info: PointerEventInfo): void {\n const pointer = this.upsertPointer(info);\n pointer.screenPos = new Vec2(info.screenX, info.screenY);\n if (info.button >= 0 && info.button <= 2) {\n pointer.buttons.add(info.button);\n pointer.isDown = true;\n this.recomputeMouseAggregate(info.button);\n } else {\n pointer.isDown = pointer.buttons.size > 0;\n }\n this.notifyPointerListeners(this.pointerDownListeners, pointer);\n }\n\n /**\n * @internal Synthetic pointer up. DOM-originated events must use\n * {@link _enqueuePointerUp}.\n */\n _applyPointerUp(info: PointerEventInfo): void {\n const pointer = this.upsertPointer(info);\n pointer.screenPos = new Vec2(info.screenX, info.screenY);\n if (info.button >= 0 && info.button <= 2) {\n pointer.buttons.delete(info.button);\n this.recomputeMouseAggregate(info.button);\n }\n pointer.isDown = pointer.buttons.size > 0;\n this.notifyPointerListeners(this.pointerUpListeners, pointer);\n if (!pointer.isDown) {\n this.consumedPointers.delete(info.id);\n if (pointer.type !== \"mouse\") {\n this.removePointer(pointer.id);\n }\n }\n }\n\n /**\n * @internal Synthetic pointer cancel. Clears all buttons on the pointer,\n * fires up-listeners, and drops the entry (unless it's a mouse). Mirrors\n * the drain-time {@link drainPointerCancel} logic.\n */\n _applyPointerCancel(id: number): void {\n const pointer = this.pointers.get(id);\n if (!pointer) return;\n const heldButtons = [...pointer.buttons];\n pointer.buttons.clear();\n pointer.isDown = false;\n for (const button of heldButtons) {\n this.recomputeMouseAggregate(button);\n }\n this.notifyPointerListeners(this.pointerUpListeners, pointer);\n this.consumedPointers.delete(id);\n if (pointer.type !== \"mouse\") {\n this.removePointer(id);\n }\n }\n\n private upsertPointer(info: PointerEventInfo): MutablePointerInfo {\n let pointer = this.pointers.get(info.id);\n if (!pointer) {\n pointer = {\n id: info.id,\n screenPos: new Vec2(info.screenX, info.screenY),\n type: info.type,\n isPrimary: info.isPrimary,\n buttons: new Set<number>(),\n isDown: false,\n };\n this.pointers.set(info.id, pointer);\n } else {\n pointer.type = info.type;\n pointer.isPrimary = info.isPrimary;\n }\n if (info.isPrimary) {\n this.primaryPointerId = info.id;\n } else if (this.primaryPointerId === null) {\n this.primaryPointerId = info.id;\n }\n return pointer;\n }\n\n private removePointer(id: number): void {\n this.pointers.delete(id);\n if (this.primaryPointerId === id) {\n // Promote any remaining tracked pointer to primary so singular getters\n // keep returning sensible state. Prefer one the browser already flagged\n // primary, otherwise the first one we find.\n let next: number | null = null;\n for (const p of this.pointers.values()) {\n if (p.isPrimary) {\n next = p.id;\n break;\n }\n if (next === null) next = p.id;\n }\n this.primaryPointerId = next;\n }\n }\n\n /**\n * Recompute the `MouseLeft/Middle/Right` aggregate edge for `button`.\n * Consumed pointers are excluded so a UI-claimed press never propagates to\n * gameplay actions, even if a second non-UI pointer simultaneously holds\n * the same button.\n */\n private recomputeMouseAggregate(button: number): void {\n const code = MOUSE_BUTTON_CODES[button];\n if (!code) return;\n let nowAny = false;\n for (const p of this.pointers.values()) {\n if (this.consumedPointers.has(p.id)) continue;\n if (p.buttons.has(button)) {\n nowAny = true;\n break;\n }\n }\n const wasAny = this.mouseButtonAggregate.has(button);\n if (nowAny && !wasAny) {\n this.mouseButtonAggregate.add(button);\n this._applyKeyDown(code);\n } else if (!nowAny && wasAny) {\n this.mouseButtonAggregate.delete(button);\n this._applyKeyUp(code);\n }\n }\n\n private notifyPointerListeners(\n listeners: Array<(info: PointerInfo) => void>,\n pointer: MutablePointerInfo,\n ): void {\n if (listeners.length === 0) return;\n // Snapshot once per emission so all listeners see the same view and a\n // misbehaving consumer can't mutate manager state. Iterate a copy of\n // `listeners` so a callback that calls its own disposer doesn't skip the\n // next one.\n const info = this.toPointerInfo(pointer);\n for (const fn of [...listeners]) {\n fn(info);\n }\n }\n\n private notifyKeyListeners(\n perCode: Map<string, Array<(code: string) => void>>,\n anyList: Array<(code: string) => void>,\n code: string,\n ): void {\n const list = perCode.get(code);\n if (list) {\n for (const fn of [...list]) fn(code);\n }\n if (anyList.length > 0) {\n for (const fn of [...anyList]) fn(code);\n }\n }\n\n private notifyActionListeners(\n perAction: Map<string, Array<(name: string) => void>>,\n name: string,\n ): void {\n const list = perAction.get(name);\n if (!list) return;\n for (const fn of [...list]) fn(name);\n }\n\n /**\n * Action names that include `code` in their bindings AND whose group is\n * currently enabled. Used for `onAction` / `onActionReleased` listener\n * fan-out so disabled-group suppression matches `isPressed` behavior.\n */\n private actionsForCode(code: string): string[] {\n const result: string[] = [];\n for (const [action, keys] of this.actionMap) {\n if (keys.includes(code) && this.isActionEnabled(action)) {\n result.push(action);\n }\n }\n return result;\n }\n\n /** @internal Clear per-frame justPressed/justReleased flags. */\n _clearFrameState(): void {\n this.justPressedKeys.clear();\n this.justReleasedKeys.clear();\n this.syntheticPressedActions.clear();\n this.syntheticActionStarts.clear();\n this.consumedWheelThisFrame = false;\n }\n\n /** Set camera for pointer world-coord conversion. */\n setCamera(camera: CameraLike): void {\n this.camera = camera;\n }\n\n /** Clear the camera reference (e.g. on scene exit). */\n clearCamera(): void {\n this.camera = null;\n }\n\n /** Get all configured action names. */\n getActionNames(): string[] {\n return Array.from(this.actionMap.keys());\n }\n\n /** @internal Advance the elapsed game-time clock. Called by InputPollSystem. */\n _advanceTime(dtMs: number): void {\n this.elapsedMs += dtMs;\n }\n\n // -- Internal: sync-path aliases (back-compat with pre-0.5.x test callers) --\n\n /** @internal Sync alias — see {@link _applyKeyDown}. */\n _onKeyDown(code: string): void {\n this._applyKeyDown(code);\n }\n /** @internal Sync alias — see {@link _applyKeyUp}. */\n _onKeyUp(code: string): void {\n this._applyKeyUp(code);\n }\n /** @internal Sync alias — see {@link _applyPointerMove}. */\n _onPointerMove(info: PointerEventInfo): void {\n this._applyPointerMove(info);\n }\n /** @internal Sync alias — see {@link _applyPointerDown}. */\n _onPointerDown(info: PointerEventInfo): void {\n this._applyPointerDown(info);\n }\n /** @internal Sync alias — see {@link _applyPointerUp}. */\n _onPointerUp(info: PointerEventInfo): void {\n this._applyPointerUp(info);\n }\n /** @internal Sync alias — see {@link _applyPointerCancel}. */\n _onPointerCancel(id: number): void {\n this._applyPointerCancel(id);\n }\n}\n","import { ServiceKey } from \"@yagejs/core\";\nimport type { RendererAdapter, Vec2 } from \"@yagejs/core\";\nimport type { InputManager } from \"./InputManager.js\";\n\n/** Service key for the InputManager. */\nexport const InputManagerKey = new ServiceKey<InputManager>(\"inputManager\");\n\n/** Minimal camera surface needed by InputManager for pointer world-coord conversion. */\nexport interface CameraLike {\n screenToWorld(screenX: number, screenY: number): { x: number; y: number };\n}\n\n/**\n * Minimal renderer surface needed by InputPlugin for canvas access and\n * coordinate mapping. Alias of the cross-package `RendererAdapter` contract.\n */\nexport type RendererLike = RendererAdapter;\n\n/** Configuration for the InputPlugin. */\nexport interface InputConfig {\n /** Target element for pointer events (default: canvas from renderer, or document). */\n target?: HTMLElement;\n /** Action map: action name -> array of physical key codes. */\n actions?: ActionMapDefinition;\n /** Input groups: group name -> array of action names belonging to it. */\n groups?: Record<string, string[]>;\n /** Key codes to call preventDefault() on (default: none). */\n preventDefaultKeys?: string[];\n /**\n * Optional override for the renderer service key. When omitted, InputPlugin\n * auto-resolves `RendererAdapterKey` — the canonical `@yagejs/renderer`\n * plugin registers itself under that key, so pointer events target its\n * canvas and coordinates route through `canvasToVirtual` out of the box.\n * Set this only if you ship a custom renderer registered under a different\n * key.\n */\n rendererKey?: ServiceKey<RendererAdapter>;\n /** Deadzone thresholds for analog inputs. */\n deadzones?: {\n /** Radial deadzone applied to stick magnitude (default 0.15). */\n stick?: number;\n /** Lower deadzone for trigger analog values (default 0.05). */\n trigger?: number;\n };\n /**\n * Trigger value at which `GamepadLT`/`GamepadRT` fire as button edges in the\n * action map (default 0.5). Below this, the trigger remains \"released\" for\n * `isPressed` purposes; the analog `getTrigger` value is unaffected.\n */\n triggerThreshold?: number;\n /**\n * Whether to poll `navigator.getGamepads()` each frame (default `true`).\n * Disable to use only synthetic input via `fireGamepadButton`/`fireGamepadAxis`\n * — useful for inspector probes that want deterministic state.\n */\n pollGamepads?: boolean;\n /**\n * Invert vertical scroll so positive `dy` means up (default `false`,\n * matching the W3C convention where positive `deltaY` is \"scroll content\n * down\"). Affects both `onWheel` callbacks and `WheelUp/Down` action edges.\n */\n wheelInvertY?: boolean;\n /**\n * Call `preventDefault()` on incoming wheel events so the page does not\n * scroll. Default `false` — opt in only if your game canvas should swallow\n * scroll. The listener is attached as `{ passive: false }` when this is\n * enabled so `preventDefault()` actually takes effect.\n */\n preventDefaultWheel?: boolean;\n}\n\n/** Information about a connected gamepad. */\nexport interface GamepadInfo {\n /** Index in `navigator.getGamepads()`. May change if pads are hot-swapped. */\n index: number;\n /** Browser-reported gamepad identifier (vendor + product). */\n id: string;\n}\n\n/**\n * Named gamepad analog axis. Sticks are exposed per axis (`leftX`/`leftY`,\n * etc.); triggers (`leftTrigger`/`rightTrigger`) carry the W3C\n * `GamepadButton.value` for buttons 6/7 under standard mapping.\n */\nexport type GamepadAxisKey =\n | \"leftX\"\n | \"leftY\"\n | \"rightX\"\n | \"rightY\"\n | \"leftTrigger\"\n | \"rightTrigger\";\n\n/**\n * Class of physical pointer device. Sourced from `PointerEvent.pointerType` on\n * real input; defaults to `\"mouse\"` for synthetic injection.\n */\nexport type PointerType = \"mouse\" | \"pen\" | \"touch\";\n\n/**\n * Read-only view of a tracked pointer. Returned from {@link InputManager.getPointers}\n * and the per-pointer event hooks. Treat as immutable — fields reflect the\n * pointer's state at query time and are not retained between frames.\n */\nexport interface PointerInfo {\n /** Browser-assigned `PointerEvent.pointerId`, or the synthetic id passed via `firePointer*`. */\n readonly id: number;\n /** Position in screen-space pixels (already routed through `canvasToVirtual` if available). */\n readonly screenPos: Vec2;\n /** Source device class. */\n readonly type: PointerType;\n /** Whether the browser flagged this as the primary pointer (`PointerEvent.isPrimary`). */\n readonly isPrimary: boolean;\n /** Currently-held button indices (0=left/primary, 1=middle, 2=right). */\n readonly buttons: ReadonlySet<number>;\n /** Convenience mirror of `buttons.size > 0`. */\n readonly isDown: boolean;\n}\n\n/**\n * Per-event payload assembled by {@link InputPlugin} from each `PointerEvent`\n * (or by `firePointer*` for synthetic injection) and forwarded to the manager's\n * internal pointer handlers.\n *\n * @internal\n */\nexport interface PointerEventInfo {\n id: number;\n screenX: number;\n screenY: number;\n type: PointerType;\n isPrimary: boolean;\n /**\n * The button whose state changed for this event. `-1` for events that don't\n * change button state (move-only). Down/up handlers ignore `-1`.\n */\n button: number;\n}\n\n/** Maps action names to arrays of physical key codes. */\nexport type ActionMapDefinition = Record<string, string[]>;\n\n/** How to handle a conflict when rebinding a key already used by another action in the same group. */\nexport type InputConflictPolicy = \"replace\" | \"keep-both\" | \"reject\";\n\n/** Options for {@link InputManager.rebind}. */\nexport interface RebindOptions {\n /** Index of the binding slot to replace. Appends if the slot does not exist. */\n slot?: number;\n /** How to resolve conflicts with other actions in the same group(s). Default: `\"reject\"`. */\n conflict?: InputConflictPolicy;\n}\n\n/** Result of a {@link InputManager.rebind} call. */\nexport interface RebindResult {\n /** Whether the rebind succeeded. */\n ok: boolean;\n /** Present when `ok` is false due to a conflict with `conflict: \"reject\"`. */\n conflict?: { action: string; key: string };\n}\n","import { System, Phase } from \"@yagejs/core\";\nimport { InputManagerKey } from \"./types.js\";\n\n/**\n * Runs at the start of each frame (EarlyUpdate, priority -100).\n * Drains DOM-buffered input events (so action-map edges land before any\n * gameplay system reads them), advances the input elapsed clock, and polls\n * connected gamepads — emitting key-down/key-up edges through the manager so\n * action queries, hold-duration, and `listenForNextKey` all work uniformly\n * across keyboard and gamepad.\n */\nexport class InputPollSystem extends System {\n readonly phase = Phase.EarlyUpdate;\n readonly priority = -100;\n\n update(dt: number): void {\n const manager = this.use(InputManagerKey);\n manager._drainInputQueue();\n manager._advanceTime(dt);\n if (manager.isPollingEnabled()) {\n manager._pollGamepads();\n }\n }\n}\n","import { System, Phase } from \"@yagejs/core\";\nimport { InputManagerKey } from \"./types.js\";\n\n/**\n * Runs at the end of each frame (EndOfFrame, priority 9000).\n * Clears per-frame justPressed/justReleased flags.\n */\nexport class InputClearSystem extends System {\n readonly phase = Phase.EndOfFrame;\n readonly priority = 9000;\n\n update(): void {\n this.use(InputManagerKey)._clearFrameState();\n }\n}\n","import type {\n DebugContributor,\n WorldDebugApi,\n HudDebugApi,\n} from \"@yagejs/debug/api\";\nimport type { InputManager } from \"./InputManager.js\";\n\nconst CROSSHAIR_SIZE = 10;\nconst CROSSHAIR_COLOR = 0xff00ff;\n\n/** Debug contributor that shows pressed actions and pointer position. */\nexport class InputDebugContributor implements DebugContributor {\n readonly name = \"input\";\n readonly flags = [\"actions\", \"pointer\"] as const;\n\n constructor(private readonly manager: InputManager) {}\n\n drawWorld(api: WorldDebugApi): void {\n if (!api.isFlagEnabled(\"pointer\")) return;\n\n const pos = this.manager.getPointerPosition();\n const g = api.acquireGraphics();\n if (!g) return;\n\n const size = CROSSHAIR_SIZE / api.cameraZoom;\n const lineWidth = 1 / api.cameraZoom;\n g.moveTo(pos.x - size, pos.y)\n .lineTo(pos.x + size, pos.y)\n .moveTo(pos.x, pos.y - size)\n .lineTo(pos.x, pos.y + size)\n .stroke({ width: lineWidth, color: CROSSHAIR_COLOR });\n }\n\n drawHud(api: HudDebugApi): void {\n if (!api.isFlagEnabled(\"actions\")) return;\n\n const pressed = this.manager\n .getActionNames()\n .filter((action) => this.manager.isPressed(action));\n\n const label = pressed.length > 0 ? pressed.join(\", \") : \"(none)\";\n api.addLine(`Input: ${label}`);\n\n const groups = this.manager.getGroups();\n if (groups.length > 0) {\n const disabled = groups.filter((g) => !this.manager.isGroupEnabled(g));\n if (disabled.length > 0) {\n api.addLine(`Disabled groups: ${disabled.join(\", \")}`);\n }\n }\n }\n}\n","const KEY_DISPLAY_NAMES: Record<string, string> = {\n // Letters\n KeyA: \"A\",\n KeyB: \"B\",\n KeyC: \"C\",\n KeyD: \"D\",\n KeyE: \"E\",\n KeyF: \"F\",\n KeyG: \"G\",\n KeyH: \"H\",\n KeyI: \"I\",\n KeyJ: \"J\",\n KeyK: \"K\",\n KeyL: \"L\",\n KeyM: \"M\",\n KeyN: \"N\",\n KeyO: \"O\",\n KeyP: \"P\",\n KeyQ: \"Q\",\n KeyR: \"R\",\n KeyS: \"S\",\n KeyT: \"T\",\n KeyU: \"U\",\n KeyV: \"V\",\n KeyW: \"W\",\n KeyX: \"X\",\n KeyY: \"Y\",\n KeyZ: \"Z\",\n\n // Digits\n Digit0: \"0\",\n Digit1: \"1\",\n Digit2: \"2\",\n Digit3: \"3\",\n Digit4: \"4\",\n Digit5: \"5\",\n Digit6: \"6\",\n Digit7: \"7\",\n Digit8: \"8\",\n Digit9: \"9\",\n\n // Function keys\n F1: \"F1\",\n F2: \"F2\",\n F3: \"F3\",\n F4: \"F4\",\n F5: \"F5\",\n F6: \"F6\",\n F7: \"F7\",\n F8: \"F8\",\n F9: \"F9\",\n F10: \"F10\",\n F11: \"F11\",\n F12: \"F12\",\n\n // Modifiers\n ShiftLeft: \"Left Shift\",\n ShiftRight: \"Right Shift\",\n ControlLeft: \"Left Ctrl\",\n ControlRight: \"Right Ctrl\",\n AltLeft: \"Left Alt\",\n AltRight: \"Right Alt\",\n MetaLeft: \"Left Meta\",\n MetaRight: \"Right Meta\",\n\n // Arrows\n ArrowUp: \"Up\",\n ArrowDown: \"Down\",\n ArrowLeft: \"Left\",\n ArrowRight: \"Right\",\n\n // Common keys\n Space: \"Space\",\n Enter: \"Enter\",\n Escape: \"Esc\",\n Tab: \"Tab\",\n Backspace: \"Backspace\",\n Delete: \"Delete\",\n Insert: \"Insert\",\n Home: \"Home\",\n End: \"End\",\n PageUp: \"Page Up\",\n PageDown: \"Page Down\",\n CapsLock: \"Caps Lock\",\n NumLock: \"Num Lock\",\n ScrollLock: \"Scroll Lock\",\n PrintScreen: \"Print Screen\",\n Pause: \"Pause\",\n ContextMenu: \"Menu\",\n\n // Punctuation / symbols\n Backquote: \"`\",\n Minus: \"-\",\n Equal: \"=\",\n BracketLeft: \"[\",\n BracketRight: \"]\",\n Backslash: \"\\\\\",\n Semicolon: \";\",\n Quote: \"'\",\n Comma: \",\",\n Period: \".\",\n Slash: \"/\",\n\n // Numpad\n Numpad0: \"Numpad 0\",\n Numpad1: \"Numpad 1\",\n Numpad2: \"Numpad 2\",\n Numpad3: \"Numpad 3\",\n Numpad4: \"Numpad 4\",\n Numpad5: \"Numpad 5\",\n Numpad6: \"Numpad 6\",\n Numpad7: \"Numpad 7\",\n Numpad8: \"Numpad 8\",\n Numpad9: \"Numpad 9\",\n NumpadAdd: \"Numpad +\",\n NumpadSubtract: \"Numpad -\",\n NumpadMultiply: \"Numpad *\",\n NumpadDivide: \"Numpad /\",\n NumpadDecimal: \"Numpad .\",\n NumpadEnter: \"Numpad Enter\",\n\n // Mouse buttons (synthetic codes from InputPlugin)\n MouseLeft: \"Left Click\",\n MouseMiddle: \"Middle Click\",\n MouseRight: \"Right Click\",\n\n // Gamepad buttons (synthetic codes from InputPollSystem; standard mapping)\n GamepadA: \"A\",\n GamepadB: \"B\",\n GamepadX: \"X\",\n GamepadY: \"Y\",\n GamepadLB: \"LB\",\n GamepadRB: \"RB\",\n GamepadLT: \"LT\",\n GamepadRT: \"RT\",\n GamepadSelect: \"Select\",\n GamepadStart: \"Start\",\n GamepadLeftStick: \"Left Stick\",\n GamepadRightStick: \"Right Stick\",\n GamepadDPadUp: \"D-Pad Up\",\n GamepadDPadDown: \"D-Pad Down\",\n GamepadDPadLeft: \"D-Pad Left\",\n GamepadDPadRight: \"D-Pad Right\",\n GamepadHome: \"Home\",\n};\n\nconst GAMEPAD_BUTTON_FALLBACK = /^GamepadButton(\\d+)$/;\n\n/** Returns a human-readable display name for a `KeyboardEvent.code` or mouse key string. */\nexport function getKeyDisplayName(code: string): string {\n const direct = KEY_DISPLAY_NAMES[code];\n if (direct !== undefined) return direct;\n const fallback = GAMEPAD_BUTTON_FALLBACK.exec(code);\n if (fallback) return `Gamepad Button ${fallback[1]}`;\n return code;\n}\n"],"mappings":"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","names":["import_core","import_core","import_core","import_core"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Plugin, EngineContext, SystemScheduler } from '@yagejs/core';
|
|
2
|
-
import { I as InputConfig } from './api-
|
|
3
|
-
export { A as ActionMapDefinition, C as CameraLike, a as
|
|
2
|
+
import { I as InputConfig } from './api-BaItBbSe.cjs';
|
|
3
|
+
export { A as ActionMapDefinition, C as CameraLike, G as GamepadAxisKey, a as GamepadInfo, b as InputConflictPolicy, c as InputManager, d as InputManagerKey, P as PointerInfo, e as PointerType, R as RebindOptions, f as RebindResult, g as RendererLike } from './api-BaItBbSe.cjs';
|
|
4
4
|
|
|
5
5
|
/** Input plugin — wires keyboard and pointer listeners, registers InputManager. */
|
|
6
6
|
declare class InputPlugin implements Plugin {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Plugin, EngineContext, SystemScheduler } from '@yagejs/core';
|
|
2
|
-
import { I as InputConfig } from './api-
|
|
3
|
-
export { A as ActionMapDefinition, C as CameraLike, a as
|
|
2
|
+
import { I as InputConfig } from './api-BaItBbSe.js';
|
|
3
|
+
export { A as ActionMapDefinition, C as CameraLike, G as GamepadAxisKey, a as GamepadInfo, b as InputConflictPolicy, c as InputManager, d as InputManagerKey, P as PointerInfo, e as PointerType, R as RebindOptions, f as RebindResult, g as RendererLike } from './api-BaItBbSe.js';
|
|
4
4
|
|
|
5
5
|
/** Input plugin — wires keyboard and pointer listeners, registers InputManager. */
|
|
6
6
|
declare class InputPlugin implements Plugin {
|