import type { GamepadAxisIndex, GamepadButtonIndex, InputBackendSample } from './input-snapshot'; /** * Closed 4-member discriminant union for mapping raw input sources to actions. * The `type` field is the discriminant; consumers switch on it with no `default` * branch (AC-08b: TypeScript checks exhaustiveness at compile time). */ export type ActionBinding = { readonly type: 'key'; readonly key: string; } | { readonly type: 'mouseButton'; readonly button: 0 | 1 | 2; } | { readonly type: 'gamepadButton'; readonly button: GamepadButtonIndex; } | { readonly type: 'gamepadAxis'; readonly axis: GamepadAxisIndex; /** * Sign applied to the raw axis value before aggregation. * - Omitted: contributes |value| (trigger semantics, e.g. right trigger on axis 2). * - `1`: contributes max(0, value) (positive direction). * - `-1`: contributes max(0, -value) (negative direction, e.g. left stick). */ readonly sign?: 1 | -1; }; /** * An action definition in the InputMap: a semantic name + one or more bindings * to raw input sources, plus an optional per-action deadzone override. */ export interface ActionConfig { /** Semantic action name (e.g. 'jump', 'moveRight'). Referenced by snap.action(name). */ readonly action: string; /** Raw input bindings that contribute to this action. Aggregated via OR/MAX. */ readonly bindings: readonly ActionBinding[]; /** * Per-action deadzone applied to analog strength remapping. * Default: 0.2 (Godot prior-art, F2). Analog values with |raw| < deadzone * produce strength=0. Values >= deadzone are linearly remapped into [0,1]. */ readonly deadzone?: number; } /** * Per-frame derived action state. Returned by deriveActionStates(); consumed * by snap.action(name) readpoints. All fields are frame-frozen (AC-11). */ export interface ActionState { readonly action: string; /** Resolved at frame sampling; radial vector reads use this value. */ readonly deadzone: number; /** true when ANY binding contributes a press (OR aggregation). */ readonly pressed: boolean; /** * true only on the frame when pressed transitions false→true. * One-frame lifetime; held state does not re-fire (AC-03). */ readonly justPressed: boolean; /** * true only on the frame when pressed transitions true→false. * One-frame lifetime (AC-03). */ readonly justReleased: boolean; /** * Deadzone-remapped analog strength in [0, 1]. Digital press → 1.0. * Analog values < deadzone → 0. Aggregate: MAX across bindings. */ readonly strength: number; /** * Raw un-deadzoned magnitude in [0, 1]. Used by getVector (which applies its * own single radial deadzone to avoid per-axis deadzone stacking, F2). * Aggregate: MAX across bindings. */ readonly raw: number; } /** * Resource key for the immutable InputMap (ActionConfig[]) inserted into * the World. Canvas-form createApp does this automatically; assemble-form * hosts insert it directly (D-7). */ export declare const INPUT_MAP_KEY = "InputMap"; /** * Derive per-frame action states from a backend sample and an InputMap. * * Pure function with no side effects. Called once per frame by the * frame-start scan system. The result is frozen into the InputSnapshot * so all snap.action() calls in the same frame see identical state (AC-11). * * @param sample - One frame's raw input backend sample (POD). * @param inputMap - ActionConfig array; duplicate action names → last-wins (D-8). * @param prevActionStates - Previous frame's action states for edge diff * (justPressed/justReleased derivation). Omitted on the first frame or * when actions are not being tracked across frames. * @returns ActionState[] with one entry per action name in inputMap (last-wins dedup). */ export declare function deriveActionStates(sample: InputBackendSample, inputMap: readonly ActionConfig[], prevActionStates?: readonly ActionState[]): ActionState[]; /** * Options for getVector deadzone override. */ export interface GetVectorOptions { /** * Override the default radial deadzone. When omitted, the deadzone is * computed as the average of the 4 per-action deadzones. */ readonly deadzone?: number; } /** * Compose a 1D axis value from two opposing actions. * * Returns `strength(pos) - strength(neg)`, range [-1, 1]. * * - Both registered: combines normally. * - One unregistered (E-3): contributes 0. * - Neither registered: returns 0. * - Same action for both ends (E-12): always 0. * * @param actionStates - Derived action states (from deriveActionStates). * @param neg - Action name for the negative direction (e.g. 'moveLeft'). * @param pos - Action name for the positive direction (e.g. 'moveRight'). */ export declare function getAxis(actionStates: readonly ActionState[], neg: string, pos: string): number; /** * Compose a 2D vector from four directional actions using a single radial * deadzone (Godot input.cpp three-branch formula, F2). * * Reads `raw` (not `strength`) from actionStates to avoid per-axis deadzone * stacking into a square deadzone. Applies one radial deadzone: * * - length <= deadzone → (0, 0) * - length > 1 → vector / length (clamp to unit circle) * - otherwise → vector * inverse_lerp(deadzone, 1, length) / length * * Default deadzone = average of the 4 actions' per-action deadzones. * `opts.deadzone` overrides it. * * @param actionStates - Derived action states. * @param negX - Action name for negative X (e.g. 'moveLeft'). * @param posX - Action name for positive X (e.g. 'moveRight'). * @param negY - Action name for negative Y (e.g. 'moveUp'). * @param posY - Action name for positive Y (e.g. 'moveDown'). * @param opts - Optional override (deadzone). */ export declare function getVector(actionStates: readonly ActionState[], negX: string, posX: string, negY: string, posY: string, opts?: GetVectorOptions): { readonly x: number; readonly y: number; }; //# sourceMappingURL=action-state.d.ts.map