import { type GamepadGlyphName, type GamepadGlyphSet } from "./gamepadModel.js"; /** * Action-binding model: games bind semantic actions ("jump", "interact") to * physical control codes; capture layers resolve raw events through this map * so gameplay code never sees keycodes. Control codes are plain strings, so * the same model serves keyboard codes, mouse buttons, touch controls, or * gamepad inputs. */ export interface ActionBinding { primary: TCode; secondary: TCode | null; } export type ActionBindingMap = Record>; /** @internal */ export declare function bindingMatches(code: TCode, binding: ActionBinding): boolean; /** First action (in the map's key order) bound to the given control code, or null. * @internal */ export declare function resolveBoundAction(code: TCode, bindings: ActionBindingMap): TAction | null; /** * Collapse left/right modifier variants of a KeyboardEvent.code so bindings * store one logical key. * @internal */ export declare function normalizeKeyCode(code: string): string; export interface ActionBindingModes { hold?: ActionBinding[]; toggle?: ActionBinding[]; } export type ActionBindingConfig = ActionBinding[] | ActionBindingModes; export type ActionStateBindingMap = Record>; export type ActionCodes = readonly TCode[] | { hold?: readonly TCode[]; toggle?: readonly TCode[]; repeatMs?: number; }; /** * Maps each game action name to the input codes (hold/toggle keys, repeat rate) that trigger it. In a * `defineGame({ input })`, pressing an action runs the same-named command with `{ yaw, pitch, aim }`; * `repeatMs` re-fires it while held (automatic weapons). * * @capability fire-input bind a key or mouse button to a named action that runs the same-named command with the aim; repeatMs auto-fires while held */ export type ActionCodesMap = Record>; /** @internal */ export declare function actionRepeatMs(codes: ActionCodes | undefined): number | undefined; export interface ShouldDispatchActionInput { pressed: boolean; down: boolean; repeatMs: number | undefined; lastFiredAt: number | null; now: number; } /** @internal */ export declare function shouldDispatchAction({ pressed, down, repeatMs, lastFiredAt, now }: ShouldDispatchActionInput): boolean; /** @internal */ export declare function toActionStateBindingMap(map: ActionCodesMap): ActionStateBindingMap; /** @internal */ export declare function hotbarSlotBindings(count: number, options?: { action?: (slot: number) => string; }): ActionCodesMap; /** 0-based slot index for a hotbar-slot action name (`slot1`, `hotbarSlot1`), or null. * @internal */ export declare function hotbarSlotActionIndex(action: string): number | null; /** @internal */ export declare function isHotbarSlotAction(action: string): boolean; /** * Convention mapping a bound input action to the command it fires: the action's * own name when a command by that name exists, otherwise a `ui.` * fallback. Reserved actions (consumed natively by the shell) and hotbar slots * yield null so the shell can handle them itself. * @internal */ export declare function resolveActionCommand(action: string, has: (command: string) => boolean, reserved: ReadonlySet): string | null; /** Short display label for a raw key/button code (e.g. `"KeyW"` → `"W"`). * @internal */ export declare function bindingLabel(code: string, glyphSet?: GamepadGlyphName | GamepadGlyphSet): string; /** Short display label for an action's first bound code, or null when unbound. * @internal */ export declare function actionLabel(map: ActionCodesMap, action: string): string | null; export interface ActionStateTracker { handleDown(code: string): TAction | null; handleUp(code: string): TAction | null; isDown(action: TAction): boolean; wasPressed(action: TAction): boolean; endFrame(): void; reset(): void; /** * Swap the binding map without dropping what is physically held: a key still down counts toward * whatever action it maps to now, with no fresh press edge. Toggle state survives for actions that * come back later. */ rebind(map: ActionStateBindingMap): void; /** The action names in the current binding map. */ actions(): readonly TAction[]; } /** @internal */ export declare function createActionStateTracker(map: ActionStateBindingMap): ActionStateTracker;