/** Parameter value a graph reads: floats for blends and comparisons, booleans for gates. */ export type AnimParamValue = number | boolean; /** The parameter set a graph evaluates against each advance. */ export type AnimParams = Readonly>; /** A state plays one clip, or blends clips by one or two parameters. */ export type AnimState = { kind: "clip"; clip: string; variants?: readonly string[]; speed?: number; loop?: boolean; rootMotion?: boolean; } | { kind: "blend1D"; param: string; points: readonly { at: number; clip: string; }[]; speed?: number; loop?: boolean; rootMotion?: boolean; } | { kind: "blend2D"; params: readonly [string, string]; points: readonly { at: readonly [number, number]; clip: string; }[]; speed?: number; loop?: boolean; rootMotion?: boolean; }; /** Comparison operators an {@link AnimCondition} supports. */ export type AnimCompare = ">" | "<" | ">=" | "<=" | "==" | "!="; /** A parameter comparison; every condition on a transition must hold. */ export interface AnimCondition { param: string; op: AnimCompare; value: AnimParamValue; } /** Edge between states. `from: "*"` matches any state except `to`. */ export interface AnimTransition { from: string | "*"; to: string; /** All must hold. */ when?: readonly AnimCondition[]; /** Fires once when this trigger was set since the last advance; consumed on use. */ trigger?: string; /** Crossfade seconds. Default 0.2. */ duration?: number; /** Only leave `from` once its normalized time reaches this (one-shots returning to locomotion). */ exitTime?: number; } /** A blend layer with its own state machine. Masked layers apply only to bones whose track names start with a prefix. */ export interface AnimLayer { id: string; entry: string; states: Readonly>; transitions: readonly AnimTransition[]; /** Bone name prefixes this layer drives; absent means the whole rig. */ mask?: readonly string[]; additive?: boolean; /** Layer influence 0..1. Default 1. */ weight?: number; } /** A named moment inside a clip (foot plant, hit frame, reload point). */ export interface AnimEvent { clip: string; atSec: number; name: string; } /** Serializable animation graph. Clip durations come from the rig at runtime (see {@link AnimGraphClipInfo}). */ export interface AnimGraph { layers: readonly AnimLayer[]; events?: readonly AnimEvent[]; } /** Per-clip duration in seconds, read from the loaded rig. */ export type AnimGraphClipInfo = Readonly>; interface LayerTransitionState { to: string; elapsed: number; duration: number; fromWeights: Record; fromTimes: Record; fromPlayback?: Record; } interface LayerState { current: string; time: number; transition: LayerTransitionState | null; selectedClip?: string; } /** Serializable evaluator state. */ export interface AnimGraphState { layers: Record; triggers: string[]; } /** One clip's contribution: weight 0..1 and the time to seek it to. */ export interface AnimClipOutput { clip: string; weight: number; time: number; layer: string; } /** What one advance asks the rig to show. */ export interface AnimGraphOutput { clips: AnimClipOutput[]; events: { name: string; clip: string; }[]; /** Root-bone travel over this advance from `rootMotion` states, in the rig's local units. */ rootDelta?: [number, number, number]; /** `true` while an influencing current or fading-out state has `rootMotion`, even with no travel. */ rootMotion?: true; } /** The evaluator handle: arm triggers, advance, inspect, snapshot and restore. */ export interface AnimGraphRuntime { graph(): AnimGraph; retune(graph: AnimGraph): void; state(): AnimGraphState; snapshot(): AnimGraphState; restore(state: AnimGraphState): void; /** Arm a trigger for the next advance. */ trigger(name: string): void; /** Current state id of a layer. */ stateOf(layerId: string): string | null; advance(dt: number, params: AnimParams, clips: AnimGraphClipInfo): AnimGraphOutput; } /** Randomness used only when entering a clip state with variants. Omit to choose the first variant. */ export interface AnimGraphRuntimeOptions { rng?: () => number; } /** Entity blackboard key the shell reads extra graph parameters from: `ctx.scene.entity.blackboard.set(id, ANIM_PARAMS_KEY, { aiming: true })`. */ export declare const ANIM_PARAMS_KEY = "anim.params"; /** Static clip weights of a state at `params`, before any crossfade. */ export declare function stateClipWeights(state: AnimState, params: AnimParams): Record; /** * Headless animation state machine and blend evaluator. It owns every clip's playback time and weight, so the * renderer only seeks and weights actions on a mixer, and headless hosts, replays, and tests advance the same * graph without three.js. Transitions are data (parameter comparisons and consumed triggers), layers can be * masked or additive, and events fire by clip time, including across loop wraps. * * @capability anim-graph data-first animation state machine with blend trees, crossfades, layers, and clip events */ export declare function createAnimGraphRuntime(initial: AnimGraph, options?: AnimGraphRuntimeOptions): AnimGraphRuntime; /** * Validates untrusted JSON (a saved scene document, a network payload) as an {@link AnimGraph}. * Malformed states, transitions to unknown states, and bad conditions are dropped; a layer whose * entry state is missing is dropped; the result is `undefined` when no layer survives. * * @capability anim-graph load an animation graph from saved JSON without trusting its shape */ export declare function parseAnimGraph(value: unknown): AnimGraph | undefined; /** A located, repairable error in an authored animation graph; paths are relative to the graph value. */ export interface AnimGraphDiagnostic { path: string; message: string; repair: string; } /** The whole authored graph is retained unchanged only when every supported field is valid. */ export interface AnimGraphValidation { graph: AnimGraph | undefined; diagnostics: readonly AnimGraphDiagnostic[]; } /** * Validate an authored graph without dropping broken combat states or weakening transition conditions. * Known malformed fields and dangling references reject the whole graph with relative repair locations; * valid data, including authored object/array order, is returned unchanged. Unknown extension fields are * retained. Clip availability belongs to the imported-rig diagnostics. Use {@link parseAnimGraph} when * permissive repair is intentional. * @capability anim-graph validate authored animation graphs with located repair diagnostics without partial fallback */ export declare function validateAnimGraph(value: unknown): AnimGraphValidation; export {};