Skip to content

@aosengine/animation ​

Classes ​

MovementComponent ​

Navmesh path following for one character.

Constructors ​

Constructor ​
ts
new MovementComponent(options?): MovementComponent;

Build a component.

Parameters ​
ParameterTypeDescription
optionsMovementOptionsSee MovementOptions.
Returns ​

MovementComponent

Properties ​

config ​
ts
readonly config: MovementConfig;

Tuning.

path ​
ts
path: Vec3[] = [];

The path being followed.

speed ​
ts
speed: number = 0;

Current speed in metres per second.

status ​
ts
status: MovementStatus = 'idle';

Current status.

targetIndex ​
ts
targetIndex: number = 0;

Index of the waypoint currently being steered toward.

Methods ​

abort() ​
ts
abort(): void;

Unreal's StopMovement — halt and clear the path.

Returns ​

void

configure() ​
ts
configure(patch): void;

Patch the tuning.

Parameters ​
ParameterTypeDescription
patchPartial<MovementConfig>Fields to change.
Returns ​

void

moveToActor() ​
ts
moveToActor(target, acceptanceRadius?): boolean;

Unreal's MoveToActor: follows a possibly-moving target.

Parameters ​
ParameterTypeDescription
targetMovementTargetThe target.
acceptanceRadius?numberOverride for this move, in metres.
Returns ​

boolean

Whether a path was found.

moveToLocation() ​
ts
moveToLocation(point, acceptanceRadius?): boolean;

Unreal's MoveToLocation.

Parameters ​
ParameterTypeDescription
pointVec3The destination.
acceptanceRadius?numberOverride for this move, in metres.
Returns ​

boolean

Whether a path was found.

moveToRandomPoint() ​
ts
moveToRandomPoint(
   center, 
   radius, 
   rng?
): boolean;

Unreal's MoveToRandomPoint.

Parameters ​
ParameterTypeDescription
centerVec3Search centre.
radiusnumberSearch radius in metres.
rng?() => numberUniform [0, 1) source.
Returns ​

boolean

Whether a path was found.

reset() ​
ts
reset(): void;

Clear the path and go idle.

Returns ​

void

setEventSink() ​
ts
setEventSink(fn): void;

Set the event sink.

Parameters ​
ParameterTypeDescription
fnMovementEventSink | nullThe sink, or null.
Returns ​

void

setGroup() ​
ts
setGroup(g): void;

Set the transform to drive.

Parameters ​
ParameterTypeDescription
gMovementGroupLike | nullThe transform, or null.
Returns ​

void

setNavMesh() ​
ts
setNavMesh(nm): void;

Set the navmesh.

Parameters ​
ParameterTypeDescription
nmNavMeshLike | nullThe navmesh, or null.
Returns ​

void

tick() ​
ts
tick(dt): void;

Advance one frame.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last tick.
Returns ​

void

Interfaces ​

AddClipOptions ​

How a clip behaves once registered.

Properties ​

additive? ​
ts
optional additive?: boolean;

Register the clip on the additive/gesture layer instead of the base layer. Additive actions are never stopped by the base layer's weight pass.

loop? ​
ts
optional loop?: boolean;

Whether the clip loops; defaults to true.


AdditiveBakeContext ​

What bakeAdditive needs besides the clip itself.

Properties ​

boneParents? ​
ts
optional boneParents?: ReadonlyMap<string, string>;

Child node name to parent node name, required by mesh-space baking.

clipsByName ​
ts
clipsByName: ReadonlyMap<string, AnimationClip>;

Every loaded clip by name, for the anim_frame and anim_scaled modes.

fps? ​
ts
optional fps?: number;

Sample rate the Ref Frame Index is interpreted against; defaults to 30.

restPose? ​
ts
optional restPose?: RestPose;

Rest pose, required by ref_pose and by mesh-space baking.


AdditiveSettings ​

The additive settings as authored, all optional.

Properties ​

additiveType? ​
ts
optional additiveType?: AdditiveType;

Unreal's Additive Anim Type.

basePoseClipName? ​
ts
optional basePoseClipName?: string | null;

Clip name the base pose is taken from, for anim_frame and anim_scaled.

basePoseType? ​
ts
optional basePoseType?: BasePoseType;

Unreal's Base Pose Type.

refFrameIndex? ​
ts
optional refFrameIndex?: number;

Unreal's Ref Frame Index.


Animator ​

The layered animator.

Properties ​

ts
readonly blink: BlinkRuntime | null;

The blink channel, or null when blink is disabled.

bodyPose ​
ts
readonly bodyPose: BodyPose;

The final skeleton pose, including the procedural overrides. Reused per frame.

boneNames ​
ts
readonly boneNames: readonly string[];

Bone names, in the order BodyPose.bones uses.

expression ​
ts
readonly expression: Float32Array;

The expression vector in the bundle's space. Reused per frame.

face ​
ts
readonly face: FaceClipPlayer;

The face-clip blender.

gaze ​
ts
readonly gaze: Float32Array;

Eye gaze as [pitchL, yawL, pitchR, yawR] in radians. Reused per frame.

gesture ​
ts
readonly gesture: GestureChannel;

The additive gesture layer.

jointOverrides ​
ts
readonly jointOverrides: ReadonlyMap<string, Float32Array<ArrayBufferLike>>;

Procedural joint rotations, by bone name.

Each entry is a PARENT-LOCAL delta rotation (xyzw) that PRE-multiplies the bone's animated local rotation. Animator.bodyPose already has them applied; this map is for rig backends that take joint overrides separately and must not have them applied twice.

variables ​
ts
readonly variables: Map<string, unknown>;

Blueprint variables the body graph reads.

Methods ​

addClip() ​
ts
addClip(
   name, 
   clip, 
   options?
): void;

Register a body clip.

Parameters ​
ParameterTypeDescription
namestringRuntime name; how state.clips and the graph address it.
clipAnimationClipThe clip, already bound to this rig's bone names.
options?AddClipOptionsSee AddClipOptions.
Returns ​

void

addFaceClip() ​
ts
addFaceClip(name, clip): void;

Register a face clip.

Parameters ​
ParameterTypeDescription
namestringRuntime name.
clipFaceClipDataARKit-52 frames; see FaceClipData.
Returns ​

void

dispose() ​
ts
dispose(): void;

Release the mixer, the actions and the clip caches.

Returns ​

void

setGraph() ​
ts
setGraph(graph): void;

Set (or clear) the body graph.

The graph is treated as IMMUTABLE from here on. Its node/edge indices, its narrowed inner lists and every transition edge's rule graph are memoised on the identity of the authored objects, so the per-frame path can allocate nothing; editing a node array in place afterwards will not be seen. To change a graph, build a new graph object and call this again — swapping is free, and the caches are WeakMaps, so the old graph's entries go with it.

Parameters ​
ParameterTypeDescription
graphBodyGraph | nullThe graph, or null to fall back to state.clips / locomotion.
Returns ​

void

setLocomotion() ​
ts
setLocomotion(index): void;

Set the locomotion index used by the velocity fallback.

Parameters ​
ParameterTypeDescription
indexLocomotionIndex | nullThe index, or null to disable the fallback.
Returns ​

void

setState() ​
ts
setState(state): void;

Set the character state for the coming frames.

Parameters ​
ParameterTypeDescription
stateCharacterStateThe state; validate untrusted input with validateCharacterState.
Returns ​

void

update() ​
ts
update(dt, context?): void;

Advance every layer by dt.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last update.
context?AnimatorUpdateContextSee AnimatorUpdateContext.
Returns ​

void


AnimatorOptions ​

Options for createAnimator.

Properties ​

ts
optional blink?: false | Partial<BlinkConfig>;

Blink tuning overrides, or false to disable the blink layer.

bones? ​
ts
optional bones?: SkeletonNames;

What this rig calls its root and head bones.

clock? ​
ts
optional clock?: Clock;

Millisecond clock for the gesture, face and blink envelopes.

Defaults to the animator's OWN accumulated dt: every update(dt) adds dt * 1000 to it, so pausing the engine pauses blinks and gestures, timeScale slows them, and a replay at a fixed dt reproduces them exactly. Pass defaultClock from this package to opt back into wall clock (performance.now()) — appropriate only for an animator driven outside the engine loop.

expressionSpace ​
ts
expressionSpace: ExpressionSpace;

The bundle's expression space.

headAim? ​
ts
optional headAim?: Partial<HeadAimConfig>;

Head-aim tuning overrides.

locomotion? ​
ts
optional locomotion?: LocomotionIndex;

Locomotion clips, for the velocity-driven fallback.

