import type { AxisBinding, AxisRange } from "./axisInput.js"; /** * How one axis responds to one kind of source. Keys want ramps (a held key should feel like a pedal * being pressed, not a switch); sticks want deadzone and curve but no lag. */ export interface AxisShapeProfile { /** Inner deadzone `0..1`; the remaining travel is rescaled so output still starts at 0 (default `0`). */ deadzone?: number; /** Raw magnitude at which output reaches full scale, `0..1` (default `1`). */ saturation?: number; /** Response exponent applied after the deadzone: `1` linear, `>1` finer near centre (default `1`). */ curve?: number; /** Units/s the output may move away from zero (default `Infinity`: no ramp). */ riseRate?: number; /** Units/s the output may move back toward zero while the input keeps its sign (default `riseRate`). */ fallRate?: number; /** Units/s the output moves when the input is released or reversed — self-centring (default `fallRate`). */ returnRate?: number; } /** Shaping for one named axis. */ export interface AxisShapeConfig { /** Profile for keys and buttons (default: pass through). */ digital?: AxisShapeProfile; /** Profile for sticks, triggers and other continuous sources (default: pass through). */ analog?: AxisShapeProfile; /** Output range (default `[-1, 1]`; use `{ min: 0, max: 1 }` for pedals). */ range?: AxisRange; /** * Multiplier from a caller-supplied signal, applied to the target before ramping — speed-sensitive * steering (`speed => 1 / (1 + speed / 30)`), weapon-sway-by-stamina, and similar. Default `1`. */ scale?: (signal: number) => number; } /** Config for {@link createAxisShaper}: one entry per axis. */ export interface AxisShaperConfig { axes: Record; } /** Per-sample options for {@link AxisShaper.shape}. */ export interface AxisShapeSample { /** Axes whose raw value came from an analog source this frame; unlisted axes use the digital profile. */ analog?: Partial> | ReadonlySet; /** Signal passed to each axis's `scale` callback (speed, stamina, zoom). */ signal?: number; } /** Shaped axis output, one number per axis. */ export type AxisValues = Record; /** Stateful per-axis response shaping between raw input and a sim. */ export interface AxisShaper { /** Shape one frame of raw axis values (as returned by `ctx.input.axis`) and return the shaped output. */ shape(dt: number, raw: Readonly>, sample?: AxisShapeSample): AxisValues; /** The last shaped output. */ value(): Readonly>; /** Replace the shaping config (settings screen, per-vehicle feel) without resetting the current output. */ retune(next: AxisShaperConfig): void; snapshot(): AxisValues; restore(state: Readonly>): void; /** Zero every axis. */ reset(): void; } /** Deadzone, saturation and curve applied to one raw value; sign is preserved. */ export declare function shapeAxisValue(raw: number, profile: AxisShapeProfile | undefined): number; /** * Creates an {@link AxisShaper}: deadzone, curve and ramp rates per axis, chosen per frame by whether the * source was a key or a stick. It sits between `ctx.input.axis(...)` and any sim (a vehicle, an aircraft, * aim), so a held key eases in and self-centres while a stick stays direct. Deterministic and serializable. * @capability axis-shaping shape raw input per axis — deadzone, response curve, keyboard ramp, self-centring, speed-sensitive scaling */ export declare function createAxisShaper(initial: AxisShaperConfig): AxisShaper; /** * Which axes an analog source is driving this frame: an axis counts as analog when any action bound to it * has a published analog magnitude (`ctx.input.analog()`). Feed the result to {@link AxisShaper.shape}. */ export declare function analogAxes(bindings: Readonly>, analog: Readonly> | null): Set;