random? ​
ts
optional random?: () => number;

Uniform [0, 1) source for blink scheduling and graph randoms.

Returns ​

number

root ​
ts
root: Object3D;

The skinned rig root. Its skeleton defines the bone order of BodyPose.


AnimatorUpdateContext ​

What update needs from the rest of the frame.

Properties ​

bodyYaw? ​
ts
optional bodyYaw?: number;

The character's own facing, in radians about +Y, for the head-aim clamp.

Without it the clamp reads root.rotation.y, which is right only when the rig root itself carries the facing. A skinned body parented under the entity's object inherits its yaw instead, and the root stays at zero — so the host passes the entity's world yaw here.

camera? ​
ts
optional camera?: Object3D<Object3DEventMap> | null;

Camera to look at when the state names no explicit lookAt.

lookAt? ​
ts
optional lookAt?: readonly [number, number, number] | null;

World point to look at; overrides both the state's lookAt and the camera.


BlinkConfig ​

Blink scheduler and envelope shape.

Properties ​

closeMs ​
ts
closeMs: number;

Lid close ramp, in milliseconds.

holdMs ​
ts
holdMs: number;

Fully-closed hold, in milliseconds.

maxInterval ​
ts
maxInterval: number;

Longest gap between blinks, in seconds.

minInterval ​
ts
minInterval: number;

Shortest gap between blinks, in seconds.

openMs ​
ts
openMs: number;

Lid open ramp, in milliseconds.


BlinkRuntime ​

A live procedural-blink channel.

Properties ​

config ​
ts
readonly config: Readonly<BlinkConfig>;

The timings currently in force.

Methods ​

applyToArkit() ​
ts
applyToArkit(out, gate?): number;

Advance the scheduler and add the blink onto an ARKit-52 weight vector.

Parameters ​
ParameterTypeDescription
outFloat32ArrayARKit-52 weight vector, written in place and clamped to 1.
gate?numberSentinel weight from the caller; 0 disables the channel.
Returns ​

number

The blink weight that was applied.

currentWeight() ​
ts
currentWeight(gate?): number;

The current blink weight, advancing the scheduler.

Call at most once per frame — it advances blink timing.

Parameters ​
ParameterTypeDescription
gate?numberSentinel weight from the caller; 0 disables the channel.
Returns ​

number

The envelope value times gate, in [0, 1].

reset() ​
ts
reset(): void;

Clear the in-flight blink and reschedule; used when a character is swapped.

Returns ​

void

setConfig() ​
ts
setConfig(patch): void;

Replace the timings.

Last-writer-wins, and a PARTIAL patch falls back to the defaults for the fields it omits rather than to the previous write — the graph node that drives this re-sends its whole node data every frame, so "keep the previous value" would make a field that was cleared in the editor stick forever.

Parameters ​
ParameterTypeDescription
patchPartial<BlinkConfig>Fields to set; omitted fields revert to BLINK_DEFAULTS.
Returns ​

void


BlinkRuntimeOptions ​

Options for createBlinkRuntime.

Properties ​

config? ​
ts
optional config?: Partial<BlinkConfig>;

Initial timings; omitted fields take their BLINK_DEFAULTS value.

now? ​
ts
optional now?: Clock;

Millisecond clock; defaults to defaultClock.

random? ​
ts
optional random?: () => number;

Uniform [0, 1) source for the inter-blink delay; defaults to Math.random.

Returns ​

number


BodyGraph ​

A body graph: the finalPose node plus everything feeding it.

Properties ​

edges ​
ts
edges: readonly GraphEdge[];

Edges, in no particular order.

nodes ​
ts
nodes: readonly GraphNode[];

Nodes, in no particular order.


BodyMotionTracks ​

A generated motion payload: per-frame bone quaternions plus a world root track.

Properties ​

bones ​
ts
bones: Readonly<Record<string, ArrayLike<number>>>;

Bone name to a flat xyzw stream, four floats per frame.

fps? ​
ts
optional fps?: number;

Sample rate; defaults to 30.

frames? ​
ts
optional frames?: number;

Frame count; inferred from the first bone track when omitted.

root? ​
ts
optional root?: ArrayLike<number>;

Flat world-metre xyz root stream, three floats per frame.


BodyPose ​

The final skeleton pose for this frame.

Properties ​

bones ​
ts
bones: Float32Array;

Per-bone local rotations, xyzw, in skeleton order.

rootPos ​
ts
rootPos: Float32Array;

The root bone's local position.


BuildBodyMotionClipOptions ​

Options for buildBodyMotionClip.

Properties ​

name? ​
ts
optional name?: string;

Clip name; defaults to generated_motion.

onMissingBone? ​
ts
optional onMissingBone?: (boneName) => void;

Called once per bone name that is absent from the rig, instead of the POC's console.warn. Omit to ignore missing bones silently.

Parameters ​
ParameterType
boneNamestring
Returns ​

void

root ​
ts
root: Object3D;

The rig root the clip binds to. Replaces the POC's window.__AVATAR_SCENE__.

rootMode? ​
ts
optional rootMode?: RootMode;

See RootMode; defaults to travel.


CharacterClipRequest ​

A clip the guest is driving explicitly, bypassing the locomotion blend.

Properties ​

name ​
ts
name: string;

Clip name as registered with addClip or addFaceClip.

time? ​
ts
optional time?: number;

Seek to this time in seconds before the next update; omit to let it run.

weight ​
ts
weight: number;

Blend weight in [0, 1].


CharacterState ​

Everything the guest says about a character for one frame.

Properties ​

clips? ​
ts
optional clips?: readonly CharacterClipRequest[];

Explicit clip drives. When present, the locomotion blend is bypassed. Names that match a face clip drive the face layer; the rest drive the body.

expression? ​
ts
optional expression?: Float32Array<ArrayBufferLike>;

An expression vector. 52 long means ARKit-52 and is composed with blink; expressionSpace.dim long means it is already in the bundle's space and is used as-is.

grounded ​
ts
grounded: boolean;

Whether the character is on the ground.

lookAt? ​
ts
optional lookAt?: readonly [number, number, number] | null;

World-space point to look at, or null to release the head.

velocity ​
ts
velocity: readonly [number, number, number];

World-space velocity in metres per second.


ClipTiming ​

How far through a clip the mixer currently is; the input rules read.

Properties ​

duration ​
ts
duration: number;

Clip length in seconds.

ratio ​
ts
ratio: number;

time / duration, in [0, 1).

remaining ​
ts
remaining: number;

Seconds left before the clip ends.

time ​
ts
time: number;

Current time in seconds.


EvalAccumulator ​

The accumulators an evaluation writes into.

Properties ​

loop ​
ts
loop: Map<string, boolean>;

Clip name to loop flag; first writer wins.

speed ​
ts
speed: Map<string, number>;

Clip name to time scale; first writer wins.

weights ​
ts
weights: Map<string, number>;

Clip name to summed weight.


ExpressionSpace ​

Which space the bundle's expression vector is in.

Face clips are always authored in ARKit-52. A bundle whose head model is GNM wants 383 (or the reduced 68) coefficients instead, so the mapping is a BUNDLE field, not a code constant — two characters in one scene can be in different spaces.

Properties ​

dim ​
ts
dim: number;

Number of channels in Animator.expression.

kind ​
ts
kind: "arkit52" | "gnm" | "gnm68";

The space.

map? ​
ts
optional map?: (arkit, out) => void;

Convert ARKit-52 weights into this space.

Required unless kind is arkit52. Must not allocate: it runs per frame.

Parameters ​
ParameterTypeDescription
arkitFloat32Array52 ARKit weights.
outFloat32Arraydim channels, written in place.
Returns ​

void


FaceClipData ​

A face clip as authored: { fps, frames }.

Properties ​

fps? ​
ts
optional fps?: number;

Sample rate, used only to synthesise timeCode when frames omit it.

frames ​
ts
frames: readonly FaceClipFrame[];

Frames in time order.


FaceClipFrame ​

One authored frame of a face clip.

Properties ​

blendshapeWeights ​
ts
blendshapeWeights: ArrayLike<number>;

ARKit-52 weights for this frame; shorter arrays are zero-padded.

timeCode? ​
ts
optional timeCode?: number;

Seconds from the clip start. Defaults to index / fps when omitted.


FaceClipPlayer ​

A live face-clip blender.

Methods ​

addFaceClip() ​
ts
addFaceClip(name, clip): void;

Register a face clip.

Parameters ​
ParameterTypeDescription
namestringRuntime key the drive weights address it by.
clipFaceClipDataThe clip data; see FaceClipData.
Returns ​

void

aliasClip() ​
ts
aliasClip(alias, sourceName): boolean;

Point a second key at an already-registered clip — no copy.

Frame data is SHARED, unlike a body-clip alias, which has to clone because three caches one action per clip object. Face clips are read-only weight tables with no per-clip playback state on them (that lives per key), so two keys over one table is correct here and costs nothing.

Parameters ​
ParameterTypeDescription
aliasstringThe new key.
sourceNamestringThe key that already resolves.
Returns ​

boolean

Whether alias now resolves.

getBlendedWeights() ​
ts
getBlendedWeights(weights): Float32Array<ArrayBufferLike> | null;

Blend every driven clip into one ARKit-52 vector.

Parameters ​
ParameterTypeDescription
weightsReadonlyMap<string, number> | nullDrive weights by clip name; null or empty means nothing plays.
Returns ​

Float32Array<ArrayBufferLike> | null

A reused 52-element buffer, or null when nothing is driven. Do not retain it across frames — it is overwritten in place.

hasClip() ​
ts
hasClip(name): boolean;
Parameters ​
ParameterTypeDescription
namestringRuntime key.
Returns ​

boolean

Whether a clip is registered under name.

play() ​
ts
play(name): void;

Start a clip's playback clock if it is not already running.

Parameters ​
ParameterTypeDescription
namestringRuntime key.
Returns ​

void

reset() ​
ts
reset(): void;

Drop every clip and every playback cursor.

Returns ​

void

stop() ​
ts
stop(name): void;

Stop a clip, so it restarts from frame 0 next time it is driven.

Parameters ​
ParameterTypeDescription
namestringRuntime key.
Returns ​

void


FaceClipPlayerOptions ​

Options for createFaceClipPlayer.

Properties ​

now? ​
ts
optional now?: Clock;

Millisecond clock; defaults to defaultClock.


GaitCycleOptions ​

Explicit search bounds and cadence constraints; units are metres and seconds.

Properties ​

bones ​
ts
bones: readonly string[];
firstFrame ​
ts
firstFrame: number;
hipRatio ​
ts
hipRatio: number;
lastFrame ​
ts
lastFrame: number;
maximumDuration? ​
ts
optional maximumDuration?: number;
maximumPeriod ​
ts
maximumPeriod: number;
minimumDuration? ​
ts
optional minimumDuration?: number;
minimumPeriod ​
ts
minimumPeriod: number;
minimumSourceSpeed? ​
ts
optional minimumSourceSpeed?: number;
speed ​
ts
speed: number;

GeneratedMotionMarker ​

The aosGeneratedMotion extras a generated clip carries.

Present with keepRootMotion !== true → the clip opted out of root motion, so its pelvis .position is stripped too (play in place). Present with keepRootMotion === true → the authored relative-travel track is kept. Absent → pelvis .position is kept, the behaviour stock and arbitrary custom uploads have always had.

Properties ​

keepRootMotion? ​
ts
optional keepRootMotion?: boolean;

Whether the authored pelvis travel track survives the prune.


GestureActionLike ​

The subset of three's AnimationAction the gesture channel drives.

Properties ​

blendMode ​
ts
blendMode: number;

Blend mode; set to ADDITIVE_BLEND_MODE while a gesture plays.

clampWhenFinished ​
ts
clampWhenFinished: boolean;

Whether the action holds its last frame when it finishes.

loop? ​
ts
optional loop?: number;

Current loop style, if the implementation exposes one.

Methods ​

isRunning() ​
ts
isRunning(): boolean;
Returns ​

boolean

Whether the action is currently scheduled on the mixer.

play() ​
ts
play(): void;

Schedule the action on the mixer.

Returns ​

void

reset() ​
ts
reset(): unknown;

Rewind the action to its start.

Returns ​

unknown

setEffectiveWeight() ​
ts
setEffectiveWeight(weight): void;

Set the effective blend weight.

Parameters ​
ParameterTypeDescription
weightnumberWeight in [0, 1].
Returns ​

void

setLoop() ​
ts
setLoop(mode, count): void;

Set the loop style.

Parameters ​
ParameterTypeDescription
modenumberLoop style, e.g. LOOP_ONCE.
countnumberRepetition count.
Returns ​

void

stop() ​
ts
stop(): void;

Remove the action from the mixer.

Returns ​

void


GestureChannel ​

A one-slot additive gesture layer.

Methods ​

activeClip() ​
ts
activeClip(): string | null;
Returns ​

string | null

The clip name of the in-flight gesture, or null.

apply() ​
ts
apply(actions): void;

Advance the envelope and write the gesture weight onto its action.

Parameters ​
ParameterTypeDescription
actionsReadonlyMap<string, GestureActionLike>Registered actions by clip name.
Returns ​

void

isActive() ​
ts
isActive(): boolean;
Returns ​

boolean

Whether a gesture envelope is in flight.

play() ​
ts
play(clipName, options?): boolean;

Start a gesture, replacing whatever was in flight.

Parameters ​
ParameterTypeDescription
clipNamestringName the clip was registered under.
options?GestureOptionsEnvelope overrides; see GestureOptions.
Returns ​

boolean

Whether the gesture started; false when it was suppressed.

setExclusiveOverride() ​
ts
setExclusiveOverride(active): void;

Declare that an exclusive body override owns the skeleton.

A conversational override — generated locomotion, or a performance-classified generated clip — already owns the skeleton exclusively. The base layer zeroes any additive gesture weight while it is active anyway, but STARTING a new envelope under one would leave it primed to pop back in for the tail of its fade-out once the override releases. So play() is suppressed while this is set. Dev/test one-shots (a prefab Test button, a clip preview) must NOT set it, which is why this is an explicit opt-in rather than "any clip is playing".

Parameters ​
ParameterTypeDescription
activebooleanWhether an exclusive override currently owns the skeleton.
Returns ​

void

stop() ​
ts
stop(): void;

Clear the channel, leaving the action's weight alone.

The one thing it does write back is the blend mode, if this channel had converted the action to additive — otherwise a borrowed base clip would stay additive forever.

Returns ​

void


GestureChannelOptions ​

Options for createGestureChannel.

Properties ​

now? ​
ts
optional now?: Clock;

Millisecond clock; defaults to defaultClock.


GestureOptions ​

Envelope overrides for a single gesture.

Properties ​

durationMs? ​
ts
optional durationMs?: number;

Total envelope length, in milliseconds.

fadeInMs? ​
ts
optional fadeInMs?: number;

Fade-in, in milliseconds.

fadeOutMs? ​
ts
optional fadeOutMs?: number;

Fade-out, in milliseconds.

peakWeight? ​
ts
optional peakWeight?: number;

Weight held between the fades.


GraphEdge ​

One edge of a body or rule graph.

Properties ​

data? ​
ts
optional data?: Readonly<Record<string, unknown>>;

Authored payload; a transition edge carries its ruleGraph here.

id? ​
ts
optional id?: string;

Optional identity; unused by the evaluator.

source ​
ts
source: string;

Source node id.

target ​
ts
target: string;

Target node id.

targetHandle? ​
ts
optional targetHandle?: string;

Which input of the target this edge feeds, e.g. a, b, alpha-in.


GraphNode ​

One node of a body or rule graph.

Properties ​

data? ​
ts
optional data?: Readonly<Record<string, unknown>>;

Authored payload.

id ​
ts
id: string;

Unique within its (sub)graph.

type ​
ts
type: string;

Node type, e.g. playClip, blend, stateMachine, ruleCompare.


GraphRuntime ​

Everything the graph evaluator needs from the outside world.

The POC read all of this from module singletons (animVariables, smRuntime, debugState) and from Date.now(). Injecting it is what makes the evaluator testable, lets two characters share one graph, and keeps the clock consistent with the rest of the package.

Properties ​

clipTimings ​
ts
clipTimings: Map<string, ClipTiming>;

Clip timings by clip name, for the anim-time rule nodes.

now ​
ts
now: Clock;

Millisecond clock.

rand? ​
ts
optional rand?: () => number;

Uniform [0, 1) source. Absent means a deterministic 0.5, so tests are reproducible.

Returns ​

number

sm ​
ts
sm: Map<string, SMState>;

State-machine state by node id.

sticky ​
ts
sticky: Map<string, StickyRandom>;

Sticky random draws by node id.

valueCache ​
ts
valueCache: Map<string, number>;

Per-frame value cache; cleared at the start of every evaluation.

variables ​
ts
variables: Map<string, unknown>;

Blueprint variables read by getVariable and varGet.


GraphRuntimeOptions ​

Options for createGraphRuntime.

Properties ​

now ​
ts
now: () => number;

Millisecond clock.

Returns ​

number

rand? ​
ts
optional rand?: () => number;

Uniform [0, 1) source; omit for the deterministic 0.5 stand-in.

Returns ​

number

variables? ​
ts
optional variables?: Iterable<readonly [string, unknown], any, any>;

Initial blueprint variables.


HeadAimConfig ​

Head-aim tuning. All angles are radians.

Properties ​

joints ​
ts
joints: readonly readonly [string, number][];

Bone names that share the aim, and the fraction each takes.

maxEyePitch ​
ts
maxEyePitch: number;

Max additional eye pitch.

maxEyeYaw ​
ts
maxEyeYaw: number;

Max additional eye yaw, on top of the head's.

maxPitch ​
ts
maxPitch: number;

Max head pitch.

maxYaw ​
ts
maxYaw: number;

Max head yaw away from the torso.

rate ​
ts
rate: number;

Follow rate in 1/seconds.


LocomotionBlend ​

The result of a 1D blend, reused across frames so the hot path allocates nothing.

Properties ​

a ​
ts
a: string | null;

Lower-speed clip name, or null when the index is empty.

alpha ​
ts
alpha: number;

Mix from a to b, in [0, 1].

b ​
ts
b: string | null;

Higher-speed clip name; equals a outside the bracketed range.

timeScale ​
ts
timeScale: number;

Playback rate for both clips, so the stride matches the ground speed.


LocomotionClipMeta ​

One retargeted locomotion clip, as locomotion.json records it.

Properties ​

file ​
ts
file: string;

GLB file name, relative to the index.

loop ​
ts
loop: boolean;

Whether the clip loops.

name ​
ts
name: string;

Runtime clip name.

speed ​
ts
speed: number;

Authored ground speed in metres per second; 0 for idle.


LocomotionIndex ​

The locomotion.json index a retarget run emits.

Properties ​

clips ​
ts
clips: readonly LocomotionClipMeta[];

The clips, in any order; sortLocomotionClips orders them.


LocomotionTake ​

Sampled local rotations and root positions from any motion service.

Properties ​

bones ​
ts
bones: Readonly<Record<string, ArrayLike<number>>>;
fps ​
ts
fps: number;
root ​
ts
root: ArrayLike<number>;

LoopConstants ​

three's loop constants, overridable so this module needs no three import.

Properties ​

loopOnce? ​
ts
optional loopOnce?: number;

three's LoopOnce.

loopRepeat? ​
ts
optional loopRepeat?: number;

three's LoopRepeat.


MoveCompletedEvent ​

The payload of an onMoveCompleted event.

POOLED: one object per component, refilled for each event. Read it inside the sink; do not retain it, and copy the fields you need to keep.

Properties ​

reason? ​
ts
optional reason?: string;

Why it failed, when it did; undefined on a success or an abort.

result ​
ts
result: "failed" | "success" | "aborted";

How the move ended.


MovementConfig ​

Movement tuning.

Properties ​

accel ​
ts
accel: number;

Metres per second squared.

acceptanceRadius ​
ts
acceptanceRadius: number;

Metres; the move completes inside this radius of the goal.

facingOffset ​
ts
facingOffset: number;

Added to the computed yaw, for models whose forward is not +Z.

maxSpeed ​
ts
maxSpeed: number;

Metres per second; ~1.4 is a human walk.

replanThreshold ​
ts
replanThreshold: number;

Metres a followed target may drift before moveToActor re-paths.

turnRate ​
ts
turnRate: number;

Radians per second.


MovementGroupLike ​

The transform the component drives: XZ position and yaw.

Properties ​

position ​
ts
position: object;

World position. Y is owned by the floor, not by this component.

x ​
ts
x: number;
y ​
ts
y: number;
z ​
ts
z: number;
rotation ​
ts
rotation: object;

World rotation; only y is written.

y ​
ts
y: number;

MovementOptions ​

Options for createMovementComponent.

Properties ​

config? ​
ts
optional config?: Partial<MovementConfig>;

Tuning overrides.


The navmesh queries the component needs.

Properties ​

floorY ​
ts
floorY: number;

Ground height the component falls back to when it has no group.

Methods ​

findPath() ​
ts
findPath(from, to): Vec3[] | null;

Find a path between two points.

Parameters ​
ParameterTypeDescription
fromVec3Start point.
toVec3Goal point.
Returns ​

Vec3[] | null

Waypoints including the goal, or null when unreachable.

getRandomReachablePoint()? ​
ts
optional getRandomReachablePoint(
   center, 
   radius, 
   rng?
): Vec3 | null;

Pick a random reachable point.

Parameters ​
ParameterTypeDescription
centerVec3Search centre.
radiusnumberSearch radius in metres.
rng?() => numberUniform [0, 1) source.
Returns ​

Vec3 | null

A point, or null when nothing is reachable.


NodeHandlers ​

Node-type overrides by node type.

Properties ​

stateMachine? ​
ts
optional stateMachine?: NodeHandler;

Handles stateMachine nodes.


PreparedMotion ​

Prepared local quaternion tracks emitted by a motion service.

Properties ​

bones ​
ts
bones: Readonly<Record<string, readonly number[] | undefined>>;
fps ​
ts
fps: number;
frames ​
ts
frames: number;

PrunableClip ​

The minimum shape a clip needs for the prune decision.

Properties ​

tracks ​
ts
tracks: PrunableTrack[];

Tracks, replaced in place with the kept subset.


PrunableTrack ​

The minimum shape a track needs for the prune decision.

Properties ​

name ​
ts
name: string;

"<nodePath>.<property>", e.g. "Armature/pelvis.position".

times? ​
ts
optional times?: ArrayLike<number>;

Keyframe times; only the length is read, to classify active vs static.


PruneOptions ​

Options for pruneBodyClipTracks.

Properties ​

generatedMarker? ​
ts
optional generatedMarker?: GeneratedMotionMarker | null;

The clip's aosGeneratedMotion extras, or null for a non-generated clip.


PruneReport ​

What a prune did, for logging and for tests.

Properties ​

active ​
ts
active: number;

Bound tracks with more than ACTIVE_KEY_THRESHOLD keys.

bound ​
ts
bound: number;

Tracks kept, i.e. bound to a node present on the rig.

samples ​
ts
samples: string[];

Up to five node paths from the unbound set, for a readable warning.

tracks ​
ts
tracks: number;

Track count before the prune.

unbound ​
ts
unbound: number;

Tracks dropped because their node is absent from the rig.


ResolvedAdditiveSettings ​

The additive settings with every default filled in.

Properties ​

additiveType ​
ts
additiveType: "local" | "mesh";

Never none.

basePoseClipName ​
ts
basePoseClipName: string | null;

Clip name the base pose is taken from, or null.

basePoseType ​
ts
basePoseType: "ref_pose" | "anim_scaled" | "anim_frame" | "local_frame";

Never none.

refFrameIndex ​
ts
refFrameIndex: number;

Ref Frame Index, defaulting to 0.


RestFrames ​

One bone's rest orientation in both skeletons, in MODEL space.

Properties ​

dstParentRest ​
ts
dstParentRest: Quat;

Target bone's PARENT rest rotation, model space.

dstRest ​
ts
dstRest: Quat;

Target bone rest rotation, model space.

srcParentRest ​
ts
srcParentRest: Quat;

Source bone's PARENT rest rotation, model space.

srcRest ​
ts
srcRest: Quat;

Source bone rest rotation, model space.


RestPoseEntry ​

One bone's rest (bind) transform.

Properties ​

position ​
ts
position: [number, number, number];

Local position.

quaternion ​
ts
quaternion: [number, number, number, number];

Local rotation, xyzw.

scale ​
ts
scale: [number, number, number];

Local scale.


RestSkeleton ​

Parent-first rest skeleton in metres, Y-up, xyzw rotations.

Properties ​

names ​
ts
names: readonly string[];
parents ​
ts
parents: readonly number[];
rotations ​
ts
rotations: readonly readonly number[][];

RuleContext ​

What a rule graph is allowed to read.

Properties ​

clipTimings? ​
ts
optional clipTimings?: ReadonlyMap<string, ClipTiming>;

Clip timings by clip name.

currentClipName? ​
ts
optional currentClipName?: string | null;

The clip the current state is playing, which the anim-time nodes read.

variables? ​
ts
optional variables?: ReadonlyMap<string, unknown>;

Blueprint variables.


RuleGraph ​

A rule graph: a ruleResult node plus everything feeding it.

Properties ​

edges? ​
ts
optional edges?: readonly GraphEdge[];

Edges, in no particular order.

nodes ​
ts
nodes: readonly GraphNode[];

Nodes, in no particular order.


SkeletonNames ​

What this rig calls the two bones the animator addresses by name.

The defaults are the UE-style names a GNM pack uses. A skinned body exported from another authoring tool spells them differently — aosrig_v0 has root and c_head — and nothing else in the animator cares, so this is the whole translation table.

Properties ​

ts
optional head?: string;

The bone head aim measures the look direction from. Defaults to head.

root? ​
ts
optional root?: string;

The bone BodyPose.rootPos is read from. Defaults to pelvis.


SMState ​

Per-state-machine runtime state, keyed by the state-machine node's id.

Properties ​

currentState ​
ts
currentState: string | null;

Current state node id, or null before the entry transition runs.

pickedClip ​
ts
pickedClip: string | null;

The clip drawn for the current state, for legacy states with no subgraph.

stateEnteredAt ​
ts
stateEnteredAt: number;

Clock reading when the current state was entered.

transition ​
ts
transition: SMTransition | null;

The in-flight crossfade, or null.


SMTransition ​

An in-flight crossfade between two states.

Properties ​

duration ​
ts
duration: number;

Crossfade length in milliseconds.

from ​
ts
from: string;

State being left.

fromPickedClip ​
ts
fromPickedClip: string | null;

The clip the from state had drawn, so the fade-out keeps playing it.

startTime ​
ts
startTime: number;

Clock reading when the crossfade started.

to ​
ts
to: string;

State being entered.


StickyRandom ​

A sticky random draw, held until its bounds change or its state is re-entered.

Properties ​

max ​
ts
max: number;

Upper bound the draw was made against.

min ​
ts
min: number;

Lower bound the draw was made against.

randomType ​
ts
randomType: string;

float or int.

value ​
ts
value: number;

The drawn value.


WeightedActionLike ​

The subset of three's AnimationAction the base layer drives.

Properties ​

clampWhenFinished ​
ts
clampWhenFinished: boolean;

Whether the action holds its last frame when it finishes.

loop? ​
ts
optional loop?: number;

Current loop style, if the implementation exposes one.

timeScale ​
ts
timeScale: number;

Playback rate.

Methods ​

isRunning() ​
ts
isRunning(): boolean;
Returns ​

boolean

Whether the action is actively playing (not a paused final pose).

isScheduled()? ​
ts
optional isScheduled(): boolean;

Scheduled includes a paused one-shot holding its final pose.

Returns ​

boolean

play() ​
ts
play(): void;

Schedule the action on the mixer.

Returns ​

void

setEffectiveWeight() ​
ts
setEffectiveWeight(weight): void;

Set the effective blend weight.

Parameters ​
ParameterTypeDescription
weightnumberWeight in [0, 1].
Returns ​

void

setLoop() ​
ts
setLoop(mode, count): void;

Set the loop style.

Parameters ​
ParameterTypeDescription
modenumberLoop style.
countnumberRepetition count.
Returns ​

void

stop() ​
ts
stop(): void;

Remove the action from the mixer.

Returns ​

void

Type Aliases ​

AdditiveType ​

ts
type AdditiveType = "none" | "local" | "mesh";

How the additive delta is computed.


BasePoseType ​

ts
type BasePoseType = "none" | "ref_pose" | "anim_scaled" | "anim_frame" | "local_frame";

What pose counts as "zero" for the delta.


BoneNameMap ​

ts
type BoneNameMap = ReadonlyMap<string, string>;

Source bone name to target bone name.


Clock ​

ts
type Clock = () => number;

A monotonic clock reading, in milliseconds.

Implementations must be monotonic and must not be mixed within one runtime: an envelope started against one clock is always expired against the same one.

Returns ​

number


GraphNodeData ​

ts
type GraphNodeData = Readonly<Record<string, unknown>>;

A node's authored payload: arbitrary JSON.


MovementEventSink ​

ts
type MovementEventSink = (type, data) => void;

Event sink.

Parameters ​

ParameterTypeDescription
typestringEvent name; only onMoveCompleted is emitted today.
dataMoveCompletedEventEvent payload, POOLED — valid until the next event. Copy what you need to keep.

Returns ​

void


MovementStatus ​

ts
type MovementStatus = "idle" | "moving" | "arrived" | "failed";

What a move ended as.


MovementTarget ​

ts
type MovementTarget = 
  | Vec3
  | {
  position: {
     x: number;
     y: number;
     z: number;
  };
}
  | {
  getWorldPosition: {
     x: number;
     y: number;
     z: number;
  };
};

Anything moveToActor can follow.


Quat ​

ts
type Quat = readonly number[];

A quaternion as four numbers in xyzw order, matching three's memory layout.

Typed as a read-only number array rather than a 4-tuple so a scratch number[] can be fed straight back in without a cast; every function here reads exactly four components.


RestPose ​

ts
type RestPose = Map<string, RestPoseEntry>;

Rest transforms by node name.


RootMode ​

ts
type RootMode = "travel" | "lock";

How the pelvis translation is handled.

travel builds the pelvis position track so the clip locomotes — walk and jump leave the ground. lock skips it so the motion plays IN PLACE, which is the shape a gesture wants: the pelvis stays at rest and the clip can layer additively over the base pose without dragging the body across the floor. Bone rotations are identical either way.


Vec3 ​

ts
type Vec3 = readonly [number, number, number];

A world-space point.

Variables ​

ACTIVE_KEY_THRESHOLD ​

ts
const ACTIVE_KEY_THRESHOLD: 10 = 10;

Above this many keys a bound track counts as animated rather than a static pose.


ADDITIVE_BLEND_MODE ​

ts
const ADDITIVE_BLEND_MODE: 2501 = 2501;

three's AdditiveAnimationBlendMode, as a number.

Kept numeric rather than imported so this module stays three-free and can be unit-tested against fake actions. The value is pinned by three's public enum.


ARKIT_COUNT ​

ts
const ARKIT_COUNT: 52 = 52;

How many ARKit channels there are; the width of every ARKit weight vector.


ts
const ARKIT_EYE_BLINK_LEFT: 0 = 0;

Index of EyeBlinkLeft, the left half of the procedural blink overlay.


ts
const ARKIT_EYE_BLINK_RIGHT: 7 = 7;

Index of EyeBlinkRight, the right half of the procedural blink overlay.


ARKIT_NAMES ​

ts
const ARKIT_NAMES: readonly ["EyeBlinkLeft", "EyeLookDownLeft", "EyeLookInLeft", "EyeLookOutLeft", "EyeLookUpLeft", "EyeSquintLeft", "EyeWideLeft", "EyeBlinkRight", "EyeLookDownRight", "EyeLookInRight", "EyeLookOutRight", "EyeLookUpRight", "EyeSquintRight", "EyeWideRight", "JawForward", "JawLeft", "JawRight", "JawOpen", "MouthClose", "MouthFunnel", "MouthPucker", "MouthLeft", "MouthRight", "MouthSmileLeft", "MouthSmileRight", "MouthFrownLeft", "MouthFrownRight", "MouthDimpleLeft", "MouthDimpleRight", "MouthStretchLeft", "MouthStretchRight", "MouthRollLower", "MouthRollUpper", "MouthShrugLower", "MouthShrugUpper", "MouthPressLeft", "MouthPressRight", "MouthLowerDownLeft", "MouthLowerDownRight", "MouthUpperUpLeft", "MouthUpperUpRight", "BrowDownLeft", "BrowDownRight", "BrowInnerUp", "BrowOuterUpLeft", "BrowOuterUpRight", "CheekPuff", "CheekSquintLeft", "CheekSquintRight", "NoseSneerLeft", "NoseSneerRight", "TongueOut"];

The 52 ARKit blendshape channel names, in wire order.


ts
const BLINK_DEFAULTS: Readonly<BlinkConfig>;

The Unreal DynamicBlinkSM timings the POC shipped with.


defaultClock ​

ts
const defaultClock: Clock;

The default clock: performance.now(), monotonic and sub-millisecond.

Returns ​

Milliseconds since the time origin.


HEAD_AIM_DEFAULTS ​

ts
const HEAD_AIM_DEFAULTS: Readonly<HeadAimConfig>;

The default head-aim tuning: 45 degrees of yaw over neck_01, neck_02 and head.


IDENTITY_QUAT ​

ts
const IDENTITY_QUAT: Quat;

The identity rotation.


IDLE_CHARACTER_STATE ​

ts
const IDLE_CHARACTER_STATE: CharacterState;

A state with nothing driven: standing still, on the ground, looking nowhere.


LOOP_ONCE ​

ts
const LOOP_ONCE: 2200 = 2200;

three's LoopOnce, as a number, for the same reason.


PACKAGE ​

ts
const PACKAGE: "@aosengine/animation";

Package identity marker for @aosengine/animation.

Example ​

ts
import { PACKAGE } from '@aosengine/animation';

console.log(PACKAGE); // '@aosengine/animation'

SM_TRANSITION_MS ​

ts
const SM_TRANSITION_MS: 300 = 300;

The crossfade length the POC hard-coded in smRuntime, in milliseconds.

Functions ​

applyWeights() ​

ts
function applyWeights(
   weights, 
   loop, 
   speed, 
   actions, 
   constants?
): void;

Apply evaluated weights to a set of mixer actions.

Every action absent from weights, or at weight <= 0, is stopped (or zeroed if it was not running). Present actions get their loop style, clamp flag and time scale written ONLY when they change — the steady-state optimisation the POC's GraphEvaluator carried, because setLoop on a running action resets its loop counter and a per-frame write made long non-looping clips restart.

Parameters ​

ParameterTypeDescription
weightsReadonlyMap<string, number> | nullClip name to weight, or null to stop everything.
loopReadonlyMap<string, boolean> | nullClip name to loop flag; a missing entry means "loop".
speedReadonlyMap<string, number> | nullClip name to time scale; a missing entry means 1.
actionsReadonlyMap<string, WeightedActionLike>Registered actions by clip name.
constantsLoopConstantsthree's loop constants; defaults match three r186.

Returns ​

void


approachAngle() ​

ts
function approachAngle(
   current, 
   target, 
   rate, 
   dt
): number;

Move current toward target along the shortest arc, framerate-corrected.

Exponential follow rather than a naive lerp: e^(-rate·2dt) is exactly (e^(-rate·dt))², so one 1/30 s step and two 1/60 s steps land in the same place. A dt-naive lerp drifts with the frame rate, which showed up as the head tracking visibly faster on a fast machine.

Parameters ​

ParameterTypeDescription
currentnumberCurrent angle in radians.
targetnumberTarget angle in radians.
ratenumberFollow rate in 1/seconds; larger is snappier.
dtnumberDelta time in seconds.

Returns ​

number

The new angle, wrapped into (-π, π].


arkitIndex() ​

ts
function arkitIndex(name): number;

Index of an ARKit channel by name, or -1 when the name is not an ARKit one.

Parameters ​

ParameterTypeDescription
namestringChannel name, case-sensitive, as it appears in ARKIT_NAMES.

Returns ​

number

The channel index in [0, 52), or -1.


bakeAdditive() ​

ts
function bakeAdditive(
   clip, 
   settings, 
   ctx
): void;

Bake clip into an additive delta IN PLACE, per the resolved settings.

Parameters ​

ParameterTypeDescription
clipAnimationClipThe clip, mutated in place.
settingsAdditiveSettings | nullThe authored additive settings, or null for the historical local-space / own-frame-0 default.
ctxAdditiveBakeContextWhat the bake may read; see AdditiveBakeContext.

Returns ​

void


blendLocomotion() ​

ts
function blendLocomotion(
   sorted, 
   speed, 
   out
): LocomotionBlend;

Pick and mix the two clips bracketing speed.

Below the slowest clip and above the fastest one the blend clamps to that clip — an idle at speed 0 and a run at 4 m/s bound the space — and only the time scale keeps changing.

Parameters ​

ParameterTypeDescription
sortedreadonly LocomotionClipMeta[]Clips ordered by ascending speed, from sortLocomotionClips.
speednumberPlanar ground speed in metres per second.
outLocomotionBlendResult written in place, from createLocomotionBlend.

Returns ​

LocomotionBlend

out.


boneMapFromJson() ​

ts
function boneMapFromJson(table): BoneNameMap;

Turn a JSON { source: target } table into a BoneNameMap.

Parameters ​

ParameterTypeDescription
tableunknownParsed mixamo_to_mh.json.

Returns ​

BoneNameMap

The map.

Throws ​

When an entry is not a string-to-string pair.


buildBodyMotionClip() ​

ts
function buildBodyMotionClip(tracks, options): AnimationClip;

Build an AnimationClip bound to a live rig from a generated tracks payload.

Parameters ​

ParameterTypeDescription
tracksBodyMotionTracksThe payload; see BodyMotionTracks.
optionsBuildBodyMotionClipOptionsSee BuildBodyMotionClipOptions.

Returns ​

AnimationClip

The clip, ready for mixer.clipAction.

Throws ​

When the payload is empty or no bone in it exists on the rig.


buildBoneParents() ​

ts
function buildBoneParents(root): Map<string, string>;

Build a child -> parent node-name map from the rig hierarchy.

Parameters ​

ParameterTypeDescription
rootObject3DThe rig root.

Returns ​

Map<string, string>

Child node name to parent node name.


buildRestPose() ​

ts
function buildRestPose(root): RestPose;

Read the rig's rest (bind) pose straight off the loaded rig root.

At load time — before the mixer plays anything — every bone sits at its rest local transform, which is exactly Unreal's "Skeleton Reference Pose".

Parameters ​

ParameterTypeDescription
rootObject3DThe rig root, freshly loaded and not yet posed.

Returns ​

RestPose

Rest transforms by node name.


clampPitch() ​

ts
function clampPitch(rawPitch, maxPitch): number;

Clamp a pitch to [-maxPitch, maxPitch] after wrapping it.

Pitch has no body-relative frame to fight over — the torso does not pitch in locomotion — so this is the plain symmetric clamp the yaw path cannot use.

Parameters ​

ParameterTypeDescription
rawPitchnumberDesired look pitch in radians; positive looks up.
maxPitchnumberMax head pitch (radians, >= 0).

Returns ​

number

The clamped pitch.


clampYawToBody() ​

ts
function clampYawToBody(
   rawYaw, 
   bodyYaw, 
   maxYaw
): number;

Clamp the desired world yaw to within ±maxYaw of the body's forward yaw, and return the result RELATIVE to the body (so the caller can smooth it and then re-add bodyYaw to get the world-space look direction).

Parameters ​

ParameterTypeDescription
rawYawnumberDesired look yaw in world space (radians; 0 = +Z).
bodyYawnumberBody forward yaw in world space (radians).
maxYawnumberMax head deviation from the body (radians, >= 0).

Returns ​

number

Clamped yaw relative to the body forward, in [-maxYaw, maxYaw].


closePositionLoop() ​

ts
function closePositionLoop(values, blendFrames?): void;

Close a packed xyz root-position track without flattening the whole stride.

Parameters ​

ParameterTypeDefault valueDescription
valuesFloat32ArrayundefinedPacked positions, mutated in place.
blendFramesnumber6Tail samples to correct, at least two.

Returns ​

void

Nothing.

Example ​

ts
closePositionLoop(rootPositions);

closeQuaternionLoop() ​

ts
function closeQuaternionLoop(values, blendFrames?): void;

Distribute quaternion seam error over the last samples, in place; q and -q are equivalent.

Parameters ​

ParameterTypeDefault valueDescription
valuesFloat32ArrayundefinedPacked xyzw samples; must contain unit rotations.
blendFramesnumber6Tail samples to correct (at least two); clamped to track length.

Returns ​

void

Nothing.

Example ​

ts
closeQuaternionLoop(rotations, 6);

computeRootDelta() ​

ts
function computeRootDelta(tracks?): [number, number] | null;

Compute the [dx, dz] world-metre XZ root travel — frame-last minus frame-0 — from a generated tracks payload's root stream.

This is the root-motion commit: when a travelling clip finishes, the character must be MOVED by this delta so the resuming base pose continues from the destination instead of snapping back to where the clip started. Y is dropped because the floor owns it.

Parameters ​

ParameterTypeDescription
tracks?| Pick<BodyMotionTracks, "root" | "frames"> | nullA payload, or any object carrying root and frames.

Returns ​

[number, number] | null

[dx, dz], or null with fewer than two frames (nothing to commit).


createAnimator() ​

ts
function createAnimator(options): Animator;

Create a layered animator.

Parameters ​

ParameterTypeDescription
optionsAnimatorOptionsSee AnimatorOptions.

Returns ​

Animator

The Animator.


createBlinkRuntime() ​

ts
function createBlinkRuntime(options?): BlinkRuntime;

Create a procedural blink channel.

Parameters ​

ParameterTypeDescription
optionsBlinkRuntimeOptionsSee BlinkRuntimeOptions.

Returns ​

BlinkRuntime

A BlinkRuntime owning its own phase and scheduler.


createEvalAccumulator() ​

ts
function createEvalAccumulator(): EvalAccumulator;

Create the accumulators an evaluation writes into.

Returns ​

EvalAccumulator

Empty accumulators, ready to be reused every frame.


createFaceClipPlayer() ​

ts
function createFaceClipPlayer(options?): FaceClipPlayer;

Create a face-clip blender.

Parameters ​

ParameterTypeDescription
optionsFaceClipPlayerOptionsSee FaceClipPlayerOptions.

Returns ​

FaceClipPlayer

A FaceClipPlayer.


createGestureChannel() ​

ts
function createGestureChannel(options?): GestureChannel;

Create a one-slot additive gesture channel.

Parameters ​

ParameterTypeDescription
optionsGestureChannelOptionsSee GestureChannelOptions.

Returns ​

GestureChannel

A GestureChannel.


createGraphRuntime() ​

ts
function createGraphRuntime(options): GraphRuntime;

Create the runtime context the evaluator reads and mutates.

Parameters ​

ParameterTypeDescription
optionsGraphRuntimeOptionsSee GraphRuntimeOptions.

Returns ​

GraphRuntime

A fresh GraphRuntime.


createLocomotionBlend() ​

ts
function createLocomotionBlend(): LocomotionBlend;

Create an empty blend result to reuse every frame.

Returns ​

LocomotionBlend

A zeroed LocomotionBlend.


createMovementComponent() ​

ts
function createMovementComponent(options?): MovementComponent;

Create a movement component.

Parameters ​

ParameterTypeDescription
optionsMovementOptionsSee MovementOptions.

Returns ​

MovementComponent

A fresh MovementComponent; there is no shared singleton.


createSMHandler() ​

ts
function createSMHandler(): NodeHandler;

The stateMachine node handler, for injection into the dispatcher.

Returns ​

NodeHandler

A handler that drives transitions then evaluates the current state, in that order — the same frame order the POC's updateSMTransitions before evaluateGraph produced.


createSMState() ​

ts
function createSMState(): SMState;

Create a fresh per-state-machine state object.

Returns ​

SMState

State stored in rt.sm and mutated in place each frame.


edgeList() ​

ts
function edgeList(data, key): readonly GraphEdge[];

Read a nested edge list, e.g. a state machine's innerEdges.

Memoised exactly as nodeList is, and under the same "graph JSON is immutable after load" contract.

Parameters ​

ParameterTypeDescription
dataReadonly<Record<string, unknown>> | undefinedAuthored payload, possibly undefined.
keystringField name.

Returns ​

readonly GraphEdge[]

The edges, or EMPTY_EDGES when the field is absent or malformed. The array is shared; never mutate it.


evaluateBody() ​

ts
function evaluateBody(
   graph, 
   rt, 
   out?, 
   handlers?
): EvalAccumulator;

Evaluate a body graph for one frame.

Parameters ​

ParameterTypeDefault valueDescription
graphBodyGraphundefinedThe graph. Its finalPose node is the root; the first edge into it is the pose that is evaluated. Treated as IMMUTABLE: its index is memoised on its identity, so an in-place edit is not re-read. Pass a new graph object to change the graph.
rtGraphRuntimeundefinedRuntime context; valueCache is cleared here, because one call is one logical frame and stale cache entries would freeze a wired alpha.
outEvalAccumulator...Accumulators to fill. Cleared first. Omit to allocate fresh ones.
handlersNodeHandlersDEFAULT_HANDLERSNode-type overrides; defaults to the built-in state machine.

Returns ​

EvalAccumulator

out, or the freshly allocated accumulators.


evaluateRule() ​

ts
function evaluateRule(graph, ctx?): boolean;

Evaluate a rule graph to a boolean.

The graph's indices are memoised on its identity, so a rule graph is treated as IMMUTABLE once evaluated — the same contract the body graph carries.

Parameters ​

ParameterTypeDescription
graphRuleGraphThe rule graph.
ctxRuleContextWhat the graph may read; see RuleContext.

Returns ​

boolean

Whether the rule fired.


hipHeightRatio() ​

ts
function hipHeightRatio(srcHipHeight, dstHipHeight): number;

Hip-height ratio between two rigs.

Parameters ​

ParameterTypeDescription
srcHipHeightnumberSource pelvis height above the floor, in metres.
dstHipHeightnumberTarget pelvis height above the floor, in metres.

Returns ​

number

The ratio, or 1 when either height is missing or zero.


isTrue() ​

ts
function isTrue(data, key): boolean;

Read a boolean field with strict === true semantics.

Parameters ​

ParameterTypeDescription
dataReadonly<Record<string, unknown>> | undefinedAuthored payload, possibly undefined.
keystringField name.

Returns ​

boolean

Whether the field is exactly true.


mapTrackName() ​

ts
function mapTrackName(trackName, boneMap): string | null;

Map a track name from the source naming convention to the target's.

A track name is "<node>.<property>"; only the node half is mapped.

Parameters ​

ParameterTypeDescription
trackNamestringSource track name, e.g. mixamorig:LeftArm.quaternion.
boneMapBoneNameMapSource bone name to target bone name.

Returns ​

string | null

The mapped track name, or null when the bone has no target.


nodeList() ​

ts
function nodeList(data, key): readonly GraphNode[];

Read a nested node list, e.g. a state machine's innerNodes.

Memoised on the identity of data. The narrowed array is built once per (data, key) pair and the same array is returned forever after, because the state machine asks for innerNodes five to eight times per frame and a fresh filter each time is per-frame garbage (AGENTS hard rule 2). The contract this buys is that graph JSON is immutable after load: mutate an authored node array in place and the evaluator will not see it. Swap the whole graph object instead — that is what Animator.setGraph is for.

Parameters ​

ParameterTypeDescription
dataReadonly<Record<string, unknown>> | undefinedAuthored payload, possibly undefined.
keystringField name.

Returns ​

readonly GraphNode[]

The nodes, or EMPTY_NODES when the field is absent or malformed. The array is shared; never mutate it.


normalizeAngle() ​

ts
function normalizeAngle(angle): number;

Wrap an angle into (-π, π].

Parameters ​

ParameterTypeDescription
anglenumberAngle in radians.

Returns ​

number

The equivalent angle in (-π, π].


numField() ​

ts
function numField(
   data, 
   key, 
   fallback
): number;

Read a numeric field, falling back when it is absent or not finite.

Parameters ​

ParameterTypeDescription
dataReadonly<Record<string, unknown>> | undefinedAuthored payload, possibly undefined.
keystringField name.
fallbacknumberValue used when the field is missing or not a finite number.

Returns ​

number

The field as a number.


pitchTo() ​

ts
function pitchTo(
   dx, 
   dy, 
   dz
): number;

World-space pitch of the direction (dx, dy, dz); positive looks up.

Parameters ​

ParameterTypeDescription
dxnumberWorld-space X offset from the head to the look target.
dynumberWorld-space Y offset from the head to the look target.
dznumberWorld-space Z offset from the head to the look target.

Returns ​

number

The pitch in radians.


planarSpeed() ​

ts
function planarSpeed(state): number;

Planar (XZ) speed of a state's velocity.

Y is excluded on purpose: a character falling at 9 m/s is not running, and feeding the fall into the locomotion blend makes the legs sprint mid-air.

Parameters ​

ParameterTypeDescription
stateCharacterStateThe character state.

Returns ​

number

Ground speed in metres per second.


pruneBodyClipTracks() ​

ts
function pruneBodyClipTracks(
   clip, 
   sceneNodes, 
   options?
): PruneReport;

Drop every track of clip that cannot (or should not) bind to sceneNodes.

pelvis.scale is always stripped — it is the rig's metres/centimetres scale defence, and a stationary avatar never needs it. pelvis.position is kept by default; a generated motion that opted OUT of root motion strips it too so the clip plays in place.

Parameters ​

ParameterTypeDescription
clipPrunableClipClip whose tracks array is replaced in place with the kept subset.
sceneNodesReadonlySet<string>Leaf node names present on the rig.
optionsPruneOptionsPrune options; see PruneOptions.

Returns ​

PruneReport

A PruneReport describing what was kept and dropped.


quatInvert() ​

ts
function quatInvert(q): Quat;

Conjugate of a unit quaternion, i.e. its inverse.

Parameters ​

ParameterTypeDescription
qQuatThe quaternion; assumed normalised, as every rest rotation is.

Returns ​

Quat

A new quaternion.


quatMultiply() ​

ts
function quatMultiply(
   a, 
   b, 
   out
): number[];

Hamilton product a * b.

Parameters ​

ParameterTypeDescription
aQuatLeft quaternion.
bQuatRight quaternion.
outnumber[]Four-element output, written in place.

Returns ​

number[]

out.


rebindLocalRotation() ​

ts
function rebindLocalRotation(
   qSource, 
   frames, 
   out
): number[];

Rebind one local rotation from the source rest frame into the target's.

The formula, in model space:

text
q_target_local = inv(P_dst) * P_src * q_source_local * inv(R_src) * R_dst

where R is a bone's rest rotation and P its parent's, both in model space. It has the two properties that make a retarget correct:

  • identical skeletons are a no-op — inv(P)·P·q·inv(R)·R = q;
  • a source pose AT REST maps to the TARGET's rest pose, whatever the two rest poses are, so a retargeted clip starts from the target's own bind pose rather than injecting the source rig's A-pose/T-pose difference as a constant offset into every frame.

The second property is the whole point: skipping it is why naively renamed Mixamo clips leave a character with permanently drooping shoulders.

Parameters ​

ParameterTypeDescription
qSourceQuatLocal rotation from the source clip.
framesRestFramesRest orientations of the bone in both skeletons.
outnumber[]Four-element output, written in place.

Returns ​

number[]

out.


rebindQuaternionTrack() ​

ts
function rebindQuaternionTrack(values, frames): Float32Array<ArrayBufferLike> | number[];

Rebind a whole quaternion keyframe track in place.

Parameters ​

ParameterTypeDescription
valuesFloat32Array<ArrayBufferLike> | number[]Flat xyzw stream, four floats per key; rewritten in place.
framesRestFramesRest orientations of the bone in both skeletons.

Returns ​

Float32Array<ArrayBufferLike> | number[]

values, for chaining.


resolveAdditiveSettings() ​

ts
function resolveAdditiveSettings(settings?): ResolvedAdditiveSettings;

Resolve a possibly-missing or partial settings object into a concrete spec.

Clips that are additive but carry no explicit config fall back to the historical behaviour: local space, referenced against frame 0 of themselves, i.e. a bare makeClipAdditive(clip) call.

Parameters ​

ParameterTypeDescription
settings?AdditiveSettings | nullThe authored settings, or null.

Returns ​

ResolvedAdditiveSettings

The resolved spec.


retargetStationaryGesture() ​

ts
function retargetStationaryGesture(
   name, 
   motion, 
   source, 
   target, 
   boneMap
): AnimationClip;

Retarget selected joints into additive bind-relative rotations. Translation is deliberately excluded: stationary interviews keep their base pose's feet. The explicit bone map should contain upper-body joints only.

Parameters ​

ParameterTypeDescription
namestringClip/gesture id.
motionPreparedMotionSource local quaternion samples.
sourceRestSkeletonSource rest skeleton, including unanimated ancestors.
targetRestSkeletonTarget rest skeleton, including unanimated ancestors.
boneMapReadonly<Record<string, string>>Source-to-target upper-body joint names.

Returns ​

AnimationClip

Additive clip; register with additive true and loop false.


scalePositionTrack() ​

ts
function scalePositionTrack(values, ratio): Float32Array<ArrayBufferLike> | number[];

Scale a position track by the hip-height ratio between the two rigs.

Root translation is the one track that does not survive a pure rotation rebind: a 1.9 m source actor's pelvis travels further per stride than a 1.6 m target's, so the target would skate. Scaling by dstHipHeight / srcHipHeight makes the stride proportional to the legs that take it.

Parameters ​

ParameterTypeDescription
valuesFloat32Array<ArrayBufferLike> | number[]Flat xyz stream, three floats per key; rewritten in place.
rationumberdstHipHeight / srcHipHeight.

Returns ​

Float32Array<ArrayBufferLike> | number[]

values, for chaining.


selectGaitCycle() ​

ts
function selectGaitCycle(take, options): object;

Find the least rotational seam error within an authored steady-motion range. Duration matches source displacement, target hip scale and desired travel speed. Offline only: validates input and allocates temporary quaternions.

Parameters ​

ParameterTypeDescription
takeLocomotionTakeSource sampled motion.
optionsGaitCycleOptionsSearch window and target gait constraints.

Returns ​

object

Inclusive frame bounds, squared angular error and playback duration.

duration ​
ts
duration: number;
end ​
ts
end: number;
score ​
ts
score: number;
start ​
ts
start: number;

Example ​

ts
const cycle = selectGaitCycle(take, {
  firstFrame: 30, lastFrame: 90, minimumPeriod: 20, maximumPeriod: 40,
  bones: ['pelvis', 'thigh_l', 'thigh_r'], hipRatio: 1, speed: 1.6,
});

sortLocomotionClips() ​

ts
function sortLocomotionClips(index): LocomotionClipMeta[];

Order an index by authored speed, ascending.

Parameters ​

ParameterTypeDescription
indexLocomotionIndexThe index.

Returns ​

LocomotionClipMeta[]

A new array, sorted. Sort once at load; never per frame.


stationaryRootTrack() ​

ts
function stationaryRootTrack(
   targetFloors, 
   restY, 
   options?
): Float32Array;

Prepare a stationary root track from target FK foot heights. Optional source foot heights preserve running flight; omitted heights pin foot contact. Physics owns horizontal travel.

Parameters ​

ParameterTypeDescription
targetFloorsArrayLike<number>Minimum foot/toe world height per frame at the target rest root height.
restYnumberTarget root rest height.
options{ contactHeight?: number; flightThreshold?: number; hipRatio?: number; sourceFloors?: ArrayLike<number>; }Contact pivot height, source scale and optional source running flight.
options.contactHeight?number-
options.flightThreshold?number-
options.hipRatio?number-
options.sourceFloors?ArrayLike<number>-

Returns ​

Float32Array

Packed xyz positions, with x/z zero.

Example ​

ts
const positions = stationaryRootTrack([0.1, 0.05, 0.1], 0.9, { contactHeight: 0.045 });

strField() ​

ts
function strField(data, key): string | null;

Read a string field.

Parameters ​

ParameterTypeDescription
dataReadonly<Record<string, unknown>> | undefinedAuthored payload, possibly undefined.
keystringField name.

Returns ​

string | null

The field, or null when it is missing or not a non-empty string.


strList() ​

ts
function strList(data, key): readonly string[];

Read a string array field, e.g. a state's clips.

Parameters ​

ParameterTypeDescription
dataReadonly<Record<string, unknown>> | undefinedAuthored payload, possibly undefined.
keystringField name.

Returns ​

readonly string[]

The strings, or an empty array.


timeScaleFor() ​

ts
function timeScaleFor(speed, clipSpeed): number;

The playback rate that matches a clip's stride to the ground speed.

Parameters ​

ParameterTypeDescription
speednumberActual ground speed.
clipSpeednumberThe clip's authored speed.

Returns ​

number

A rate in [0.5, 2], or 1 when the clip is an in-place idle.


validateCharacterState() ​

ts
function validateCharacterState(value): CharacterState;

Validate an unknown value as a CharacterState.

Parameters ​

ParameterTypeDescription
valueunknownThe candidate, typically decoded from the guest's frame output.

Returns ​

CharacterState

A validated state. Array fields are copied; the expressionFloat32Array is NOT copied, because it is the hot path and the guest owns a stable buffer for it.

Throws ​

Describing the first field that is wrong.


validateLocomotionIndex() ​

ts
function validateLocomotionIndex(value): LocomotionIndex;

Validate an unknown value as a LocomotionIndex.

locomotion.json is produced by an offline tool and shipped as an asset, so it is untrusted input by the time it reaches the runtime.

Parameters ​

ParameterTypeDescription
valueunknownParsed JSON.

Returns ​

LocomotionIndex

The validated index.

Throws ​

When the shape is wrong.


writeLocomotionWeights() ​

ts
function writeLocomotionWeights(
   blend, 
   weights, 
   speeds
): void;

Write a blend result into the weight / speed maps the base layer applies.

Parameters ​

ParameterTypeDescription
blendLocomotionBlendA result from blendLocomotion.
weightsMap<string, number>Cleared and filled with clip name to weight.
speedsMap<string, number>Cleared and filled with clip name to time scale.

Returns ​

void


yawTo() ​

ts
function yawTo(dx, dz): number;

World-space yaw of the direction (dx, dz), matching three's +Z forward.

Parameters ​

ParameterTypeDescription
dxnumberWorld-space X offset from the head to the look target.
dznumberWorld-space Z offset from the head to the look target.

Returns ​

number

The yaw in radians, 0 when the target is dead ahead on +Z.