Skip to content

@gameable/animation ​

Classes ​

LifeModel ​

The life as plain numbers.

Constructors ​

Constructor ​
ts
new LifeModel(seed?): LifeModel;
Parameters ​
ParameterTypeDefault valueDescription
seednumber1The seed of every choice made here.
Returns ​

LifeModel

Properties ​

glances ​
ts
glances: number = 0;

How many glances away have begun (a measurement reads it).

Accessors ​

time ​
Get Signature ​
ts
get time(): number;

Seconds on the model's own clock.

Returns ​

number

Seconds stepped so far.

Methods ​

step() ​
ts
step(i): LifeOut;

Advance by one frame.

Parameters ​
ParameterTypeDescription
iLifeInThis frame's inputs.
Returns ​

LifeOut

The outputs, reused in place.


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 ​

ActionAnswer ​

The answer to a request. One object is reused.

Properties ​

ok ​
ts
ok: boolean;
reason ​
ts
reason: ActionReason;
words ​
ts
words: string;

The reason in plain words, with the numbers ("the bar is 0.95 m; this hurdle clears 0.4 to 0.8 m").


ActionClip ​

An action read on one rig's table. Frames are indices into the set's arrays.

Properties ​

actFirst ​
ts
readonly actFirst: number;

The act.

actLast ​
ts
readonly actLast: number;
airSeconds ​
ts
readonly airSeconds: number;

Seconds the act lasts in the take.

clearance ​
ts
readonly clearance: number;

Metres the feet pass over the object's top in the take (negative: the read has them through it); Infinity without an object the feet go over.

contacts ​
ts
readonly contacts: readonly ActionContact[];
entryFirst ​
ts
readonly entryFirst: number;

Where a moving body may come in.

entryLast ​
ts
readonly entryLast: number;
exitFirst ​
ts
readonly exitFirst: number;

The way out.

exitLast ​
ts
readonly exitLast: number;
first ​
ts
readonly first: number;

The first and last frame it may play.

headroom ​
ts
readonly headroom: number;

Metres between the top of the head and a beam's underside as the body passes under it in the take (negative: the read has the head through it); Infinity without a beam.

key ​
ts
readonly key: number;

The frame the body is fitted to the object at: its root over the object's middle, or the act's first.

kind ​
ts
readonly kind: string;
last ​
ts
readonly last: number;
name ​
ts
readonly name: string;
object ​
ts
readonly object: 
  | Readonly<Required<ActionObjectSource>>
  | null;

The object in the take, or null.

path ​
ts
readonly path: Float32Array;

Per frame from first: the root's place (x to the left, z ahead) and facing (radians) in the frame of the performer's start.

peak ​
ts
readonly peak: number;

Metres the hips rise over the act.

points ​
ts
readonly points: Float32Array;

Per frame from first: ACTION_POINTS points in the root's frame (x left, y over the floor, z ahead): the hands, the feet, the top of the head, the toes.

release ​
ts
readonly release: number;

The frame something held is let go, or -1.

rise ​
ts
readonly rise: Float32Array;

Per frame from first: how much of the act's rise the hips have, 0 to 1 (0 at its ends).

speedIn ​
ts
readonly speedIn: number;

The root's speed over the entry and at the way out, metres a second.

speedOut ​
ts
readonly speedOut: number;
start ​
ts
readonly start: number;

Where a standing body comes in.

take ​
ts
readonly take: number;

The take's index in the set.

travel ​
ts
readonly travel: Float32Array;

Per frame from first: metres travelled since first.

windupFirst ​
ts
readonly windupFirst: number;

The gathering before the act (the act's first frame twice when it has none).


ActionContact ​

A limb on something, in frames of the set.

Properties ​

first ​
ts
readonly first: number;
last ​
ts
readonly last: number;
limb ​
ts
readonly limb: number;

Its index in ACTION_LIMBS.


ActionContactSource ​

A limb on something, from a moment to a moment of the take, seconds.

Properties ​

from ​
ts
from: number;
limb ​
ts
limb: ActionLimb;
to ​
ts
to: number;

ActionEvent ​

An event. One object is reused: copy what you keep.

Properties ​

action ​
ts
action: string;

The action's name.

limb ​
ts
limb: number;

The limb, for a contact, a release or a clip (an index into ACTION_LIMBS), or -1.

name ​
ts
name: ActionEventName;
reason ​
ts
reason: ActionReason;
target ​
ts
target: number;

The target's id, or -1.

vx ​
ts
vx: number;

How fast that point moves, world metres a second (a release gives the object this).

vy ​
ts
vy: number;
vz ​
ts
vz: number;
x ​
ts
x: number;

Where, world metres: the contact point, the hand at a release, the limb that clipped. For landed: where the body landed (its own place over the ground), at the height of the floor it landed on. For the rest: where the body is, at the height of its floor.

y ​
ts
y: number;
z ​
ts
z: number;

ActionHolds ​

Hands and feet held to points in the world: what the layer needs of a limb hold (limbs in the order of ACTION_LIMBS). hold is called every frame a limb is held, with where it must be now.

Methods ​

hold() ​
ts
hold(
   limb, 
   x, 
   y, 
   z
): void;
Parameters ​
ParameterType
limbnumber
xnumber
ynumber
znumber
Returns ​

void

release() ​
ts
release(limb): void;
Parameters ​
ParameterType
limbnumber
Returns ​

void


ActionKind ​

One action of the list.

Properties ​

air ​
ts
readonly air: ActionAir;

How the time off the ground is played.

aside ​
ts
readonly aside: number;

Metres the body may be off the line through the object's middle when it comes in.

fits ​
ts
readonly fits: readonly ("length" | "take-off spot" | "height" | "hand placement" | "seat height")[];

What of the object the take is fitted to.

from ​
ts
readonly from: readonly ("walking" | "standing" | "running")[];

What a body may be doing when it is asked: the entry is chosen by pose and foot.

heading ​
ts
readonly heading: number;

Radians its heading may be off the way across the object.

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

Metres the real object's height may be under (negative) and over the take's.

inStride ​
ts
readonly inStride: boolean;

Whether it is used at speed, in stride (the first class), or from standing.

kind ​
ts
readonly kind: string;

What a game asks for.

note ​
ts
readonly note: string;

What is missing, when something is.

object ​
ts
readonly object: ActionObjectKind;

The object it needs (none: it is done anywhere).

physics ​
ts
readonly physics: string;

What the physics does in it.

status ​
ts
readonly status: ActionStatus;

Where it stands today.

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

How far the strides of the run-up may be shortened and lengthened (1 is as recorded).

title ​
ts
readonly title: string;

In plain words.

touches ​
ts
readonly touches: readonly ("left-hand" | "right-hand" | "left-foot" | "right-foot")[];

The limbs that touch the object (held to their contact points).


ActionLayer ​

Actions on a character.

Properties ​

action ​
ts
readonly action: string;

The action asked for or playing, or ''.

actions ​
ts
readonly actions: ActionSet;

The set's actions in force.

lift ​
ts
readonly lift: number;

Metres the hips are lifted (or lowered) over the take's own height this frame.

measures ​
ts
readonly measures: ActionMeasures;
on ​
ts
on: boolean;

The switch: off, the layer does nothing.

phase ​
ts
readonly phase: "" | "entry" | "act" | "windup" | "approach" | "recovery";

Where in the action: approach, entry, windup, act, recovery, or ''.

state ​
ts
readonly state: "idle" | "armed" | "playing";

idle; armed (asked, waiting for the right foot and distance); playing.

Methods ​

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

Lay the fit over the pose (the hips' arc), hold the limbs, say what happened. After motion.update.

Parameters ​
ParameterTypeDescription
dtnumberSeconds.
Returns ​

void

cancel() ​
ts
cancel(): boolean;

Take a request back. An action already in its act cannot be taken back.

Returns ​

boolean

Whether it was.

direct() ​
ts
direct(frame): void;

Direct the motion layer for this frame. Before motion.update.

Parameters ​
ParameterTypeDescription
frameReadonly<MotionFrame>The game's place, facing and wanted velocity (the motion layer's own frame).
Returns ​

void

request() ​
ts
request(
   name, 
   target?, 
   options?
): Readonly<ActionAnswer>;

Ask for an action, at an object when it needs one.

Parameters ​
ParameterTypeDescription
namestringThe action's name in the set.
target?Readonly<ActionTarget> | nullThe object, as the game has it.
options?ActionRequestOptionsHow it is carried out.
Returns ​

Readonly<ActionAnswer>

Whether it was taken, and if not, why.

reset() ​
ts
reset(): void;

Forget everything at once.

Returns ​

void

restore() ​
ts
restore(): void;

Take last frame's lift off the hips. Before the motion layer's own restore.

Returns ​

void

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

Another set's actions (the motion layer moved to another table).

Parameters ​
ParameterTypeDescription
actionsActionSetThe actions.
Returns ​

void


ActionLayerOptions ​

Options for createActionLayer.

Properties ​

actions ​
ts
actions: ActionSet;

The set's actions, read on this rig (buildActions).

ground? ​
ts
optional ground?: ((x, y, z) => number) | null;

The ground's height under a world point (as the feet's layer takes it); absent, the floor under the root: a landing is then never without a floor.

hips? ​
ts
optional hips?: string;

The pelvis, by this rig's name. Default Hips.

holds? ​
ts
optional holds?: ActionHolds | null;

Holds hands and feet to their contact points, when the character has it.

motion ​
ts
motion: MotionLayer;

The motion layer it directs.

onEvent? ​
ts
optional onEvent?: ((event) => void) | null;

Told every event.

points? ​
ts
optional points?: readonly string[];

The joints the action's points are (the order of ACTION_POINTS). Default SOMA's.

root ​
ts
root: Object3D;

The rig root: the character's own frame, the bones under it.


ActionMeasures ​

What the layer is doing, for a measurement and a debug view.

Properties ​

airMetres ​
ts
airMetres: number;
airPlayed ​
ts
airPlayed: number;
airTake ​
ts
airTake: number;

Seconds in the air: the take's, and as played.

carried ​
ts
carried: number;

The speed carried, metres a second.

clearance ​
ts
clearance: number;

Metres the feet clear the object by, as planned.

entryCost ​
ts
entryCost: number;
entryFrame ​
ts
entryFrame: number;

The frame the body came in at (within its take), and what the feet were off by.

missAlong ​
ts
missAlong: number;

Metres the take-off was from its mark, along the way and across it.

missAside ​
ts
missAside: number;
rate ​
ts
rate: number;
rise ​
ts
rise: number;

Metres the hips' arc rises, and metres travelled in the air.

stride ​
ts
stride: number;

The strides' scale and the clock's rate in force.


ActionObjectSource ​

The object as it stood in the take, against the performer's start (he faces ahead).

Properties ​

ahead ​
ts
ahead: number;

From the floor point under his hips at the take's start to its middle, ahead, metres.

depth? ​
ts
optional depth?: number;

Along his path, metres.

height ​
ts
height: number;

Its top over the floor, metres (a beam: its underside).

kind ​
ts
kind: ActionObjectKind;
left? ​
ts
optional left?: number;

To his left, metres.

width? ​
ts
optional width?: number;

Across the performer's path, metres.


ActionRequestOptions ​

How a request is carried out.

Properties ​

plain? ​
ts
optional plain?: boolean;

The plain way, for a comparison: the clip simply started at its distance, on whatever foot, as recorded, with a plain ease; nothing fitted.


ActionRigNames ​

What a rig calls the joints an action is read by.

Properties ​

hips ​
ts
hips: string;
points ​
ts
points: readonly string[];

In the order of ACTION_POINTS: left hand, right hand, left foot, right foot, head top, left toes, right toes.


ActionSet ​

A set's actions, read on one rig.

Properties ​

clips ​
ts
readonly clips: readonly ActionClip[];
phase ​
ts
readonly phase: Float32Array;

Per frame of the whole set: where the feet are in their stride, 0 to 1 (0 as the left foot lands, a half as the right does), or NaN where no stride is under way.

refused ​
ts
readonly refused: readonly object[];

Actions left out, and why.

restY ​
ts
readonly restY: Float32Array;

The rest height over the floor of each of an action's points on this rig, metres.

stride ​
ts
readonly stride: Float32Array;

Per frame of the whole set: metres the root travels over the stride around it (two steps), or 0.

table ​
ts
readonly table: MotionTable;
travel ​
ts
readonly travel: Float32Array;

Per frame of the whole set: metres the root has travelled since its take's start.


ActionSource ​

An action as a motion set file states it. Times are seconds into its take.

Properties ​

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

The act: from leaving the floor to landing (a duck: the low part).

contacts? ​
ts
optional contacts?: readonly ActionContactSource[];

Hands and feet on the object.

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

Where a body already moving may come in: the run-up at speed, from and to.

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

Where the body is handed back: the search may take it from the first, must by the second.

kind ​
ts
kind: string;

Its kind in the action list (hurdle, jump ...).

name ​
ts
name: string;

What a game asks for by name (several takes of one kind may exist).

object? ​
ts
optional object?: ActionObjectSource;

The object in the take; absent, the action is done anywhere.

release? ​
ts
optional release?: number;

The moment something held is let go (a throw).

start? ​
ts
optional start?: number;

Where a standing body comes in. Default: the take's start.

take ​
ts
take: string;

The take it is a range of.

windup? ​
ts
optional windup?: readonly [number, number];

The gathering before the act, when it has one worth naming.


ActionTarget ​

The object an action is asked at, as the game has it.

Properties ​

depth ​
ts
depth: number;
height ​
ts
height: number;

Its top over that floor (a beam: its underside), metres.

id ​
ts
id: number;

The game's own number for it (a physics body's id), said back in events.

width ​
ts
width: number;

Across the way, and along it, metres.

x ​
ts
x: number;

Its middle, on the floor it stands on: world metres.

y ​
ts
y: number;
yaw ​
ts
yaw: number;

The way across it, radians about +Y (0 is +Z); the character may come from either side.

z ​
ts
z: number;

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.


AnimationIntent ​

The intention, read.

Properties ​

clips ​
ts
clips: readonly string[];

The clips the intention covers, by name.

intent ​
ts
intent: AnimationIntentKind;
life ​
ts
life: object;

The package's own clips for the life's purposes, by purpose.

glance ​
ts
glance: string | null;
idle ​
ts
idle: string;
talk ​
ts
talk: string | null;
style ​
ts
style: string;

One line about the manner, or ''.


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.

bodyWeights ​
ts
readonly bodyWeights: ReadonlyMap<string, number>;

The body clip weights handed to the mixer this frame, by clip name, after the fade and the walk blend's fill: what is really playing. Reused per frame; read, never keep.

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.

fadeSeconds ​
ts
fadeSeconds: number;

The fade on every change of the explicit clip weights, seconds; 0 applies a set at once. See AnimatorOptions.fade.

footPlant ​
ts
readonly footPlant: FootPlant | null;

The feet's layer, or null when the animator has none.

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.

headAim ​
ts
readonly headAim: HeadAimConfig;

The head aim's tuning, live: share, eyeShare, the limits and the rate may be changed between frames. The joint list is fixed at creation.

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.

life ​
ts
readonly life: LifeLayer | null;

The life layer, or null when the animator has none.

motion ​
ts
readonly motion: MotionLayer | null;

The motion layer, or null when the animator has none (yet: see Animator.setMotion).

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

onClipEnd() ​
ts
onClipEnd(listener): () => void;

Hear a clip end (a once-only clip finishing, a looping clip coming round). Reported from inside update, once per clip per end.

With a motion layer, a clip only the walk blend plays (the standing, walking and running clips it mixes from the speed asked) says 'loop' only on a frame where the mixer's pose is the one drawn: while a take is written over it, that clip still goes round underneath, unseen, and nothing is said of it. Such a 'loop' is told once the layer has run that frame; a clip named in state.clips is told at once, drawn or not.

Parameters ​
ParameterTypeDescription
listenerClipEndListenerWhat to tell.
Returns ​

A function that stops telling it.

() => 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

setMotion() ​
ts
setMotion(layer, extras?): void;

Give the animator its motion layer after it was made (a character that stood and idled while its motion set was still arriving), or take it away with null. The layer comes in under the life and over the mixer, as one given at the start does; the body moves over to it by the layer's own inertial blend, never a pop. A layer taken away has its last writing taken off the bones first, and so have the layers that ran around it.

Parameters ​
ParameterTypeDescription
layerMotionLayer | nullThe layer, or null for none.
extras?AnimatorMotionExtras | nullThe layers run around it (actions, the upper body, hands held to contact points: see AnimatorMotionExtras); they come and go with the layer. Omit for none.
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


AnimatorMotionExtras ​

Layers an animator runs around its motion layer, each a plain function so the animator knows nothing of what they are: an action directs the motion layer before it runs and fits the pose after it; the upper body plays over it; hands are held to contact points after the feet. Each takes its own writing off the bones again before the next frame's mixer, in the reverse order.

Properties ​

after? ​
ts
optional after?: (dt) => void;

After the motion layer, under the life.

Parameters ​
ParameterType
dtnumber
Returns ​

void

before? ​
ts
optional before?: (frame) => void;

Before the motion layer: its direction for this frame.

Parameters ​
ParameterType
frameMotionFrame
Returns ​

void

last? ​
ts
optional last?: (dt) => void;

After the feet: the last word on the pose.

Parameters ​
ParameterType
dtnumber
Returns ​

void

restoreAfter? ​
ts
optional restoreAfter?: () => void;

Take off what after wrote: after the life's restore, before the motion layer's.

Returns ​

void

restoreLast? ​
ts
optional restoreLast?: () => void;

Take off what last wrote: before the feet's own restore.

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.

fade? ​
ts
optional fade?: number | false;

The fade on every change of the explicit clip weights (state.clips), in seconds: a change from one set of weights to another takes this long, the old clips fading out as the new fade in. Default 0.4; false applies each set at once (the mixer of before). Settable later through Animator.fadeSeconds.

footPlant? ​
ts
optional footPlant?: FootPlant | null;

The feet's layer (createFootPlant): while the walk blend plays, a foot its clips' contacts say is down is held where it landed, on the ground under it. Run after the life, before the pose is read; it does nothing until its on is set. Omit for an animator without one.

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

Head-aim tuning overrides.

life? ​
ts
optional life?: LifeLayer | null;

The life layer (createLifeLayer): breath, weight shifts, glances, the look by the character's Life setting, the package's holds. Laid over the pose after the mixer and before the head aim; while it owns the look (on, with a target) the head aim parks and the eyes come from it, and its blink gate closes the blink channel when the setting says the character does not blink. Omit for an animator without one.

locomotion? ​
ts
optional locomotion?: LocomotionIndex;

Locomotion clips, for the velocity-driven fallback.

motion? ​
ts
optional motion?: MotionLayer | null;

The motion layer (createMotionLayer): the body moved by matching whole takes to the state's velocity and the body's facing, its starts, stops and turns the takes' own. Run after the mixer and under the life; while a take has the body its contacts feed the feet's layer. It does nothing until its on is set. Omit for an animator without one.

motionExtras? ​
ts
optional motionExtras?: AnimatorMotionExtras | null;

Layers run around the motion layer (actions, the upper body, hands held to contact points): see AnimatorMotionExtras. Only with a motion layer; omit for none.

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 ​

bodyX? ​
ts
optional bodyX?: number;

The character's place in the world (its walker's), metres along x and z: what the motion layer keeps the drawn body to. Needed only by an animator with one.

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.

bodyZ? ​
ts
optional bodyZ?: number;
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.


BoundPoseAdjust ​

A PoseAdjustRecord bound to a list of joints: what a layer lays on a take's pose.

Properties ​

count ​
ts
readonly count: number;

How many joints of the list the record turns.

hipsMove ​
ts
readonly hipsMove: Float32Array;

The hips' move, metres (zeros when the record has none).

missing ​
ts
readonly missing: readonly string[];

The record's joints the list lacks.

turned ​
ts
readonly turned: Uint8Array;

Per joint of the list: 1 where the record turns it.

turns ​
ts
readonly turns: Float32Array;

Per joint of the list: its turn, x y z w (identity where it has none).


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.

speed? ​
ts
optional speed?: number;

Playback rate for this clip; 1 (the default) is the clip's own.

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.


Dir ​

A direction from the character's own face: + yaw toward its own left, + pitch up, degrees.

Properties ​

pitch ​
ts
pitch: number;
yaw ​
ts
yaw: number;

DirectedWalk ​

A character sent somewhere.

Properties ​

active ​
ts
readonly active: boolean;

Whether a walk or a turn is under way.

arrival ​
ts
readonly arrival: Readonly<WalkArrival>;

How the last walk ended.

ask ​
ts
readonly ask: Float32Array;

The velocity to hand the character this frame (world metres a second along x and z): what character.setState or the animator's state takes.

body ​
ts
readonly body: Float32Array;

What the feel pass asks of the body's parts this frame (WALK_BODY says where each number is): laid on the bones, sprung, by createWalkFeelLayer. All zero while the feel is off, and once a walk has arrived.

feel ​
ts
readonly feel: WalkFeel;

The feel pass: its one switch and its four parts (see WalkFeel). May be changed at any time.

onArrive ​
ts
onArrive: ((arrival) => void) | null;

Told when a walk or a turn has ended.

onStop ​
ts
onStop: ((left) => void) | null;

Told once per walk, when its stop begins (the stop of the set it has chosen, the slow-down of the one take it plays, or the stop a cancel asks for): the metres still to the spot.

onStopped ​
ts
onStopped: ((off) => void) | null;

Told once per walk, after DirectedWalk.onStop and before DirectedWalk.onArrive: the first moment the body no longer travels (under 10 cm a second for a tenth of a second). A stop's last settling step, and the body settling over its feet, come after it. Given the metres it is from the spot then.

paces ​
ts
readonly paces: Readonly<Record<WalkPace, number>>;

The set's speeds by pace name, metres a second (run: 0 on a set that only walks).

phase ​
ts
readonly phase: "steps" | "facing" | "idle" | "settling" | "walking" | "stopping";

'idle', or what it is doing: 'steps', 'walking', 'stopping', 'settling', 'facing'.

plan ​
ts
readonly plan: Readonly<WalkPlan>;

The plan in force.

turningUnderWay ​
ts
readonly turningUnderWay: boolean;

Whether the walk holds the layer on a performed turn under way at a run (MotionLayer.turnUnderWay 'performed'): from the landing it is entered at to the landing it is left at. A take that states such a turn plays at no other time.

Methods ​

cancel() ​
ts
cancel(): void;

Stop where it is, by the takes' own stop.

Returns ​

void

face() ​
ts
face(facing, walker): Readonly<WalkPlan>;

Turn the character on the spot to face a way.

Parameters ​
ParameterTypeDescription
facingnumberRadians about +Y.
walkerReadonly<Walker>The game's place for the character now.
Returns ​

Readonly<WalkPlan>

The plan.

go() ​
ts
go(request, walker): Readonly<WalkPlan>;

Send the character to a spot.

Parameters ​
ParameterTypeDescription
requestWalkRequestWhere, facing which way, at what pace, by when.
walkerReadonly<Walker>The game's place for the character now.
Returns ​

Readonly<WalkPlan>

The plan.

stopRoom() ​
ts
stopRoom(pace): number;

How far a body running at a pace still travels when it is stopped by the set's quickest stop: the room a run needs before a spot (for a caller that must know whether a body that comes in running can still stop on it). 0 for a pace the set walks.

Parameters ​
ParameterTypeDescription
pacenumberMetres a second.
Returns ​

number

Metres.

update() ​
ts
update(dt, walker): boolean;

Every frame, before the character is updated: moves the walker as the takes move the body, and sets DirectedWalk.ask.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last frame.
walkerWalkerThe game's place for the character: moved.
Returns ​

boolean

Whether a walk or a turn is under way.


DirectedWalkOptions ​

Options for createDirectedWalk.

Properties ​

feel? ​
ts
optional feel?: boolean | Partial<WalkFeel>;

The feel pass: true for all of it, or its parts by name (see WalkFeel). Default off.

motion ​
ts
motion: MotionLayer;

The character's motion layer.


EaseAheadOptions ​

What easeAhead is asked beside the needs.

Properties ​

ends? ​
ts
optional ends?: boolean;

Whether the curve ends on the last sample's own need (true), or only never under it. Left out: true.

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

The most the curve may FALL from sample i to sample i + 1 (one entry a sample), where that is not the same as the most it may rise (rate). Left out: rate.

round? ​
ts
optional round?: number;

The rounding's half width, samples: the curve starts giving way up to twice this before the rate alone would have it. Left out: 2. 0: no rounding.

start? ​
ts
optional start?: number;

The value the curve starts from on the first sample (what was given up when the take was asked). Left out: the first sample's need.


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.


FollowPart ​

One part of "Looks at you": on or off, and how far.

Properties ​

amount ​
ts
amount: FollowAmount;
on ​
ts
on: boolean;

FootContacts ​

A clip's feet on the ground, frame by frame.

Properties ​

authored ​
ts
readonly authored: boolean;

True when the clip's file states them (a reading of the performance it was made from); false when they were read off the feet's height.

fps ​
ts
readonly fps: number;

The frames a second the tracks are sampled at (the clip's own).

left ​
ts
readonly left: ArrayLike<number>;

One value per frame: 1 while the left foot is down, 0 while it is up.

ts
readonly right: ArrayLike<number>;

The same for the right foot.


FootPlant ​

The feet's layer on a rig.

Properties ​

gate ​
ts
gate: number;

1 lets the layer work; 0 shuts it at once (a physics body reacting to a hit).

ground ​
ts
ground: FootGround | null;

The ground under a point; null for the flat floor under the root.

heel ​
ts
heel: "as-posed" | "knee" | "shared" | "step";

What is done about a heel the pose has under the floor at a landing. 'as-posed' (the default): nothing, the foot is where the take has it. 'knee': the foot is raised until the heel's pad stands on the floor, the knee taking all of it. 'shared': the same, with the pelvis raised by half the depth and the other leg reaching down. 'step': the foot is raised the same and set down further from the hip, the leg as long as the take has it, so the step is longer and the knee and the hips stay. An option for a rehearsal: it changes the look of a step, and nothing switches it on.

legs ​
ts
legs: "performed" | "bent";

How straight a leg the layer solves may be. 'bent' (the default; left unset is the same, to the last number): never over 0.995 of its length, so a leg the pose has straighter than that is bent a little as soon as the layer moves it, and the pelvis is lowered by what the bending takes (about 4 mm once a walking step, for the front leg just before its heel lands). 'performed': where the pose has a leg straighter than 0.995, as straight as the pose has it at that update and no straighter: the knee is bent no more than the move bends it, and the pelvis is not lowered for it. A leg the pose has more bent is bounded at 0.995 as always, and a leg is never asked to be longer than its bones. Nothing switches it on.

measures ​
ts
readonly measures: FootPlantMeasures;

What the layer did, after the last update.

on ​
ts
on: boolean;

The switch: off, the layer writes nothing.

Methods ​

reset() ​
ts
reset(): void;

Let every hold go at once (a teleport).

Returns ​

void

restore() ​
ts
restore(): void;

Take last frame's writing off the bones the mixer did not write since. Before the mixer.

Returns ​

void

update() ​
ts
update(context): void;

Hold the feet and solve the legs over the posed bones. After the mixer and the life.

Parameters ​
ParameterTypeDescription
contextFootPlantContextThe frame.
Returns ​

void


FootPlantContext ​

What update needs from the frame.

Properties ​

carried? ​
ts
optional carried?: boolean;

Whether the pose is still being carried from one take to another (a jump's blend dying away). A foot that is down then is held from where it is at once, the leg taking what is left of the blend, instead of going on with the pose until the pose's own foot has come to rest: inside a blend it does not for a quarter of a second, and a foot on the floor travels 8 to 12 cm at the first step of a walk. Not given: as without it.

contacts ​
ts
contacts: ArrayLike<number> | null;

Per leg, how much its foot is down (0 to 1; down from three quarters, so a foot is held only while the clips of a blend agree it is down), or null when nothing says (an explicit clip has the body): then no foot is held, the ground still lifts them.

dt ​
ts
dt: number;

Seconds since the last update.

holdAtRest? ​
ts
optional holdAtRest?: boolean;

Hold the feet that are down while the character stands too. Absent or false, no foot is held under 0.15 m/s (a standing foot is the idle's own business). True when whole takes move the body: a take says which feet are down while it stands, shifts its weight and comes to rest, and those are the moments a foot must not creep.

maxPull? ​
ts
optional maxPull?: number;

The furthest a held foot is kept from where the pose puts it this frame, metres, in place of the layer's own maxPull. Whole takes joined by jumps need a longer leash than a blend of cycles: at a jump the new take has the planted foot somewhere else, and a foot let go there slides through the blend instead of staying down until it lifts.

speed ​
ts
speed: number;

The character's ground speed, metres a second.


FootPlantLeg ​

One leg the layer solves, by bone name.

Properties ​

ts
foot: string;

The foot (the ankle): what is held.

shin ​
ts
shin: string;

The shin (the knee).

thigh ​
ts
thigh: string;

The thigh (the hip joint).

toe? ​
ts
optional toe?: string;

The ball of the foot, when the rig has it: where the ground's slope is read to.


FootPlantMeasures ​

What the layer did this frame, for a measurement.

Properties ​

foot ​
ts
readonly foot: Float32Array;

Per leg, the ankle's world place after the solve: x, y, z.

held ​
ts
readonly held: Uint8Array;

Per leg, 1 while its foot is held.

lift ​
ts
readonly lift: Float32Array;

Per leg, how far the ground lifts (+) or lowers the foot, metres.

pelvisDrop ​
ts
pelvisDrop: number;

How far the pelvis is lowered, metres.

pelvisRise ​
ts
pelvisRise: number;

How far the pelvis is raised for a sunk heel, metres (only with FootPlant.heel 'shared').

pull ​
ts
readonly pull: Float32Array;

Per leg, how far the hold has the foot from the pose's place, metres.

steps ​
ts
steps: number;

Landings since the layer was made.


FootPlantOptions ​

Options for createFootPlant.

Properties ​

easeOut? ​
ts
optional easeOut?: number;

Seconds a released foot takes back to the pose's own place. Default 0.12.

ground? ​
ts
optional ground?: FootGround | null;

The ground under a point; absent or null, the ground is the flat floor under the root.

hips ​
ts
hips: string;

The pelvis, by this rig's name.

legs ​
ts
legs: readonly FootPlantLeg[];

The legs, left then right (the order of the contacts).

maxDrop? ​
ts
optional maxDrop?: number;

The most the pelvis is lowered for a leg that cannot reach, metres. Default 0.3.

maxPull? ​
ts
optional maxPull?: number;

The furthest a held foot is kept from where the pose puts it, metres. Default 0.12.

maxStep? ​
ts
optional maxStep?: number;

The most the ground may lift or lower a foot against the character's floor, metres. Default 0.5.

onStep? ​
ts
optional onStep?: (leg, x, y, z) => void;

Told when a foot comes down: the leg's index (0 left, 1 right) and the world point where it landed (on the ground).

Parameters ​
ParameterType
legnumber
xnumber
ynumber
znumber
Returns ​

void

root ​
ts
root: Object3D;

The rig root: the character's own frame (+Y up), its origin on the floor, the bones under it.


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.


GetUpClip ​

A get-up read on one rig.

Properties ​

contacts ​
ts
readonly contacts: readonly GetUpContact[];

The stretches a hand or a foot is planted on the floor.

endX ​
ts
readonly endX: number;

Where it stands at its last frame, in the take's own world: the hips over the ground, and the way it faces (radians about +Y, 0 faces +Z).

endYaw ​
ts
readonly endYaw: number;
endZ ​
ts
readonly endZ: number;
first ​
ts
readonly first: number;
last ​
ts
readonly last: number;
lie ​
ts
readonly lie: GetUpLie;

How the body lies at its first frame.

lift ​
ts
readonly lift: Float32Array;

Per frame from first: metres the take's height was moved by to put the floor under the body.

name ​
ts
readonly name: string;

The take's name.

points ​
ts
readonly points: Float32Array;

Per frame from first: GETUP_POINTS points in the take's own world (x, y over the floor, z), the floor already under the body.

rise ​
ts
readonly rise: number;

The frame (from first) the body leaves the ground at: the last at which its hips are lower than GETUP_GROUND_SHARE of their height at the last frame. What comes before is the part on the ground (lying, propping up, a shake of the head).

run ​
ts
readonly run: GetUpRun | null;

Of a take that ends in a run (style: 'run'): its path and its running steps; else null.

seconds ​
ts
readonly seconds: number;

Seconds it lasts as performed.

springs ​
ts
readonly springs: boolean;

Whether its file marks a stretch the body is off the floor (getup.air): it springs, both feet in the air. A take without the mark is taken to keep a foot on the floor.

style ​
ts
readonly style: GetUpStyle;
take ​
ts
readonly take: number;

The take's index in the set, and the first and last frame played (indices into the set's arrays).

up ​
ts
readonly up: number;

The frame (from first) from which the body is up enough to be moved: from it to the last frame the hips are at GETUP_UP_SHARE or more of their height at the last frame and both feet are on the floor. The last frame when the take has no such stretch.


GetUpContact ​

A hand or a foot planted on the floor, in frames from the clip's first.

Properties ​

first ​
ts
readonly first: number;
last ​
ts
readonly last: number;
limb ​
ts
readonly limb: number;

0 left hand, 1 right hand, 2 left foot, 3 right foot.

stated? ​
ts
readonly optional stated?: boolean;

True for a plant the file states (getup.hands): the limb is on the floor there whatever height the read has it at.


GetUpFit ​

How a take fits a body, as fitGetUp finds it. One object is reused by its caller.

Properties ​

distance ​
ts
distance: number;

The pose distance: the root mean square of what is left between the points, metres.

furthest ​
ts
furthest: number;

The furthest any one point is from where the take has it, metres.

x ​
ts
x: number;
yaw ​
ts
yaw: number;

The turn about the vertical that lays the take over the body, radians, and the move after it, metres.

z ​
ts
z: number;

GetUpHolds ​

Hands and feet held to points in the world: what the layer needs of a limb hold (limbs 0 left hand, 1 right hand, 2 left foot, 3 right foot). hold is called every frame a limb is held, with where it must be.

Methods ​

endOf() ​
ts
endOf(limb, out): Float32Array;

Where a limb's end is now, in the world, as the bones stand: fills and returns out (x, y, z).

Parameters ​
ParameterType
limbnumber
outFloat32Array
Returns ​

Float32Array

hold() ​
ts
hold(
   limb, 
   x, 
   y, 
   z, 
   orient?, 
   atOnce?
): void;

Hold a limb's end at a world point. atOnce: at its full weight from the first update (a limb only kept out of the floor: the point is a hair from where it is drawn).

Parameters ​
ParameterType
limbnumber
xnumber
ynumber
znumber
orient?ArrayLike<number> | null
atOnce?boolean
Returns ​

void

keepOver()? ​
ts
optional keepOver(
   limb, 
   y, 
   fresh?
): void;

Keep a limb's end from being aimed under a height, in height only, until it is at rest again (the limb hold's keepOver); fresh: only for a hold that began on a limb at rest. A hold without it is never asked.

Parameters ​
ParameterType
limbnumber
ynumber
fresh?boolean
Returns ​

void

release() ​
ts
release(limb): void;
Parameters ​
ParameterType
limbnumber
Returns ​

void


GetUpLayer ​

A fallen character's get-up.

Properties ​

active ​
ts
readonly active: boolean;

Whether the get-up has the whole body (entering or rising): the host keeps its other layers off it.

measures ​
ts
readonly measures: GetUpMeasures;
movable ​
ts
readonly movable: boolean;

Whether the body is up enough to be moved while the take still has it (rising, up said): GetUpLayer.release hands it over. False without upAndRunning.

place ​
ts
readonly place: Float32Array;

Where the character stands when it is up: world x and z of its own place (the rig's origin), and the way it faces (radians about +Y). Set by begin.

placeNow ​
ts
readonly placeNow: Float32Array;

With a take that ends in a run: the body's own place this frame (world x and z of the rig's origin, and the way it travels, radians about +Y), from the last update.

progress ​
ts
readonly progress: number;

How far through the get-up the body is, 0 to 1 (1 from the moment it stands).

runOff ​
ts
readonly runOff: Float32Array;

With a take that ends in a run, from stood: how the set's run takes over: the foot that comes down at the take's last frame (0 left, 1 right), the seconds until then, and the metres a second it travels then.

runs ​
ts
readonly runs: boolean;

Whether the take that has the body (or has just handed it over) ends in a run: the host then brings the game's place to GetUpLayer.placeNow every frame, not to GetUpLayer.place.

set ​
ts
readonly set: GetUpSet;

The set in force.

settle ​
ts
readonly settle: number;

With a take that ends in a run: how far the body has come onto its own path, 0 to 1 (1 from where its hips are up). The host eases the game's place from where it lay to placeNow by it.

state ​
ts
readonly state: "idle" | "entering" | "rising" | "handing";

idle; entering (the fallen pose carried into the take); rising; handing (the take's last pose dying away over the character's own).

Methods ​

begin() ​
ts
begin(style?, way?): boolean;

Get up from the pose the bones hold now (the physics body's, as it lies).

Parameters ​
ParameterTypeDescription
style?GetUpStyleThe style asked; the layer's own when absent.
way?GetUpWayFor 'run': where the body is going (GetUpWay). A run nobody can make from how the body lies (no such take, the wrong way, no room) gets an ordinary one. For 'quick': its toward chooses among several quick takes that lie as the body lies.
Returns ​

boolean

Whether a take was found: false leaves everything as it was.

cancel() ​
ts
cancel(): void;

Let go at once (the body was floored again).

Returns ​

void

hurry() ​
ts
hurry(): void;

A move waits for this body (a walk to a spot is asked, a stick is held): the part of the take on the ground lasts no longer than shakeOff seconds from the asking. Where the take would lie longer, the pose drawn now is carried into a later frame of it by a blend sized as the way in is. Asked once or every frame: what is already short enough is left.

Returns ​

void

measure() ​
ts
measure(): void;

After the limb hold's own update: read how far each held limb's end is from where its hold began.

Returns ​

void

readLie() ​
ts
readLie(): Readonly<GetUpLieRead>;

How the body lies now, read off the bones as they stand.

Returns ​

Readonly<GetUpLieRead>

The reading (one object, reused).

release() ​
ts
release(): boolean;

Take the body out of the rise: from the next frame the take's legs die away over what poses the body now (over feet that stay where they stand, with feetStay), and the rest of the take plays on over the trunk, the arms and the head while it dies away. GetUpLayer.place is set to where the body stands NOW (over its feet, with standOverFeet), and stood is said.

Returns ​

boolean

Whether the body was handed over: only while GetUpLayer.movable.

restore() ​
ts
restore(): void;

Take last frame's writing off the bones. Before the mixer (and after the limb hold's own restore).

Returns ​

void

runWay() ​
ts
runWay(way?): number;

The way the body would run off, were it asked up into a run now from the pose the bones hold: radians about +Y in the world. Nothing is begun or changed.

Parameters ​
ParameterTypeDescription
way?GetUpWayWhere the body is going, as for GetUpLayer.begin.
Returns ​

number

The way, or NaN when no take that ends in a run can be made from here.

setSet() ​
ts
setSet(set): void;

Another set's get-ups.

Parameters ​
ParameterTypeDescription
setGetUpSetThe get-ups.
Returns ​

void

switchTo() ​
ts
switchTo(style, way?): boolean;

Change the take for one of another style while the body is still on the ground (before up): the pose drawn now is carried into the new take's lying frame as a fallen pose is, and the get-up's clock runs on. Only for a take OF the style asked that lies as the body is drawn now; else nothing changes. For a move that is asked while an ordinary get-up has begun: switchTo('run'), and where no run can be made, switchTo('quick').

A quick stand-up ('quick') is changed to only when it is NEVER SLOWER: the seconds from now until the body is up are reckoned for the take it has (what is left of it) and for the quick one (its way in and its frames to up), the part on the ground of each cut to the shake-off as GetUpLayer.hurry cuts it, and the take is changed only for a gain of a fifth of a second or more (measures.quickGain). A take that ends in a run is never left for one.

Parameters ​
ParameterTypeDescription
styleGetUpStyleThe style asked.
way?GetUpWayFor 'run': where the body is going (GetUpWay). For 'quick': its toward, as for GetUpLayer.begin.
Returns ​

boolean

Whether the take was changed.

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

Play on and write the pose. After every other layer; the limb hold runs after this.

Parameters ​
ParameterTypeDescription
dtnumberSeconds.
Returns ​

void


GetUpLayerOptions ​

Options for createGetUpLayer.

Properties ​

contactFirst? ​
ts
optional contactFirst?: boolean;

The contact comes first (OFF unless true; with it off every frame is drawn as before). A hand the take's file states on the floor (getup.hands) is ON the floor, and the trunk gives, never the arm's reach:

  • where the read has the shoulder higher than the arm is long, the SHOULDER comes down to the hand: the trunk leans about its lowest joint, eased over a few frames, by as much as brings the shoulder within the arm's reach of the hand's place on the floor (40 degrees at most); the hand is held straight under where the pose has it, and is let go for the gap its arm leaves only once the lean has come as far as it goes (measures.statedGap still says that gap);
  • where the pose has a stated hand, or either elbow, UNDER the floor (a body carried by its hands with its back in the air, which the set's floor rule presses down), the whole body comes up until neither is, eased as the lift that keeps a knee or the trunk out of the floor is: the hand keeps its place and the arm its bend.
feetStay? ​
ts
optional feetStay?: boolean;

On by default (absent or true) wherever GetUpLayerOptions.footDown is given (without it the layer cannot know of a foot and nothing is done); false switches it off (every frame is then drawn as before there was such a cure). Without it, while the body is handed back, what is left of the take's last pose dies away over the pose that moves the body now; the take ends in a wide stance, a walk's first step is narrow, and a foot that stands on the floor is drawn across the floor from the one to the other. With it a foot that stands when the body stands, and that the takes moving the body now have on the floor, stays as it stood (its place, its height and its turn) until those takes lift it, then eases to where they have it, in the air; a foot its leg cannot reach any more is let go sooner. The hand-back lasts until both feet are let go and eased out (the blend itself is as long as before). A body nothing moves (it stands in its own stance) is handed back exactly as without it.

footDown? ​
ts
optional footDown?: ((foot) => number) | null;

For feetStay: whether what moves the body now has a foot on the floor (0 the left foot, 1 the right): 1 on the floor, 0 lifted, -1 nothing moves the body (it stands). Asked every frame of the hand-back, after the takes have posed the body.

ground? ​
ts
optional ground?: ((x, y, z) => number) | null;

The floor's height under a world point; absent (or where it finds none), the floor the rig stands on.

handsOverFloor? ​
ts
optional handsOverFloor?: boolean | "not-just-held";

On by default (absent or true); false switches it off (every frame is then drawn as before there was such a cure). Without it a hand or a foot the layer only keeps out of the floor is eased onto its place as every hold is, and for that moment it can be drawn under the floor: at a push-off the take's own pose has a hand several centimetres under it, and the hold that planted the hand has just let it go. With it such a limb is kept over the floor in HEIGHT from the first frame (the holds' keepOver), over the ground it is eased as before, so nothing is moved sideways at once; and a planted limb let go because its hold folded the elbow is kept over the floor in the same frame. 'not-just-held': the same, but only for a limb no hold had or was letting go of when the keeping began.

holds? ​
ts
optional holds?: GetUpHolds | null;

Holds hands and feet to the floor, when the character has it.

maxDistance? ​
ts
optional maxDistance?: number;

The furthest a take's lying pose may be from the body's, metres. Default 0.5.

names? ​
ts
optional names?: GetUpRigNames;

What the rig calls the joints a get-up is read by. Default SOMA's.

onEvent? ​
ts
optional onEvent?: ((name) => void) | null;

Told every event.

poseAdjust? ​
ts
optional poseAdjust?: PoseAdjustRecord | null;

The character's own pose adjustment (its package's poseAdjust): laid on the take's pose of every joint but the hips (which a get-up places in the world), so the body is handed back to its takes and its own stand without a step. Omit for none.

riseRate? ​
ts
optional riseRate?: number;

With upAndRunning, after GetUpLayer.hurry: how many times as fast as performed the rise is played, from the frame the hips leave the ground. Default 1 (as performed).

root ​
ts
root: Object3D;

The rig root: the character's own frame, the bones under it.

set ​
ts
set: GetUpSet;

The set's get-ups, read on this rig (buildGetUps).

shakeOff? ​
ts
optional shakeOff?: number;

With upAndRunning, after GetUpLayer.hurry: the most seconds the body stays on the ground from the moment it was asked up (the take's lying, propping up and shaking it off, until its hips leave the ground). A take whose part on the ground is longer is entered further in, by a blend sized as the way in is. Default 1; 0: none of it (the body is carried straight into the frame the rise begins at).

standOverFeet? ​
ts
optional standOverFeet?: boolean;

On by default (absent or true); false switches it off (every frame is then drawn as before there was such a cure). Without it, where the character stands when it is up (GetUpLayer.place) is where the take's last frame has its HIPS, less where the hips stand over the character's own place at rest. A take ends in a stance of its own, the hips seldom over the middle of the feet, so the stance handed back to stands a hand's width beside the feet and they are drawn across the floor. With it the place is where the take's last frame has the middle between its ANKLES, less that middle at rest: the stance handed back to stands over the feet, and what is left between the two is taken up by the hips, over feet that barely move.

style? ​
ts
optional style?: GetUpStyle;

The style asked for when begin names none. Default ordinary.

upAndRunning? ​
ts
optional upAndRunning?: boolean;

On by default (absent or true); false switches it off (up is never said, GetUpLayer.hurry and GetUpLayer.release do nothing, and every frame is drawn as before there was such a thing). With it the layer says up once, when the body is up enough to be moved (the clip's up frame; at the latest when it stands), and from then a host may take the body out of the rise with release. A get-up nobody hurries or releases is drawn exactly as without it.


GetUpLieRead ​

How a body lies, as readGetUpLie reads it. One object is reused by its caller.

Properties ​

faceUp ​
ts
faceUp: number;

How far the chest faces up (1: flat on its back, -1: flat on its front).

heading ​
ts
heading: number;

Which way the head points over the ground from the hips, radians about +Y (0 is +Z).

leftUp ​
ts
leftUp: number;

How far the body's left points up (1: flat on its right side).

lie ​
ts
lie: GetUpLie | null;

The side it lies on, or null when it does not lie (it sits, kneels or stands).

upright ​
ts
upright: number;

How upright the trunk is (1: upright, 0: level).


GetUpMeasures ​

What the layer did, for a measurement and a debug view.

Properties ​

blendSeconds ​
ts
blendSeconds: number;

Seconds the blend into the take lasts.

cut ​
ts
cut: number;

Seconds of the take left out by hurry (its part on the ground cut to shakeOff).

distance ​
ts
distance: number;

The pose distance at the hand-over into the take, and the furthest point's, metres.

furthest ​
ts
furthest: number;
guarding ​
ts
readonly guarding: Uint8Array;

Per limb: 1 while it is not planted and only kept from going under the floor.

handDistance ​
ts
handDistance: number;

The furthest point between the take's last pose and the pose handed back to, metres, and that blend's seconds.

handSeconds ​
ts
handSeconds: number;
holding ​
ts
readonly holding: Uint8Array;

Per limb (left hand, right hand, left foot, right foot): 1 while the get-up holds it to the floor.

hurried ​
ts
hurried: boolean;

Whether a host said a move waits (GetUpLayer.hurry) during the last get-up.

leanMost ​
ts
leanMost: number;

contactFirst: the most the trunk was leaned to bring a shoulder down to a stated hand during the last get-up, radians (0 without it).

letGo ​
ts
letGo: number;

Holds let go because the limb would have been stretched too far.

lie ​
ts
lie: GetUpLie | null;

How the body lay when it was last asked to get up, and the take chosen ('': none fitted).

posed ​
ts
readonly posed: Float32Array;

Per limb: metres its end joint stands over the floor under it as the take's pose has it this frame, before any hold (negative: the pose itself has the joint under the floor).

quickGain ​
ts
quickGain: number;

Seconds sooner the body is up by the quick stand-up the get-up was last changed for than by the take it had, as the layer reckoned it at the change; 0 when it was not changed for one.

ranSeconds ​
ts
ranSeconds: number;

Seconds from the asking until a take that ends in a run handed over to the set's run; -1 until then.

releasedSeconds ​
ts
releasedSeconds: number;

Seconds from the asking until a host took the body out of the rise (release); -1 when none did.

slid ​
ts
readonly slid: Float32Array;

Per limb: metres its end is from where its hold began, over the ground (0 while it is not held).

slidMost ​
ts
slidMost: number;

The most any held limb's end was from where its hold began during the last get-up, metres.

stated ​
ts
readonly stated: Uint8Array;

Per limb: 1 while the take's file states it on the floor (getup.hands), held or not: a limb stated and not held is one its arm could not reach the floor with.

statedGap ​
ts
statedGap: number;

The most a hand its file states on the floor was held OVER it during the last get-up, metres, because its arm did not reach (0: every stated hand reached the floor).

style ​
ts
style: GetUpStyle | null;

The style of the take chosen (null: none fitted). Not always the style asked: a style no take of the set fits for how the body lies falls back to an ordinary get-up.

switched ​
ts
switched: boolean;

Whether the take over the body was changed for one of another style on its way (GetUpLayer.switchTo).

take ​
ts
take: string;
turn ​
ts
turn: number;

The most any joint is turned against its parent between the fallen pose and the take's lying frame, radians.

turned ​
ts
turned: number;

How far a take that ends in a run is to be turned toward the way asked, radians (0: not), and how far it has been by now.

turnedNow ​
ts
turnedNow: number;
upSeconds ​
ts
upSeconds: number;

Seconds from the asking until the body was up enough to be moved (up); -1 until then.

yaw ​
ts
yaw: number;

The turn about the vertical that laid the take over the body, radians.


GetUpRigNames ​

What a rig calls the joints a get-up is read by.

Properties ​

hips ​
ts
hips: string;

The pelvis: the joint a take's root path places.

points ​
ts
points: readonly string[];

In the order of GETUP_POINTS.


GetUpRun ​

What a take that ends in a run carries besides, read on one rig: see GetUpClip.run.

Properties ​

endFoot ​
ts
readonly endFoot: number;

The foot that comes down at the last frame (0 left, 1 right).

endSpeed ​
ts
readonly endSpeed: number;

Metres a second it travels at the last frame, as its file states.

footfalls ​
ts
readonly footfalls: readonly object[];

The running touch-downs: the frame from first, which foot (0 left, 1 right), how fast the body travels at it (metres a second: the file's, else the take's end speed) and how far over the ground it has come by it from where it lies (metres). The body can be handed over to the set's own run at any of them.

free ​
ts
readonly free: Uint8Array;

Per frame from first: 1 where the take may be turned about the vertical toward the way asked: from where its hips leave the ground, in frames in which the file's foot contacts have neither foot on the floor and no hand or foot is planted (a body turned while a limb is on the floor drags that limb over it, or bends it against its hold). A take whose file states no foot contacts: every such frame without a plant.

hand ​
ts
readonly hand: number;

The frame (from first) the body is handed over at when nothing says sooner: GETUP_RUN_HAND_S before the last.

path ​
ts
readonly path: Float32Array;

Per frame from first: the body's own place in the take's own world (x, z: under its hips, less where the hips stand over the character's place at rest) and the way it travels (radians about +Y, 0 is +Z; while it still lies: the way it runs off).

travel ​
ts
readonly travel: number;

Metres over the ground from where it lies to where its last frame has it.

up ​
ts
readonly up: number;

The frame (from first) the hips are up: from here it runs.

way ​
ts
readonly way: number;

The way it runs off at its last frame, in the take's own world (radians about +Y, 0 is +Z).


GetUpRunSource ​

What the file states of a take that ends in a run (the take's run block): seconds into the take.

Properties ​

endSpeed ​
ts
endSpeed: number;

How fast he travels at the take's last frame, metres a second.

footfalls ​
ts
footfalls: readonly object[];

The running touch-downs from there on, in order: when, which foot (0 left, 1 right), and how fast he travels at it when the file says (speedMps), metres a second.

up ​
ts
up: number;

The moment the hips are up (hipsUp85): from here he runs.


GetUpSet ​

A set's get-ups, read on one rig.

Properties ​

clips ​
ts
readonly clips: readonly GetUpClip[];
data ​
ts
readonly data: MotionData;

The set the get-ups are stretches of.

hipsParent ​
ts
readonly hipsParent: Float32Array;

Where the hips' parent stands on the rig at rest: x y z, then its rotation x y z w (rig space).

refused ​
ts
readonly refused: readonly object[];

Get-ups left out, and why.

restFeet ​
ts
readonly restFeet: Float32Array;

Where the middle between the two ankles stands over the rig's own place at rest (x, z).

restHips ​
ts
readonly restHips: Float32Array;

Where the hips stand over the rig's own place at rest (x, z): what a body handed back stands over.

thickness ​
ts
readonly thickness: Float32Array;

How far the skin is from each point's joint on this rig, metres.


GetUpSource ​

A get-up as a motion set file states it. Times are seconds into its take.

Properties ​

air? ​
ts
optional air?: readonly [number, number];

A stretch the body is off the floor (a spring's flight): its height is kept as read.

hands? ​
ts
optional hands?: readonly object[];

The stretches the CLIP shows a hand on the floor bearing weight (getup.hands; 0 the left hand, 1 the right): stated where the read of a pushing hand floats over the floor.

lying ​
ts
lying: number;

The last moment the body lies on the floor: where a fallen body comes in.

run? ​
ts
optional run?: GetUpRunSource;

Of a take whose style is run: where its running steps fall.

standing ​
ts
standing: number;

The moment it stands again: where the body is handed back.

style ​
ts
style: GetUpStyle;
take ​
ts
take: string;

The take it is a stretch of.


GetUpWay ​

Where a body that gets up is going: asked of a take that ends in a run, which runs off its own way and travels while it plays, and of a quick stand-up, which ends facing a way of its own (of that one only toward is read).

Properties ​

pace? ​
ts
optional pace?: number;
room? ​
ts
optional room?: number;

Metres to the spot the body is sent to, that way. The take is handed over to the set's own run at the LATEST of its running steps from which the run can still stop before the spot (the step's travel, the run's stop from there and 0.3 m fit the room) and still bend to the way asked: with little room at an early step, with room enough at its last. No such step: the take is not taken. Absent: room enough.

spot? ​
ts
optional spot?: readonly [number, number];

The spot the body is sent to, world x and z. Given, the layer reckons the way and the room ITSELF, from where the body lies, and toward and room are not read: for a take that ends in a run from where that take has the body's own place at its first frame, laid over the body (where its travel is counted from); for a quick stand-up from under the body's hips. A host whose own place for the character is not under the body (it stands where the character stood before it fell, or is part-way to where it will stand) says the spot, never a way and a room measured from that place: a body thrown a metre toward a spot two and a half metres from where it stood has a metre and a half of room.

stop? ​
ts
optional stop?: number;

With a room: the metres the set's run still travels when it is stopped at pace (metres a second; the host's walk knows: DirectedWalk.stopRoom). From a step the body travels faster at, the stop is taken to grow with the square of the speed. Absent: 0.

toward? ​
ts
optional toward?: number;

The way the body is to go, radians about +Y in the world (0 is +Z).

Of a quick stand-up ('quick'): of the set's quick takes that lie as the body lies, the one that has the body taking its first step this way soonest: the seconds until it is up and the seconds the turn on the spot then costs for what its end facing, once laid over the body, leaves of this way (nothing under 35 degrees, a quarter of a second rising to 0.55 s for a turn right round: quickTurnSeconds); two as soon: the one that leaves 15 degrees or more less to turn, else the nearer lying pose. Absent: the one that is up soonest, then the nearer lying pose. Either way a take that keeps a foot on the floor goes before one that springs (its file marks a stretch off the floor, getup.air), unless the spring is 0.2 s or more sooner. (A set with one quick take for how the body lies: that one, whatever the way.)

Of a take that ends in a run ('run'): of the set's takes that end in a run and lie as the body lies, the one that runs off nearest this way; none when, after its turn (below), the way is further off its run than the run can still bend: 45 degrees for a body that is only given a way (a stick), and to a spot (a room is given) 10 degrees at most and no more than a bend at turnRate reaches in the room left. Absent: the take whose lying pose is nearest. The take chosen is then TURNED toward this way, by 30 degrees at most, about where the body is, and only in frames in which none of its hands and feet is on the floor (from where its hips leave the ground: the lying body is never swung round, a planted limb never dragged or bent against its hold), at 3 radians a second at most; a take with few such frames before its hand-over is turned less. What is left of the way is the run's own bend after the hand-over.

turnRate? ​
ts
optional turnRate?: number;

How fast the set's run turns a body that is asked to bear off its heading, radians a second: with a room, the run after the hand-over reaches a way a off its own only when the room left is at least twice its radius (its speed by this) times the sine of a. Default 0.64 (37 degrees a second: the tracked set at 4 m/s, bearing right).


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 ​

eyeShare? ​
ts
optional eyeShare?: number;

How much of what is left the eyes take (1, the default: all of it within their range).

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.

share? ​
ts
optional share?: number;

How far toward the target the aimed joints turn, as a fraction of the look (1, the default: all the way within maxYaw / maxPitch; 0.55 is the Gameable studio's "head as it is"). The eyes take what is left.


HoldLimb ​

One limb the layer can hold, by bone name: two bones and the joint at their end.

Example ​

ts
import { createLimbHold, type HoldLimb } from 'gameable/animation';

const leftHand: HoldLimb = { upper: 'LeftArm', lower: 'LeftForeArm', end: 'LeftHand' };
const limbHold = createLimbHold({ root: rigRoot, limbs: [leftHand] });

Properties ​

bend? ​
ts
optional bend?: "back" | "forward";

Which way the middle joint points until a clearly bent pose has said its hinge: back (an elbow: back and down) or forward (a knee). Absent, it is told from the rig: a limb whose upper joint stands no higher over the floor than the limb is long is a leg.

end ​
ts
end: string;

The end joint (the wrist, or the ankle): a child of lower. What is held.

lower ​
ts
lower: string;

The lower bone (the elbow, or the knee): a child of upper.

upper ​
ts
upper: string;

The upper bone (the shoulder joint, or the hip joint).


Holds ​

A package's holds, read.

Properties ​

arms ​
ts
arms: boolean;

The arms are held.

at ​
ts
at: "rest";

Where they are held: at the rest (the captured pose).

joints ​
ts
joints: readonly string[];

The held joints, in the skeleton's order.


LegNames ​

One leg the life keeps planted: the thigh, the shin and the foot, by bone name.

Properties ​

foot ​
ts
foot: string;
shin ​
ts
shin: string;
thigh ​
ts
thigh: string;

LifeIn ​

What the model needs each frame.

Properties ​

clip ​
ts
clip: number;

0..1: how much a clip (a walk, a wave) has the body.

dt ​
ts
dt: number;

Seconds since the last step.

look ​
ts
look: Dir | null;

Where the person (or whatever is looked at) is from the face, or null for nothing.

shares ​
ts
shares: LookShares;

The shares and the liveliness from the Life setting.

state ​
ts
state: LifeState;
voice ​
ts
voice: number;

The voice's loudness right now, 0..1 (0 when nobody speaks).

walking ​
ts
walking: boolean;

The character is walking: it looks where it is going, with a glance back at the person.


LifeJointNames ​

What a rig calls the joints the life lays itself on.

Properties ​

chest ​
ts
chest: string;

The chest: the breath's upper half and the body's turn toward the look.

clavicles ​
ts
clavicles: readonly [string, string];

The two collar bones, left then right.

eyes? ​
ts
optional eyes?: readonly [string, string];

The two eye joints, when the rig has them: where the look is measured from.

ts
head: string;

The head.

hips ​
ts
hips: string;

The pelvis: where the weight shift travels.

legs ​
ts
legs: readonly LegNames[];

The legs the feet's hold solves.

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

The joints a turn of the head is shared over, and each one's share (they should sum to 1).

spineLow ​
ts
spineLow: string;

The base of the spine: the sway and the hip's roll.

spineMid ​
ts
spineMid: string;

The middle of the spine: the breath's lower half and the chest's lean.


LifeLayer ​

The life on a rig.

Properties ​

measures ​
ts
readonly measures: LifeMeasures;

Where the pelvis and the feet are, after the last update.

model ​
ts
readonly model: LifeModel;

The model behind it (a measurement reads its counts).

on ​
ts
readonly on: boolean;

Whether the layer writes anything: the game's switch AND the setting's on.

setting ​
ts
readonly setting: LifeSetting;

The setting in force.

target ​
ts
readonly target: "person" | "away" | "ahead" | "none";

The look's target this frame.

Methods ​

blinkGate() ​
ts
blinkGate(): number;

The blink channel's gate: 0 when the setting says the character does not blink.

Returns ​

number

ownsAim() ​
ts
ownsAim(): boolean;

Whether the layer owns the look this frame (on, with a target): the head aim parks.

Returns ​

boolean

restore() ​
ts
restore(): void;

Take last frame's writing off the bones the mixer did not write since. update does it itself; an animator with a layer under the life calls it first, before that layer's own.

Returns ​

void

setOn() ​
ts
setOn(on): void;

A game's switch: off, the layer writes nothing and the animator's own head aim is back.

Parameters ​
ParameterType
onboolean
Returns ​

void

setSetting() ​
ts
setSetting(setting): void;

A new setting (a page's Calm / Natural / Lively), in force from the next frame.

Parameters ​
ParameterType
settingLifeSetting
Returns ​

void

setState() ​
ts
setState(state, voice?): void;

The conversation's state and the voice's loudness (0..1), from the host.

Parameters ​
ParameterType
stateLifeState
voice?number
Returns ​

void

update() ​
ts
update(context): void;

Lay the life over the posed bones.

Parameters ​
ParameterType
contextLifeUpdateContext
Returns ​

void


LifeLayerOptions ​

Options for createLifeLayer.

Properties ​

holds? ​
ts
optional holds?: readonly string[];

Joints the package holds at their rest under every clip (holds.joints), or none.

idleClip? ​
ts
optional idleClip?: string;

The base clip whose weight says how much the life has the body (default idle).

joints ​
ts
joints: LifeJointNames;

The joints, by this rig's names.

root ​
ts
root: Object3D;

The rig root: the character's own frame (+Z forward, +Y up), the bones under it.

seed? ​
ts
optional seed?: number;

The seed of every choice the model makes.

setting ​
ts
setting: LifeSetting;

The character's Life setting.


LifeMeasures ​

Where the character's pelvis and feet are this frame, in the rig's own frame (metres).

Properties ​

footSlip ​
ts
footSlip: number;

How far each foot is from where the pose put it before the life moved the pelvis (metres).

hipsX ​
ts
hipsX: number;
hipsY ​
ts
hipsY: number;
hipsZ ​
ts
hipsZ: number;
leftFootY ​
ts
leftFootY: number;
rightFootY ​
ts
rightFootY: number;

LifeOut ​

Degrees and millimetres, laid over the pose by the rig side.

Properties ​

breath ​
ts
breath: number;

The breath's wave this frame, -1..1 (the inhale quicker than the exhale).

chestBreath ​
ts
chestBreath: number;

The breath's turns, degrees of pitch (+ up, the chest opening back) on each of the spine's two joints, of roll on the left collar bone (the right takes the opposite), of pitch on the head.

chestPitch ​
ts
chestPitch: number;
chestYaw ​
ts
chestYaw: number;
clavBreath ​
ts
clavBreath: number;
eyes ​
ts
eyes: Dir;
head ​
ts
head: Dir;

The look: where the face points (the head's turn, to be shared down the neck), the body's turn, the eyes'.

headBreath ​
ts
headBreath: number;
headPitch ​
ts
headPitch: number;

The head's own turns from the postures and the nods, degrees: + up, + roll to its left.

headRoll ​
ts
headRoll: number;
hipRoll ​
ts
hipRoll: number;

The hip joint's roll (degrees) and the chest's lean (+ forward) and roll from the postures.

pelvis ​
ts
pelvis: object;

The pelvis' travel (mm: + the character's own left, + forward, + up) and turn (degrees).

fwd ​
ts
fwd: number;
pitch ​
ts
pitch: number;
roll ​
ts
roll: number;
side ​
ts
side: number;
up ​
ts
up: number;
yaw ​
ts
yaw: number;
spineSway ​
ts
spineSway: number;

The slow sway at the base of the spine, degrees of roll.

target ​
ts
target: "person" | "away" | "ahead" | "none";

What the look is on: the person, a glance away, ahead, or nothing.


LifeSetting ​

The setting as the studio keeps it.

Properties ​

ts
blink: boolean;

The character blinks by itself now and then.

blinkRate ​
ts
blinkRate: number;

How often the blinks come, as a multiplier on the 2 to 6 s the eyes wait (0.25 to 3).

eyes ​
ts
eyes: boolean;

The eyes move at all toward what the character looks at.

follow ​
ts
follow: object;

"Looks at you": the eyes, the head and the body turning toward what the character looks at.

body ​
ts
body: FollowPart;
eyes ​
ts
eyes: FollowPart;
head ​
ts
head: FollowPart;
level ​
ts
level: LifeLevel;
lookUp ​
ts
lookUp: LookUp;
on ​
ts
on: boolean;

Off: the character still speaks and does what it is asked; the small unasked things rest.

variation ​
ts
variation: number;

How uneven the talking gestures are, 0 to 100.


LifeUpdateContext ​

What update needs from the frame.

Properties ​

baseWeights ​
ts
baseWeights: ReadonlyMap<string, number>;

The base layer's weights by clip name, this frame.

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

The camera, looked at when nothing else is; null for nobody.

dt ​
ts
dt: number;

Seconds since the last update.

gaze ​
ts
gaze: Float32Array;

The animator's gaze buffer ([pitchL, yawL, pitchR, yawR], radians), written when the life owns the look.

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

A world point to look at, or null.

walking ​
ts
walking: boolean;

The character is walking.


LimbHold ​

The limbs' holds on a rig.

Example ​

ts
import type { LimbHold } from 'gameable/animation';

// A vault: the left hand is on the box from 0.4 s to 0.9 s of the action.
function vault(limbHold: LimbHold, seconds: number, box: { x: number; y: number; z: number }): void {
  if (seconds >= 0.4 && seconds < 0.9) limbHold.hold(0, box.x, box.y, box.z);
  else limbHold.release(0);
}

Properties ​

gate ​
ts
gate: number;

1 lets the layer work; 0 shuts it at once (a physics body reacting to a hit).

measures ​
ts
readonly measures: LimbHoldMeasures;

What the layer did, after the last update.

on ​
ts
on: boolean;

The switch: off, the layer writes nothing and lets every hold go.

Methods ​

endOf() ​
ts
endOf(limb, out): Float32Array;

Where a limb's end joint is now, in the world, as the bones stand (after the last update).

Parameters ​
ParameterTypeDescription
limbnumberThe limb's number.
outFloat32ArrayThree numbers, filled with x, y, z; left as it is for a limb the rig lacks.
Returns ​

Float32Array

out.

hold() ​
ts
hold(
   limb, 
   x, 
   y, 
   z, 
   orient?, 
   atOnce?
): void;

Hold a limb's end joint at a world point from now on. Call it every frame with a moving point, or once. The hold eases in from where the limb is drawn now, so a limb held again while its last hold still eases out does not go back to the pose first. Ask while the layer is on: off or gated shut, it lets the hold go at its next update.

Parameters ​
ParameterTypeDescription
limbnumberThe limb's number in LimbHoldOptions.limbs.
xnumberThe point, world metres.
ynumberThe point's height.
znumberThe point's depth.
orient?ArrayLike<number> | nullThe end joint's rotation to hold as well (a world quaternion, x y z w). Absent or null, the end joint keeps the pose's own world rotation.
atOnce?booleanTrue for a hold that begins at its full weight, with no ease in: only for a limb nothing holds or is letting go of (one still easing out of a hold is eased in as ever: it is drawn away from its pose), and only for a point that is where the limb is drawn already, or a hair from it. A point further off moves the limb there in one frame.
Returns ​

void

keepOver() ​
ts
keepOver(
   limb, 
   y, 
   fresh?
): void;

Keep a limb's end joint from being aimed under a height, from the next update on, in HEIGHT only: while a hold eases in, has the limb or lets it go, the place aimed at is raised to this height wherever the ease would have it lower; over the ground it stays where the ease has it. A limb let go by a hold that had it above the height does not jump (the ease starts above the height and is stopped at it); a limb at rest whose hold begins under the height stands at the height from that hold's first update. Forgotten when the limb is at rest again.

Parameters ​
ParameterTypeDescription
limbnumberThe limb's number.
ynumberThe height, world metres; NaN for none.
fresh?booleanTrue to keep the height only for a hold that began on a limb at rest (no hold had it or was letting go of it); a hold that took over a limb another hold had just let go is then eased as ever, under the height too.
Returns ​

void

release() ​
ts
release(limb): void;

Let a limb go: it eases back to the pose's own place over easeOut.

Parameters ​
ParameterTypeDescription
limbnumberThe limb's number.
Returns ​

void

reset() ​
ts
reset(): void;

Let every hold go at once (a teleport).

Returns ​

void

restore() ​
ts
restore(): void;

Take last frame's writing off the bones nothing else wrote since. Before the mixer.

Returns ​

void

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

Ease the holds and solve the held limbs over the posed bones. After the life and the feet.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last update.
Returns ​

void


LimbHoldMeasures ​

What the layer did this frame, for a measurement.

Example ​

ts
import type { LimbHoldMeasures } from 'gameable/animation';

function shortOfTheLedge(measures: LimbHoldMeasures): boolean {
  // the right hand is held, and still more than 2 cm from its point
  return measures.weight[1] === 1 && measures.error[1] > 0.02;
}

Properties ​

error ​
ts
readonly error: Float32Array;

Per limb, metres from the end joint to where the solve aimed it, after the solve (a point out of reach).

pull ​
ts
readonly pull: Float32Array;

Per limb, metres the solve moved the end joint from where the pose had it.

weight ​
ts
readonly weight: Float32Array;

Per limb, how much the hold has it now, 0 to 1.


LimbHoldOptions ​

Options for createLimbHold.

Example ​

ts
import { createLimbHold, SOMA_HOLD_LIMBS, type LimbHoldOptions } from 'gameable/animation';

const options: LimbHoldOptions = { root: rigRoot, limbs: SOMA_HOLD_LIMBS, easeIn: 0.1 };
const limbHold = createLimbHold(options);

Properties ​

easeIn? ​
ts
optional easeIn?: number;

Seconds a hold takes to have the limb. Default 0.12.

easeOut? ​
ts
optional easeOut?: number;

Seconds a released limb takes back to the pose's own place. Default 0.18.

limbs ​
ts
limbs: readonly HoldLimb[];

The limbs, in the order hold and release number them. One the rig lacks keeps its number and is never held.

maxReach? ​
ts
optional maxReach?: number;

A limb is solved only as far as this share of its full length (never quite straight, unless the pose itself has it straighter). Default 0.995.

root ​
ts
root: Object3D;

The rig root: the character's own frame (+Y up, +Z ahead), the bones under it. Make the layer with the rig at rest: the hinges' first directions are read off it.


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 of a, so its stride matches the ground speed (speed / a.speed); 1 for an in-place idle. timeScaleB is b's. At a clamped end the two are equal.

timeScaleB ​
ts
timeScaleB: number;

Playback rate of b.


LocomotionClipMeta ​

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

Properties ​

contacts? ​
ts
optional contacts?: FootContacts;

When each foot is on the ground over the clip, when the clip says or its feet were read: what the feet's layer holds a foot by (createFootPlant), and, when authored, what lines the clip's steps up with the other gaits' on the shared phase.

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.


LocomotionPhase ​

The shared phase of the walk blend: where the two clips of the bracket are in their cycle, in [0, 1), advanced each frame by the weighted cadence of the two (each at its own rate), so their feet land on the same beat. One per animator; reused.

Properties ​

cycle ​
ts
cycle: number;

Whole cycles gone by since the phase began: which stride a clip holding several strides is in.

looped ​
ts
looped: number;

How many whole cycles went by in the last advance (0 or 1): a 'loop' for the listeners.

phase ​
ts
phase: number;

The cycle's phase, in [0, 1).


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>;

LookShares ​

The shares the life layer runs with, from the setting's words.

Properties ​

body ​
ts
body: number;

Of the look's turn to the side, the upper body's, at liveliness 1.

eyes ​
ts
eyes: number;

Of what is left for the eyes after the head and the body: 1 = all the way.

head ​
ts
head: number;

Of the look, where the face points (the body's turn included), at liveliness 1.

liveliness ​
ts
liveliness: number;

Calm 0.6, Natural 1, Lively 1.4; 0 when the setting is off.

lookUp ​
ts
lookUp: LookUpScale;

LookUpScale ​

How often the character looks at the person, as scales on the glances' waits and holds.

Properties ​

atCool ​
ts
atCool: number;
atHold ​
ts
atHold: number;
awayCool ​
ts
awayCool: number;
awayHold ​
ts
awayHold: 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.


MotionBand ​

The speeds one gait of a set covers.

Properties ​

cadence ​
ts
readonly cadence: number;

Its cadence over those frames, steps a minute, and the length of a step, metres.

fastest ​
ts
readonly fastest: number;
frames ​
ts
readonly frames: number;

How many level frames it was read from.

from ​
ts
readonly from: number;

The speeds it serves: those, with a stride's steps made as much shorter or longer as a steady stride's may be (MOTION_STRIDE_SHORTEST, MOTION_STRIDE_LONGEST; a run's not at all: MOTION_RUN_STRIDE_SHORTEST, MOTION_RUN_STRIDE_LONGEST) and, only beyond that, the stride played up to a seventh slower or faster (MOTION_RATE_SLOWEST, MOTION_RATE_FASTEST). Inside the band a stride's rate stays the take's own within a few hundredths; it is at its limit only at the band's very edge, and below from or above to the game is told (MotionPace.limited). from is counted from the slowest steady speed AS PERFORMED: a take the set plays faster than it was performed (its stated retime) serves its own slow pace too, played as the performer walked it (MotionStretch.performed).

On a set that carries a sprint part a run's and a sprint's to is counted otherwise: the fastest any of the gait's steady stretches goes when it is played a twentieth faster (MOTION_RATE_FASTEST_BESIDE_SPRINT), a fallback take's not faster at all, so to is a speed a take really reaches. A sprint's from likewise: the slowest any of its steady stretches goes, played a seventh slower.

gait ​
ts
readonly gait: number;

The gait's code (GAIT_WALK, GAIT_RUN or GAIT_SPRINT).

name ​
ts
readonly name: MotionGaitName;

Its name.

slowest ​
ts
readonly slowest: number;

The slowest and the fastest steady speed its takes show, metres a second: the tenth and the ninetieth of a hundred of its level frames' speeds, a level stretch counting only when a take holds it for a whole stride, about a second (a take's one fast patch is not a speed the character can hold). The takes of a set's getups part never count: a body crawling to its feet is no pace of a walk.

step ​
ts
readonly step: number;
to ​
ts
readonly to: number;

MotionBinaryHeader ​

A binary set's header: everything that is not a per-frame number.

Properties ​

bits ​
ts
bits: number[];

Per joint, the bits each stored number of its rotation has (10 to 15).

format ​
ts
format: "soma-motion-bin";
fps ​
ts
fps: number;

Frames a second, every take.

joints ​
ts
joints: string[];

The joints the takes move, in the order of the tracks.

rest ​
ts
rest: Record<string, unknown>;

Everything the text file says about the set outside its takes.

takes ​
ts
takes: MotionBinaryTake[];

The takes, in the order of their blocks.

version ​
ts
version: 1;

MotionBinaryIndex ​

A binary set's header as read, with where its takes end in the file.

Properties ​

bodyStart ​
ts
readonly bodyStart: number;

Where the body starts in the file, bytes.

ends ​
ts
readonly ends: readonly number[];

Per take (the header's order): the byte of the file its block ends before.

fileBytes ​
ts
readonly fileBytes: number;

The whole file's length, bytes.

ts
readonly header: MotionBinaryHeader;

MotionBinaryTake ​

One take in a binary set's header.

Properties ​

at ​
ts
at: number;

Its place in the text file's takes.

bytes ​
ts
bytes: number;
contacts ​
ts
contacts: boolean;

Whether the feet's contacts follow the root path.

frames ​
ts
frames: number;

How many frames.

name ​
ts
name: string;

The take's name.

offset ​
ts
offset: number;

Where its block starts in the body, and its length, bytes.

rest ​
ts
rest: Record<string, unknown>;

Everything else the text file says about the take (its module, tags, ranges, retime ...).

root ​
ts
root: object;

The root path: where its first frame is (x, y, z, metres) and the step it is stored in, metres.

start ​
ts
start: number[];
step ​
ts
step: number;
still ​
ts
still: number[][];

The joints that never move in it: the joint's index, then its rotation x y z w.

tracks ​
ts
tracks: object[];

The take's other per-frame tracks, in the order they follow in the block: where each sits in the take (['heading'], ['pivot', 'left']) and how it is stored (u8: a byte a frame; f32: a 32-bit number a frame).

kind ​
ts
kind: "u8" | "f32";
path ​
ts
path: string[];

MotionBodyReading ​

The body's own path, for reading a gait from the hips: see readMotionGaits.

Properties ​

feet ​
ts
readonly feet: Float32Array;

frames x 6: the ankles against the root, left then right, each x (to the left), y (over the floor) and z (ahead), metres.

hipsHeight ​
ts
readonly hipsHeight: Float32Array;

frames: the hips' height over the floor, metres.

turn? ​
ts
readonly optional turn?: Float32Array<ArrayBufferLike>;

frames: the body's turn to the next frame, radians, when it is known: a body turning on the spot is not standing (it is no place to idle, and no take's move-off).


MotionData ​

A motion set, packed: shared by every character that plays it.

Properties ​

asRead? ​
ts
readonly optional asRead?: object;

The takes the set plays faster than they were performed, AS THE FILE STORES THEM (as performed), for playing one at its own pace: rotations is those takes' frames as read (n x joints x 4, one take after another), and at says, per frame of the set, which of them it stands for (a frame and a fraction; -1 for a frame of a take that was not resampled, of the running part, or that the set says is never played as performed). A slow walk played from these is the performance itself, frame for frame, not the sped-up copy played slowly. Absent when the set has no such take.

at ​
ts
readonly at: Float32Array;
rotations ​
ts
readonly rotations: Float32Array;
contacts ​
ts
readonly contacts: Float32Array;

frames x 2: the feet's contacts the files state (left, right), 0 to 1; zeros where none is stated.

footSpeed? ​
ts
readonly optional footSpeed?: Float32Array<ArrayBufferLike>;

frames x 2: each foot's speed over the ground as the files state it (left, right), metres a second, at the pace the take is played; zeros where a take does not say.

fps ​
ts
readonly fps: number;
frames ​
ts
readonly frames: number;

Frames in all.

hips ​
ts
readonly hips: Float32Array;

frames x 3: the hips' path in each take's own world.

joints ​
ts
readonly joints: readonly string[];

The joints the takes move, in the order of MotionData.rotations.

kind ​
ts
readonly kind: string;
modules ​
ts
readonly modules: readonly string[];

The parts of the set kept (the takes' modules, in the order met).

name ​
ts
readonly name: string;
pivot? ​
ts
readonly optional pivot?: Float32Array<ArrayBufferLike>;

frames x 2: where the files state a foot on the ground is moving over it (left, right), 0 to 1; zeros where a take does not say (MotionTake.statedPivot).

refused ​
ts
readonly refused: readonly object[];

Takes left out, and why.

retimed? ​
ts
readonly optional retimed?: Float32Array<ArrayBufferLike>;

frames: how many frames of the take as it was PERFORMED each frame stands for: 1 where it is as read, the take's stated retime where it moves (1.26 on the walking frames of a take the set plays 1.26 times faster than it was performed), whether the factor was applied here or already in the file (applied: true). A steady stretch played that much slower goes as the performer did: its own slow walk (MotionStretch.performed). Absent when no take is retimed.

rotations ​
ts
readonly rotations: Float32Array;

frames x joints x 4: parent-local rotations as the takes state them.

takeOf ​
ts
readonly takeOf: Uint16Array;

Per frame, the index of its take.

takes ​
ts
readonly takes: readonly MotionTake[];

MotionDebug ​

What the layer is doing, for a debug view.

Properties ​

at ​
ts
at: number;

The same frame in the set's arrays (table.gaits.now[at]), or -1.

changeGap ​
ts
changeGap: number;
changeLifted ​
ts
changeLifted: boolean;
changeMissed ​
ts
changeMissed: string;

The last change made for want of a frame whose feet agree: the take gone to ('': none yet), how far the frame gone to had the worst foot that is down in both from where the body had it (metres), and whether a foot the body stood on was in the air there (or one it had in the air down).

changes ​
ts
readonly changes: Uint32Array;

With MotionLayer.changeEntry 'planted', the changes a body in motion has made since the layer was made: at the frame chosen; at another frame of its take near it; either of those after the take playing went on for it; and as 'matched' makes them, for want of a frame whose feet agree.

cost ​
ts
cost: number;

The last search's best cost.

frame ​
ts
frame: number;

The frame within it.

gait ​
ts
gait: MotionGaitName;

What the body is doing at that frame, and where the take is heading from it.

jumpFrom ​
ts
jumpFrom: number;

The last jump: where the body was in the set's arrays (between two frames: a fraction; -1: on no take) and the frame it went to (-1: no jump yet).

jumps ​
ts
jumps: number;
jumpTo ​
ts
jumpTo: number;
loops ​
ts
loops: number;

How many times it has gone round a stretch's loop since the layer was made (each is also counted in jumps).

matched ​
ts
readonly matched: Float32Array;

The same for the take playing.

own ​
ts
own: number;

The rate at which the frames playing go as the performer did: 1, or under 1 while a take the set plays faster than it was performed is played at its own performed pace (a slow walk). rate / own is how far the stride is off the performer's own rate.

rate ​
ts
rate: number;

How much faster or slower its strides are played right now to meet the speed asked for.

retime ​
ts
retime: number;

How much faster than it was read the take was made to play when the set was packed (1: as read).

root ​
ts
readonly root: Float32Array;

The drawn character's root: world x, z and facing.

searches ​
ts
searches: number;

Searches and jumps since the layer was made.

searchMs ​
ts
searchMs: number;

Milliseconds the last search took.

stretch ​
ts
stretch: number;

The steady stretch the body is going round (an index into table.gaits.stretches), or -1: see "a steady walk is one take going round" at the top of this file.

stride ​
ts
stride: number;

How much longer or shorter its steps are made right now to meet the speed asked for (1: as performed).

take ​
ts
take: string;

The take playing ('' when the body is the mixer's).

toward ​
ts
toward: MotionGaitName;
wanted ​
ts
readonly wanted: Float32Array;

The path asked for: three points (x, z) in the root's frame, then three facings (sin, cos).


MotionDecodeOptions ​

Which takes decodeMotionSet reads.

Properties ​

available? ​
ts
optional available?: number;

How many of the file's bytes are at hand (a file still arriving): only the takes whose blocks are whole within them are read. Default: all of bytes.

modules? ​
ts
optional modules?: readonly string[];

Only the takes of these modules (a take with no module counts as ''). Default: every take.


MotionDirection ​

A direction given to the layer from outside its search: an action (a jump, a hurdle) plays a range of a take, entered and left by the same carried jumps. Everything here is neutral until something sets it: a layer nobody directs behaves exactly as before.

Properties ​

hold ​
ts
hold: boolean;

While true no search runs: the take plays on from where it is. A take that ends is searched from anyway.

jumpTo ​
ts
jumpTo: number;

A frame of the set (an index into its arrays) to move to at the next update, carried like any jump; the body need not be moving. -1 for none. Taken once.

lookTo ​
ts
readonly lookTo: Float32Array;

A point for the head and the eyes to lead to, in place of the layer's own (world x and z; the third number 1 while it is given, 0 for none): MotionLayer.look is then this point at the head's height, said to be led to. A walk to a spot looks at the spot; a turn on the spot, at where it will face.

plain ​
ts
plain: boolean;

While true a jump is not carried by its speed: a plain ease from the last pose (for a comparison).

rate ​
ts
rate: number;

The take's clock: 1 plays as recorded, 2 twice as fast.

release ​
ts
release: boolean;

True: search at the next update and move to the best frame whatever plays. Taken once.

shift ​
ts
readonly shift: Float32Array;

Extra movement of the drawn body at the next update: world metres along x and z, radians of turn. Taken once.

stopStyle ​
ts
stopStyle: MotionStopStyle | "plain" | null;

The style of the stop while a walk sent to a spot has the body (MotionLayer.stopStyle's meaning), or null: the layer's own.

stride ​
ts
stride: number;

The take's travel over the ground, scaled: over 1 the strides are longer, under 1 shorter.


MotionEncodeOptions ​

How encodeMotionSet writes a set.

Properties ​

bits? ​
ts
optional bits?: number;

Bits per stored number of a rotation, 10 to 15. Default 15.

coarse? ​
ts
optional coarse?: (joint) => boolean;

Which joints are stored coarsely. Default: the fingers (Thumb, Index, Middle, Ring, Pinky).

Parameters ​
ParameterType
jointstring
Returns ​

boolean

coarseBits? ​
ts
optional coarseBits?: number;

The same for the joints coarse names. Default 10.

order? ​
ts
optional order?: readonly string[];

The order of the modules. Default MOTION_MODULE_ORDER.


MotionFootTurns ​

One foot as a body stands: its foot joint's turn and its toe joint's turn in the body's own frame (not against their parents), x y z w. Only where "up" lies in each is read.

Properties ​

foot ​
ts
foot: readonly number[];

The foot joint's turn.

toe? ​
ts
optional toe?: readonly number[];

The toe joint's turn; absent: the toe joint as the rig (or the set) has it on that foot.


MotionFrame ​

What update needs from the frame.

Properties ​

dt ​
ts
dt: number;

Seconds since the last update.

vx ​
ts
vx: number;

The velocity the game wants (or moves it at), world metres a second.

vz ​
ts
vz: number;
x ​
ts
x: number;

The game's place for the character (its capsule), world metres.

yaw ​
ts
yaw: number;

The game's facing for it, radians about +Y (0 faces +Z).

z ​
ts
z: number;

MotionGaits ​

A set's takes read for their gaits.

Properties ​

bands ​
ts
readonly bands: readonly MotionBand[];

The gaits that move, slowest first, each with the speeds it covers. Empty: the set only stands.

cadence ​
ts
readonly cadence: Float32Array;

Per take: its cadence over its level frames, steps a minute (0 when it has too few steps to say): what says a walk was performed at half pace, whatever the take is called.

entries ​
ts
readonly entries: readonly number[];
level ​
ts
readonly level: Uint8Array;

frames: 1 where the body's speed is level (a steady walk or run).

now ​
ts
readonly now: Uint8Array;

frames: the gait at the frame.

pace ​
ts
readonly pace: Float32Array;

frames: the body's speed around the frame (the mean over a second), metres a second.

rests ​
ts
readonly rests: number;

How many frames a body may idle on (rest), and, by the gait's code, how many it may enter a walk, a run and a sprint at (the first, standing's, is 0).

runToWalk ​
ts
readonly runToWalk: boolean;
serves ​
ts
readonly serves: Uint16Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike>;

frames: what the frame serves, bits of MOTION_SERVES. A byte a frame, as ever, on a set without a sprint part; two bytes a frame on a set that carries one (the sprint's three bits lie above a byte).

sprints ​
ts
readonly sprints: boolean;

Whether the set carries a sprint part (MOTION_SPRINT_MODULE): takes that are the sprint gait's.

standOf ​
ts
readonly standOf: Int16Array;

frames: the index of the frame's stand in MotionGaits.stands, or -1.

stands ​
ts
readonly stands: readonly MotionStand[];

Every stand of half a second or more, in the order of the frames.

stretches ​
ts
readonly stretches: readonly MotionStretch[];

Every steady stretch (level frames in one gait), in the order of the frames.

stretchOf ​
ts
readonly stretchOf: Int16Array;

frames: the index of the frame's steady stretch in MotionGaits.stretches, or -1.

toward ​
ts
readonly toward: Uint8Array;

frames: the gait the take is heading to from the frame.

unsteady ​
ts
readonly unsteady: Float32Array;

frames: how little steady going the take has left from the frame, 0 to 1: 0 with four seconds or more of level frames in its gait (or of standing) ahead, 1 with none (a move-off, a slow-down, the last stride before one). A body asked to keep going steadily, or to keep standing, prefers a frame with a long way to go when it has to move on, so it settles on a take's long steady stretch (or a long stand) instead of circling in the last stride of a short one.

walkToRun ​
ts
readonly walkToRun: boolean;

Whether the set has a take that speeds up from a walk into a run, and one that slows from a run into a walk.


MotionLayer ​

A character moved by matching whole takes.

Properties ​

begun ​
ts
readonly begun: boolean;

Whether the layer has made an update since it was made, reset or shut (on, gate). Until it has, it knows no facing of the body's: at its first update it takes the game's facing as the body's own. A game that turns its facing far in the very frame the layer begins has the body drawn turned with it; a walk sent to a spot waits for this before it turns the game's facing for a turn on the spot.

carried ​
ts
readonly carried: Float32Array;

The take's own share of MotionLayer.velocity: how the take playing moves and turns the body this frame, before the body is drawn back toward the game's place and facing. A game that moves its walker by this (instead of by its own speed) lets the take carry the character: nothing slides, a start or a stop takes the time the performer took, and the body is drawn back to the walker wherever the game could not move it as far as it was carried. A game that steers its walker itself adds its own turn to THIS turn (to the whole velocity it would add the layer's answer to its own steering, and turn twice).

changeEntry ​
ts
changeEntry: "matched" | "planted";

Where a body IN MOTION goes over to another take, or to another place of its own: a walk to another walk, into a curve or a turn, into a stop or a small step, and a run the same; whether the layer's search chose the frame or an action named it (direction.jumpTo). 'matched' (the default): at the frame chosen, the moment it is chosen, whatever foot the body stands on: that foot may be a hand's length or more from where the frame has it against the body, or in the air there, and travels that far over the floor as the take changes (a hold of the feet hides it for a moment and lets it go as a glide). 'planted': only at a frame where the same feet are down as in the frame playing and each is within 3 cm of where the frame playing has it against the body (the takes' own reading of the feet, as stopEntry reads them: the drawn foot is not asked). When the frame chosen is not such a one: the nearest frame of its take within half a second of it that is, and that still makes the turn asked (the turn that take makes by itself from there is no more than 10 degrees further from the turn asked than the chosen frame's). When there is none, a WALK that is asked to go on or round (not to stop) goes on in the take playing, and the change is tried again at every update with whatever frame is then chosen, for one stride at the most (until 0.15 s after its second footfall, and never longer than 1.5 s): it turns that much later and further on. When none has agreed by then, or the take playing is at its end, or the body runs, or the frame heads for a stand (a stop begun a stride late stands a stride past where it was asked; a run's stride is two metres and more): the change is made as 'matched' makes it, and counted with the take's name and the foot's gap (debug.changes, debug.changeMissed, debug.changeGap), so the takes a set lacks can be named. A WALK SENT TO A SPOT looks for its stop a stride ahead instead, as stopEntry 'planted' does, and enters it at its footfall. No step is made longer or shorter for it and no take is retimed: only WHEN the take changes, and at which of its frames. While a change waits a search is made at every update. Not touched: a body that stands (a move-off, a turn on the spot), the loop of a steady stretch going round, a run entered under way (enterRun), a performance (play). Read at every change.

contacts ​
ts
readonly contacts: Float32Array;

Per foot (left, right), 1 while the take playing says it is down.

cursor ​
ts
readonly cursor: number;

The frame playing, as an index into the set's arrays (between two frames: a fraction), or -1.

debug ​
ts
readonly debug: MotionDebug;
direction ​
ts
readonly direction: MotionDirection;

What an action asks of the layer: see MotionDirection.

engaged ​
ts
readonly engaged: boolean;

Whether a take has the body this frame.

gate ​
ts
gate: number;

1 lets the layer work; 0 shuts it at once (a physics body reacting to a hit).

look ​
ts
readonly look: Float32Array;

Where the body is about to go: a world point (x, y, z) some metres along the way asked for, at the head's height, and in the fourth number 1 while the head and the eyes should lead there (from the moment a standing body is asked to go, and whenever the way asked for is well off the way it faces), else 0. An animator with a life layer looks there unless the game has named something to look at.

naturalness ​
ts
naturalness: number;

See MotionLayerOptions.naturalness.

offset ​
ts
readonly offset: Float32Array;

Where the drawn character stands against the game's place: x, z (world metres) and the turn (radians about +Y). The host applies it to whatever holds the rig and the points.

on ​
ts
on: boolean;

The switch: off, the layer writes nothing.

pace ​
ts
readonly pace: Readonly<MotionPace>;

What the speed asked for came to on this set: the gait it is moved in, the speed given, and whether the set does not cover the speed asked (limited: the character then moves at given, the nearest speed its takes cover; a game that needs it faster needs takes that are).

performing ​
ts
readonly performing: boolean;

Whether a performance asked for with MotionLayer.play is being played through.

responsiveness ​
ts
responsiveness: number;

See MotionLayerOptions.responsiveness.

speed ​
ts
readonly speed: number;

The speed of the take playing, metres a second.

standing ​
ts
readonly standing: "set" | "own";

What the body stands on: see MotionLayerOptions.standing.

steadyPace ​
ts
readonly steadyPace: number;

The pace a stop's style is chosen by (MotionLayer.stopStyle), metres a second: a run's STEADY pace, the same at every moment of its stride. While the body goes round a steady stretch of its set and has played a whole stride of it: the pace that stride is played at (the stretch's own pace, by the rate and the length of step the layer plays it with: the speed asked, as far as the stride has been eased to it). Until then (a body still moving off, or just come onto the stretch from another pace: what a jump carried of its speed has not died away), and in any take that is no steady stretch: the body's own speed at this instant. The speed at the instant rises and falls through every stride (by 5 to 13 percent on the shared set's runs): read alone, one steady run near a style's lowest pace was stopped by the style at some moments of its stride and by the takes that state none at others. A walk sent to a spot reads the same number.

stop ​
ts
readonly stop: Readonly<MotionMatch>;

The stop MotionLayer.stopTravel last found: its frame in the set's arrays (-1: none) and how well the body would be carried into it (the search's cost). A walk sent to a spot takes the body to that very frame when its travel is what is left, so the stop it measured is the stop it walks.

stopEnd ​
ts
stopEnd: "corrected" | "short";

Where a walk sent to a spot ends its stop. 'corrected' (the default): as ever, the stop the body is carried into best is taken while its steps can be made to end on the spot, and when it stands more than 15 cm off, one more step of the set puts it right (ahead, back or to a side). 'short' (off unless a game states it): no step is taken after the stop, the body stays where its stop leaves it; and with takes played as performed (takesPlayed other than 'fitted') the stop is begun where its own travel, as performed, ends at the spot or short of it (5 cm past counts as at it): a stop that would carry the body past the spot is left for one that does not, and of those the one that ends nearest weighs most. Nothing is made longer, shorter, quicker or slower for it: only which stop is taken and when it is begun. What is left is how far short of the spot the nearest such stop ends. Read by the walk at every update.

stopEntry ​
ts
stopEntry: "matched" | "planted";

Where a WALK sent to a spot enters its stop. 'matched' (the default): at the frame the body is carried into best the moment that stop's travel is what is left, whatever foot the walk is on: a foot the walk has planted may be a hand's length from where the stop's frame has it against the body, and travels that far over the floor as the take changes. 'planted': the stop is looked for a stride ahead and waited for, and entered at a frame where the same feet are down as in the walk and each planted foot is where the walk has it against the body (within 3 cm), and which leaves a later hold of the feet a foot to place: no foot is down that stays down until the stand, and a foot in its last time in the air has a fifth of a second of it left. The walk's own steps until then are made up to a tenth longer or shorter, so the stop's own are nearer as performed, and a stop whose own planted feet travel more than 12 cm by the take itself is not entered so. Such a stop is a step longer than the one 'matched' takes: it begins earlier and the body stands a little later. Where no such frame ends on the spot: the frame that leaves a foot to place whose planted foot is nearest; then one that passes the spot by no more than 15 cm; only where the set has none of these for the way left, as 'matched'. A run's stop, a stick let go and a walk of one take from stand to stand are not touched by it. Read while the walk looks for its stop.

stopFoot ​
ts
stopFoot: "any" | "landed";

Which feet the stop a walk sent to a spot FALLS BACK ON may have down. A walk takes the stop the layer's search finds the moment that stop's travel is what is left; when that stop has become too long for what is left it takes, of the stops that still end on the spot, the one the body is carried into best (and a quick arrival at a run always chooses so). 'any' (the default): whatever foot the body is on, as before; the frame may have down a foot the body has in the air. 'landed': never such a frame. A foot is in the air when the take playing has it up at its frame, does not set it down within a fifth of a second, and has its ankle more than 3 cm higher over the floor than the stop's frame has it (the take's own reading: the drawn foot is not asked, so a body still blending from another take is not covered). While only such frames end on the spot the walk goes on, for half a second in one walk at the most; then its stop is left to the layer's own search from where the body is, and the plan says limited. The stop the search itself finds is not touched by it. Read while the walk looks for its stop.

stopQuery ​
ts
readonly stopQuery: Float32Array;

The request MotionLayer.stopTravel last made, as the set's table scales it: what motionCost compares a frame with. Good until the layer's next update.

stopStyle ​
ts
stopStyle: MotionStopStyle | "plain";

How a body in motion asked to stand comes to its stand: 'gradual' (the default: it slows and stands upright), 'hard' (it brakes), or 'plain'. A set says which of its takes are stops of a style (a take's stopStyle: such a take is that stop and nothing else). A running body asked to stand is answered ONLY by the stops of the style asked, whatever its pace, where the set has one for a run; where it has none (a set that states no style, a walk's stop, a sprint's stop on the shared set) and for 'plain', it is answered by the takes that state no style, exactly as the set answers without its styled stops. A stop of a style is played to its own stand before the body is handed back to its stance. Read when the stop is chosen: a stop under way is played on. A walk sent to a spot states its own meanwhile (direction.stopStyle).

stride ​
ts
stride: number;

How long the take's steps are made: its travel over the ground times this (1: as performed; with what a steady stride's steps are made to meet the speed asked, kept between 0.7 and 1.35). Only the length of a step changes, never its timing, and with the feet's layer on a planted foot still stands still: what a walk sent to a spot lands its last step with.

table ​
ts
readonly table: MotionTable;

The set in force.

takesPlayed ​
ts
takesPlayed: "performed" | "fitted" | "chosen";

Whether a take may be played other than it was performed. 'fitted' (the default): as ever, a stride's steps are made longer or shorter and its clock slower or faster for the pace asked, the walk makes a stop's and a near spot's steps longer or shorter to end on the spot, and a turn is made larger or smaller for the angle asked. 'performed' (a TRIAL, off unless told): none of that reaches a take. Every step is as long as the performer's, every take goes at the performer's clock and every turn turns what the performer turned; the pace asked, the spot and the angle are met only by which take is played and when it is begun, and what that leaves stays: the body goes at the nearest performed pace and stands where the stop's own steps end. 'chosen' (a TRIAL): the same, and the walk makes its choices for it: a stop is begun at the moment its own travel ends nearest the spot, and a stop entered on the planted foot is chosen with the walk's steps as performed. An action's own scales are left as they are.

turn ​
ts
turn: "easy" | "quick";

See MotionLayerOptions.turn.

turnEntry ​
ts
turnEntry: "whole" | "turning";

Where a marked turn on the spot is entered. 'whole' (the default): at its first frame, the performer's wind-up and all. 'turning': where its turning begins, a tenth of a second before the take turns the body faster than 60 degrees a second (or, an unhurried turn, before it has turned it 5 degrees), the inertial blend covering what is left out: for a body that must be off at once (a walk sent to a spot sets it for a turn before a run, or a quick arrival, and sets it back).

turnScale ​
ts
turnScale: number;

The same for the take's turning: its turn times this (kept between 0.5 and 1.6).

turnStarts ​
ts
turnStarts: boolean;

Whether the quick turning starts a set states are chosen by the angle asked. Off (the default), nothing is chosen by them. On: a standing body asked a velocity well off its facing enters the stated start whose turn serves the way (made a little smaller or larger, up to 15 degrees left to be steered) and is left on it until its turn is made; a walk sent to a spot counts such a start for an angle up to 15 degrees beyond what its own turn makes, and of two starts that have the body travelling as soon takes the one whose own turn is nearer the angle. A set that states none is not touched by it.

turnUnderWay ​
ts
turnUnderWay: "performed" | "steered";

How a body already running is brought round when a walk sends it to a spot well off its way. 'steered' (the default): as ever, the game's facing is steered to the spot and the drawn body follows it. 'performed' (off unless a game states it): when the set holds a take that states a turn under way at a run to that side (MotionTakeSource.turnUnderWay) and the spot lies between about 25 degrees off his way and the angle from which the set's turning takes already answer (about 80), the walk enters that take at a landing of the foot it begins on, where the planted foot agrees (within 3 cm against the body, within a stride; never part-way into it), plays it as performed, turns the game's facing only as the take turns the body, and leaves it for the run at the last landing from which it does not carry him past the way to the spot (by more than 5 degrees; what is still to turn then is steered). Nothing is made longer, shorter, quicker or slower for it. When it cannot be entered (no such take to that side, no agreeing landing within a stride, no room for its arc and the stop after it) the run is steered as ever and the plan says limited. Read by the walk when it is sent.

velocity ​
ts
readonly velocity: Float32Array;

How the body moves this frame: world metres a second along x and z, and its turn in radians a second: the take's own travel AND the pull that draws the body back toward the game's place and facing. What the feet's layer reads as the body's speed. A game that lets the take carry its walker moves the walker by MotionLayer.carried, not by this: a place moved by the pull toward itself moves away from the body as fast as the body comes, so a distance between the two never closes and carries the place on for as long as it lasts (a standing character glides).

Methods ​

enterRun() ​
ts
enterRun(
   foot, 
   ahead, 
   speed
): void;

Start in the set's steady run, in step and at speed: for a body that comes RUNNING out of something else that had it (a get-up's take that ends in a run). At the next update the layer is on the steady stretch of the gait asked for then (a run or faster; when a walk or nothing is asked then: the run that covers speed, or on a set without one the steady stride of the gait asked), at the place of its stride from which foot comes down ahead seconds later, its strides played for speed at first and eased to the speed asked as ever. Nothing is carried from the pose the bones hold (no move-off, no blend from a stand): the caller cross-fades what it drew over the run. Forgotten when the layer is shut at the next update, or the set has no steady stretch with a loop for that gait (the body then moves off as from a stand).

Parameters ​
ParameterTypeDescription
footnumberThe foot that comes down next: 0 the left, 1 the right.
aheadnumberSeconds until it does.
speednumberMetres a second the body travels now.
Returns ​

void

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

Play a take through as one performance: the body is carried to the frame at once (eased, as into a move-off) and the take plays on undisturbed, whatever is asked meanwhile, until it stands again after having moved (or ends). Then the layer goes back to matching, and stride and turnScale go back to 1. For a move the game has chosen whole: a few steps to a spot, a turn on the spot.

Parameters ​
ParameterTypeDescription
framenumberThe frame to start at, in the set's arrays (a stand's frame, usually).
Returns ​

void

reset() ​
ts
reset(): void;

Forget everything at once (a teleport): the body is the mixer's, the offset zero.

Returns ​

void

restore() ​
ts
restore(): void;

Take last frame's writing off the bones the mixer did not write since. Before the mixer.

Returns ​

void

setTable() ​
ts
setTable(table): void;

Another set (a table read on this rig): the body moves over to it by an inertial blend. When the new set holds the very take that is playing (the rest of a set that came in parts), the body plays on from the same frame of it.

Parameters ​
ParameterTypeDescription
tableMotionTableThe table.
Returns ​

void

stopTravel() ​
ts
stopTravel(frame): number;

If the body were asked to stand now: how far the stop the layer would choose still travels before it stands, metres (-1 when the set has no stop for it). Nothing is changed by asking. What a walk sent to a spot begins its stop by.

Parameters ​
ParameterTypeDescription
frameMotionFrameThe game's place and facing (its velocity is not read).
Returns ​

number

update() ​
ts
update(frame): void;

Match, play and write the pose. After the mixer, before the life and the feet.

Parameters ​
ParameterTypeDescription
frameMotionFrameThe game's place, facing and wanted velocity.
Returns ​

void


MotionLayerOptions ​

Options for createMotionLayer.

Properties ​

blendSeconds? ​
ts
optional blendSeconds?: number;

Seconds a jump's offset takes to die away. Default 0.25.

changeEntry? ​
ts
optional changeEntry?: "matched" | "planted";

Where a body in motion goes over to another take: 'matched' (the default) or 'planted'. See MotionLayer.changeEntry.

mayLook? ​
ts
optional mayLook?: (must) => boolean;

Asked before every search, so a host with many characters can spread their searches over its frames. must is true for a search that cannot wait (the body has no frame, its take has run out, the frame playing no longer serves what is asked, or the request changed sharply): it is made whatever the answer, and the call only lets the host count it. For a search that is merely due (a tenth of a second since the last), answer false to put it off to the next frame; it stays due until it is made.

Parameters ​
ParameterType
mustboolean
Returns ​

boolean

naturalness? ​
ts
optional naturalness?: number;

How far the drawn character may leave the game's place and facing to move as the take does, 0 to 1 (default 0.6): 0 glues it to the game's place (the feet then slide to keep up), 1 lets the take carry it up to 1.5 m and half a turn away.

onOffset? ​
ts
optional onOffset?: (x, z, turn) => void;

Told every update where the drawn character stands against the game's place (world metres along x and z, and the turn in radians): the host moves whatever holds the rig and the points by it, before the layers after this one read the bones in the world.

Parameters ​
ParameterType
xnumber
znumber
turnnumber
Returns ​

void

ownHands? ​
ts
optional ownHands?: boolean;

Keep the fingers as the character's own (default true): as the rig holds them when the layer is made (its captured hand pose), whatever the takes say. A take's read places the fingers differently from the character's own hand pose, and nothing in standing, walking or running needs them.

poseAdjust? ​
ts
optional poseAdjust?: PoseAdjustRecord | null;

The character's own pose adjustment (its package's poseAdjust, read by parsePoseAdjust): laid on every pose read from a take, before the blend, so a take is drawn as the character's own clips already are. The mixer's pose (the character's own stand and clips, which carry it already) is never touched. Omit for none: the takes are then written as stored.

responsiveness? ​
ts
optional responsiveness?: number;

How hard the search follows the game's request, 0 to 1 (default 0.6): higher, the path and the facing asked for are expected sooner, so sharper takes are chosen.

root ​
ts
root: Object3D;

The rig root: the character's own frame, the bones under it.

searchSeconds? ​
ts
optional searchSeconds?: number;

Seconds between searches. Default 0.1.

standing? ​
ts
optional standing?: "set" | "own";

What the body stands on. 'own' (default): the mixer's pose, which is the character's own captured stance and idle; the body is eased from it into a take at the take's move-off and settles back into it a quarter of a second after a stop has come to rest. 'set': the set's own standing (the takes' stands, an idle take), never handed back.

stopEnd? ​
ts
optional stopEnd?: "corrected" | "short";

Where a walk sent to a spot ends its stop: 'corrected' (the default) or 'short'. See MotionLayer.stopEnd.

stopEntry? ​
ts
optional stopEntry?: "matched" | "planted";

Where a walk sent to a spot enters its stop: 'matched' (the default) or 'planted'. See MotionLayer.stopEntry.

stopFoot? ​
ts
optional stopFoot?: "any" | "landed";

Which feet the stop a walk sent to a spot falls back on may have down: 'any' (the default) or 'landed'. See MotionLayer.stopFoot.

stopStyle? ​
ts
optional stopStyle?: MotionStopStyle | "plain";

How a body in motion asked to stand comes to its stand, where the set has stops that state a style (a take's stopStyle): 'gradual' (the default), 'hard', or 'plain'. See MotionLayer.stopStyle.

table ​
ts
table: MotionTable;

The set, read on this rig (buildMotionTable).

takesPlayed? ​
ts
optional takesPlayed?: "performed" | "fitted" | "chosen";

Whether a take may be played other than it was performed: 'fitted' (the default), 'performed' or 'chosen'. See MotionLayer.takesPlayed.

turn? ​
ts
optional turn?: "easy" | "quick";

The pace of a turn on the spot, where the set marks its turns by pace (MotionTable.turns): 'quick' (the default: a game that turns a standing character's facing itself, under a stick) or 'easy' (an unhurried turn: a character in a room, a walk sent at a stroll). The other pace is taken where the one asked has no turn that covers the angle. A set that marks no turns is not touched by it.

turnStarts? ​
ts
optional turnStarts?: boolean;

Whether a start its take states as a quick turning start (turnStart, borne out by the take: MotionTable.starts) is chosen by the angle asked. Default false: a set's starts are chosen as they were before the set stated any. See MotionLayer.turnStarts.

turnUnderWay? ​
ts
optional turnUnderWay?: "performed" | "steered";

How a body already running is brought round when it is sent well off its way: 'steered' (the default) or 'performed'. See MotionLayer.turnUnderWay.


MotionLegNames ​

One leg of a rig, by bone name, for buildMotionTable.

Properties ​

foot ​
ts
foot: string;
shin ​
ts
shin: string;
thigh ​
ts
thigh: string;
toe ​
ts
toe: string;

MotionMatch ​

What a search found.

Properties ​

cost ​
ts
cost: number;

Its cost: the squared distance between its features and the query's.

frame ​
ts
frame: number;

The frame, or -1 when the table has none to land on.


MotionPace ​

What a speed asked for comes to on a set.

Properties ​

asked ​
ts
asked: number;

The speed asked for, metres a second.

gait ​
ts
gait: number;

The gait it is moved in: GAIT_STAND, GAIT_WALK, GAIT_RUN or GAIT_SPRINT.

given ​
ts
given: number;

The speed given: the one asked for when the set covers it, else the nearest it covers below.

limited ​
ts
limited: boolean;

Whether the set does not cover the speed asked for.


MotionParseOptions ​

What parseMotionSet keeps of a file.

Properties ​

maxRetime? ​
ts
optional maxRetime?: number;

The most a take may have to be played faster than it was read (its stated retime) to be kept. Default 1.6: a walk performed at under about 60 % of a natural pace is left out and listed in refused, because playing it faster brings its cadence up but leaves its steps as short as they were performed.

modules? ​
ts
optional modules?: readonly string[];

The parts of the set to keep, by the takes' module: a character that only walks keeps ['idle', 'walk'], one that only runs ['idle', 'run'], one that does both adds 'blend' (the takes that go from one to the other), one that sprints 'sprint'. Absent: every part but actions (takes with an object in them are not for getting about). A take that names no module is always kept.


MotionRigJoint ​

One joint of a MotionRigSnapshot.

Properties ​

name ​
ts
name: string;

The joint's name.

parent ​
ts
parent: number;

Its parent's place in the snapshot's list, or -1 for a child of the rig's root.

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

Its place and turn against its parent, and its scale: x y z, x y z w, x y z.

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

MotionRigNames ​

What a rig calls the joints the table is read by.

Properties ​

hips ​
ts
hips: string;

The pelvis: the joint a take's root path places.

legs ​
ts
legs: readonly [MotionLegNames, MotionLegNames];

The legs, left then right.


MotionRigSnapshot ​

The joints a motion table reads, as plain numbers: parents before children.

Properties ​

joints ​
ts
joints: MotionRigJoint[];

MotionSetSource ​

A motion set file (soma-motion).

Properties ​

format ​
ts
format: "soma-motion";
kind? ​
ts
optional kind?: string;

The kind of game it is for (third-person, shooter ...), when it says (else set.template).

name? ​
ts
optional name?: string;

The set's name: what a game picks it by (set.id stands in when the file has no name).

set? ​
ts
optional set?: object;

The studio's own naming of the set.

id? ​
ts
optional id?: string;
template? ​
ts
optional template?: string;
takes ​
ts
takes: MotionTakeSource[];
version ​
ts
version: 1;

MotionSpotTurn ​

A turn on the spot a set marks: a stretch of a take that begins standing, turns the body round by stepping and ends standing.

Properties ​

from ​
ts
readonly from: number;

Its first frame (the last standing frame before the turn) and the frame it ends on (the first standing frame after), in the set's arrays.

quick ​
ts
readonly quick: boolean;

Whether it was performed quick (else easy).

seconds ​
ts
readonly seconds: number;

Seconds from from to to.

take ​
ts
readonly take: number;

The take's index.

to ​
ts
readonly to: number;
turn ​
ts
readonly turn: number;

How far it turns the body in all, radians (left positive): the take's own root turn over it on this rig.


MotionStand ​

A stretch of a take in which the body stands.

Properties ​

first ​
ts
readonly first: number;

Its first and last frame in the set's arrays.

last ​
ts
readonly last: number;
leaves ​
ts
readonly leaves: number;

The gait the take moves off into after it (GAIT_WALK, GAIT_RUN, GAIT_SPRINT), or 0 when it stays.

take ​
ts
readonly take: number;

The take's index.


MotionStarts ​

Every move-off of a set, read from the takes themselves: see readMotionStarts.

Properties ​

ofStand ​
ts
readonly ofStand: Int32Array;

Per stand of MotionGaits.stands: where its move-off's numbers begin in values, or -1 when it is none.

values ​
ts
readonly values: Float32Array;

MOTION_START.numbers numbers per move-off, in the order of the stands.


MotionStretch ​

A stretch of a take in which the body holds one gait at a level speed, and the loop a long walk (or run) goes round in it.

Properties ​

cadence ​
ts
readonly cadence: number;

Its own cadence over the loop, steps a minute (two to a stride), 0 without a loop.

fallback ​
ts
readonly fallback: boolean;

Whether its take is one the set marks as a fallback.

first ​
ts
readonly first: number;

Its first and last level frame in the set's arrays.

from ​
ts
readonly from: number;

The loop: playing reaches to with the body where it was at from in its stride (the same foot down, the same place in the step, the same speeds), a whole number of strides later, so it goes on from from with nothing to see. Both -1 when the stretch has no such pair (it is shorter than a stride, or the body's reading was not given).

gait ​
ts
readonly gait: number;

The gait held (GAIT_WALK, GAIT_RUN or GAIT_SPRINT).

last ​
ts
readonly last: number;
pace ​
ts
readonly pace: number;

Its own pace: the body's travel over the loop by its time, metres a second (over the stretch, without a loop).

performed ​
ts
readonly performed: number;

How fast its frames are played to go as the performer did: 1 for a take as read, under 1 for a WALK the set plays faster than it was performed (0.79 for a stated retime of 1.26; a run is always 1: it is played as the set stores it). At that rate its pace is pace * performed and its cadence cadence * performed: the slow walk that was performed, which a slow pace asked for is answered with.

seconds ​
ts
readonly seconds: number;

Seconds once round the loop (0 without one).

take ​
ts
readonly take: number;

The take's index.

to ​
ts
readonly to: number;
turn ​
ts
readonly turn: number;

How much the take itself turns the body over the loop, radians a frame: a performer never walks dead straight. A body asked to keep going as it is leaves this out, so its heading is its own and the stretch goes round without curving away.


MotionTable ​

A motion set read on one rig: what a character plays and matches.

Properties ​

ahead ​
ts
readonly ahead: Float32Array;

frames x 12: the path ahead as read (3 x (x, z), then 3 x (sin, cos) of the facing), unscaled.

buildMs ​
ts
readonly buildMs: number;

Milliseconds the table took to build.

contacts ​
ts
readonly contacts: Uint8Array;

frames x 2: 1 while the foot (left, right) is down: on the ground AND planted. A foot the take has on the ground but travelling over it (the step out that opens a start to the side, a shuffle, a pivot in a turn on the spot, a first step leaving late) is not down while it travels, and is down again from where it comes to rest.

data ​
ts
readonly data: MotionData;
down ​
ts
readonly down: Float32Array;

frames x 2: how much the foot is down, 0 to 1 (down from a half). Read between two frames it gives a landing and a lift between frames: a run's foot is down for only two or three frames of a take. What the feet's layer holds a foot by.

features ​
ts
readonly features: Float32Array;

frames x MOTION_FEATURES: normalised and weighted.

feet? ​
ts
readonly optional feet?: MotionTableFeet;

With feet: 'own' (MotionTableOptions.feet): the fixed turns that lay a take's ankle and toe turns on her own stand's sole. Absent otherwise: a take's feet are played as performed.

footYaw ​
ts
readonly footYaw: Float32Array;

frames x 2: how the foot (left, right) points over the floor against the root's facing, radians (left positive): the line from its ankle to its ball, as the take has it on this rig. What a stop entered on a planted foot is compared by, so that a foot on the floor is not asked to turn there.

gaits ​
ts
readonly gaits: MotionGaits;

The takes read for their gaits: standing, walking or running at every frame (sprinting, in the takes of a set's sprint part), where each frame is heading, what it serves, the stands, and the speeds the set covers.

hipsJoint ​
ts
readonly hipsJoint: number;

The pelvis' index in the set's joints.

hipsPosition ​
ts
readonly hipsPosition: Float32Array;

frames x 3: the hips against the root (x to the character's left, y over this rig's floor, z ahead).

hipsRotation ​
ts
readonly hipsRotation: Float32Array;

frames x 4: the hips' rotation against the root's facing.

matchable ​
ts
readonly matchable: Uint8Array;

frames: 1 where a search may land (the take goes on long enough from there).

matchableCount ​
ts
readonly matchableCount: number;

How many frames a search looks at.

mean ​
ts
readonly mean: Float32Array;

Per feature: its mean and the scale it was multiplied by ((raw - mean) * scale).

penalty ​
ts
readonly penalty: Float32Array;

frames: what a frame costs a search before anything is compared: MOTION_FALLBACK_COST on the frames of a take the set marks as a fallback, 0 elsewhere.

rootSpeed ​
ts
readonly rootSpeed: Float32Array;

frames: the root's speed over the ground, metres a second.

rootStep ​
ts
readonly rootStep: Float32Array;

frames x 3: the root's step to the next frame, in its own frame (x, z) and its turn (radians).

scale ​
ts
readonly scale: Float32Array;
standing ​
ts
readonly standing: Float32Array;

The feet and the hips of this rig standing at rest, as a query states them (features 12 to 26, raw: the feet's places against the root, every speed zero): what the body is doing before any take has it.

starts ​
ts
readonly starts: MotionStarts;

Every move-off of the set (a stand a take leaves into a walk, a run or a faster gait and holds it), read off the takes: how far each turns the body as it starts, how soon it is moving, by which frame its turn is made, how far before it is up to its pace (MOTION_START). What a walk sent to a spot and a standing body asked a velocity choose a start that turns by.

stopStyle ​
ts
readonly stopStyle: Uint8Array;

frames: the code of the stop style (MOTION_STOP_STYLES) on every frame at which a stop of that style may be ENTERED: a frame of a take that states the style, in its slow-down to a stand and before its brake (MOTION_STOP_ENTRY); 0 everywhere else. No frame of such a take is matchable: no search finds it, only a body asked to stand in that style is answered with it (MotionLayer.stopStyle).

stopStylePace ​
ts
readonly stopStylePace: Float32Array;

Per stop style's code: the pace its stops are run into, metres a second (the slowest run-in among the takes that state it; 0: the set has no stop of that style). A run whose steady pace is under MOTION_STOP_RATE_LEAST of it is not answered by that style (motionStopStyleAnswers).

toStand ​
ts
readonly toStand: Float32Array;

frames x 2: what the take still does from the frame before it next stands: the metres its body travels and the radians it turns (left positive). 0 and 0 where it stands; the travel is -1 where the take ends before it stands again. What a walk sent to a spot fits its last steps by, and how a turn on the spot is chosen for an angle.

travel ​
ts
readonly travel: Float32Array;

Per take: the share of the body's travel as read that its feet account for (1: the feet carry the body exactly as far as it travels). A read from a clip often has the body travelling further than its legs step, the foot it stands on sliding forward under it: the take's travel is brought down by what its time on the ground says is too long (its travel in the air, a run's flight or a jump, is not counted as too long), evenly over the take, so a planted foot is still in the world and the speed is the one the strides really make. Takes of the actions part are never touched.

tree ​
ts
readonly tree: MotionTree;

The matchable frames sorted into a tree of boxes, so a search need not look at every frame: the features are turned onto the axes the frames differ along most, frames alike sit together in a leaf, each leaf and each branch knows the lowest and highest value on every axis inside it, and a branch whose box is already further from the query than the best frame found is passed over whole. The answer is the one a look at every frame gives (to the last digit a 32-bit number holds); only the time differs.

turnAt ​
ts
readonly turnAt: Int16Array;

frames: the index in MotionTable.turns of the marked turn a frame is in (from to before to), or -1.

turnLeft ​
ts
readonly turnLeft: Float32Array;

frames: inside a marked turn, how far the take still turns the body before the turn's end, radians (left positive); 0 elsewhere.

turns ​
ts
readonly turns: readonly MotionSpotTurn[];

The turns on the spot the set marks (MotionTakeSource.turns), read on this rig. Such a stretch is a turn on the spot and nothing else: no search lands inside it (it is not a walk, however fast the hips travel in a quick pivot), the stand before it is no move-off into a walk or a run, and a standing body asked to face another way is given it whole, from from to to. Empty for a set that marks none.


MotionTableFeet ​

With feet: 'own' (MotionTableOptions.feet): the fixed turns a layer lays on a take's pose so her soles lie as her own stand's. For each foot k (0 left, 1 right): foot = take's foot x turns[k * 2] and toe = inverse(turns[k * 2]) x take's toe x turns[k * 2 + 1].

Properties ​

joints ​
ts
readonly joints: Int16Array;

The set's joints: left foot, left toe, right foot, right toe; -1 for one the set does not move.

turns ​
ts
readonly turns: Float32Array;

Four turns, x y z w each: the left foot's, the left toe's, the right foot's, the right toe's.


MotionTableOptions ​

Options for buildMotionTable.

Properties ​

feet? ​
ts
optional feet?: "performed" | "own";

How a take's ankle and toe turns are laid on HER feet.

  • 'performed' (the default; absent is the same, to the last number): the performer's joint turns as they stand, written onto her foot and toe joints. A character whose foot joint rests turned otherwise than the performer's flat foot (a skeleton made standing on a raised heel, a shoe) then has her sole tilted by that difference on every frame of every take: toes up, the ball off the floor, no heel-off.
  • 'own': the same turns laid on HER OWN stand's sole: one fixed turn for each foot joint and each toe joint, such that where the performer's foot lies flat her sole lies as it lies in her own stand, and her toes likewise. Nothing is made flat: the roll from the heel's landing to the toes' leaving, and the toes' bend, stay the move's own, frame for frame. Only the sole's plane is matched (by the shortest turn), so where her feet point is not changed. The table's own reading of her soles (the floor under a run, the stand by her sole) is by the foot so laid, and the table carries the turns (MotionTable.feet) for the layer that plays it. Where the performer's flat foot cannot be had (feetFlat absent, and the set neither walks with stated marks nor stands still on both feet), the word does nothing.
feetFlat? ​
ts
optional feetFlat?: readonly MotionFootTurns[];

With feet: 'own': the PERFORMER's feet as he stands flat, when the caller or the set knows them: the left foot, then the right, in the takes' own frame. Absent: measured here: the foot at the middle of each stance the set's walking takes state, the other foot in the air (it lies flat there, within the degree or two a walking foot turns in a frame); in a set without such a stance, the feet where the body stands still, upright, on both.

feetRest? ​
ts
optional feetRest?: readonly MotionFootTurns[];

With feet: 'own': HER feet as she stands, when the caller wants another stand than the rig's own rest (her registered rest with her idle adjustment laid in, say): the left foot, then the right. Absent: the rig's rest, as the table's builder is handed it.

stand? ​
ts
optional stand?: "middle" | "sole" | "bearing";

How a walk and a stand are stood on the rig's floor: which height the hips are DRAWN at. Nothing else of the table is read by it: every joint is the take's own, and the marks (which foot is down: what the feet's hold, the choice of a take and a stop's entry read), the features a pose is matched by, the gaits and a run's floor are the same numbers whatever is stated here.

  • 'middle' (the default; absent is the same, to the last number): by the middle of the ankle and the ball joints of the feet marked down. It has the heel's tip under the floor through a heel strike.
  • 'sole': on HER lowest sole point of the feet marked down (the ball of the foot or the heel's tip, on this rig's own feet), frame by frame, joined straight where no foot is marked, smoothed like the middle (a fifth of a second either side).
  • 'bearing': on her lowest sole point of every foot that BEARS, and the sole has a third point, the toe's end (the joint after the toe joint, turned with the toe joint; a rig without one keeps two points). A mark is only the place to look: a foot bears from the first frame a point of its sole is down where it lands (a mark comes on once the ankle is still, often after the heel is down) until its lowest point, the toe's end once the foot has rolled onto it, is a centimetre off where it stood (a mark often ends as the heel lifts: the push-off comes after it). So the body is held down over the rear foot while it rolls from its heel's lift to its toes' leaving. Where both feet bear and do not agree about the floor (a read's two feet seldom do, to the centimetre), the floor goes from the one to the other eased over the time they bear together, a fifth of a second at most: from the rear toes to the front heel across a walk's change of feet. What they disagree by is then left on them: the rear toes under the floor or the front heel over it, by a share each. Only next to its own mark, and outside it only while its lowest point is slower over the ground than a swung foot's: a foot in the air (a run's flight, a jump, the toes swung low past the other foot) never counts, and a foot coming down or lifting never pulls the body down after it. And the hips are never drawn changing height between two frames by more than the take's own largest change (2 mm a frame at the least): what the floor's changes would add to the take's fastest frames is held back, and left on a foot for a frame or two.

MotionTake ​

One take inside MotionData.

Properties ​

asPerformed? ​
ts
readonly optional asPerformed?: boolean;

False when the set says the take is never played at the pace it was performed at (performed.asPerformed: false); absent or true, a retimed take may be.

counted? ​
ts
readonly optional counted?: boolean;

False when the set says the take is not counted in its comparison numbers (MotionTakeSource.counted); absent: counted.

fallback ​
ts
readonly fallback: boolean;

Whether the set marks the take as a fallback.

first ​
ts
readonly first: number;

Its first frame in the set's arrays.

last ​
ts
readonly last: number;

Its last frame (inclusive).

module ​
ts
readonly module: string;

The part of the set the file says it belongs to ('' when it does not say).

name ​
ts
readonly name: string;
retime ​
ts
readonly retime: number;

How much faster than it was read the take is played (1: as read).

statedContacts ​
ts
readonly statedContacts: boolean;

Whether its file stated the feet's contacts.

statedPivot? ​
ts
readonly optional statedPivot?: boolean;

Whether its file stated, per foot and frame, where a foot on the ground moves over it and how fast (pivot and footSpeedMps, both): see MotionData.pivot.

stopStyle? ​
ts
readonly optional stopStyle?: MotionStopStyle;

The style of stop the set says the take is (MotionTakeSource.stopStyle); absent: an ordinary take.

tags ​
ts
readonly tags: readonly string[];
travelOverFeet ​
ts
readonly travelOverFeet: boolean;

Whether its file says its travel was already brought to what its feet carry.

turns? ​
ts
readonly optional turns?: readonly object[];

The turns on the spot the file marks in it (MotionTakeSource.turns): from and to as frames of the set's arrays, and whether it was performed quick. Absent or empty: none.

turnStart? ​
ts
readonly optional turnStart?: object;

The quick start that turns the file states in it (MotionTakeSource.turnStart): the turn in radians (left positive) and its last standing frame, as a frame of the set's arrays. Absent: none stated.

from ​
ts
readonly from: number;
turn ​
ts
readonly turn: number;
turnUnderWay? ​
ts
readonly optional turnUnderWay?: object;

The turn under way at a run the file states in it (MotionTakeSource.turnUnderWay): what its path turns in all (radians, left positive) and every landing in order: the frame in the set's arrays, the foot (0 the left, 1 the right) and how far the path has turned by then (radians). At least three landings. Absent: none stated.

steps ​
ts
readonly steps: readonly object[];
turn ​
ts
readonly turn: number;

MotionTakeSource ​

One take of a motion set file.

Properties ​

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

Per joint name: parent-local rotations, x y z w per frame.

contacts? ​
ts
optional contacts?: 
  | {
  left: ArrayLike<number>;
  right: ArrayLike<number>;
}
  | null;

When each foot is on the ground, when the reading has it: one value per frame, 1 down and 0 up, or the share of the frame it is down (a reading made at a higher frame rate than the take is stored at says where between two frames a foot lands and lifts).

counted? ​
ts
optional counted?: boolean;

false: the take is NOT counted in the set's comparison numbers (each feature's mean and spread, by which a search weighs one frame against another: MotionTable.mean, MotionTable.scale). Those numbers are measured on the character's own body over every frame a search can land on, so a take added to a set moves them a little and with them the choice among the takes that were already there. A take that says counted: false is weighed by the numbers of the takes that are counted, and leaves them exactly as they were: a set grows by such a take without any earlier choice changing for that reason. It is chosen like any other take. Absent or true: counted, as ever. (The takes of a sprint part are never counted: see buildMotionTable.)

fallback? ​
ts
optional fallback?: boolean;

The set's own word that this take is a fallback (slow, retimed or off its gait's pace): its frames answer a request only when no other take's do about as well.

footSpeedMps? ​
ts
optional footSpeedMps?: 
  | {
  left: ArrayLike<number>;
  right: ArrayLike<number>;
}
  | null;

Each foot's speed over the ground as the reading measured it, metres a second, one value per frame.

fps ​
ts
fps: number;

Frames a second.

frames ​
ts
frames: number;

How many frames.

kind? ​
ts
optional kind?: string;

What the take is, when the file says (locomotion, turn).

module? ​
ts
optional module?: string;

The part of the set the take belongs to (idle, walk, run, blend, actions, sprint), when the file says. A take of the sprint part is the sprint gait's: nothing else says so (see GAIT_SPRINT).

name ​
ts
name: string;

The take's name.

pace? ​
ts
optional pace?: string;

The pace the take was performed at, where a set has a move at more than one (easy, quick).

performed? ​
ts
optional performed?: 
  | {
  asPerformed?: boolean;
}
  | null;

The set's own word on the pace the take was performed at. asPerformed: false says the take is never played at that pace (it serves only as retimed); true, or nothing, that a take with a stated retime may be: a slow pace asked for is then answered with the slow walk that was performed (MotionStretch.performed). Whatever else the object holds (the performed speed, cadence and step, a band's name such as sprint or fast) is for people: the engine measures those itself on the character's body, and tells a sprint by the take's part alone (module).

pivot? ​
ts
optional pivot?: 
  | {
  left: ArrayLike<number>;
  right: ArrayLike<number>;
}
  | null;

Where a foot the contacts say is on the ground is MOVING over it, when the reading says: one value per frame, 1 where it moves (a pivot, a shuffle, a step out, a landing still gliding in), 0 where it rests. With MotionTakeSource.footSpeedMps it is what tells a planted foot from one that is only on the ground; a take without them is read for that off its own joints.

retime? ​
ts
optional retime?: 
  | number
  | {
  applied?: boolean;
  factor: number;
};

Play the take's MOVING stretches this much faster than they were read (1.6: a walk performed at half pace, brought to a natural cadence; between 0.25 and 4). Where the take stands it is played as read (its standing second stays a second, its shift of weight keeps its own time), and the factor eases in as the body gets going: none under a quarter of the take's top speed, full from two thirds of it. Applied once, when the set is packed: the take is resampled at the set's frame rate, so its speeds, its contacts and everything read from them are the retimed take's. Its step length stays what was performed. The studio writes it as { factor, applied }: applied: true says the take's frames are already at that pace, and nothing more is done.

root ​
ts
root: ArrayLike<number>;

The hips' path in the take's own world, x y z per frame, metres.

stopStyle? ​
ts
optional stopStyle?: string;

The style of the stop this take is: 'gradual' (the body slows and stands upright) or 'hard' (it brakes). A take that states one is a stop of that style and NOTHING ELSE: it answers only a body in motion asked to stand in that style (MotionLayer.stopStyle), from the frames of its own slow-down. No walk, no run, no standing and no start ever lands on it, it is left out of the set's comparison numbers as a take that says counted: false is, and it sets no pace of any gait: with no such stop asked, the set plays exactly as it does without the take. Any other word, or none: an ordinary take.

tags? ​
ts
optional tags?: readonly string[];

What the take holds, in plain words (run, stop, turn), for a debug view.

travelOverFeet? ​
ts
optional travelOverFeet?: 
  | {
  applied?: boolean;
}
  | null;

What the studio measured of the take's travel against its feet's. With applied: true the take's path was already brought to what its feet carry, and the engine's own guard against a body that travels further than its feet step stands down for this take; otherwise the path is as read, and the guard does its own measuring.

turns? ​
ts
optional turns?: readonly object[];

The turns on the spot of a take the file calls kind: 'turn': each from its last standing frame before the turn to its first standing frame after it (frames into the take, as stored), with the pace it was performed at (easy or quick; the take's own pace when a turn does not say). A turn so marked is a turn on the spot and nothing else: see MotionTable.turns. A list that states no pace is read as a note (an older file's), and the take is read off its joints like any other.

turnStart? ​
ts
optional turnStart?: 
  | {
  from?: number;
  made?: number;
  to?: number;
  turnDeg?: number;
}
  | null;

A quick start that turns, as the studio states one: the take stands, then moves off turning the body by turnDeg (the way it travels after against its facing in the stand, degrees, his left positive); from is its last standing frame, made the frame by which the turn is nearly made and to the first frame at nine tenths of the pace it reaches (frames into the take, as stored). The engine reads every move-off off the take itself (MotionTable.starts) and checks this against what it read; a start so stated, and borne out, is chosen by the angle asked (a walk sent to a spot, and a standing body asked a velocity). Anything else in the block is the studio's own.

The same statement (its turnDeg and from, as MotionTake.turnStart keeps them; the set's word alone, borne out or not) says of a take of the run part that it is a start and no pace of the run: none of its level frames is counted among the speeds and steps a band is read from. In any other part it does not change what is counted.

turnUnderWay? ​
ts
optional turnUnderWay?: 
  | {
  steps?: (
     | {
     foot?: string;
     frame?: number;
     pathTurnedSoFarDeg?: number;
   }
    | null)[];
  turnDeg?: number;
}
  | null;

The set says this take is a turn made UNDER WAY at a run, as performed: he runs in, turns his way round over some steps without stopping and runs out. turnDeg is what the path turns in all (degrees, his left positive) and steps every landing of a foot in order: the foot ('left' or 'right'), its frame (into the take, as stored) and how far the path has turned by then (pathTurnedSoFarDeg). The take's first and last landing are where it joins a run. A take that states it is that turn and nothing else: it is in no search (no plain run ever plays its running steps), holds no steady stretch, sets no pace and is weighed as a take that says counted: false is, so a set reads the same with it. It is played only when a walk sent to a spot enters it (MotionLayer.turnUnderWay). Anything else in the block is the studio's own.


MotionWeights ​

How much each group of features counts in a match.

Properties ​

facing ​
ts
facing: number;

Which way it will face.

feet ​
ts
feet: number;

Where the feet are.

feetSpeed ​
ts
feetSpeed: number;

How fast the feet move.

hipsSpeed ​
ts
hipsSpeed: number;

How fast the hips move.

path ​
ts
path: number;

Where the root will be (three points ahead).


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.


PoseAdjustRecord ​

A character's pose adjustment, as its package carries it (poseAdjust in character.json).

Properties ​

adjust ​
ts
adjust: Record<string, [number, number, number, number]>;

Per joint (the package skeleton's own names): a turn, quaternion x y z w.

move? ​
ts
optional move?: Record<string, [number, number, number]>;

Per joint: metres in the parent's frame, added to where the joint sits.

space ​
ts
space: "parent";

The frame the turns are in: the joint's parent's.

version ​
ts
version: 1;

The record's version: 1.


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.


SeatedAhead ​

A take known ahead: what an overlay (SeatedOverlay.ahead) can say of the move it plays before the move is played, without moving its plays on. The seated pose asks for each sample of the take once, when the take is asked (serial changes), stands the take's turn at that sample on the bones, and works out what the sample needs to stay out of a keep-out shape.

Properties ​

at ​
ts
readonly at: number;

Where the take is on the frame being written, in samples (a part of a sample counts), read after SeatedOverlay.trunk was called. Past the last sample (or not a number that has an end): no take plays any more.

samples ​
ts
readonly samples: number;

How many samples the take asked last has (its first frame is sample 0), and the seconds of the take's own time between two.

serial ​
ts
readonly serial: number;

A number that changes each time another take is asked. 0: no take was asked yet.

step ​
ts
readonly step: number;

Methods ​

give()? ​
ts
optional give(
   slot, 
   sample, 
   x, 
   y, 
   z
): void;

Told once for each sample when a plan is made: how far the hand or foot of a driven limb is to give way at that sample, eased over the take; the overlay moves the limb's end by it while the take plays. With sample under 0: nothing is given at any sample.

Parameters ​
ParameterTypeDescription
slotnumber0: the acting limb; 1: the also.
samplenumberWhich sample, or under 0 for none at all.
xnumberMetres in the seat's own frame.
ynumberMetres.
znumberMetres.
Returns ​

void

limb()? ​
ts
optional limb(
   sample, 
   spots, 
   slot, 
   give
): number;

Lay a limb the take drives on the bones as the take lays it at a sample (the limb standing on its own spot from the trunk as it stands on the bones now), its hand or foot moved by give; what an earlier call wrote is put back first. With sample under 0 the bones are only put back. Left out: no driven limb is planned.

Parameters ​
ParameterTypeDescription
samplenumberWhich sample, or under 0 to put the bones back.
spotsReadonly<SeatedSpots>Where the seat, the grips and the rests are this frame.
slotnumber0: the overlay's acting limb; 1: its also.
giveReadonly<Vector3>How far the hand or foot is moved from where the take lays it, metres in the seat's own frame.
Returns ​

number

The limb laid (0 the left hand, 1 the right hand, 2 the left foot, 3 the right foot), or -1 when the take lays none there.

nudge()? ​
ts
optional nudge(slot, more): boolean;

On a drawn frame, after SeatedOverlay.limbs: move the hand or foot of a driven limb further by more and lay the limb again (the net under the plan: a ball of the limb is inside the shape on this frame). The overlay keeps what it was moved by and lets it go again, slowly, on the frames after.

Parameters ​
ParameterTypeDescription
slotnumber0: the acting limb; 1: the also.
moreReadonly<Vector3>How much further, metres in the seat's own frame.
Returns ​

boolean

Whether the limb was laid again.

nudgeBack()? ​
ts
optional nudgeBack(
   which, 
   more, 
   middle?
): boolean;

On a drawn frame, after SeatedOverlay.limbs: move the hand or foot of a limb on its way back further by more and bend the limb to it (a ball of the limb is inside the shape on this frame). The overlay keeps what it was moved by and lets it go again, slowly, on the frames after.

Parameters ​
ParameterTypeDescription
whichnumberThe limb.
moreReadonly<Vector3>How much further, metres in the seat's own frame.
middle?booleanWhether the elbow or knee is moved instead, the hand or foot staying where it is (the ball that is inside rides on the bone above the elbow or knee).
Returns ​

boolean

Whether the limb was bent again.

settles()? ​
ts
optional settles(which): boolean;

Whether a limb is one the overlay has let go of and still brings back to its spot (the limb of a move that was replaced or stopped, or of a held pose that was let go of). Its way back is in no plan: the seat keeps it out of the shape on the drawn frames with SeatedAhead.nudgeBack.

Parameters ​
ParameterTypeDescription
whichnumberThe limb: 0 the left arm, 1 the right arm, 2 the left leg, 3 the right leg.
Returns ​

boolean

Whether it is on its way back.

stand() ​
ts
stand(
   sample, 
   spots, 
   pelvis
): boolean;

Stand the take's own turn at a sample on the bones of the trunk, the neck and the head, in full (with no blend in or out), over what stands on them (the seated pose alone). Nothing else is written and no play moves on; the seated pose puts the bones back.

Parameters ​
ParameterTypeDescription
samplenumberWhich sample, 0 to samples - 1.
spotsReadonly<SeatedSpots>Where the seat, the grips and the rests are this frame.
pelvisQuaternionWritten: the pelvis' own turn on the seat at that sample, in the pelvis' own frame (as SeatedOverlay.pelvis answers it).
Returns ​

boolean

Whether the pelvis is turned at all at that sample.


SeatedBody ​

A rider's body as rounded shapes that lie on its real surface, measured once off the character's own mesh (packages/animation/tools/measure_body.py), so that a keep-out shape stops the body where it truly touches. A ball named part 'hips', a hand's or a boot's is not held off the shape: the hips sit on the seat, a hand holds its grip and a boot stands on its rest.

Properties ​

balls ​
ts
balls: readonly SeatedBodyBall[];

The balls.


SeatedBodyBall ​

One rounded part of a rider's body: a ball carried by one joint (SeatedBody).

Properties ​

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

Its middle with the rig at rest, in the rig's own frame (+z forward, +y up), in the rig's units.

joint ​
ts
joint: string;

The joint that carries it, by the rig's own name. A joint the seated pose does not turn itself (a twist joint, a finger) stands for the nearest joint above it that it does.

part ​
ts
part: string;

The part of the body it belongs to, in plain words ('chest', 'left thigh'): for reports.

radius ​
ts
radius: number;

Its radius, in the rig's units.


SeatedFeel ​

The feel of a seated rider: with one given (SeatedSpots.feel) the trunk and the head follow the machine by springs (SEATED_FEEL); the hips stay on the seat, and every hand and foot on its spot. Left out, the pose is a direct function of the machine, as before.

Properties ​

amount? ​
ts
optional amount?: number;

How much of the feel: 0 none, 1 as built. Left out: 1.

mass? ​
ts
optional mass?: number;

The rider's mass, kilograms: a heavier rider follows slower, into a hold and out of it. Left out: 70.


SeatedFit ​

A rider's fit of seated takes: see the module's words.

Properties ​

bend ​
ts
readonly bend: Vector3;

The way the elbow or knee points off the line from the shoulder to the wrist (hip to ankle) on the frame pose last read, world, of length 1: his in the body's frame, mixed with hers as the seat's solver holds it by the share of her own spot; hers alone where his limb is nearly out straight.

extent ​
ts
readonly extent: number;

How far the limb is stretched on the frame pose last read: the distance from the shoulder or hip joint to the wrist or ankle as a share of the limb's two lengths (1: out straight). Her elbow or knee is bent as the seat's solver held it when the take began (SeatedFit.start), opened and closed by what HIS has opened and closed since his neutral: it moves as fast as his did, no faster. (Her shoulder is not where his was: a fist drawn back beside his chest would fold her arm double and throw it open again, and the last degrees of an elbow add only millimetres of reach.) The moves' layer sends the wrist or ankle toward its place at this stretch, and to the place itself at her own spot.

limbs ​
ts
readonly limbs: readonly (SeatedFitLimb | null)[];

Per limb: what the fit reads of it, or null for a limb the rig lacks or that does not hang from the pelvis.

written ​
ts
readonly written: Vector3;

Where the pose pose last wrote, by itself, has the wrist or ankle, world: the limb's two joints are then bent by what that is off wanted.

Methods ​

measure() ​
ts
measure(
   limb, 
   first, 
   last, 
   neutral, 
   endsRiding, 
   change?, 
   strike?, 
   fromBase?
): SeatedFitTake | null;

Measure a take on a limb, once.

Parameters ​
ParameterTypeDescription
limbnumberThe limb's number.
firstnumberThe take's first frame in the set.
lastnumberIts last.
neutralnumberThe set's frame of the performer's neutral for it (its own first frame, or another take's).
endsRidingbooleanWhether it ends riding (its hand or foot back on its rest).
change?booleanWhether it was performed from the riding posture: laid as a change at every distance (SeatedFitTake.change). Left out: false.
strike?numberThe set's frame of its strike (SeatedFitTake.peak). Left out, or not a frame of the take: the frame his hand or foot is furthest out.
fromBase?booleanFor a take laid as a change: its change is counted in the frame of what the limb hangs from (SeatedFitTake.fromBase). Left out: false.
Returns ​

SeatedFitTake | null

The measure, or null for a limb the fit cannot read.

place() ​
ts
place(
   limb, 
   take, 
   frame, 
   seat, 
   wanted
): number;

Where the wrist or ankle goes on a frame of a take, with the rider as she sits now and her own spot where pose last found it. Nothing is written but wanted.

Parameters ​
ParameterTypeDescription
limbnumberThe limb's number.
takeSeatedFitTakeThe take's measure.
framenumberThe set's frame (a float).
seatQuaternionHow the seat is turned, world.
wantedVector3Written, world.
Returns ​

number

The share of her own spot in it.

pose() ​
ts
pose(
   limb, 
   take, 
   frame, 
   seat, 
   pose, 
   offset, 
   wanted
): number;

The limb's pose for a frame of a take, on the rider as she sits NOW (call after the seat's solver has written the limb and before anything else writes it): each of the limb's joints' turn against its parent is written into pose, and where the wrist or ankle goes is written into wanted.

Parameters ​
ParameterTypeDescription
limbnumberThe limb's number.
takeSeatedFitTakeThe take's measure.
framenumberThe set's frame (a float).
seatQuaternionHow the seat is turned, world.
poseFloat32Arraycolumns x 4 numbers at offset: the limb's columns are written.
offsetnumberWhere the pose starts in pose.
wantedVector3Written: where the wrist or ankle goes, world.
Returns ​

number

The share of her own spot in it: 1 at the neutral, 0 where the hand or foot is wholly where the performer has it; always 1 for a take laid as a change (her own spot plus his change).

start() ​
ts
start(limb): void;

A take begins on a limb: how far her own limb is stretched now, as the seat's solver holds it, is kept (her elbow or knee opens from there). Call before the take's first pose.

Parameters ​
ParameterTypeDescription
limbnumberThe limb's number.
Returns ​

void


SeatedFitLimb ​

One limb, as the fit reads a take on it.

Properties ​

baseAt ​
ts
readonly baseAt: number;

Where in path the limb's first own bone is (an arm's collar bone): the bone above it is what the limb hangs from (the chest). -1: none.

columns ​
ts
readonly columns: readonly number[];

Per bone of path: its column in the pose written (SeatedFitOptions.columns), or -1 for a bone that is not the limb's own.

endColumns ​
ts
readonly endColumns: readonly number[];
endJoints ​
ts
readonly endJoints: readonly number[];
ends ​
ts
readonly ends: readonly Object3D<Object3DEventMap>[];

The limb's joints under the wrist or ankle that the set moves (fingers, toes), parents first; each one's place in the set and its column.

joints ​
ts
readonly joints: readonly number[];

Where each is in the set (-1: the set does not move it).

lowerAt ​
ts
readonly lowerAt: number;
path ​
ts
readonly path: readonly Object3D<Object3DEventMap>[];

Every bone from the one under the hips down to the wrist or ankle, top first.

upperAt ​
ts
readonly upperAt: number;

Where in path the shoulder or hip joint and the elbow or knee are.


SeatedFitOptions ​

Options for createSeatedFit.

Properties ​

columns ​
ts
columns: readonly string[];

The names of the pose's columns: the joint each four numbers of a written pose are for.

data ​
ts
data: MotionData;

The set, and which of its joints is the pelvis.

hipJoints ​
ts
hipJoints: readonly [Object3D<Object3DEventMap>, Object3D<Object3DEventMap>];
hips ​
ts
hips: Object3D;

The pelvis, and the two hip joints (left, right): their line says which way a performer faces.

hipsJoint ​
ts
hipsJoint: number;
limbs ​
ts
limbs: readonly (
  | {
  end: Object3D;
  lower: Object3D;
  mask: readonly string[];
  upper: Object3D;
}
  | null)[];

Per limb (left arm, right arm, left leg, right leg): its shoulder or hip joint, its elbow or knee, its wrist or ankle, and the names of its own joints.

pelvisTurns? ​
ts
optional pelvisTurns?: Float32Array<ArrayBufferLike> | null;

frames x 4, per frame of the set: how far the performer's pelvis has turned on the seat since his neutral, in the pelvis' own frame, as far as the rider's pelvis takes it (the set's poses are then stated against a pelvis that turns so). Absent or null: the pelvis is still, as a seated take is stored.

root ​
ts
root: Object3D;

The rig root.


SeatedFitTake ​

What a take is, to the fit: measured once per take and limb.

Properties ​

carried ​
ts
readonly carried: Vector3;

How far his shoulder or hip joint (the limb's first joint) is carried from where it is on the neutral frame, on the frame it is carried furthest, in the body's frame, the rig's own units: which way and how far his body leans in the take.

change ​
ts
change: boolean;

The take was performed FROM THE RIDING POSTURE (performedFrom: 'riding' in its block): its hand or foot is laid as his CHANGE from the neutral frame onto the rider's own spot at every distance, and its joints as his change onto her own. False: the mix by distance.

drift ​
ts
readonly drift: Vector3;

What the performer ends off that rest by, or zero for a take that does not end riding.

driftEnds ​
ts
readonly driftEnds: readonly Quaternion[];
driftRel ​
ts
readonly driftRel: Vector3;
driftTurns ​
ts
readonly driftTurns: readonly Quaternion[];
endExtent ​
ts
endExtent: number;

How far his limb is stretched on the take's last frame, for a take that ends riding (else as on the neutral frame).

endsRiding ​
ts
endsRiding: boolean;

Whether the take ends riding (its hand or foot back on its rest).

facing ​
ts
readonly facing: Quaternion;

The way the performer faces on the neutral frame, in the set's own frame.

far ​
ts
far: number;

The frame (of the set) his hand or foot is furthest from its rest: the drift is taken out from there to the take's end.

first ​
ts
first: number;

The take's first frame (of the set).

fromBase ​
ts
fromBase: boolean;

A hand that goes with the body: its change is counted in the frame of what his arm hangs from (his chest, as it stands on each frame) and laid in the rider's own chest's frame, not in the hips' and the seat's: a hand that goes out to his side, away from his body, goes out to her side, away from hers, however much further forward she lies. restRel: where his hand is on the neutral frame, from the top of his chest, in his chest's frame; driftRel: what it ends off that by.

last ​
ts
last: number;

The take's last frame (of the set).

neutral ​
ts
neutral: number;

The set's frame of the performer's neutral for this take.

peak ​
ts
peak: number;

The frame (of the set) of the take's strike, or the frame his hand or foot is furthest from its rest when the take states none; where his hand or foot is on it, from its rest (as reach, what he ends off his rest by taken out); how far his limb is stretched on it.

peakExtent ​
ts
peakExtent: number;
peakReach ​
ts
readonly peakReach: Vector3;
reach ​
ts
readonly reach: Vector3;

Where his hand or foot is on that frame, from its rest, in the body's frame (+x his left, +y up, +z ahead), the rig's own units.

rest ​
ts
readonly rest: Vector3;

Where the performer's hand or foot rests (on the neutral frame), from the hips, in the body's frame, the rig's own units.

restEnds ​
ts
readonly restEnds: readonly Quaternion[];
restExtent ​
ts
restExtent: number;

How far his limb is stretched on the neutral frame: shoulder to wrist (hip to ankle) over the limb's two lengths.

restRel ​
ts
readonly restRel: Vector3;
restTurns ​
ts
readonly restTurns: readonly Quaternion[];

For a take laid as a change. His turn of each bone of the limb's path against its parent on the neutral frame, and what each has turned by on the take's last frame since then (nothing, for a take that does not end riding); the same of the limb's ends.

shared ​
ts
shared: boolean;

Whether the take states its strike: only then is the limb stretched to his share of its length on it.

swivel ​
ts
swivel: Float32Array<ArrayBufferLike> | null;

For a take laid as a change: per frame of the take (first to last), how far his elbow or knee has swung about his limb's line since the neutral frame, radians (frames on which his limb is nearly out straight take it from the frames around them). Null when his limb is nearly out straight on the neutral frame itself, or the fit cannot read it: the rider's own way of bending is then carried alone.

swivelDrift ​
ts
swivelDrift: number;

What that swing is on the take's last frame, taken out over the way back; 0 for a take that does not end riding.


SeatedHandNames ​

The first joints of three fingers, by bone name: they say which way the palm faces.

Properties ​

index ​
ts
index: string;

The index finger's first joint.

little ​
ts
little: string;

The little finger's first joint.

middle ​
ts
middle: string;

The middle finger's first joint.


SeatedJointNames ​

What a rig calls the joints a seated pose is written on.

Properties ​

arms ​
ts
arms: readonly [SeatedLimbNames, SeatedLimbNames];

The arms, left then right.

balls? ​
ts
optional balls?: readonly [string, string];

The ball of each foot, left then right: where the sole is, and which way the foot points.

head ​
ts
head: string;

The head.

hips ​
ts
hips: string;

The pelvis.

knuckles? ​
ts
optional knuckles?: readonly [SeatedHandNames, SeatedHandNames];

Three knuckles of each hand, left then right: which way the palm faces.

legs ​
ts
legs: readonly [SeatedLimbNames, SeatedLimbNames];

The legs, left then right.

spine ​
ts
spine: readonly string[];

The spine from the pelvis up; the last one carries the arms. Names the rig lacks are left out. Whatever lies between the last one and the head is the neck.


SeatedKeepOut ​

The shape of what a character sits on that no part of its body may enter (SeatedSpots.keepOut): the thing's top as a map of heights, and where the thing is this frame. Everything under the map's surface counts as the thing.

Properties ​

body? ​
ts
optional body?: Readonly<SeatedBody> | null;

The rider's own body (SeatedBody). Left out: rounded shapes from the skeleton's proportions alone (SEATED.bodyThigh and its neighbours), which fit a slim body.

clearance? ​
ts
optional clearance?: number;

The gap left between the body and the surface, metres. Left out: 0.01.

field? ​
ts
optional field?: Readonly<SeatedKeepOutField> | null;

The same shape as distances (SeatedKeepOutField). With it SeatedPose.gapAt and SeatedPose.keepGap are true distances to the shape's surface, which grow steadily from far away (no step at the maps' edges or over the thing's highest part): what a move that approaches the thing softly needs. The pose itself is held off the shape by the maps as before: the same pose to the last bit with the field and without. Left out: the two measures are as before.

frame ​
ts
frame: SeatedSpot;

The frame the map is stated in, world: the thing's own (its +y up, its +z forward).

laid? ​
ts
optional laid?: boolean;

Whether what is laid over the pose (a move played from the seat: SeatedOverlay) is kept out of the shape as the pose is: its trunk, its neck and its head. Left out or false: a move is laid on as it is, whatever it goes into (the pose itself is still held off the shape, and every gap is still measured and said: SeatedPose.gapOf, keepGap). OFF UNLESS ASKED (true), because the limit as it stands is not usable yet: it comes on within two drawn frames and takes more of a move than touching would (measured on takes performed from the riding posture: a long kick that never enters the machine has its back raised 17 to 18 degrees and a forearm turned 28 to 36 degrees in one drawn frame).

laidLimbs? ​
ts
optional laidLimbs?: boolean;

Whether a limb the overlay drives (its acting, its also) is turned to keep it out of the shape. NOT READY: left out, false. On a real seat the swing of an elbow about the line from the shoulder to the hand cannot clear a forearm that lies across a bar: the limb is then turned by all it may be at once (measured on a forward throw: the upper arm 82 degrees in one drawn frame, and the arm still 3 cm inside). The gap of a driven limb is measured and said either way (SeatedPose.gapOf, keepGap).

map ​
ts
map: Readonly<SeatedKeepOutMap>;

The map.

sides? ​
ts
optional sides?: Readonly<SeatedKeepOutSides> | null;

The thing's sides. With them a part of the body counts as inside only where it is both under the top and between the sides (a knee pressed against a tank's flank is beside it, not in it), and a leg that would be inside a side is moved outward until it lies against it. Left out: everything under the top counts as the thing.


SeatedKeepOutField ​

The shape of a thing a character sits on as distances: a grid of columns by rows by layers places step metres apart in the thing's own frame, the first at (x0, y0, z0), a row running across the thing (+x), the rows going up (+y), the layers along it (+z); distances[(layer * rows + row) * columns + column] is how far that place is from the shape's surface, metres: over 0 outside the shape, under 0 inside it. Made once from the two maps of the same model (packages/animation/tools/keepout_field.py), so it says the same shape. Read between its places; outside the grid the way to the grid is added to the nearest place's distance.

Properties ​

columns ​
ts
columns: number;

How many places across (x), up (y) and along (z).

distances ​
ts
distances: ArrayLike<number>;

The distances, metres: layer by layer, each row by row.

layers ​
ts
layers: number;
rows ​
ts
rows: number;
step ​
ts
step: number;

The distance between two places, metres.

x0 ​
ts
x0: number;

The first place, metres in the thing's frame.

y0 ​
ts
y0: number;
z0 ​
ts
z0: number;

SeatedKeepOutMap ​

The top of a thing a character sits on, as a map of heights: a grid of columns by rows places step metres apart in the thing's own frame, the first at (x0, z0), a row running across the thing (+x), the rows going along it (+z); heights[row * columns + column] is the height of the thing's surface there (its y, metres), or a number that is not finite where there is nothing. Made once from the thing's own model (a ray shot down at each place, or its triangles laid into the grid).

Properties ​

columns ​
ts
columns: number;

How many places across (x) and along (z).

heights ​
ts
heights: ArrayLike<number>;

The heights, row by row.

rows ​
ts
rows: number;
step ​
ts
step: number;

The distance between two places, metres.

x0 ​
ts
x0: number;

The first place's x and z in the thing's frame, metres.

z0 ​
ts
z0: number;

SeatedKeepOutSides ​

The sides of a thing a character sits on, as a map: a grid of columns by rows places step metres apart in the thing's own frame, a row running along the thing (+z) from z0, the rows going up (+y) from y0; left[row * columns + column] is how far the thing's surface reaches to its left there (its x, metres) and right[...] how far to its right, or a number that is not finite where there is nothing at that height. Made once from the thing's own model, with the map of its top (packages/animation/tools/keepout_shape.py).

Properties ​

columns ​
ts
columns: number;

How many places along (z) and up (y).

left ​
ts
left: ArrayLike<number>;

The furthest surface to the left (+x) and to the right (-x) at each place.

right ​
ts
right: ArrayLike<number>;
rows ​
ts
rows: number;
step ​
ts
step: number;

The distance between two places, metres.

y0 ​
ts
y0: number;

The first place's height and its place along, metres.

z0 ​
ts
z0: number;

SeatedLaidPlan ​

What a plan made ahead holds (SeatedPose.laidPlan).

Properties ​

back ​
ts
back: number;

The largest share of the hips' turn on the seat any sample needs taken back, 0 to 1, and the largest raise of the back any needs, radians.

limbGive ​
ts
limbGive: number;
limbNeeding ​
ts
limbNeeding: number;

How many samples a driven limb's hand or foot gives way on, the furthest it gives way, metres, and how many samples that does not keep the limb out.

limbStuck ​
ts
limbStuck: number;
ms ​
ts
ms: number;

Milliseconds the plan took to make.

needing ​
ts
needing: number;

How many samples need something given up to stay out of the shape. 0: the take needs nothing, and nothing is done.

raise ​
ts
raise: number;
rate ​
ts
rate: number;

The fastest what is given up may come on or go on any sample, radians a second of the take's own time (the take's own trunk's speed there, or SEATED.aheadRate).

samples ​
ts
samples: number;
serial ​
ts
serial: number;

The take's number (SeatedAhead.serial) and how many samples it has.

stuck ​
ts
stuck: number;

How many samples even the whole raise does not keep out (the net then acts there).


SeatedLimbNames ​

The three joints of an arm or a leg, by bone name: shoulder, elbow, wrist; hip, knee, ankle.

Properties ​

end ​
ts
end: string;

The wrist or the ankle.

lower ​
ts
lower: string;

The elbow or the knee.

upper ​
ts
upper: string;

The shoulder or the hip joint.


SeatedMoveEvent ​

A move's moment, as SeatedMoves.onEvent is told it. The record is reused: copy what you keep.

Properties ​

amount ​
ts
amount: number;

contact with a target: how far the wrist or ankle is from it, metres. Otherwise 0.

limb ​
ts
limb: number;

The limb's number (SEATED_MOVE_LIMBS); -1 for a take in which no limb acts.

move ​
ts
move: string;

The move's name, as asked.

name ​
ts
name: "done" | "failed" | "release" | "started" | "contact";

started; contact on the take's strike frame; release on a throw's let-go frame; done on the take's last frame (the limb then settles back onto its spot, or its last pose is held: SeatedMoveRequest.hold); failed when a move is replaced by another (replaced) or stopped (cancelled) before its last frame.

reason ​
ts
reason: string;

Why, for failed. For contact: out-of-range when a target was given and lay outside the take's reach (the take played as performed), else empty.

vx ​
ts
vx: number;

How fast that point moves in the world, metres a second (what it rides on included).

vy ​
ts
vy: number;
vz ​
ts
vz: number;
x ​
ts
x: number;

Where the acting wrist or ankle is, world metres; for a take in which no limb acts, the top of the chest.

y ​
ts
y: number;
z ​
ts
z: number;

SeatedMoveRequest ​

What is asked of SeatedMoves.play.

Properties ​

hands? ​
ts
optional hands?: "follow" | "hold";

What the hands that do not act do in a performed kick whose lean a fixed grip cannot follow: 'follow', the hand on the far side from the lean goes with the body as the performer's did (he holds no real bar) and comes back onto its grip, the other hand holds; 'hold', both hands stay on their grips and the lean is taken back as far as they need. Left out: what the take says (hands in its block), else 'hold' (until a move is kept out of the machine: a full lean can bring the head down onto the bars).

It also PICKS THE TAKE where the set holds one move twice for a side: performed with both hands on the bars (hands: 'hold' in its block, or nothing) and performed with a hand let go (hands: 'follow'). The take whose hands is what is asked here (left out: 'hold') is played; with one take of the move on that side, that take. A take that states handThatGoes says which hand goes with the body.

hold? ​
ts
optional hold?: boolean;

For a take that does not end riding (its block's endsIn is a held pose's name: the punch's arm out, the carry after a grab, hanging off the side): whether its LAST POSE IS KEPT after its last frame (the trunk's and the head's turn, the pelvis' turn on the seat, the acting limb where it was laid, a hand that went with the body) until another move is played or SeatedMoves.stop is called. Left out or true: kept (SeatedMoves.held then says the pose). False: it is let go of on its last frame and the limb eased back onto its spot. done is said on the take's last frame either way. For a take that ends riding it changes nothing.

move ​
ts
move: string;

The move's name: a take's seated.move (else the take's own name), or that name without the side it ends in (kick_long for kick_long_left and kick_long_right), the side then given in side.

rate? ​
ts
optional rate?: number;

How fast the take is played. Default 1.

side? ​
ts
optional side?: "left" | "right";

The side the move goes TO: the take that says it goes there (toward: a punch across the body to the left is thrown with the right arm; a hit to the left drives the body to the left). For a take that says no side, or ahead, the side of its limb (which hand carries, which hand throws ahead); a take with neither a side nor an acting limb serves either side. Absent: the first take of that move in the set. (A move performed to the right is stored also as its mirror: the layer does not mirror a take.)

skipLead? ​
ts
optional skipLead?: boolean;

True: the take starts at the frame the performer first moves on (its block's firstMovesFrame, SeatedMoveSource.lead), so its strike and every other moment come that much sooner; a moment that lies in the lead-in is said on the first frame. What the take's turns are counted from stays its first frame (the trunk's zero, the limb's neutral). Left out or false, or for a take that states no lead-in: the take is played from its first frame, as before.

target? ​
ts
optional target?: SeatedMoveTarget | null;

Where the acting hand's wrist or foot's ankle should strike, world metres. The object is read every frame around the strike: keep it and move it with what is struck.


SeatedMoves ​

Performed moves from the seat on one rig: the seated pose's overlay.

Example ​

ts
import type { SeatedMoves } from 'gameable/animation';

function kick(moves: SeatedMoves, rival: { x: number; y: number; z: number }): void {
  if (moves.play({ move: 'kick', side: 'right', target: rival }) === null)
    console.warn('this set has no kick on the right');
}

Extends ​

Properties ​

acting ​
ts
readonly acting: number;

The limb the overlay has taken off its spot, which the trunk is not held back for: 0 the left hand, 1 the right hand, 2 the left foot, 3 the right foot; -1 for none.

Inherited from ​

SeatedOverlay.acting

ahead? ​
ts
readonly optional ahead?: SeatedAhead;

The take the overlay plays, known ahead (SeatedAhead). With it and a keep-out shape that asks for the limit, what each frame of the take needs to stay out of the shape is worked out once, when the take is asked, and eased over the take's own time; the limit that meets the shape frame by frame then only stands under it as a net. Left out: the limit works frame by frame, as before.

Inherited from ​

SeatedOverlay.ahead

also? ​
ts
readonly optional also?: number;

A second limb the overlay has taken off its spot (a hand that goes with the body in a kick), which the trunk is not held back for either: numbered as acting; -1 or left out for none.

Inherited from ​

SeatedOverlay.also

bend ​
ts
readonly bend: number;

How much of the bend to the target is on the limb now, 0 to 1.

held ​
ts
readonly held: string;

The pose held: the endsIn of a take that did not end riding and whose last pose is kept (SeatedMoveRequest.hold: out, carry, hanging ...), '' when nothing is held. While it is held nothing of the layer's moves, the limb counts as acting (the trunk is not held back for it), and the pose follows the seat.

move ​
ts
readonly move: string;

The move playing, '' when none is.

moves ​
ts
readonly moves: readonly SeatedMoveSource[];

The moves this body can play: the set's seated takes whose limb the rig has.

onEvent ​
ts
onEvent: ((event) => void) | null;

Told each of a move's moments.

playing ​
ts
readonly playing: boolean;

True while a take plays (not while a limb only settles back, nor while a take's last pose is held).

refusal ​
ts
readonly refusal: "" | "unknown-move" | "not-in-pose";

Why the last SeatedMoves.play answered null: unknown-move (the set has no such move on that side for this body), or not-in-pose (the take starts from a held pose, its block's startsIn, and the rider does not hold that pose with that limb now: play the take that ends in it first). '' after a play that was taken.

refused ​
ts
readonly refused: readonly object[];

The takes left out, and why (a take the set did not keep, a limb the rig lacks).

seconds ​
ts
readonly seconds: number;

Where the take playing is, seconds into it in its own time (a take whose lead-in was skipped starts at its lead); 0 when none plays.

Methods ​

limbs() ​
ts
limbs(dt, spots?): void;

After the limbs are solved: the last writing of the frame.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last frame.
spots?Readonly<SeatedSpots>Where the seat, the grips and the rests are this frame (what apply was given).
Returns ​

void

Inherited from ​

SeatedOverlay.limbs

pelvis()? ​
ts
optional pelvis(
   dt, 
   spots, 
   out
): boolean;

The pelvis' own turn on the seat this frame, asked before trunk: how far a performed move rolls and swivels the hips, in the pelvis' own frame. The pose turns the pelvis by it about the seat's spot (the hips roll ON the seat: they do not leave it), and solves the legs and the arms from the pelvis as it then stands. It is taken back with the trunk's turn, by the same share, when a hand that holds its grip could not reach. Left out, or answered false: the hips are never turned, as before.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last frame.
spotsReadonly<SeatedSpots>Where the seat, the grips and the rests are this frame.
outQuaternionWritten: the turn, in the pelvis' own frame.
Returns ​

boolean

Whether the pelvis is turned at all this frame.

Inherited from ​

SeatedOverlay.pelvis

play() ​
ts
play(request): Readonly<SeatedMoveSource> | null;

Play a move. One that is playing is replaced (its limb is carried over or eased back, never cut; it is said failed, replaced).

A take that starts from a HELD pose (its block's startsIn is not riding: the punch's way back, the carry) is played only while the layer holds that pose with the same limb (SeatedMoves.held): it goes on from the held pose without a jump, its trunk's, head's and pelvis' turn counted from the first frame of the take that led into the pose (the performer's own riding pose), so a way out and its way back end riding. Asked in any other pose it is refused. A take that starts riding may be asked at any time: asked while a pose is held it replaces it, the limb carried over.

Parameters ​
ParameterTypeDescription
requestSeatedMoveRequestThe move, its side, its rate, its target.
Returns ​

Readonly<SeatedMoveSource> | null

The take chosen, or null (and nothing changes; SeatedMoves.refusal says why) when the set has no such move on that side for this body, or the take starts from a held pose the rider is not in.

reset() ​
ts
reset(): void;

Forget everything at once (the character left its seat): no play, no easing, nothing said.

Returns ​

void

restore() ​
ts
restore(): void;

Take last frame's writing off the bones. Before the seated pose's own restore.

Returns ​

void

stop() ​
ts
stop(): boolean;

Let go: the limb is eased back onto its spot (said failed, cancelled). A pose that is held is let go of the same way; nothing is said of it (its take was said done).

Returns ​

boolean

Whether a move was playing or a pose was held.

trunk() ​
ts
trunk(dt, spots?): void;

After the trunk and the head are written, before the limbs are solved.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last frame.
spots?Readonly<SeatedSpots>Where the seat, the grips and the rests are this frame (what apply was given).
Returns ​

void

Inherited from ​

SeatedOverlay.trunk


SeatedMovesOptions ​

Options for createSeatedMoves.

Properties ​

blendSeconds? ​
ts
optional blendSeconds?: number;

Seconds a limb takes to leave its spot and to settle back on it. Default 0.3 (up to twice that when carried far).

data ​
ts
data: MotionData;

The set, read with its riding part (parseMotionSet(json, { modules: ['riding'] })).

joints? ​
ts
optional joints?: SeatedJointNames;

What the rig calls its limbs' joints; left out, found by seatedJointsFor.

moves ​
ts
moves: readonly SeatedMoveSource[];

The seated takes as the file states them (parseSeatedMoveSources).

onEvent? ​
ts
optional onEvent?: ((event) => void) | null;

Told each of a move's moments.

pelvisShare? ​
ts
optional pelvisShare?: number;

The share of a take's own turn of the pelvis (SeatedMoveSource.pelvis) the rider's pelvis takes on the seat, 0 to 1. Default 1: it rolls and swivels as the performer's did. 0: the hips are never turned, as before.

poseAdjust? ​
ts
optional poseAdjust?: PoseAdjustRecord | null;

The character's own pose adjustment, laid on the take's pose of the acting limb.

root ​
ts
root: Object3D;

The rig root: the character's own frame, the bones under it.


SeatedMoveSource ​

One seated take, as a set's file states it.

Properties ​

acts? ​
ts
optional acts?: boolean;

Whether a limb acts in it. False for a hit or a jostle taken (kind: 'react'): the take turns the trunk and the head alone, every hand and foot stays held to its spot, and limb then only names the limb the set stated (it is not posed). Absent: true.

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

The pose the take ends in (endsIn): riding, or a held pose's name. Absent: riding. A take that ends in a held pose keeps its last pose (SeatedMoveRequest.hold).

hands? ​
ts
optional hands?: "follow" | "hold" | null;

What the hands that do not act do in it (SeatedMoveRequest.hands): the block's hands, or null when it does not say. Where a set holds one move twice for a side, performed with both hands on the bars (hold) and with a hand let go (follow), it is what the layer picks the take by.

handThatGoes? ​
ts
optional handThatGoes?: "left" | "right" | null;

The hand that goes with the body in it (handThatGoes: left or right, the hand the performer's own left the bar with), or null when the block does not say: the layer then works it out (the hand on the far side from the lean, in a kick).

kind? ​
ts
optional kind?: string;

What the take is, in the set's own word (kind: strike, react, throw ...); absent or '' when it says none.

lead? ​
ts
optional lead?: number;

SECONDS of the take's still lead-in: the frame the performer first moves on (the block's firstMovesFrame, 4 to 10 in the first performed set) over the take's frame rate. 0 or absent when the block states none, or one that is not a frame of the take. A game may skip it (SeatedMoveRequest.skipLead).

limb ​
ts
limb: SeatedMoveLimb;

The limb it is performed with. A move performed on the other side is another take.

move ​
ts
move: string;

What a game asks for (kick): the block's move, else the take's name.

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

The performer's pelvis' own turn on every frame of the take, as read (pelvis.hipsAsPerformed: x y z w a frame, the same convention as the take's Hips), or null. A take that states it is stored against a STILL pelvis, the pelvis' turn since the first frame carried into the first joint of the spine and the two thighs: the layer turns the rider's pelvis on the seat by it and takes it back out of those three.

performedFrom? ​
ts
optional performedFrom?: "riding" | null;

The posture the take was PERFORMED FROM (performedFrom): riding for a take whose clip starts on a picture of the rider herself on her machine, so that its first frame IS the rider's own pose and whatever the read's first frame differs from her rest by is the reader's error. The acting hand or foot of such a performed take (one that states startsIn) is laid as the performer's CHANGE from his first frame onto the rider's own rest AT EVERY DISTANCE, its joints and fingers as his change onto her own, and a hand that goes with the body the same (seatedFit). Null or absent (and any other word, the studio's own): as before, her own spot near the rest and the performer's place from the hips far from it.

reach ​
ts
reach: number;

How far the limb's end may be bent to a target from where the take puts it at the strike, metres (reachM); 0: never.

release ​
ts
release: number | null;

Seconds into the take a throw lets go (the block's releaseFrame), or null.

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

The take whose last pose this one starts in (startsFrom.take), or null: the trunk's, the pelvis' and the limb's turn are counted from THAT take's first frame (the performer's own riding pose). A take that starts in a held pose and names none is counted from the one take of the set that starts riding and ends in that pose with the same limb; when there is none, or several, from its own first frame.

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

The pose the take starts in (startsIn): riding, or a held pose's name (carry, out). A take that says it is a PERFORMED take: its first frame (for a take that starts from a held pose, the first frame of the take named in startsFrom) is the performer's own riding pose, and its acting limb is laid on the rider as a change from that pose (seatedFit). Absent or null: the limb is posed as stored, from the rider's own chest or hips, as before. A take that starts in a held pose is played only while the layer holds that pose with the same limb (SeatedMoves.play).

strike ​
ts
strike: number | null;

Seconds into the take of its strike (the block's strikeFrame), or null when it has none.

take ​
ts
take: string;

The take's name in the set.

toward? ​
ts
optional toward?: "left" | "right" | "ahead" | null;

The side the move goes TO (toward): left or right of the rider, ahead, or null when the take says none. A move across the body goes to the side opposite its limb (the right arm strikes to the left); a hit or a jostle goes to the side the body is driven to. It is the side a game asks by (SeatedMoveRequest.side).

trunk ​
ts
trunk: number;

The share of the take's turn of the trunk and the head the rider takes, 0 to 1 (trunk).


SeatedMoveTarget ​

A point in the world, read every frame while a move bends its limb to it: it may move.

Properties ​

x ​
ts
x: number;

World metres.

y ​
ts
y: number;
z ​
ts
z: number;

SeatedOverlay ​

Something laid over the seated pose, between its steps: a performed move played from the seat (a kick, a punch, a throw: createSeatedMoves). The seated pose is written in two steps, and the overlay is called after each:

  1. the hips on the seat, the trunk leaned, the head levelled; then SeatedOverlay.trunk, which may turn the trunk and the head further (never the hips: an overlay that has the pelvis roll or swivel ON the seat says so with SeatedOverlay.pelvis, and the pose turns it about the seat's spot);
  2. every hand held to its grip and every foot to its rest, FROM the trunk as it now stands (so a hand that holds on stays on its grip whatever the trunk does); then SeatedOverlay.limbs, which may take a limb off its spot.

A turn of the trunk that would pull a holding hand off its grip is taken back as far as needed (SEATED.reachHeld). An overlay that writes nothing leaves the pose the same to the last bit.

With a keep-out shape that asks for it (SeatedSpots.keepOut with laid: true; off unless asked, see SeatedKeepOut.laid) the trunk, the neck and the head are kept out of the shape whatever the overlay turns them to: the back is RAISED about the seat's own left as far as that takes (the turn to the side and the twist are kept; only the fold into the shape is given up; the head keeps the turn it was given), softly from SEATED.laidSoft off the shape, and never nearer to it than the pose alone already is. Where raising the back is not enough the turn itself is taken back. What was given up is said: SeatedPose.laidRaised and SeatedPose.laidKept.

NOT READY, off unless the shape says laidLimbs: true (SeatedKeepOut.laidLimbs): a limb the overlay has driven (acting, also) is kept out of the shape after the overlay's limbs step: its elbow or its knee is swung about the line from its first joint to its end (the hand or the foot stays where the move put it), and as the swing grows the whole limb is turned about its first joint with it, up for an arm, outward for a leg (SeatedPose.laidLimb); softly, and never asked to be further off the shape than the same limb was on its own spot this frame. The hand and the foot themselves are not tried against the shape (they rest on the machine).

Extended by ​

Properties ​

acting ​
ts
readonly acting: number;

The limb the overlay has taken off its spot, which the trunk is not held back for: 0 the left hand, 1 the right hand, 2 the left foot, 3 the right foot; -1 for none.

ahead? ​
ts
readonly optional ahead?: SeatedAhead;

The take the overlay plays, known ahead (SeatedAhead). With it and a keep-out shape that asks for the limit, what each frame of the take needs to stay out of the shape is worked out once, when the take is asked, and eased over the take's own time; the limit that meets the shape frame by frame then only stands under it as a net. Left out: the limit works frame by frame, as before.

also? ​
ts
readonly optional also?: number;

A second limb the overlay has taken off its spot (a hand that goes with the body in a kick), which the trunk is not held back for either: numbered as acting; -1 or left out for none.

Methods ​

limbs() ​
ts
limbs(dt, spots?): void;

After the limbs are solved: the last writing of the frame.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last frame.
spots?Readonly<SeatedSpots>Where the seat, the grips and the rests are this frame (what apply was given).
Returns ​

void

pelvis()? ​
ts
optional pelvis(
   dt, 
   spots, 
   out
): boolean;

The pelvis' own turn on the seat this frame, asked before trunk: how far a performed move rolls and swivels the hips, in the pelvis' own frame. The pose turns the pelvis by it about the seat's spot (the hips roll ON the seat: they do not leave it), and solves the legs and the arms from the pelvis as it then stands. It is taken back with the trunk's turn, by the same share, when a hand that holds its grip could not reach. Left out, or answered false: the hips are never turned, as before.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last frame.
spotsReadonly<SeatedSpots>Where the seat, the grips and the rests are this frame.
outQuaternionWritten: the turn, in the pelvis' own frame.
Returns ​

boolean

Whether the pelvis is turned at all this frame.

trunk() ​
ts
trunk(dt, spots?): void;

After the trunk and the head are written, before the limbs are solved.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last frame.
spots?Readonly<SeatedSpots>Where the seat, the grips and the rests are this frame (what apply was given).
Returns ​

void


SeatedPose ​

A seated pose on one rig.

Properties ​

heldUp ​
ts
readonly heldUp: number;

With a keep-out shape: how far the back's lean is held up from the lean the pose, its springs and the feel have it at this frame, radians (0: the shape takes nothing).

joints ​
ts
readonly joints: SeatedJointNames;

The names the pose is written on.

keepGap ​
ts
readonly keepGap: number;

With a keep-out shape: whether every part of the body that is held off it (the trunk, the neck, the head, the arms, the legs) is out of it, as the pose was written this frame (after anything laid over it has written its limbs): under 0 where a part is inside, by that much, metres (nothing was left to give way); over 0 where all are out (how far the nearest place tried on the body is from being inside, up or sideways: not the shortest way to the shape, and without an end where no part is over the shape at a height its sides have). With the shape's distances (SeatedKeepOut.field): the true distance from the nearest of those parts to the shape's surface, always a number, with no step. NaN without a shape.

kept ​
ts
readonly kept: number;

How much of what a reference pose and the feel add to the trunk is in use: 1, or less when a hand that holds its grip could not have reached with all of it, or when a keep-out shape left no other way to keep the trunk out of it.

kneeMiss ​
ts
readonly kneeMiss: Float32Array;

How far the middle of each knee joint ended from where its knee spot asks it to be, metres: left, right. NaN for a knee with no spot. More than a few millimetres means the leg's two lengths do not let the knee reach the spot with the foot on its rest.

laidBack ​
ts
readonly laidBack: number;

With a take known ahead (SeatedOverlay.ahead) and a keep-out shape: the share of the hips' own turn on the seat that was taken back this frame, 0 to 1 (a part that rides on the hips or on the first joint of the spine would have entered the shape). 0 where nothing had to give.

laidKept ​
ts
readonly laidKept: number;

With something laid over the pose: the share of its turn of the trunk (and of the pelvis) that was kept this frame, 0 to 1: under 1 where a hand that holds its grip could not reach, or where raising the back did not keep the trunk out of a keep-out shape. 1 where nothing was taken back, and with nothing laid.

laidLimb ​
ts
readonly laidLimb: number;

With something laid over the pose and a keep-out shape: how far the limbs the overlay has driven (its acting and its also) were turned this frame to keep them out of the shape, radians: the most of them. 0 where none had to give.

laidNet ​
ts
readonly laidNet: number;

With a take known ahead and a keep-out shape: how many frames, since this pose was made, the limit under the plan had to act (a part was truly inside the shape after the plan: the machine or the rider stood otherwise than when the take was asked). A plan that holds leaves it where it was.

laidPlan ​
ts
readonly laidPlan: Readonly<SeatedLaidPlan> | null;

With a take known ahead and a keep-out shape: the plan made for the take asked last (SeatedLaidPlan), or null when none was made. Read only: the same record is written again for each take.

laidRaised ​
ts
readonly laidRaised: number;

With something laid over the pose (SeatedOverlay) and a keep-out shape: how far the back was raised this frame to keep what was laid out of the shape, radians. 0 where nothing had to give.

lean ​
ts
readonly lean: number;

How far the back leans forward now, radians.

miss ​
ts
readonly miss: Float32Array;

How far each hand and foot ended from where it was to be, metres: left hand, right hand, left foot, right foot. NaN for one with no spot. More than a few millimetres means the spot is out of the limb's reach.

reference ​
ts
readonly reference: Readonly<SeatedReference> | null;

The reference pose in use this frame: the one given, or, with several poses, their mix as the machine's lean, its speed and its braking (and the feel's springs) have it now. Null with none. Read only: the same record is written again each frame.

Methods ​

apply() ​
ts
apply(
   spots, 
   dt, 
   over?
): void;

Write the pose. Call after the animator and before the skin reads the bones; call SeatedPose.restore before the animator next runs.

Parameters ​
ParameterTypeDescription
spotsSeatedSpotsWhere the seat, the grips and the rests are, world.
dtnumberSeconds since the last frame.
over?SeatedOverlay | nullSomething laid over the pose between its steps (a move played from the seat), or nothing: the pose alone, as before.
Returns ​

void

gapAt() ​
ts
gapAt(middle, radius): number;

With a keep-out shape: how far a ball is from being inside the shape as the shape stood in the last frame written (a caller that moves a limb itself, a move played from the seat, asks for the limb's own balls). Under 0: inside by that much, metres; over 0: out of it (how far its nearest place tried is from being inside, up or sideways; without an end where the ball is not over the shape at a height its sides have, so it steps from there to a centimetre or two as a ball comes down over the thing). With the shape's distances (SeatedKeepOut.field): the true distance from the ball to the shape's surface (the distance at its middle less its radius), which changes by no more than the ball moves, from any distance. NaN without a shape.

Parameters ​
ParameterTypeDescription
middleVector3The ball's middle, world.
radiusnumberIts radius, metres.
Returns ​

number

The gap, metres.

gapOf() ​
ts
gapOf(part): number;

With a keep-out shape: the smallest gap of one part of the body to the shape, as the bones now stand (after a frame is written: the frame as drawn), with no gap asked for. Under 0: that part is inside by that much, metres. NaN without a shape, or where the body has no ball of that part that is held off the shape.

Parameters ​
ParameterTypeDescription
partSeatedBodyPartWhich part: the trunk with the neck, the head, an arm or a leg (without the hand, the foot and what lies on the seat: those are never held off a shape).
Returns ​

number

The gap, metres.

restore() ​
ts
restore(): void;

Take the writing off: every bone as the animation left it.

Returns ​

void


SeatedPoseOptions ​

Options for createSeatedPose.

Properties ​

joints? ​
ts
optional joints?: SeatedJointNames;

The joints, by this rig's names; left out, found by seatedJointsFor.

root ​
ts
root: Object3D;

The rig root, the bones under it AT REST: the character's own frame (+z forward, +y up).


SeatedPoses ​

Several poses of one rider on one machine, blended by what the machine does (SeatedSpots.poses): the pose on a machine that runs straight, and the pose in a turn to each side, in full once the machine leans leanFull. Between, every amount is mixed (mixSeatedReferences); the hips and the head (SEATED_REFERENCE_FIRST) are in full at firstShare of that lean already, so they go into the turn before the rest of the body.

Properties ​

brake? ​
ts
optional brake?: Readonly<SeatedReference> | null;

The pose under braking: sitting up, slid forward against the tank, the arms braced. With one given the rider goes to it as the machine brakes, whatever its speed (the braking is read off the seat's own path): not at all under brakeFrom, in full from brakeFull. A turn's pose stays laid on top. With the feel a spring of its own follows the braking (the rider comes up at once, passes the pose a little and settles), and the feel's own fold forward under braking is taken out by as much. Left out: nothing.

brakeFrom? ​
ts
optional brakeFrom?: number;

The braking under which the braking pose is not used at all, m/s2. Left out: 1.5.

brakeFull? ​
ts
optional brakeFull?: number;

The braking from which the braking pose is in full, m/s2. Left out: 6.

firstShare? ​
ts
optional firstShare?: number;

The share of leanFull at which the hips and the head are in the turn's pose in full. Left out: 0.6.

lead? ​
ts
optional lead?: number;

Seconds the hips and the head run ahead of a lean that is growing, with the feel on (they follow the lean as it will be this much later). Left out: 0.15.

leanFull? ​
ts
optional leanFull?: number;

The machine's lean at which a turn's pose is in full, degrees. Left out: 35.

left? ​
ts
optional left?: Readonly<SeatedReference> | null;

The pose in a turn to the rider's left (the machine leaned to its left). Left out: the straight pose.

right? ​
ts
optional right?: Readonly<SeatedReference> | null;

The pose in a turn to the rider's right. Left out: the straight pose.

speedTuck? ​
ts
optional speedTuck?: number;

The speed from which the pose at speed is in full, m/s. Left out: 30.

speedUpright? ​
ts
optional speedUpright?: number;

The speed at and under which the upright pose is in full, m/s. Left out: 0 (standing still).

straight ​
ts
straight: Readonly<SeatedReference>;

The pose on a machine that stands upright and runs straight.

turnSlow? ​
ts
optional turnSlow?: number;

The share of a turn's pose laid on a rider who is going slowly (all of it at speed). Left out: 0.4.

upright? ​
ts
optional upright?: Readonly<SeatedReference> | null;

The pose standing still and slow: upright and easy. With one given, straight is the pose at speed (a tuck), and the two are mixed by the machine's speed read off the seat's own path: upright in full at speedUpright and under, straight in full from speedTuck, smoothly between (with the two left out: a fifth of the way down at 30 km/h, six tenths at 60, nine tenths at 90). The turns' poses are laid on top as their difference from straight: in full at speed, turnSlow of it when slow. Left out: straight at any speed.


SeatedReference ​

How one rider sits on one machine, where the seat leaves the body free: amounts in DEGREES, each optional (left out: 0), each held within 60. "Left" and "right" are the rider's own. Turns and tilts are measured against the seat (its forward and its up), so a record holds on any machine and at any size of the rider.

Properties ​

ankleLeft? ​
ts
optional ankleLeft?: number;

How far the left foot follows its shin, 0 to 100. At 0 the foot lies as its rest lies (level across, the toes where footLeft turns them). At 100 the foot is in line with the lower leg as seen from behind: the knee, the ankle and the bottom of the foot on one straight line, the foot's sideways tilt taken from the shin and its toes straight ahead (footLeft is then not used); the heel's rise is kept and the rest stays under the same place of the foot.

ankleRight? ​
ts
optional ankleRight?: number;

How far the right foot follows its shin, 0 to 100.

armsStraight? ​
ts
optional armsStraight?: number;

How far the arms are straightened, 0 to 100. At 0 the reach to a grip uses nine tenths of an arm's length (the elbows well bent). At 100 it uses nearly all of it (the elbow of the arm that reaches furthest about 8 degrees off straight): the arms braced. The back's lean is the least that lets both hands reach, so straighter arms sit the rider more upright; how upright is decided by where the machine's grips are and by the rider's own arms. The hands stay on their grips.

backRound? ​
ts
optional backRound?: number;

The back rounded: the chest pitched further forward than the hips' lean alone gives it, the spine between taking it bone by bone (a hollow back is negative). The head stays up from it.

ballLeft? ​
ts
optional ballLeft?: number;

Where the left foot rest lies under the foot: 0 where the pose has it (six tenths of the way from under the ankle to the ball), 100 under the ball of the foot itself. With heelLeft the foot then stands on its ball, the heel up. From 0 to 100.

ballRight? ​
ts
optional ballRight?: number;

Where the right foot rest lies under the foot: 0 where the pose has it, 100 under the ball.

chestTilt? ​
ts
optional chestTilt?: number;

The chest leaned to a side against the seat: the left shoulder lower is positive.

chestTurn? ​
ts
optional chestTurn?: number;

The chest turned against the seat about its up; to the left is positive. The spine between takes it bone by bone. Less hipsTurn it is the trunk's twist.

elbowLeft? ​
ts
optional elbowLeft?: number;

The left elbow raised outward about the line from the shoulder to the wrist (dropped inward is negative).

elbowRight? ​
ts
optional elbowRight?: number;

The right elbow raised outward (dropped inward is negative).

footLeft? ​
ts
optional footLeft?: number;

The left foot's toes turned outward on its rest (inward is negative). The sole stays on the rest.

footRight? ​
ts
optional footRight?: number;

The right foot's toes turned outward (inward is negative).

headNod? ​
ts
optional headNod?: number;

The head nodded: the chin lower is positive.

headTilt? ​
ts
optional headTilt?: number;

The head tilted to a side: the left ear lower is positive.

headTurn? ​
ts
optional headTurn?: number;

The head turned about its up; to the left is positive.

heelLeft? ​
ts
optional heelLeft?: number;

The left heel raised off level, the ball of the foot on the rest (lowered is negative).

heelRight? ​
ts
optional heelRight?: number;

The right heel raised off level (lowered is negative).

hipsBack? ​
ts
optional hipsBack?: number;

The hips moved BACK along the saddle from the seat spot (forward is negative), in HUNDREDTHS of the rider's own height (the head joint over the ankles, at the rider's size), so the same record holds for a rider of any size. The back then leans further to reach the grips. Held within 60.

hipsDown? ​
ts
optional hipsDown?: number;

The hips lowered toward the saddle (raised is negative), hundredths of the rider's height.

hipsSide? ​
ts
optional hipsSide?: number;

The hips moved off the saddle's middle to the rider's left (to the right is negative), hundredths of the rider's height.

hipsTilt? ​
ts
optional hipsTilt?: number;

The pelvis tilted on the seat: the left hip lower is positive (the weight on the left).

hipsTurn? ​
ts
optional hipsTurn?: number;

The pelvis turned on the seat about the seat's up; to the left is positive. The middle of the hip joints stays over the seat.

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

Where the left knee rests in THIS pose, in the seat's own frame (metres from the seat spot: +x the rider's left, +y up, +z forward): closed on the tank in one pose, out and down in another. It is a knee spot (SeatedSpots.knees) that belongs to the pose and is used in place of the seat's own. Left out or null: the seat's own knee spot, if any.

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

Where the right knee rests in this pose, in the seat's own frame, metres.

lean? ​
ts
optional lean?: number;

The back leaned further forward than the least that lets both hands reach their grips: the trunk comes forward and down and the elbows bend more. Only forward (0 or more), and only as far as the hands still reach as well as they did. Not read off a take: the machine's own grips decide the lean.

shoulderLeft? ​
ts
optional shoulderLeft?: number;

The left shoulder brought forward (back is negative).

shoulderRight? ​
ts
optional shoulderRight?: number;

The right shoulder brought forward (back is negative).

wristLeft? ​
ts
optional wristLeft?: number;

The left hand dropped further over its grip than the pose's own set (raised is negative). The bar stays in the palm.

wristRight? ​
ts
optional wristRight?: number;

The right hand dropped further over its grip (raised is negative).


SeatedReferenceFrame ​

What readSeatedReference reads a pose from.

Properties ​

facingDeg? ​
ts
optional facingDeg?: number;

Which way the performer's seat faces in the take's world, degrees about up from +z (to the left is positive). Left out, it is read off the performer: the level line from the middle of the two ankles to the middle of the two wrists, which the machine holds.

joints? ​
ts
optional joints?: SeatedJointNames;

The joints, by this rig's names; left out, found by seatedJointsFor.

root ​
ts
root: Object3D;

The rig root, the bones under it AT REST (the character's own skeleton).

Methods ​

rotation() ​
ts
rotation(name, out): Quaternion | null;

A joint's turn against its parent on the frame read, by bone name (the hips': against the take's own world), or null for a joint the take does not move (it stays at rest).

Parameters ​
ParameterTypeDescription
namestringThe bone's name.
outQuaternionWritten.
Returns ​

Quaternion | null

out, or null.


SeatedSpot ​

A place in the world with a facing: its +z forward, its +y up, its +x to the left.

Properties ​

position ​
ts
readonly position: Vector3;

Where, world.

quaternion ​
ts
readonly quaternion: Quaternion;

How it is turned, world.


SeatedSpots ​

Where a seated character meets what it sits on, this frame.

Properties ​

feel? ​
ts
optional feel?: Readonly<SeatedFeel> | null;

The feel: the body follows the machine by springs instead of directly. Left out: as before. Give it every frame it is wanted; a frame without it starts it again at rest.

feet ​
ts
feet: readonly [SeatedSpot | null, SeatedSpot | null];

The foot rests, left then right (the top of each), or null for a foot left to the animation.

hands ​
ts
hands: readonly [SeatedSpot | null, SeatedSpot | null];

The grips, left then right, or null for a hand left to the animation. A grip's +x runs along its bar toward the character's left, its +z is the way the knuckles point.

keepOut? ​
ts
optional keepOut?: Readonly<SeatedKeepOut> | null;

The shape of the thing sat on that the body may not enter (a motorbike's tank, its bars, its sides): a real limit, whatever the pose asks. The trunk, the neck and the head go no lower than where they touch it: a pose's further lean, a spring passing its rest and the feel's fold forward all come to rest on it, softly (SEATED.keepSoft). The back stays as upright as that needs, down to the least lean that lets the hands reach with the arms out nearly straight; where even that lean leaves the trunk inside (a rider hung off to a side), what the pose and the feel add to the trunk gives way as far as needed (SeatedPose.kept says how much is left). A head that would be inside is tipped back up. An elbow or a forearm that would be inside is raised outward until it is clear; with the shape's sides, a knee, a thigh or a shin that would be inside a side is moved outward until it lies against it. The body is taken as rounded shapes carried by its joints (SeatedKeepOut.body: the rider's own, measured off its mesh, or shapes from the skeleton's proportions). The hips stay on the seat, every hand on its grip and every foot on its rest; those and what lies on the seat (the first half of each thigh) or at a grip (the last quarter of each forearm) are not held off. Left out: no limit, as before.

knees? ​
ts
optional knees?: 
  | readonly [SeatedSpot | null, SeatedSpot | null]
  | null;

Where each knee rests on the side of what is sat on (a motorbike's tank), left then right, or null for a knee left to the pose: the point on the surface the knee's inner side lies against. With one given the leg is bent so that its knee rests there, with the foot on its rest and the hips on the seat. A spot the leg's two lengths cannot bring the knee to is not met: the knee then stays against the same side (at the spot's distance from the middle of what is sat on) and goes as near the spot as it can, so one spot serves a rider of any size (SeatedPose.kneeMiss says how far off it ends). The side is the plane through the spot across the spot's own +x (as with every spot, +x is the rider's left: the way out of the side at the left knee, the way in at the right): a spot that is not turned stands for a side that runs straight along the machine, and one turned about its up for a tank that widens. Left out: the knees point forward and a little out, as before.

pose? ​
ts
optional pose?: Readonly<SeatedReference> | null;

The reference pose this rider follows on this seat where the seat leaves the body free (a hand-set record, or one read off a performed take: readSeatedReference). Left out: the pose's own, the same on both sides, as before.

poses? ​
ts
optional poses?: Readonly<SeatedPoses> | null;

Several poses of this rider on this seat, mixed by what the machine does: the pose running straight and the pose in a turn to each side, in full once the machine leans leanFull. The hips and the head go into a turn first (they are in full at a share of that lean), the rest of the body with the lean. With the feel the mix follows the feel's own springs, the hips and the head a little ahead of a lean that is growing, so the rider sets up for a turn, and comes back out of it late and with a settle. Used in place of pose. Left out: pose, as before.

recline? ​
ts
optional recline?: number;

How far the seat leans back in the frame of the thing it is part of, radians; left out or 0 for a seat that stands upright in its thing (a motorbike's). Not the thing's own tilt on a slope: only how the seat is built.

seat ​
ts
seat: SeatedSpot;

The seat: the top of its surface under the hips.


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 ​

head? ​
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.


Sprung ​

A spring toward a target with a half-life (the studio's springTo, critically damped).

Properties ​

v ​
ts
v: number;
x ​
ts
x: number;

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.


StrideReading ​

How a looping clip's steps sit in its cycle, read off its contacts.

Properties ​

offset ​
ts
offset: number;

Where in the loop the left foot first lands, as a share of the loop, in [0, 1).

strides ​
ts
strides: number;

Strides in the loop (a stride: one left step and one right); at least 1.


UpperBodyLayer ​

An action or a held pose on part of the body, over any movement underneath.

Example ​

ts
import type { UpperBodyLayer } from 'gameable/animation';

function wave(upperBody: UpperBodyLayer): void {
  upperBody.onDone = () => console.log('waved');
  if (!upperBody.play({ take: 'wave', mask: 'right-arm' })) console.warn('no wave in this set');
}

Properties ​

gate ​
ts
gate: number;

1 lets the layer work; 0 shuts it at once (a physics body reacting to a hit).

on ​
ts
on: boolean;

The switch: off, the layer writes nothing and forgets its play.

onDone ​
ts
onDone: (() => void) | null;

Told once when a play that is neither looped nor held reaches its end. (Not told when the play is stopped, replaced or forgotten.) It may start the next play.

playing ​
ts
readonly playing: boolean;

True while a play has the masked joints (not while only an offset dies away).

seconds ​
ts
readonly seconds: number;

Seconds of the take played so far, counted from the play's from in the take's own time (rate speeds it; a loop starts again from 0).

take ​
ts
readonly take: string;

The take playing, '' when none is.

Methods ​

play() ​
ts
play(request): boolean;

Start a play. It replaces the one under way, if any: the joints are carried over, never cut. A joint of the mask the rig lacks or the set does not move stays with the movement underneath. Ask while the layer is on: off or gated shut, it forgets the play at its next update.

Parameters ​
ParameterTypeDescription
requestUpperBodyPlayThe take, the mask and how it is played.
Returns ​

boolean

False (and nothing changes) when the set has no such take or the layer no such mask.

reset() ​
ts
reset(): void;

Forget everything at once (a teleport): no play, no offset, nothing written.

Returns ​

void

restore() ​
ts
restore(): void;

Take last frame's writing off the bones nothing else wrote since. Before the mixer.

Returns ​

void

setTable() ​
ts
setTable(table): void;

Another set (a table read on this rig). A play under way is let go, inertially: its take belongs to the set before.

Parameters ​
ParameterTypeDescription
tablePick<MotionTable, "data" | "hipsJoint">The table.
Returns ​

void

stop() ​
ts
stop(): void;

Let go: the masked joints go back to the movement underneath, inertially.

Returns ​

void

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

Play on and write the masked joints. After the matched takes, before the life and the feet.

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last update.
Returns ​

void


UpperBodyLayerOptions ​

Options for createUpperBodyLayer.

Example ​

ts
import { createUpperBodyLayer, type UpperBodyLayerOptions } from 'gameable/animation';

const options: UpperBodyLayerOptions = { root: rigRoot, table, blendSeconds: 0.3 };
const upperBody = createUpperBodyLayer(options);

Properties ​

blendSeconds? ​
ts
optional blendSeconds?: number;

Seconds a start or a stop takes to settle. Default 0.3. (A pose carried far takes up to twice as long, as the matched takes' jumps do.)

masks? ​
ts
optional masks?: Record<string, readonly string[]>;

Masks beside SOMA's (SOMA_UPPER_BODY_MASKS), by name: the joints each one takes. A name SOMA already has replaces SOMA's. Joints above the pelvis only: the pelvis itself is never written.

poseAdjust? ​
ts
optional poseAdjust?: PoseAdjustRecord | null;

The character's own pose adjustment (its package's poseAdjust): laid on the take's pose of each masked joint, as the matched takes' layer lays it. Omit for none.

root ​
ts
root: Object3D;

The rig root: the character's own frame, the bones under it.

table ​
ts
table: Pick<MotionTable, "data" | "hipsJoint">;

The set whose takes are played, read on this rig (buildMotionTable). The layer reads the set itself (data) and which of its joints is the pelvis (hipsJoint), no more: a set that is only played over another pose (a seated rider's moves) can be given as those two, without a whole table.


UpperBodyPlay ​

One play: a take (or a part of it) on a mask.

Example ​

ts
import type { UpperBodyPlay } from 'gameable/animation';

// Carry a box: both arms hold the take's last pose, a quarter of the walk's swing stays.
const carry: UpperBodyPlay = { take: 'carry-box', mask: 'both-arms', hold: true, swing: 0.25 };
upperBody.play(carry);

Properties ​

from? ​
ts
optional from?: number;

Where in the take the play starts, seconds. Default 0.

hold? ​
ts
optional hold?: boolean;

At to, hold the last pose until stop(). Default false.

loop? ​
ts
optional loop?: boolean;

Play round and round from from to to. Default false: at to the layer lets go by itself.

mask ​
ts
mask: UpperBodyMaskName | string & object;

The mask: one of SOMA's, or one given in UpperBodyLayerOptions.masks.

rate? ​
ts
optional rate?: number;

How fast the take is played. Default 1 (and 1 for anything that is not a number over 0).

relative? ​
ts
optional relative?: boolean;

Lay the take's TURN on the pose underneath, instead of the take's pose itself: each masked joint is turned, as its parent sees it, by what the take has turned it since the play's from. For a pose underneath that was solved for this body and this place (a seated rider's trunk, leaned as far as its own grips need) and must not be pulled to the performer's own posture. The share a joint takes of that turn is what swing and spineShare leave it (swing: 0.5 on a head: half the take's turn of the head). The character's pose adjustment is not laid on it (the pose underneath carries its own). Default false.

relativeTo? ​
ts
optional relativeTo?: object;

With relative: the pose the take's turn is counted FROM, when it is not the play's own from: a moment of another take of the set, or another moment of this one. A take that starts from a held pose (a punch's way back, its first frame the arm-out pose with the chest already turned) is counted from the first frame of the take that led into the pose, so it ends where that take began; a take whose still lead-in is skipped (from past its first frame) is still counted from its first frame. at is seconds into that take (default 0, its first frame). Left out: the play's from, as before. A take the set does not have refuses the play. Without relative it is not read.

at? ​
ts
optional at?: number;
take ​
ts
take: string;
spineShare? ​
ts
optional spineShare?: number;

The share of the take's pose the masked spine joints (Spine1, Spine2, Chest) take, 0 to 1; they keep the rest of the movement underneath. Default 0.5.

swing? ​
ts
optional swing?: number;

How much of the movement underneath stays on the masked joints, 0 to 1 (the arms' swing damped, not frozen). Default 0: the take's pose wholly. A carry uses about 0.25.

take ​
ts
take: string;

A take's name in the table's set.

to? ​
ts
optional to?: number;

Where in the take it ends, seconds. Default the take's end.


WalkArrival ​

How a walk ended.

Properties ​

error ​
ts
error: number;

Metres from the spot, and radians from the facing asked.

facingError ​
ts
facingError: number;
seconds ​
ts
seconds: number;

Seconds it took.


Walker ​

The game's own place for the character: moved by the walk while one is under way.

Properties ​

x ​
ts
x: number;
yaw ​
ts
yaw: number;

Radians about +Y.

z ​
ts
z: number;

WalkFeel ​

The feel pass on what the walk ITSELF drives (never on a performed take): one switch, off by default, and its four parts, each on with it unless put off. A walk that reaches the right place at the right time is blocking; this is the weight on top of it.

Properties ​

facing ​
ts
facing: boolean;

At a turn on the spot the head goes first to where it will face, and a small facing is taken up eased.

on ​
ts
on: boolean;

The one switch. Off (the default): the walk is, to the last bit, as it was before the pass.

pace ​
ts
pace: boolean;

The speed asked of the takes rises and falls eased, over a time that follows the pace.

settle ​
ts
settle: boolean;

After arrival the body comes back over its feet on a spring, the chest after the hips.

steer ​
ts
steer: boolean;

Steering with weight: a walk's turn rate toward the spot comes on and off no faster than a limit, the head and the chest lead the hips toward the spot, and at a run the body leans into the curve.


WalkFeelLayer ​

The feel pass on a character's body.

Properties ​

from ​
ts
from: Float32Array<ArrayBufferLike> | null;

What is asked of the body: a walk's DirectedWalk.body, or null for nothing.

on ​
ts
on: boolean;

Whether it writes. Off, what it had on the body comes off on its springs, then nothing.

values ​
ts
readonly values: Float32Array;

What is on the body now (WALK_FEEL_VALUES): radians.

Methods ​

reset() ​
ts
reset(): void;

Its springs to rest at once (a character moved somewhere else).

Returns ​

void

restore() ​
ts
restore(): void;

Take its writing off the bones again (before the mixer writes the next frame).

Returns ​

void

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

Every frame, after the takes have written the pose and before the life: steps the springs and lays them on the bones.

Parameters ​
ParameterTypeDescription
dtnumberSeconds.
Returns ​

void


WalkFeelLayerOptions ​

Options for createWalkFeelLayer.

Properties ​

joints? ​
ts
optional joints?: LifeJointNames;

What the rig calls its joints. Default: SOMA's.

root ​
ts
root: Object3D;

The character's rig: the bones are found under it by name.


WalkPlan ​

What a request came to.

Properties ​

distance ​
ts
distance: number;

Metres to the spot, and the turn to head for it, radians.

gait ​
ts
gait: "walk" | "sprint" | "run";

The gait it goes in: the name of the set's band (a walk, a run, or a faster one a set brings).

kind ​
ts
kind: "turn" | "steps" | "walk" | "none";

'none': already there. 'turn': only a turn. 'steps': one take, stand to stand. 'walk': a start, a walk, a stop.

limited ​
ts
limited: boolean;

The speed it is given is not the one asked: the pace or the time asked for is outside what the set covers, or a run was asked to a spot too near to run to at that speed (it then runs more slowly, or walks); or, set while it walks: no stop of the set ended on the spot from where the body was, and the one that passes it least was taken.

seconds ​
ts
seconds: number;
speed ​
ts
speed: number;

The speed it goes at, metres a second, and the seconds it expects to take.

stride ​
ts
stride: number;

How much its steps are lengthened (over 1) or shortened to land on the spot.

turn ​
ts
turn: number;

WalkRequest ​

Where to go, and how.

Properties ​

arrive? ​
ts
optional arrive?: "easy" | "quick";

How it stops: 'easy' (default: the takes' unhurried stops, for a presenter or a character in a room) or 'quick' (the shortest stops the set has, for a character that must be on the spot now; at a run: of the stops that end on the spot, the one that has the body still soonest, waited for when it is not due yet).

by? ​
ts
optional by?: number;

Arrive within this many seconds if the set's walking speeds allow it.

facing? ​
ts
optional facing?: number;

The facing to arrive with, radians about +Y (0 faces +Z). Absent: as it comes.

pace? ​
ts
optional pace?: number | WalkPace;

The pace: a name, or metres a second. Default 'normal'. Inside what the set's walk covers it walks; above it, it runs (kept to what the set's run covers, and to what there is room for); between the two it goes in the nearer, and the plan says limited.

start? ​
ts
optional start?: "best" | "moving";

How it sets off toward a spot well off the way it faces. 'best' (default): a move-off of the set that turns the body as it starts, or a turn on the spot first, whichever has it travelling sooner by the set's own times. 'moving': the body is in motion already though the takes do not have it yet (it comes running out of a get-up): planned as a walk asked of a body under way, never a turn on the spot or a few steps first; its steering bends the way to the spot inside its first strides.

stop? ​
ts
optional stop?: MotionStopStyle;

The style of its stop, where the set has stops that state one (a run's, on the shared set): 'gradual' (it slows and stands upright) or 'hard' (it brakes). It says WHICH KIND of stop; arrive says how soon it must be there. Absent: the character's own (MotionLayer.stopStyle, gradual unless the game set it), except for a quick arrival, which then stops by the takes that state no style, as it did before a set stated any.

x ​
ts
x: number;

The spot, world metres.

z ​
ts
z: number;

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


WeightFader ​

A weight fader.

Properties ​

applied ​
ts
readonly applied: ReadonlyMap<string, number>;

The weights as applied this step, by clip name; the object is reused.

seconds ​
ts
seconds: number;

The fade's length, seconds; settable at any time, applies from the next step.

Methods ​

reset() ​
ts
reset(): void;

Forget everything: the next step applies its weights at once.

Returns ​

void

step() ​
ts
step(wanted, dt): ReadonlyMap<string, number>;

Move the applied weights toward wanted by dt seconds.

Parameters ​
ParameterTypeDescription
wantedReadonlyMap<string, number>The weights the game wants, by clip name. Names absent want 0.
dtnumberSeconds since the previous step.
Returns ​

ReadonlyMap<string, number>

applied, the weights to hand the mixer this step.

Type Aliases ​

ActionAir ​

ts
type ActionAir = "as-recorded" | "ballistic";

How the time off the ground is played.


ActionEventName ​

ts
type ActionEventName = "started" | "contact" | "release" | "landed" | "done" | "failed";

What an action says while it happens.


ActionLimb ​

ts
type ActionLimb = "left-hand" | "right-hand" | "left-foot" | "right-foot";

A limb an action can hold to a contact point.


ActionObjectKind ​

ts
type ActionObjectKind = 
  | "none"
  | "bar"
  | "beam"
  | "box"
  | "ledge"
  | "low-box"
  | "gap"
  | "seat"
  | "crate"
  | "ball";

What an action is done at.


ActionReason ​

ts
type ActionReason = 
  | ""
  | "unknown-action"
  | "needs-object"
  | "too-high"
  | "too-low"
  | "too-close"
  | "too-far"
  | "not-lined-up"
  | "wrong-foot"
  | "busy"
  | "seated"
  | "hit"
  | "clipped"
  | "no-floor"
  | "cancelled";

Why a request was refused or an action failed ('': it was not).


ActionStatus ​

ts
type ActionStatus = "built-seen" | "built-not-seen" | "designed" | "waiting-for-take";

Where an action stands today. built-seen: built and seen on screen (the note says when it does not yet read as meant: today only the hurdle and the jump do); built-not-seen: built, run, not yet right on screen; designed: stated, never run; waiting-for-take: it needs a take that does not exist yet, or one remade.


AdditiveType ​

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

How the additive delta is computed.


AnimationIntentKind ​

ts
type AnimationIntentKind = "included" | "style" | "none";

What the creator meant.


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.


ClipEndKind ​

ts
type ClipEndKind = "ended" | "loop";

Why a clip's end was reported: the clip played once and finished, or a looping clip came round to its start.


ClipEndListener ​

ts
type ClipEndListener = (name, kind, time) => void;

Told when a clip ends or comes round.

Parameters ​

ParameterTypeDescription
namestringThe clip's runtime name.
kindClipEndKind'ended' (a once-only clip finished) or 'loop' (a looping clip wrapped).
timenumberThe clip's local time at the report, seconds.

Returns ​

void


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


FollowAmount ​

ts
type FollowAmount = "less" | "default" | "more";

How far a part turns after a look.


FootGround ​

ts
type FootGround = (x, y, z) => number;

The ground's height under a world point: the world y of the ground at (x, z), looked for around the height y (the floor the character stands on); NaN when there is none.

Parameters ​

ParameterType
xnumber
ynumber
znumber

Returns ​

number


GetUpEventName ​

ts
type GetUpEventName = "started" | "up" | "stood" | "done" | "cancelled";

What a get-up says while it happens.


GetUpLie ​

ts
type GetUpLie = "back" | "front" | "left" | "right";

How a body lies: on its back, its front, or a side (left: its left side is on the floor).


GetUpStyle ​

ts
type GetUpStyle = "ordinary" | "quick" | "run";

ordinary: the plain get-up. quick: a spring straight back onto the feet. run: from the ground straight up into a run: the take never stands, it ends on a running footfall at speed, and its file states where its running steps fall (GetUpRunSource).


GraphNodeData ​

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

A node's authored payload: arbitrary JSON.


LifeLevel ​

ts
type LifeLevel = "calm" | "natural" | "lively";

How much of every small motion: Calm, Natural or Lively.


LifeState ​

ts
type LifeState = "idle" | "listening" | "thinking" | "speaking";

The conversation's state, as the host says it.


LookUp ​

ts
type LookUp = "rarely" | "sometimes" | "often";

How often the character looks at the person.


MotionGaitName ​

ts
type MotionGaitName = "stand" | "walk" | "run" | "sprint";

The gaits by name, in the order of their codes.


MotionStopStyle ​

ts
type MotionStopStyle = "gradual" | "hard";

How a body in motion comes to a stand, where its set has stops that state a style (MotionTakeSource.stopStyle): 'gradual', it slows and stands upright; 'hard', it brakes.


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.


SeatedAmount ​

ts
type SeatedAmount = Exclude<keyof SeatedReference, "kneeLeft" | "kneeRight">;

The names of a SeatedReference's amounts that are numbers.


SeatedBodyPart ​

ts
type SeatedBodyPart = "trunk" | "head" | "left-arm" | "right-arm" | "left-leg" | "right-leg";

A part of the body a keep-out shape holds off itself (SeatedPose.gapOf).


SeatedMoveLimb ​

ts
type SeatedMoveLimb = "left-arm" | "right-arm" | "left-leg" | "right-leg";

The limb a seated take is performed with.


UpperBodyMaskName ​

ts
type UpperBodyMaskName = "spine-up" | "left-arm" | "right-arm" | "both-arms" | "head";

The masks every SOMA character has: the spine and everything above it, one arm, both arms, or the neck and head.

Example ​

ts
import type { UpperBodyMaskName } from 'gameable/animation';

const mask: UpperBodyMaskName = 'left-arm';
upperBody.play({ take: 'wave', mask });

Vec3 ​

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

A world-space point.


WalkPace ​

ts
type WalkPace = "stroll" | "normal" | "brisk" | "run";

A pace by name: the set's own slowest, middle and fastest steady walk, and 'run', the middle of the steady speeds its run shows.

Variables ​

ACTION_LIMBS ​

ts
const ACTION_LIMBS: readonly ActionLimb[];

The limbs, in the order of every per-limb array.


ACTION_LIST ​

ts
const ACTION_LIST: readonly ActionKind[];

The list, version 1. The first class is what a running game uses in stride; the second is done from standing or a walk.

Example ​

ts
import { ACTION_LIST } from 'gameable/animation';

for (const action of ACTION_LIST) console.log(action.kind, action.status, action.title);

ACTION_POINT_HEAD ​

ts
const ACTION_POINT_HEAD: 4 = 4;

The top of the head among an action's points.


ACTION_POINTS ​

ts
const ACTION_POINTS: 7 = 7;

Points of the body an action is read by: the four limbs, the top of the head, the toes.


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.


AOSRIG_SEATED_JOINTS ​

ts
const AOSRIG_SEATED_JOINTS: SeatedJointNames;

The engine's sample skeleton and a studio export of the first format (aosrig_v0).


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.


ts
const BLINK_RATE_RANGE: readonly [number, number];

The blink rate's ends, as the studio's slider has them.


DEFAULT_FADE_SECONDS ​

ts
const DEFAULT_FADE_SECONDS: 0.4 = 0.4;

Default fade, seconds.


defaultClock ​

ts
const defaultClock: Clock;

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

Returns ​

Milliseconds since the time origin.


EVERYDAY_MOTION_URL ​

ts
const EVERYDAY_MOTION_URL: string;

The engine's shared motion set, Everyday: the takes every exported character without a set of its own moves by (standing, walking, running, the stretches between, actions), in the compact form. EVERYDAY_MOTION_URL is where the file is, beside this package (assets/everyday-v1.motion.bin); the character bridge finds it there with no wiring from a game. A build without the file leaves every character moving as it did before.

Example ​

ts
import { EVERYDAY_MOTION_URL, parseMotionBytes, parseMotionSet } from 'gameable/animation';

const response = await fetch(EVERYDAY_MOTION_URL);
const { data } = parseMotionBytes(new Uint8Array(await response.arrayBuffer()), parseMotionSet);
console.log(data.name, data.modules);

FOLLOW ​

ts
const FOLLOW: Readonly<Record<"eyes" | "head" | "body", Readonly<Record<FollowAmount, number>>>>;

The studio's FOLLOW table: each part's share by its amount.


GAIT_RUN ​

ts
const GAIT_RUN: 2 = 2;

A frame's gait: running (both feet off the ground between steps).


GAIT_SPRINT ​

ts
const GAIT_SPRINT: 3 = 3;

A frame's gait: sprinting. Never read off the body (to its joints a sprint is a run): the moving frames of the takes a set keeps in its sprint part (MOTION_SPRINT_MODULE).


GAIT_STAND ​

ts
const GAIT_STAND: 0 = 0;

A frame's gait: standing.


GAIT_WALK ​

ts
const GAIT_WALK: 1 = 1;

A frame's gait: walking (a foot always down).


GETUP_GROUND_SHARE ​

ts
const GETUP_GROUND_SHARE: 0.3 = 0.3;

A body is still on the ground while its hips are under this share of the height they stand at when the get-up ends.


GETUP_LIMB_POINTS ​

ts
const GETUP_LIMB_POINTS: readonly number[];

The hands' and the feet's points (the order of the limb hold: left hand, right hand, left foot, right foot).


GETUP_MODULE ​

ts
const GETUP_MODULE: "getups" = 'getups';

The part (module) of a set its get-ups are takes of.


GETUP_POINTS ​

ts
const GETUP_POINTS: 18 = 18;

The points of the body a get-up is read by, in the order of every per-point array: the hips, the chest, the head and its top, then left and right of the shoulders, the elbows, the hands, the hip joints, the knees, the ankles and the toes.


GETUP_RUN_HAND_S ​

ts
const GETUP_RUN_HAND_S: 0.2 = 0.2;

A take that ends in a run is handed over to the set's own run this long before its last frame, seconds.


GETUP_UP_SHARE ​

ts
const GETUP_UP_SHARE: 0.85 = 0.85;

A body is up enough to be moved once its hips are at this share of the height they stand at when the get-up ends.


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.


LIFE ​

ts
const LIFE: Readonly<{
  ahead: Readonly<{
     pitch: -4;
     yaw: 0;
  }>;
  bodyYawMax: 15;
  breath: Readonly<{
     chestDeg: 1.1;
     clavDeg: 0.6;
     headDeg: 0.3;
     hz: 0.27;
     swayDeg: 0.2;
     swayHz: 0.12;
  }>;
  chestTauS: 0.6;
  eyePitchDown: 25;
  eyePitchUp: 22;
  eyeYawMax: 30;
  glanceEvery: Readonly<{
     idle: readonly [number, number];
     listening: readonly [number, number];
     speaking: readonly [number, number];
     thinking: readonly [number, number];
  }>;
  glanceHoldS: readonly [number, number];
  glancePitch: readonly [number, number];
  glanceYaw: readonly [number, number];
  headPitchMax: 25;
  headTauS: 0.32;
  headYawMax: 55;
  listenNodDeg: readonly [number, number];
  listenNodEvery: readonly [number, number];
  listenNodFirst: readonly [number, number];
  listenNodS: readonly [number, number];
  listenSoftRoll: 1.2;
  nod: 3;
  restBeforeGlanceS: 0.4;
  shiftDropMm: 3;
  shiftHalfLifeS: 0.42;
  shiftMm: readonly [number, number];
  shiftRoll: 1.8;
  shiftYaw: 1.2;
  swayFwd: readonly readonly [number, number][];
  swayLeanDegPerMm: 0.064;
  swaySide: readonly readonly [number, number][];
  tauBody: 0.9;
  tauHead: 0.28;
  tauVary: 1.4;
  thinkPitch: readonly [number, number];
  thinkSoftRoll: -1.5;
  thinkYaw: readonly [number, number];
  varyChest: 0.8;
  varyEvery: readonly [number, number];
  varyHeadRoll: 2;
  varyHipRoll: 1.2;
  walkGlanceEvery: readonly [number, number];
  walkGlanceHoldS: readonly [number, number];
}>;

The studio's numbers, in one place.


LIFE_DEFAULT ​

ts
const LIFE_DEFAULT: Readonly<LifeSetting>;

The studio's default: on, Natural, the eyes all the way, the head as it was, the body slightly.


LIFE_GAIN ​

ts
const LIFE_GAIN: Readonly<Record<LifeLevel, number>>;

The studio's LIFE_GAIN: how much of everything, by level.


LOCOMOTION_CLIP_NAMES ​

ts
const LOCOMOTION_CLIP_NAMES: Readonly<{
  idle: "idle";
  jog: "jog";
  jogBack: "jog_back";
  jumpLand: "jump_land";
  jumpLoop: "jump_loop";
  jumpStart: "jump_start";
  run: "run";
  runStart: "run_start";
  runStop: "run_stop";
  sprint: "sprint";
  strafeLeft: "strafe_left";
  strafeRight: "strafe_right";
  turnLeft: "turn_left";
  turnRight: "turn_right";
  walk: "walk";
}>;

The names of a locomotion set's clips, by what a game asks for.


LOOK_UP ​

ts
const LOOK_UP: Readonly<Record<LookUp, Readonly<LookUpScale>>>;

The studio's LOOK_UP table: Sometimes is the glance table as written.


LOOP_ONCE ​

ts
const LOOP_ONCE: 2200 = 2200;

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


MOTION_BINARY_MAGIC ​

ts
const MOTION_BINARY_MAGIC: 1112493395 = 0x424f4d53;

The file's first four bytes, as a little-endian number: "SMOB".


MOTION_BINARY_VERSION ​

ts
const MOTION_BINARY_VERSION: 1 = 1;

The layout's version.


MOTION_ENTRY_REACH_S ​

ts
const MOTION_ENTRY_REACH_S: 0.6 = 0.6;

Seconds before a stand's last frame within which a body may enter its move-off.


MOTION_FALLBACK_COST ​

ts
const MOTION_FALLBACK_COST: 2 = 2;

What a frame of a fallback take costs a search (a match's own cost is 1 to 3): enough that another take's frame about as good is chosen, not so much that a request only the fallback serves goes unanswered.


MOTION_FEATURES ​

ts
const MOTION_FEATURES: 27 = 27;

Numbers in a frame's feature vector.


MOTION_GAIT_NAMES ​

ts
const MOTION_GAIT_NAMES: readonly MotionGaitName[];

The gaits' names by code (GAIT_STAND, GAIT_WALK, GAIT_RUN, GAIT_SPRINT).


MOTION_HORIZONS ​

ts
const MOTION_HORIZONS: readonly number[];

How far ahead the path is read, seconds.


MOTION_MODULE_ORDER ​

ts
const MOTION_MODULE_ORDER: readonly string[];

The order takes are written in, by module; a module not named here comes after (a set's getups, which so stay last). It is also every part the engine knows a set by, for a reader that wants the whole of one with its actions: a sprint part is named here so that it comes with the whole, after the parts every character needs.


MOTION_RATE_FASTEST ​

ts
const MOTION_RATE_FASTEST: 1.15 = 1.15;

The gaits of a motion set: what its takes are doing at every frame (standing, walking, running, read from the feet), where each frame is heading, and the speeds the set covers per gait, from the takes' own measured speeds and cadence (never their names). A request is answered only in the gait that covers its speed: never a run played slowly. A speed no take covers is brought to the nearest one covered below it, and MotionLayer.pace says so. A sprint is the one gait a set has to mark: the takes of its sprint part (MOTION_SPRINT_MODULE) are GAIT_SPRINT, with their own band, start and stop; beside them the run's band ends where a run take really goes, and the walk and the run below that are exactly what they are without the part. Every steady stretch of a take is read too (gaits.stretches: its own pace and cadence, and the loop a long walk goes round in it), and motionStrideFor / motionRateFor say how a steady stride meets a speed: by the length of its steps first, its rate last. Every move-off is read as well (table.starts, MOTION_START: how far each turns the body as it starts, how soon it is moving, by which frame its turn is made), and motionStartScale says whether a start serves an angle asked, its own turn made a little smaller or larger; a start its take states as a quick turning start (turnStart) also serves an angle up to MOTION_START_STEER beyond that.

Example ​

ts
import {
  buildMotionTable,
  GAIT_STAND,
  MOTION_GAIT_NAMES,
  MOTION_START,
  MOTION_START_STEER,
  motionPaceFor,
  motionRateFor,
  motionStartScale,
  motionStrideFor,
  parseMotionSet,
} from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
for (const band of table.gaits.bands)
  console.log(band.name, band.from, 'to', band.to, 'm/s at', band.cadence, 'steps a minute');
const pace = motionPaceFor(table.gaits, 2, GAIT_STAND, { gait: 0, asked: 0, given: 0, limited: false });
console.log(MOTION_GAIT_NAMES[pace.gait], pace.given, pace.limited);
for (const stretch of table.gaits.stretches)
  console.log(stretch.pace, 'm/s,', stretch.cadence, 'steps a minute, a loop of', stretch.seconds, 's');
// a steady walking stride asked to go at 85 % of its own pace: its steps 12 % shorter, its rate 4 % slower
console.log(motionStrideFor(0.85), motionRateFor(0.85));
// the starts that would turn a standing body a quarter turn to its left, and how
const starts = table.starts.values;
for (let o = 0; o < starts.length; o += MOTION_START.numbers) {
  const marked = starts[o + MOTION_START.marked] === 1;
  const scale = motionStartScale(
    starts[o + MOTION_START.turn],
    Math.PI / 2,
    marked ? MOTION_START_STEER : 0,
  );
  if (scale > 0) console.log('first metre after', starts[o + MOTION_START.seconds], 's, its turn made', scale);
}

MOTION_RATE_FASTEST_BESIDE_SPRINT ​

ts
const MOTION_RATE_FASTEST_BESIDE_SPRINT: 1.05 = 1.05;

On a set that carries a sprint part, where the run's band ENDS and how a sprint's stride is played: a run's top is the fastest any of its steady takes goes played at most this much faster than it was performed, a fallback take's not at all, and a sprint's stride is never played faster than that. A run played a seventh faster at its top turns its legs over at a sprinter's steps a minute on a runner's short steps (measured on the shared set: 226 steps a minute at 5.0 m/s), which is what such a set's sprint takes are there to answer instead. BELOW that top a run is played as on any set (its stride up to MOTION_RATE_FASTEST): a run asked at 3 m/s must not change because a sprint was added to the set. A walk is not touched (motionRateFastest).


MOTION_RATE_FASTEST_FALLBACK_BESIDE_SPRINT ​

ts
const MOTION_RATE_FASTEST_FALLBACK_BESIDE_SPRINT: 1 = 1;

The gaits of a motion set: what its takes are doing at every frame (standing, walking, running, read from the feet), where each frame is heading, and the speeds the set covers per gait, from the takes' own measured speeds and cadence (never their names). A request is answered only in the gait that covers its speed: never a run played slowly. A speed no take covers is brought to the nearest one covered below it, and MotionLayer.pace says so. A sprint is the one gait a set has to mark: the takes of its sprint part (MOTION_SPRINT_MODULE) are GAIT_SPRINT, with their own band, start and stop; beside them the run's band ends where a run take really goes, and the walk and the run below that are exactly what they are without the part. Every steady stretch of a take is read too (gaits.stretches: its own pace and cadence, and the loop a long walk goes round in it), and motionStrideFor / motionRateFor say how a steady stride meets a speed: by the length of its steps first, its rate last. Every move-off is read as well (table.starts, MOTION_START: how far each turns the body as it starts, how soon it is moving, by which frame its turn is made), and motionStartScale says whether a start serves an angle asked, its own turn made a little smaller or larger; a start its take states as a quick turning start (turnStart) also serves an angle up to MOTION_START_STEER beyond that.

Example ​

ts
import {
  buildMotionTable,
  GAIT_STAND,
  MOTION_GAIT_NAMES,
  MOTION_START,
  MOTION_START_STEER,
  motionPaceFor,
  motionRateFor,
  motionStartScale,
  motionStrideFor,
  parseMotionSet,
} from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
for (const band of table.gaits.bands)
  console.log(band.name, band.from, 'to', band.to, 'm/s at', band.cadence, 'steps a minute');
const pace = motionPaceFor(table.gaits, 2, GAIT_STAND, { gait: 0, asked: 0, given: 0, limited: false });
console.log(MOTION_GAIT_NAMES[pace.gait], pace.given, pace.limited);
for (const stretch of table.gaits.stretches)
  console.log(stretch.pace, 'm/s,', stretch.cadence, 'steps a minute, a loop of', stretch.seconds, 's');
// a steady walking stride asked to go at 85 % of its own pace: its steps 12 % shorter, its rate 4 % slower
console.log(motionStrideFor(0.85), motionRateFor(0.85));
// the starts that would turn a standing body a quarter turn to its left, and how
const starts = table.starts.values;
for (let o = 0; o < starts.length; o += MOTION_START.numbers) {
  const marked = starts[o + MOTION_START.marked] === 1;
  const scale = motionStartScale(
    starts[o + MOTION_START.turn],
    Math.PI / 2,
    marked ? MOTION_START_STEER : 0,
  );
  if (scale > 0) console.log('first metre after', starts[o + MOTION_START.seconds], 's, its turn made', scale);
}

MOTION_RATE_NATURAL ​

ts
const MOTION_RATE_NATURAL: 0.04 = 0.04;

Inside that range a stride's rate stays within this share of the take's own (a walker going a little slower also steps a little slower: a quarter of the change, never more than this).


MOTION_RATE_SLOWEST ​

ts
const MOTION_RATE_SLOWEST: 0.87 = 0.87;

A stride is played at most this much slower or faster than it was performed: the last resort, for a speed that the stride's length alone does not reach (see motionStrideFor).


MOTION_RUN_STRIDE_LONGEST ​

ts
const MOTION_RUN_STRIDE_LONGEST: 1 = 1;

The gaits of a motion set: what its takes are doing at every frame (standing, walking, running, read from the feet), where each frame is heading, and the speeds the set covers per gait, from the takes' own measured speeds and cadence (never their names). A request is answered only in the gait that covers its speed: never a run played slowly. A speed no take covers is brought to the nearest one covered below it, and MotionLayer.pace says so. A sprint is the one gait a set has to mark: the takes of its sprint part (MOTION_SPRINT_MODULE) are GAIT_SPRINT, with their own band, start and stop; beside them the run's band ends where a run take really goes, and the walk and the run below that are exactly what they are without the part. Every steady stretch of a take is read too (gaits.stretches: its own pace and cadence, and the loop a long walk goes round in it), and motionStrideFor / motionRateFor say how a steady stride meets a speed: by the length of its steps first, its rate last. Every move-off is read as well (table.starts, MOTION_START: how far each turns the body as it starts, how soon it is moving, by which frame its turn is made), and motionStartScale says whether a start serves an angle asked, its own turn made a little smaller or larger; a start its take states as a quick turning start (turnStart) also serves an angle up to MOTION_START_STEER beyond that.

Example ​

ts
import {
  buildMotionTable,
  GAIT_STAND,
  MOTION_GAIT_NAMES,
  MOTION_START,
  MOTION_START_STEER,
  motionPaceFor,
  motionRateFor,
  motionStartScale,
  motionStrideFor,
  parseMotionSet,
} from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
for (const band of table.gaits.bands)
  console.log(band.name, band.from, 'to', band.to, 'm/s at', band.cadence, 'steps a minute');
const pace = motionPaceFor(table.gaits, 2, GAIT_STAND, { gait: 0, asked: 0, given: 0, limited: false });
console.log(MOTION_GAIT_NAMES[pace.gait], pace.given, pace.limited);
for (const stretch of table.gaits.stretches)
  console.log(stretch.pace, 'm/s,', stretch.cadence, 'steps a minute, a loop of', stretch.seconds, 's');
// a steady walking stride asked to go at 85 % of its own pace: its steps 12 % shorter, its rate 4 % slower
console.log(motionStrideFor(0.85), motionRateFor(0.85));
// the starts that would turn a standing body a quarter turn to its left, and how
const starts = table.starts.values;
for (let o = 0; o < starts.length; o += MOTION_START.numbers) {
  const marked = starts[o + MOTION_START.marked] === 1;
  const scale = motionStartScale(
    starts[o + MOTION_START.turn],
    Math.PI / 2,
    marked ? MOTION_START_STEER : 0,
  );
  if (scale > 0) console.log('first metre after', starts[o + MOTION_START.seconds], 's, its turn made', scale);
}

MOTION_RUN_STRIDE_SHORTEST ​

ts
const MOTION_RUN_STRIDE_SHORTEST: 1 = 1;

The same for a run, which has no room at all: a run's foot is down for a fifth of a second and is not held where it lands, so whatever its steps are made shorter or longer by is a foot sliding over the ground while it is down (measured on the shared set's runs at 3 m/s with the feet's layer on: 6 cm a step with the steps 9 % shorter, 3 to 4 cm with them 3 % longer, against 1 slide in 54 steps with them as performed). A run meets a speed by its rate alone, as it always did.


MOTION_SERVES ​

ts
const MOTION_SERVES: Readonly<{
  enterRun: 32;
  enterSprint: 512;
  enterWalk: 16;
  rest: 8;
  run: 4;
  slowToWalk: 64;
  sprint: 256;
  stand: 1;
  stopRun: 128;
  stopSprint: 1024;
  walk: 2;
}>;

The bits of MotionGaits.serves: what a request may be answered with.

  • stand, walk, run: the frame heads to that gait (or is the take's move-off into it).
  • slowToWalk: the frame is a run slowing into a walk: it serves a request to walk only for a body that is running now (a body that walks never passes through it).
  • stopRun: the frame is a run slowing to a stand, down to the last walking steps it comes to a stand through: it serves a request to stand only for a body that is running now or is in such a stop (a walk stops with walking steps, never with a run's).
  • rest: the frame stands, with at least half a second of standing after it: where a body that stands may idle.
  • enterWalk, enterRun: the frame is in a stand the take leaves into that gait, within reach of its last standing frame: where a body that stands may enter the take.
  • sprint, enterSprint, stopSprint: the same three for the sprint gait, on a set that carries a sprint part (only then is MotionGaits.serves wide enough for them): the frame heads to a sprint (or is the take's drive-off into one); it is in the stand a sprint's start leaves from; it is a sprint coming to a stand, which serves a request to stand only for a body that is sprinting now.

MOTION_SPRINT_MODULE ​

ts
const MOTION_SPRINT_MODULE: "sprint" = 'sprint';

The part of a set (its takes' module) whose takes are the sprint gait's.


MOTION_START ​

ts
const MOTION_START: Readonly<{
  gait: 1;
  made: 4;
  madeMetres: 5;
  marked: 8;
  numbers: 9;
  pace: 7;
  reach: 6;
  seconds: 3;
  stand: 0;
  turn: 2;
}>;

Where each number of a move-off's reading lies in MotionStarts.values, and how many numbers one move-off has (numbers).

  • stand: the stand it leaves, an index into MotionGaits.stands.
  • gait: the gait it leaves into, by its code.
  • turn: the turn the body has made once it is under way (2 m travelled), radians, left positive.
  • seconds: the seconds from its last standing frame to its first metre.
  • made, madeMetres: the frame of the set its turn is made by (from there the body stays within 4 degrees of turn), and the metres travelled by then.
  • reach: the metres travelled before it goes at nine tenths of the pace it levels at.
  • pace: that pace, metres a second.
  • marked: 1 when its take states it as a quick start that turns (turnStart) and what the take states agrees with what was read; else 0.

MOTION_START_STEER ​

ts
const MOTION_START_STEER: number;

The gaits of a motion set: what its takes are doing at every frame (standing, walking, running, read from the feet), where each frame is heading, and the speeds the set covers per gait, from the takes' own measured speeds and cadence (never their names). A request is answered only in the gait that covers its speed: never a run played slowly. A speed no take covers is brought to the nearest one covered below it, and MotionLayer.pace says so. A sprint is the one gait a set has to mark: the takes of its sprint part (MOTION_SPRINT_MODULE) are GAIT_SPRINT, with their own band, start and stop; beside them the run's band ends where a run take really goes, and the walk and the run below that are exactly what they are without the part. Every steady stretch of a take is read too (gaits.stretches: its own pace and cadence, and the loop a long walk goes round in it), and motionStrideFor / motionRateFor say how a steady stride meets a speed: by the length of its steps first, its rate last. Every move-off is read as well (table.starts, MOTION_START: how far each turns the body as it starts, how soon it is moving, by which frame its turn is made), and motionStartScale says whether a start serves an angle asked, its own turn made a little smaller or larger; a start its take states as a quick turning start (turnStart) also serves an angle up to MOTION_START_STEER beyond that.

Example ​

ts
import {
  buildMotionTable,
  GAIT_STAND,
  MOTION_GAIT_NAMES,
  MOTION_START,
  MOTION_START_STEER,
  motionPaceFor,
  motionRateFor,
  motionStartScale,
  motionStrideFor,
  parseMotionSet,
} from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
for (const band of table.gaits.bands)
  console.log(band.name, band.from, 'to', band.to, 'm/s at', band.cadence, 'steps a minute');
const pace = motionPaceFor(table.gaits, 2, GAIT_STAND, { gait: 0, asked: 0, given: 0, limited: false });
console.log(MOTION_GAIT_NAMES[pace.gait], pace.given, pace.limited);
for (const stretch of table.gaits.stretches)
  console.log(stretch.pace, 'm/s,', stretch.cadence, 'steps a minute, a loop of', stretch.seconds, 's');
// a steady walking stride asked to go at 85 % of its own pace: its steps 12 % shorter, its rate 4 % slower
console.log(motionStrideFor(0.85), motionRateFor(0.85));
// the starts that would turn a standing body a quarter turn to its left, and how
const starts = table.starts.values;
for (let o = 0; o < starts.length; o += MOTION_START.numbers) {
  const marked = starts[o + MOTION_START.marked] === 1;
  const scale = motionStartScale(
    starts[o + MOTION_START.turn],
    Math.PI / 2,
    marked ? MOTION_START_STEER : 0,
  );
  if (scale > 0) console.log('first metre after', starts[o + MOTION_START.seconds], 's, its turn made', scale);
}

MOTION_STOP_ENTRY ​

ts
const MOTION_STOP_ENTRY: 0.85 = 0.85;

A stop that states a style is entered BEFORE ITS BRAKE: at a frame where its take still goes at this share or more of the fastest it goes (its run-in). Entered later, a body is dropped into the middle of a brake it did not begin: its feet are wherever its own stride had them, not where the braking steps put them.


MOTION_STOP_RATE_LEAST ​

ts
const MOTION_STOP_RATE_LEAST: 0.75 = 0.75;

A stop that states a style was performed at one pace and answers a range of them: its take is played this much slower than performed at most, for a body that comes slower (see STOP_RATE_MOST in the layer for a faster one). A run whose steady pace is under this share of the style's run-in is answered by the takes that state no style (motionStopStyleAnswers: the one place the bound is compared, for the layer and for a walk sent to a spot alike).


MOTION_STOP_STYLES ​

ts
const MOTION_STOP_STYLES: readonly ("" | MotionStopStyle)[];

The stop styles by their code in MotionTable.stopStyle: 0 is a take that states none, 1 'gradual', 2 'hard'.


MOTION_STRIDE_LONGEST ​

ts
const MOTION_STRIDE_LONGEST: 1.04 = 1.04;

The gaits of a motion set: what its takes are doing at every frame (standing, walking, running, read from the feet), where each frame is heading, and the speeds the set covers per gait, from the takes' own measured speeds and cadence (never their names). A request is answered only in the gait that covers its speed: never a run played slowly. A speed no take covers is brought to the nearest one covered below it, and MotionLayer.pace says so. A sprint is the one gait a set has to mark: the takes of its sprint part (MOTION_SPRINT_MODULE) are GAIT_SPRINT, with their own band, start and stop; beside them the run's band ends where a run take really goes, and the walk and the run below that are exactly what they are without the part. Every steady stretch of a take is read too (gaits.stretches: its own pace and cadence, and the loop a long walk goes round in it), and motionStrideFor / motionRateFor say how a steady stride meets a speed: by the length of its steps first, its rate last. Every move-off is read as well (table.starts, MOTION_START: how far each turns the body as it starts, how soon it is moving, by which frame its turn is made), and motionStartScale says whether a start serves an angle asked, its own turn made a little smaller or larger; a start its take states as a quick turning start (turnStart) also serves an angle up to MOTION_START_STEER beyond that.

Example ​

ts
import {
  buildMotionTable,
  GAIT_STAND,
  MOTION_GAIT_NAMES,
  MOTION_START,
  MOTION_START_STEER,
  motionPaceFor,
  motionRateFor,
  motionStartScale,
  motionStrideFor,
  parseMotionSet,
} from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
for (const band of table.gaits.bands)
  console.log(band.name, band.from, 'to', band.to, 'm/s at', band.cadence, 'steps a minute');
const pace = motionPaceFor(table.gaits, 2, GAIT_STAND, { gait: 0, asked: 0, given: 0, limited: false });
console.log(MOTION_GAIT_NAMES[pace.gait], pace.given, pace.limited);
for (const stretch of table.gaits.stretches)
  console.log(stretch.pace, 'm/s,', stretch.cadence, 'steps a minute, a loop of', stretch.seconds, 's');
// a steady walking stride asked to go at 85 % of its own pace: its steps 12 % shorter, its rate 4 % slower
console.log(motionStrideFor(0.85), motionRateFor(0.85));
// the starts that would turn a standing body a quarter turn to its left, and how
const starts = table.starts.values;
for (let o = 0; o < starts.length; o += MOTION_START.numbers) {
  const marked = starts[o + MOTION_START.marked] === 1;
  const scale = motionStartScale(
    starts[o + MOTION_START.turn],
    Math.PI / 2,
    marked ? MOTION_START_STEER : 0,
  );
  if (scale > 0) console.log('first metre after', starts[o + MOTION_START.seconds], 's, its turn made', scale);
}

MOTION_STRIDE_SHORTEST ​

ts
const MOTION_STRIDE_SHORTEST: 0.82 = 0.82;

A steady stride's steps are made at most this much shorter or longer than they were performed to meet a speed: the length of a step is what a walker changes first. Shorter is free (the legs reach less far than they were performed to); longer is not: the leg behind is already straight when its foot leaves the ground, so a step made longer lowers the pelvis and bends the front knee as its heel lands (measured on the shared set's steady walk with the feet held: 12 degrees of knee at heel strike as performed, 13 with the steps 3 % longer, 17 with 6 %, 20 with 9 %; 11 with them 18 % shorter).


MOTION_WEIGHTS ​

ts
const MOTION_WEIGHTS: Readonly<MotionWeights>;

The default weights: the path leads, the pose keeps the feet in step.


PACKAGE ​

ts
const PACKAGE: "@gameable/animation";

Package identity marker for gameable/animation.

Example ​

ts
import { PACKAGE } from 'gameable/animation';

console.log(PACKAGE); // 'gameable/animation'

SEATED ​

ts
const SEATED: Readonly<{
  aheadBlend: number;
  aheadClear: 0.002;
  aheadLimbClear: 0.01;
  aheadLimbDrift: 0.05;
  aheadLimbMost: 0.6;
  aheadLimbNear: 10;
  aheadLimbShare: 0.6;
  aheadOut: 0.25;
  aheadRate: number;
  aheadRound: 2;
  backSoft: 0.02;
  backTime: 0.04;
  barTurn: 0.5;
  bodyElbow: 0.136;
  bodyForearm: readonly number[];
  bodyHead: 0.066;
  bodyKnee: 0.126;
  bodyNeck: 0.043;
  bodyShin: readonly number[];
  bodyThigh: readonly number[];
  bodyTrunkAhead: 0.087;
  bodyTrunkRound: 0.6;
  bodyTrunkWide: readonly number[];
  bodyUpperArm: readonly number[];
  curl: readonly number[];
  headLevel: 0.6;
  headTurn: 1.2;
  headTurnMax: number;
  heelMost: number;
  heldEase: 0.4;
  hipRise: 0.058;
  hipsShare: 0.6;
  keepArmRate: number;
  keepClear: 0.01;
  keepKnee: 0.2;
  keepNod: number;
  keepPress: 0.008;
  keepSoft: number;
  keepSwivel: number;
  kneeHalf: 0.036;
  laidLift: number;
  laidRaise: number;
  laidSoft: 0.05;
  laidSwing: number;
  leanBack: number;
  leanFree: number;
  leanMax: number;
  leanMin: number;
  leanSeconds: 0.15;
  neckBack: number;
  palmAlong: 0.6;
  palmOut: 0.35;
  reach: 0.9;
  reachHeld: 0.985;
  reachSoft: 0.95;
  reachStraight: 0.9975;
  reachStraightMost: 0.9985;
  reclineFull: number;
  reclineReach: 0.08;
  referenceMost: number;
  shoe: 0.06;
  soleAlong: 0.6;
  soleUnder: 0.15;
  turnLean: 0.3;
  turnLeanMax: number;
  wristDrop: number;
}>;

The pose's numbers: shares of the character's own lengths, and angles.


SEATED_FEEL ​

ts
const SEATED_FEEL: Readonly<{
  carry: 0.5;
  carryMax: number;
  headDamping: 0.6;
  headHz: 1;
  mass: 70;
  massMax: 250;
  massMin: 30;
  pitch: number;
  pitchMax: number;
  speedMost: 150;
  speedSeconds: 0.08;
  trunkDamping: 0.5;
  trunkHz: 1.5;
}>;

The feel's numbers (SeatedFeel): the rider's body follows the machine's lean, its bars and its changes of speed by springs, so it lags, overshoots a little and settles, instead of being a direct function of the machine each frame.

A spring here is stated by its frequency and its damping (1 would be no overshoot at all). After a sudden change of the machine, a spring of damping 0.5 passes its rest by 16 % of the change and one of 0.6 by 9.5 %. A rider of another mass has the frequencies times sqrt(70 / mass): slower into a hold and out of it when heavier.


SEATED_FIT ​

ts
const SEATED_FIT: Readonly<{
  bendClear: 0.08;
  follow: 0.15;
  radius: 0.3;
  radiusOfGap: 2;
  reachLand: 0.98;
  reachMost: 0.999;
  settleFrames: 6;
}>;

The seated fit's numbers.


SEATED_MOVE_LIMBS ​

ts
const SEATED_MOVE_LIMBS: readonly SeatedMoveLimb[];

The limbs in the order an event numbers them: 0 the left hand, 1 the right hand, 2 the left foot, 3 the right foot (as an action's contacts are numbered).

Example ​

ts
import { SEATED_MOVE_LIMBS } from 'gameable/animation';

console.log(SEATED_MOVE_LIMBS[3]); // 'right-leg'

SEATED_MOVES_MODULE ​

ts
const SEATED_MOVES_MODULE: "riding" = 'riding';

The part of a set's file (its takes' module) that holds the seated takes.


SEATED_POSES ​

ts
const SEATED_POSES: Readonly<{
  brakeFrom: 1.5;
  brakeFull: 6;
  driveSeconds: 0.35;
  driveTaken: 0.8;
  firstShare: 0.6;
  lead: 0.15;
  leanFull: 35;
  speedDamping: 0.85;
  speedHz: 0.85;
  speedTuck: 30;
  speedUpright: 0;
  turnSlow: 0.4;
}>;

What SeatedPoses takes for what it leaves out.


SEATED_REFERENCE_FIRST ​

ts
const SEATED_REFERENCE_FIRST: readonly SeatedAmount[];

The amounts that go FIRST when a rider moves from one pose to another (SeatedPoses): the hips and the head. A rider sets the hips and looks into a turn before the machine is fully leaned.


SEATED_REFERENCE_KEYS ​

ts
const SEATED_REFERENCE_KEYS: readonly SeatedAmount[];

The names of a SeatedReference's angles (degrees), in the order a reader prints them.


SEATED_REFERENCE_MOST ​

ts
const SEATED_REFERENCE_MOST: 60 = 60;

The most any amount of a SeatedReference is taken as, degrees either way.


SEATED_REFERENCE_PLACES ​

ts
const SEATED_REFERENCE_PLACES: readonly SeatedAmount[];

The names of a SeatedReference's amounts that are not angles: where the hips are on the saddle (hundredths of the rider's height), where each rest lies under its foot, how far each foot follows its shin and how far the arms are straightened (0 to 100).


SM_TRANSITION_MS ​

ts
const SM_TRANSITION_MS: 300 = 300;

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


SOMA_ACTION_RIG ​

ts
const SOMA_ACTION_RIG: ActionRigNames;

SOMA's skeleton (aosrig-v2).


SOMA_FOOT_PLANT_LEGS ​

ts
const SOMA_FOOT_PLANT_LEGS: readonly FootPlantLeg[];

SOMA's skeleton (aosrig-v2): its legs, left then right, as the feet's layer takes them.


SOMA_GETUP_RIG ​

ts
const SOMA_GETUP_RIG: GetUpRigNames;

SOMA's skeleton (aosrig-v2).


SOMA_HOLD_LIMBS ​

ts
const SOMA_HOLD_LIMBS: readonly HoldLimb[];

SOMA's limbs, in a fixed order: 0 the left hand, 1 the right hand, 2 the left foot, 3 the right foot.

Example ​

ts
import { createLimbHold, SOMA_HOLD_LIMBS } from 'gameable/animation';

const limbHold = createLimbHold({ root: rigRoot, limbs: SOMA_HOLD_LIMBS });
limbHold.on = true;
limbHold.hold(1, ledge.x, ledge.y, ledge.z); // the right hand on the ledge

SOMA_LIFE_JOINTS ​

ts
const SOMA_LIFE_JOINTS: LifeJointNames;

SOMA's skeleton (aosrig-v2): the studio's split of a head turn (head 0.65, Neck2 0.2, Neck1 0.15).


SOMA_MOTION_RIG ​

ts
const SOMA_MOTION_RIG: MotionRigNames;

SOMA's skeleton (aosrig-v2).


SOMA_SEATED_JOINTS ​

ts
const SOMA_SEATED_JOINTS: SeatedJointNames;

A studio export of the second format (the SOMA skeleton). Its fingers start with a joint in the palm, so the knuckles are each finger's second joint.


SOMA_UPPER_BODY_MASKS ​

ts
const SOMA_UPPER_BODY_MASKS: Readonly<Record<UpperBodyMaskName, readonly string[]>>;

SOMA's joints per mask. spine-up is the spine (Spine1, Spine2, Chest), the neck and head, and both arms with their shoulders, hands and fingers; an arm is its shoulder, arm, forearm, hand and fingers; head is Neck1, Neck2 and Head. The pelvis and the legs are in no mask: they stay with the movement underneath.

Example ​

ts
import { createUpperBodyLayer, SOMA_UPPER_BODY_MASKS } from 'gameable/animation';

// A mask of one's own beside SOMA's: the right arm without its shoulder.
const forearm = SOMA_UPPER_BODY_MASKS['right-arm'].filter((name) => name !== 'RightShoulder');
const upperBody = createUpperBodyLayer({ root: rigRoot, table, masks: { 'right-reach': forearm } });

UE_SEATED_JOINTS ​

ts
const UE_SEATED_JOINTS: SeatedJointNames;

The UE-style names of a retargeted body.


WALK_BODY ​

ts
const WALK_BODY: Readonly<{
  chest: 1;
  head: 0;
  lean: 2;
  numbers: 6;
  restX: 3;
  restZ: 4;
  settling: 5;
}>;

What the walk asks of the body's parts (DirectedWalk.body): where each number is. Angles in radians against the hips' facing, left positive; metres in the body's own frame (x to its left, z ahead). All zero while the feel is off.


WALK_FEEL ​

ts
const WALK_FEEL: Readonly<{
  chestMost: number;
  chestShare: 0.25;
  faceDamping: 0.75;
  faceHertz: 1.1;
  headMost: number;
  headShare: 0.6;
  leadFromM: 0.5;
  leadWholeM: 1.2;
  leanMost: number;
  leanShare: 0.7;
  paceFloor: 0.2;
  paceRisePerMps: 0.1;
  paceRiseS: 0.25;
  settleHalfLifeS: 0.11;
  settleLeft: 0.03;
  settleMostS: 0.6;
  steerAccel: 8;
}>;

The feel pass's numbers, in one place.


WALK_FEEL_BODY ​

ts
const WALK_FEEL_BODY: Readonly<{
  chestHalfLifeS: 0.26;
  headHalfLifeS: 0.12;
  leanDamping: 0.5;
  leanHertz: 1.3;
  restDamping: 0.45;
  restHertz: 1.5;
  restMost: number;
  restShare: 0.1;
  still: 0.00001;
}>;

The numbers of the feel pass's part on the body, in one place.


WALK_FEEL_VALUES ​

ts
const WALK_FEEL_VALUES: Readonly<{
  chest: 1;
  head: 0;
  lean: 2;
  numbers: 5;
  pitch: 3;
  roll: 4;
}>;

Where each number of WalkFeelLayer.values is.

Functions ​

actionKindOf() ​

ts
function actionKindOf(kind): ActionKind | null;

An action of the list by its kind.

Parameters ​

ParameterTypeDescription
kindstringWhat a game asks for.

Returns ​

ActionKind | null

The entry, or null when the list has none of that kind.

Example ​

ts
import { actionKindOf } from 'gameable/animation';

console.log(actionKindOf('hurdle')?.height); // [-0.2, 0.2]

advanceLocomotionPhase() ​

ts
function advanceLocomotionPhase(
   blend, 
   speed, 
   speeds, 
   durations, 
   dt, 
   phase, 
   times, 
   strides?
): void;

Advance the shared phase so the mix carries the character at the ground speed, and give each travelling clip its time.

Both clips of the bracket cycle once per phase cycle. At a cadence of f cycles a second a clip plays at the rate f * duration and its planted feet carry the character at speed * f * duration; the mix carries it at the weighted sum, so the cadence that makes that the ground speed s is

text
f = s / (w_a * speed_a * duration_a + w_b * speed_b * duration_b)

which is the clip's own s / speed / duration when one clip has the whole weight. A clip that stands in place (speed 0) adds nothing to the sum, keeps its own time and is left to the mixer; the phase holds still when nothing travels.

With strides (a clip's reading from its contacts, readStrides), one phase cycle is one stride: a clip holding n strides plays 1 / n of itself per cycle, turned so its left foot lands at phase 0, and so do the other gaits' clips: the same foot is down in both clips of the bracket whatever moment of the step each was cut at. A clip without a reading is one stride from its own start, as before.

Parameters ​

ParameterTypeDescription
blendLocomotionBlendThe blend this frame.
speednumberThe ground speed, metres a second.
speedsReadonlyMap<string, number>Clip name to the clip's speed (its planted feet's travel at rate 1).
durationsReadonlyMap<string, number>Clip name to the clip's duration in seconds.
dtnumberSeconds since the last advance.
phaseLocomotionPhaseThe phase, advanced in place.
timesMap<string, number>Cleared and filled with clip name to the clip's time this frame, seconds, for the clips on the phase.
strides?ReadonlyMap<string, StrideReading>Clip name to how its steps sit in its cycle, for the clips that say.

Returns ​

void


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


bindPoseAdjust() ​

ts
function bindPoseAdjust(
   record, 
   joints, 
   hips?
): BoundPoseAdjust;

Bind a record to the joints a layer writes, in the layer's own order.

Parameters ​

ParameterTypeDefault valueDescription
recordPoseAdjustRecordundefinedThe record (parsePoseAdjust).
jointsreadonly string[]undefinedThe layer's joints, by name.
hipsstring'Hips'The hips' name among them, for the record's move.

Returns ​

BoundPoseAdjust

The turns as arrays, joint by joint: made once, read every frame.

Example ​

ts
import { bindPoseAdjust, parsePoseAdjust } from 'gameable/animation';

const record = parsePoseAdjust({ version: 1, space: 'parent', adjust: { Chest: [0, 0, 0, 1] } });
if (record !== null) console.log(bindPoseAdjust(record, ['Hips', 'Chest'], 'Hips').count);

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.


blinkIntervalsOf() ​

ts
function blinkIntervalsOf(s): 
  | {
  maxInterval: number;
  minInterval: number;
}
  | null;

The blink runtime's timings for a setting: null when the setting says the character does not blink (then there is no blink of its own at all), else the studio's 2 to 6 s divided by the rate.

Parameters ​

ParameterTypeDescription
sLifeSettingThe setting.

Returns ​

| { maxInterval: number; minInterval: number; } | null

{ minInterval, maxInterval } in seconds, or null for no blinks.

Example ​

ts
import { blinkIntervalsOf, readLifeSetting } from 'gameable/animation';

console.log(blinkIntervalsOf(readLifeSetting({ blink: true, blinkRate: 2 }))); // { minInterval: 1, maxInterval: 3 }
console.log(blinkIntervalsOf(readLifeSetting({ blink: false }))); // null

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.


buildActions() ​

ts
function buildActions(
   sources, 
   table, 
   root, 
   names?
): ActionSet;

Read a set's actions on one rig's table. Call with the rig at rest (as buildMotionTable is): the limbs' lengths are read off it. The takes the actions are ranges of are taken out of the table's general search (table.matchable is cleared over them): they are entered only when asked for.

Parameters ​

ParameterTypeDefault valueDescription
sourcesreadonly ActionSource[]undefinedThe actions as the file states them.
tableMotionTableundefinedThe set, read on this rig.
rootObject3DundefinedThe rig's root.
namesActionRigNamesSOMA_ACTION_RIGWhat the rig calls the joints an action is read by.

Returns ​

ActionSet

The actions, with every frame's place in its stride.

Example ​

ts
import { buildActions, buildMotionTable, parseActionSources, parseMotionSet } from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
const actions = buildActions(parseActionSources(json).actions, table, rigRoot);
console.log(actions.clips.map((clip) => `${clip.name}: ${clip.airSeconds.toFixed(2)} s in the air`));

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.


buildGetUps() ​

ts
function buildGetUps(
   data, 
   sources, 
   root, 
   names?
): GetUpSet;

Read a set's get-ups on one rig. Call with the rig at rest (as buildMotionTable is): the limbs' lengths and the feet's height are read off it.

Parameters ​

ParameterTypeDefault valueDescription
dataMotionDataundefinedThe set, read with its getups part.
sourcesreadonly GetUpSource[]undefinedThe get-ups as the file states them (parseGetUpSources).
rootObject3DundefinedThe rig's root (the character's own frame, its origin on the floor).
namesGetUpRigNamesSOMA_GETUP_RIGWhat the rig calls the joints a get-up is read by.

Returns ​

GetUpSet

The get-ups.

Throws ​

When the rig lacks one of those joints.

Example ​

ts
import { buildGetUps, parseGetUpSources, parseMotionSet } from 'gameable/animation';

const data = parseMotionSet(json, { modules: ['getups'] });
const getUps = buildGetUps(data, parseGetUpSources(json).getups, rigRoot);
console.log(getUps.clips.map((clip) => `${clip.name}: from its ${clip.lie}, ${clip.seconds.toFixed(1)} s`));

buildMotionTable() ​

ts
function buildMotionTable(
   data, 
   root, 
   names?, 
   weights?, 
   options?
): MotionTable;

Read a motion set on one rig: the root, the hips against it, the feet, the floor per stance, the contacts and the features of every frame. Call with the rig at rest (before an animator poses it), standing on its floor (the root's origin): the legs' lengths and how high the ankles and the balls of the feet stand at rest are read off it, and a take's planted feet are stood on the floor by those heights.

Parameters ​

ParameterTypeDefault valueDescription
dataMotionDataundefinedThe packed set.
rootObject3DundefinedThe rig's root (the character's own frame, its origin on the floor).
namesMotionRigNamesSOMA_MOTION_RIGWhat the rig calls its pelvis and legs.
weightsReadonly<MotionWeights>MOTION_WEIGHTSHow much each group of features counts.
optionsReadonly<MotionTableOptions>{}How the takes are stood on the floor (MotionTableOptions.stand); absent, the table is what it always was.

Returns ​

MotionTable

The table.

Throws ​

When the rig or the set lacks the pelvis or a leg.

Example ​

ts
import { buildMotionTable, parseMotionSet, SOMA_MOTION_RIG } from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot, SOMA_MOTION_RIG);
console.log(table.matchableCount, 'frames to search, built in', table.buildMs, 'ms');

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.


chooseGetUp() ​

ts
function chooseGetUp(
   set, 
   body, 
   lie, 
   style, 
   most, 
   out
): number;

The get-up for a body: of the takes of the style asked that lie as the body lies, the one whose lying pose is nearest; when the style asked has none, an ordinary one. None when no take lies as the body does, or the nearest is further than most.

Parameters ​

ParameterTypeDescription
setGetUpSetThe set's get-ups.
bodyArrayLike<number>The body's GETUP_POINTS points in the world (x, y over its floor, z).
lieGetUpLieHow the body lies (readGetUpLie).
styleGetUpStyleThe style asked.
mostnumberThe furthest a pose distance may be, metres.
outGetUpFitThe chosen take's fit, filled.

Returns ​

number

The get-up's index in set.clips, or -1.

Example ​

ts
import { chooseGetUp, readGetUpLie } from 'gameable/animation';

const read = readGetUpLie(bodyPoints, 0, { lie: null, heading: 0, faceUp: 0, leftUp: 0, upright: 0 });
const fit = { yaw: 0, x: 0, z: 0, distance: 0, furthest: 0 };
const chosen = read.lie === null ? -1 : chooseGetUp(set, bodyPoints, read.lie, 'ordinary', 0.5, fit);
console.log(chosen < 0 ? 'no take fits: the old rise' : set.clips[chosen].name, fit.distance);

clampBlinkRate() ​

ts
function clampBlinkRate(r): number;

Clamp a blink rate to the slider's range.

Parameters ​

ParameterTypeDescription
runknownThe candidate.

Returns ​

number

A rate in [0.25, 3], or 1 when the candidate is not a number.


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, "frames" | "root"> | 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).


createActionLayer() ​

ts
function createActionLayer(options): ActionLayer;

Put actions on a character.

Parameters ​

ParameterTypeDescription
optionsActionLayerOptionsSee ActionLayerOptions.

Returns ​

ActionLayer

The layer; set on to let it work.

Example ​

ts
import { buildActions, createActionLayer, parseActionSources } from 'gameable/animation';

const actions = createActionLayer({
  root: rigRoot,
  motion,
  actions: buildActions(parseActionSources(json).actions, motion.table, rigRoot),
  onEvent: (event) => console.log(event.name, event.action, event.reason),
});
actions.on = true;
// the game: hurdle that bar
const answer = actions.request('hurdle', { id: 7, x: 0, y: 0, z: 12, yaw: 0, height: 0.7, width: 1.2, depth: 0.04 });
if (!answer.ok) console.log(answer.words);
// every frame: actions.direct(frame); motion.update(frame); actions.apply(dt);

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.


createDirectedWalk() ​

ts
function createDirectedWalk(options): DirectedWalk;

Make a directed walk for a character under the motion layer.

Parameters ​

ParameterTypeDescription
optionsDirectedWalkOptionsSee DirectedWalkOptions.

Returns ​

DirectedWalk

The walk.

Example ​

ts
import { createDirectedWalk } from 'gameable/animation';

const walk = createDirectedWalk({ motion });
const walker = { x: 0, z: 0, yaw: 0 }; // the game's place for the character
walk.onArrive = (arrival) => console.log('there, within', arrival.error, 'm');
walk.go({ x: 3, z: 2, facing: Math.PI, pace: 'stroll' }, walker);
// every frame, before the character's animator updates:
walk.update(dt, walker);
holder.position.set(walker.x, 0, walker.z);
holder.rotation.y = walker.yaw;
animator.setState({ velocity: [walk.ask[0], 0, walk.ask[1]] });

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.


createFootPlant() ​

ts
function createFootPlant(options): FootPlant;

Create the feet's layer on a rig.

Parameters ​

ParameterTypeDescription
optionsFootPlantOptionsSee FootPlantOptions.

Returns ​

FootPlant

The layer.

Example ​

ts
import { createAnimator, createFootPlant } from 'gameable/animation';

const footPlant = createFootPlant({
  root: rigRoot,
  hips: 'Hips',
  legs: [
    { thigh: 'LeftLeg', shin: 'LeftShin', foot: 'LeftFoot', toe: 'LeftToeBase' },
    { thigh: 'RightLeg', shin: 'RightShin', foot: 'RightFoot', toe: 'RightToeBase' },
  ],
  ground: (x, y, z) => heightOfTheGround(x, z),
  onStep: (leg) => playStep(leg),
});
footPlant.on = true;
const animator = createAnimator({ root: rigRoot, expressionSpace, locomotion, footPlant });

createGestureChannel() ​

ts
function createGestureChannel(options?): GestureChannel;

Create a one-slot additive gesture channel.

Parameters ​

ParameterTypeDescription
optionsGestureChannelOptionsSee GestureChannelOptions.

Returns ​

GestureChannel

A GestureChannel.


createGetUpLayer() ​

ts
function createGetUpLayer(options): GetUpLayer;

Put a get-up on a character.

Parameters ​

ParameterTypeDescription
optionsGetUpLayerOptionsSee GetUpLayerOptions.

Returns ​

GetUpLayer

The layer.

Example ​

ts
import { buildGetUps, createGetUpLayer, createLimbHold, parseGetUpSources, SOMA_HOLD_LIMBS } from 'gameable/animation';

const hold = createLimbHold({ root: rigRoot, limbs: SOMA_HOLD_LIMBS }); // made with the rig at rest
hold.on = true;
const getUp = createGetUpLayer({
  root: rigRoot,
  set: buildGetUps(data, parseGetUpSources(json).getups, rigRoot),
  holds: hold,
});
// the physics body lies on the floor and has written the bones:
if (!getUp.begin()) console.log('no take lies as the body does: keep the old rise');
// every frame: hold.restore(); getUp.restore(); ...the animator...; getUp.update(dt); hold.update(dt);

createGraphRuntime() ​

ts
function createGraphRuntime(options): GraphRuntime;

Create the runtime context the evaluator reads and mutates.

Parameters ​

ParameterTypeDescription
optionsGraphRuntimeOptionsSee GraphRuntimeOptions.

Returns ​

GraphRuntime

A fresh GraphRuntime.


createLifeLayer() ​

ts
function createLifeLayer(options): LifeLayer;

Create the life on a rig.

Parameters ​

ParameterTypeDescription
optionsLifeLayerOptionsSee LifeLayerOptions.

Returns ​

LifeLayer

The layer.

Example ​

ts
import { createLifeLayer, readLifeSetting, SOMA_LIFE_JOINTS } from 'gameable/animation';

const life = createLifeLayer({
  root: rigRoot,
  joints: SOMA_LIFE_JOINTS,
  setting: readLifeSetting(descriptor.life),
  holds: ['LeftShoulder', 'LeftArm'],
});
const animator = createAnimator({ root: rigRoot, expressionSpace: { kind: 'arkit52', dim: 52 }, life });

createLimbHold() ​

ts
function createLimbHold(options): LimbHold;

Create the limbs' holds on a rig.

Parameters ​

ParameterTypeDescription
optionsLimbHoldOptionsSee LimbHoldOptions.

Returns ​

LimbHold

The layer; set on to let it work.

Example ​

ts
import { createLimbHold, SOMA_HOLD_LIMBS } from 'gameable/animation';

const limbHold = createLimbHold({ root: rigRoot, limbs: SOMA_HOLD_LIMBS });
limbHold.on = true;
// every frame: restore before the mixer, update after every other layer
limbHold.restore();
mixer.update(dt);
if (handOnTheBox) limbHold.hold(0, box.x, box.y, box.z);
else limbHold.release(0);
limbHold.update(dt);
console.log('short by', limbHold.measures.error[0], 'm');

createLocomotionBlend() ​

ts
function createLocomotionBlend(): LocomotionBlend;

Create an empty blend result to reuse every frame.

Returns ​

LocomotionBlend

A zeroed LocomotionBlend.


createLocomotionPhase() ​

ts
function createLocomotionPhase(): LocomotionPhase;

Create a phase to reuse every frame.

Returns ​

LocomotionPhase

A phase at 0.


createMotionLayer() ​

ts
function createMotionLayer(options): MotionLayer;

Put a character under a motion set.

Parameters ​

ParameterTypeDescription
optionsMotionLayerOptionsSee MotionLayerOptions.

Returns ​

MotionLayer

The layer; set on to let it work.

Example ​

ts
import { buildMotionTable, createMotionLayer, parseMotionSet } from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
const motion = createMotionLayer({ root: rigRoot, table });
motion.on = true;
// every frame, after the mixer:
motion.restore();
motion.update({ dt, x: capsule.x, z: capsule.z, yaw: capsuleYaw, vx: wanted.x, vz: wanted.z });
holder.position.x += motion.offset[0];

createMovementComponent() ​

ts
function createMovementComponent(options?): MovementComponent;

Create a movement component.

Parameters ​

ParameterTypeDescription
optionsMovementOptionsSee MovementOptions.

Returns ​

MovementComponent

A fresh MovementComponent; there is no shared singleton.


createSeatedFit() ​

ts
function createSeatedFit(options): SeatedFit;

Make a rider's fit of the seated takes of a set.

Parameters ​

ParameterTypeDescription
optionsSeatedFitOptionsSee SeatedFitOptions.

Returns ​

SeatedFit

The fit.

Example ​

ts
import { createSeatedFit, type SeatedFitOptions } from 'gameable/animation';

function fitOf(options: SeatedFitOptions): void {
  const fit = createSeatedFit(options);
  // the right arm (limb 1) in a take that fills the set's frames 0 to 45 and ends riding
  const take = fit.measure(1, 0, 45, 0, true);
  console.log(take?.rest, take?.far);
}

createSeatedMoves() ​

ts
function createSeatedMoves(options): SeatedMoves | null;

Put performed moves from the seat on a rig.

Parameters ​

ParameterTypeDescription
optionsSeatedMovesOptionsSee SeatedMovesOptions.

Returns ​

SeatedMoves | null

The layer, or null for a rig without a body to seat (a head by itself).

Example ​

ts
import {
  createSeatedMoves,
  createSeatedPose,
  parseMotionSet,
  parseSeatedMoveSources,
} from 'gameable/animation';

const seated = createSeatedPose({ root: rig });
const moves = createSeatedMoves({
  root: rig,
  data: parseMotionSet(json, { modules: ['riding'] }),
  moves: parseSeatedMoveSources(json).moves,
  onEvent: (event) => console.log(event.name, event.move),
});
moves?.play({ move: 'kick', side: 'right', target: rivalHip });
// each frame: the layer's writing off first, then the pose's; after the animator, both on
moves?.restore();
seated?.restore();
mixer.update(dt);
seated?.apply({ seat, hands: [gripLeft, gripRight], feet: [restLeft, restRight] }, dt, moves);

createSeatedPose() ​

ts
function createSeatedPose(options): SeatedPose | null;

A seated pose for one rig, read off its skeleton at rest.

Make it while the bones stand at rest (before an animator has moved them): the lengths, the directions and the palm's and the sole's frames are read then.

Parameters ​

ParameterTypeDescription
optionsSeatedPoseOptionsThe rig root and, when the rig's names are not ones the engine knows, the joints.

Returns ​

SeatedPose | null

The pose, or null for a rig without the joints (a head by itself).

Example ​

ts
import { createSeatedPose } from 'gameable/animation';

const seated = createSeatedPose({ root: rig });
// each frame, after the animator:
seated?.apply({ seat, hands: [gripLeft, gripRight], feet: [restLeft, restRight] }, dt);
// and before it next runs:
seated?.restore();

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.


createUpperBodyLayer() ​

ts
function createUpperBodyLayer(options): UpperBodyLayer;

Put an upper-body layer on a rig.

Parameters ​

ParameterTypeDescription
optionsUpperBodyLayerOptionsSee UpperBodyLayerOptions.

Returns ​

UpperBodyLayer

The layer; set on to let it work.

Example ​

ts
import { buildMotionTable, createUpperBodyLayer, parseMotionSet } from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
const upperBody = createUpperBodyLayer({ root: rigRoot, table });
upperBody.on = true;
upperBody.play({ take: 'wave', mask: 'right-arm' });
// every frame: restore before the mixer, update after the matched takes
upperBody.restore();
mixer.update(dt);
upperBody.update(dt);

createWalkFeelLayer() ​

ts
function createWalkFeelLayer(options): WalkFeelLayer;

Make the feel pass's layer for a character.

Parameters ​

ParameterTypeDescription
optionsWalkFeelLayerOptionsSee WalkFeelLayerOptions.

Returns ​

WalkFeelLayer

The layer.

Example ​

ts
import { createDirectedWalk, createWalkFeelLayer } from 'gameable/animation';

const walk = createDirectedWalk({ motion, feel: true });
const feel = createWalkFeelLayer({ root: rig });
feel.from = walk.body;
// every frame: restore before the mixer, update after the motion layer
feel.restore();
feel.update(dt);

createWeightFader() ​

ts
function createWeightFader(seconds?): WeightFader;

Create a weight fader.

Parameters ​

ParameterTypeDefault valueDescription
secondsnumberDEFAULT_FADE_SECONDSHow long a weight takes to go from 0 to 1 (or back). Default 0.4.

Returns ​

WeightFader

The fader.

Example ​

ts
import { createWeightFader } from 'gameable/animation';

const fader = createWeightFader(0.4);
fader.step(new Map([['idle', 1]]), 1 / 60); // the first set applies at once
const mid = fader.step(new Map([['wave', 1]]), 0.2); // halfway: idle 0.5, wave 0.5
console.log(mid.get('idle'), mid.get('wave')); // 0.5 0.5

decodeMotionSet() ​

ts
function decodeMotionSet(bytes, options?): MotionSetSource;

Read a binary motion set back into the shape its text file parses to, the tracks as typed arrays: hand the result to parseMotionSet, as you would the parsed text. The takes come in the text file's order, whichever modules are asked for; with only the first bytes of the file at hand, the takes that can be read come in the file's own order (its modules' order: the order they arrive in).

Parameters ​

ParameterTypeDescription
bytesUint8ArrayThe file's bytes from its start (all of them, or as many as have arrived).
optionsMotionDecodeOptionsWhich takes.

Returns ​

MotionSetSource

The set. Its takes is empty when none of those asked for is whole yet.

Throws ​

When the bytes are not a binary motion set, or its header has not all arrived.

Example ​

ts
import { decodeMotionSet, parseMotionSet } from 'gameable/animation';

const bytes = new Uint8Array(await (await fetch('/motion/everyday.motion.bin')).arrayBuffer());
const walkOnly = parseMotionSet(decodeMotionSet(bytes, { modules: ['idle', 'walk'] }));
const everything = parseMotionSet(decodeMotionSet(bytes));
console.log(walkOnly.frames, 'of', everything.frames, 'frames');

easeAhead() ​

ts
function easeAhead(
   need, 
   rate, 
   count, 
   out, 
   work, 
   options?
): number;

Ease a take's needs into a curve (EaseAheadOptions).

Parameters ​

ParameterTypeDescription
needArrayLike<number>The need on each sample, 0 or more.
rateArrayLike<number>The most the curve may change from sample i to sample i + 1, over 0 (one entry a sample; the last is not read).
countnumberHow many samples.
outFloat64ArrayWritten: the curve, one value a sample.
workFloat64ArrayScratch, at least count long.
optionsEaseAheadOptionsThe start, the end, the rounding.

Returns ​

number

The curve's largest value: 0 when the take needs nothing (out is then all zeros).

Example ​

ts
import { easeAhead } from 'gameable/animation';

const need = new Float64Array([0, 0, 0, 0, 0.3, 0.3, 0, 0, 0, 0]);
const rate = new Float64Array(10).fill(0.1);
const curve = new Float64Array(10);
easeAhead(need, rate, 10, curve, new Float64Array(10));
console.log(Array.from(curve, (x) => x.toFixed(2)).join(' ')); // rises before sample 4, never under 0.3 on 4 and 5

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.


encodeMotionSet() ​

ts
function encodeMotionSet(source, options?): Uint8Array;

Write a motion set as one compact binary file. The takes are stored as the text file has them (nothing is retimed or resampled here): reading the binary gives the same set.

Parameters ​

ParameterTypeDescription
sourceMotionSetSourceThe set, as its text file parses.
optionsMotionEncodeOptionsHow finely, and in which order.

Returns ​

Uint8Array

The file's bytes.

Throws ​

When the set has no takes, or a take's tracks are not the lengths it says.

Example ​

ts
import { decodeMotionSet, encodeMotionSet } from 'gameable/animation';

const bytes = encodeMotionSet(JSON.parse(text));
console.log(text.length, 'characters of text,', bytes.length, 'bytes');
console.log(decodeMotionSet(bytes).takes.length, 'takes');

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.


fitGetUp() ​

ts
function fitGetUp(
   clip, 
   body, 
   out
): GetUpFit;

Lay a get-up's lying frame over a body: the turn about the vertical and the move over the ground that bring the take's points nearest the body's, and what is left between them.

Parameters ​

ParameterTypeDescription
clipGetUpClipThe get-up.
bodyArrayLike<number>The body's GETUP_POINTS points in the world (x, y over ITS floor, z).
outGetUpFitFilled and returned.

Returns ​

GetUpFit

out.

Example ​

ts
import { fitGetUp, type GetUpFit } from 'gameable/animation';

const fit: GetUpFit = { yaw: 0, x: 0, z: 0, distance: 0, furthest: 0 };
fitGetUp(set.clips[0], bodyPoints, fit);
console.log('pose distance', fit.distance.toFixed(2), 'm; furthest point', fit.furthest.toFixed(2), 'm');

getUpBlendSeconds() ​

ts
function getUpBlendSeconds(furthest, turn?): number;

How long the blend between two poses lasts, from how far the furthest point has to travel and how far the most turned joint has to turn: the longer of that far at about 0.9 metres a second and that turn at about 3 radians a second, never under 0.3 s or over 1.2 s.

Parameters ​

ParameterTypeDefault valueDescription
furthestnumberundefinedMetres the furthest point travels.
turnnumber0Radians the most turned joint turns against its parent. Default 0.

Returns ​

number

Seconds.

Example ​

ts
import { getUpBlendSeconds } from 'gameable/animation';

console.log(getUpBlendSeconds(0.1), getUpBlendSeconds(0.6), getUpBlendSeconds(3)); // 0.3, 0.667, 1.2
console.log(getUpBlendSeconds(0.1, Math.PI)); // a joint half a turn off: 1.047

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.


isMotionBinary() ​

ts
function isMotionBinary(bytes): boolean;

Whether bytes are a binary motion set (they start with the magic).

Parameters ​

ParameterTypeDescription
bytesUint8ArrayThe first bytes of a file, at least four.

Returns ​

boolean

Whether they are.

Example ​

ts
import { isMotionBinary } from 'gameable/animation';

const bytes = new Uint8Array(await (await fetch('/motion/everyday.motion.bin')).arrayBuffer());
console.log(isMotionBinary(bytes) ? 'binary' : 'text');

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.


layPoseAdjust() ​

ts
function layPoseAdjust(
   bound, 
   j, 
   q, 
   o
): void;

Lay a joint's turn on a pose read from a take: q = turn * q, in place. A joint the record does not turn is left exactly as it is.

Parameters ​

ParameterTypeDescription
boundBoundPoseAdjustThe bound record.
jnumberThe joint's place in the list it was bound to.
qFloat32ArrayQuaternions, x y z w.
onumberThe joint's offset into q.

Returns ​

void

Example ​

ts
import { bindPoseAdjust, layPoseAdjust, parsePoseAdjust } from 'gameable/animation';

const record = parsePoseAdjust({
  version: 1,
  space: 'parent',
  adjust: { Chest: [0.0262, 0, 0, 0.9997] },
});
const pose = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1]); // Hips, Chest as a take has them
if (record !== null) layPoseAdjust(bindPoseAdjust(record, ['Hips', 'Chest']), 1, pose, 4);
console.log(pose[4]); // the chest, turned by the record

lookSharesOf() ​

ts
function lookSharesOf(s): LookShares;

The setting's words as the shares the life layer runs with (the studio's lookSharesOf): a part switched off never turns toward anything, the eyes' share is 0 while the eyes' own switch is off, and liveliness is the level's gain (0 when off).

Parameters ​

ParameterTypeDescription
sLifeSettingThe setting.

Returns ​

LookShares

The shares.

Example ​

ts
import { lookSharesOf, readLifeSetting } from 'gameable/animation';

const shares = lookSharesOf(readLifeSetting(undefined));
console.log(shares.head, shares.body, shares.eyes); // 0.55 0.1 0

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.


mirrorSeatedReference() ​

ts
function mirrorSeatedReference(pose): SeatedReference;

The same pose to the other side: a turn to the left written once gives the turn to the right (every left amount becomes the right one, every turn and tilt changes its sign, each knee's place crosses the saddle's middle). A start for the other side's record, which a person then makes its own: a rider is not the same on both sides.

Parameters ​

ParameterTypeDescription
poseReadonly<SeatedReference>The pose.

Returns ​

SeatedReference

A new record: the pose mirrored.

Example ​

ts
import { mirrorSeatedReference } from 'gameable/animation';

const right = { ...mirrorSeatedReference(left), headTilt: 4 };

mixSeatedPoses() ​

ts
function mixSeatedPoses(
   poses, 
   speed, 
   turn, 
   first, 
   out, 
   brake?
): SeatedReference;

The one pose a rider is in, out of the poses of a set (SeatedPoses): the upright pose and the pose at speed mixed by speed, and a turn's pose laid on top as its difference from the pose at speed (turnSlow of it when slow, all of it at speed), the hips and the head (SEATED_REFERENCE_FIRST) by a share of their own. Under braking the pose without the turn goes brake of the way to the set's braking pose first.

Parameters ​

ParameterTypeDefault valueDescription
posesReadonly<SeatedPoses>undefinedThe set.
speednumberundefinedHow far from the upright pose to the pose at speed, 0 to 1 (with no upright pose it changes nothing).
turnnumberundefinedHow far into a turn's pose: toward the left turn's when positive, the right turn's when negative.
firstnumberundefinedThe same for the hips and the head.
outSeatedReferenceundefinedWritten (every numeric amount, and both knees); a scratch record to keep.
brakenumber0How far toward the braking pose, 0 to 1 (a spring may carry it a little past either end); with no braking pose it changes nothing. Left out: 0.

Returns ​

SeatedReference

out.

Example ​

ts
import { mixSeatedPoses } from 'gameable/animation';

const pose = mixSeatedPoses({ upright, straight, left, right }, 0.5, 0.3, 0.6, {});

mixSeatedReferences() ​

ts
function mixSeatedReferences(
   from, 
   to, 
   share, 
   firstTo, 
   firstShare, 
   out
): SeatedReference;

Mix two poses into one: every amount goes share of the way from the first pose to the second, the hips and the head (SEATED_REFERENCE_FIRST) firstShare of the way to firstTo (they may be further on, or on their way to another pose). An amount a pose leaves out counts as 0. A knee's place is mixed when both poses state it; where only one does, the first pose's stands (its place, or none), so that nothing jumps: state a knee in every pose of a set, or in none.

Parameters ​

ParameterTypeDescription
fromReadonly<SeatedReference>The first pose.
toReadonly<SeatedReference>The second pose, for everything but the hips and the head.
sharenumberHow far toward to: 0 the first pose, 1 the second (a spring may carry it a little past).
firstToReadonly<SeatedReference>The second pose for the hips and the head.
firstSharenumberHow far the hips and the head are toward firstTo.
outSeatedReferenceWritten (every numeric amount, and both knees); a scratch record to keep.

Returns ​

SeatedReference

out.

Example ​

ts
import { mixSeatedReferences } from 'gameable/animation';

const pose = mixSeatedReferences(straight, turnLeft, 0.4, turnLeft, 0.7, {});

motionCost() ​

ts
function motionCost(
   table, 
   frame, 
   scaled, 
   steady?
): number;

What one frame costs against a query (the same measure as searchMotion).

Parameters ​

ParameterTypeDefault valueDescription
tableMotionTableundefinedThe table.
framenumberundefinedThe frame.
scaledArrayLike<number>undefinedThe query as the table scales it (what searchMotion left in its scratch).
steadynumber0As for searchMotion.

Returns ​

number

The squared distance.


motionPaceFor() ​

ts
function motionPaceFor(
   gaits, 
   asked, 
   current, 
   out
): MotionPace;

What a speed asked for comes to on a set: the gait that covers it and the speed given. Where two gaits cover it, the one the body is in stays (so a walk speeding up stays a walk until the walk's own top, and a run slowing down stays a run until the run's own slowest). A speed no gait covers is brought down to the top of the gait below it (or up to the slowest covered, under that), and limited says so: never a faster gait played slowly.

Parameters ​

ParameterTypeDescription
gaitsMotionGaitsThe set's reading.
askednumberThe speed asked for, metres a second.
currentnumberThe gait the body is in now.
outMotionPaceFilled in place.

Returns ​

MotionPace

out.

Example ​

ts
import { GAIT_STAND, motionPaceFor } from 'gameable/animation';

const pace = motionPaceFor(table.gaits, 2.0, GAIT_STAND, { gait: 0, asked: 0, given: 0, limited: false });
if (pace.limited) console.log('this character walks at', pace.given, 'm/s at most before it runs');

motionRateFastest() ​

ts
function motionRateFastest(
   gaits, 
   gait, 
   fallback
): number;

The most a steady stride is played faster than it was performed on a set: MOTION_RATE_FASTEST, a seventh, for a walk and a run on any set. A SPRINT's stride (only a set with a sprint part has one) is played at most a twentieth faster (MOTION_RATE_FASTEST_BESIDE_SPRINT), and a fallback take of the sprint never faster than it was performed (MOTION_RATE_FASTEST_FALLBACK_BESIDE_SPRINT). A run beside a sprint part is kept from being played fast at its top by where its band ends (MotionBand.to), not by this: below that it is played as on any set.

Parameters ​

ParameterTypeDescription
gaitsMotionGaitsThe set's reading.
gaitnumberThe stride's gait.
fallbackbooleanWhether its take is one the set marks as a fallback.

Returns ​

number

The rate, 1 or more.

Example ​

ts
import { GAIT_RUN, motionRateFastest, motionRateFor } from 'gameable/animation';

const most = motionRateFastest(table.gaits, GAIT_RUN, false); // 1.15; a sprint's: 1.05
console.log(motionRateFor(1.2, GAIT_RUN, most));

motionRateFor() ​

ts
function motionRateFor(
   ratio, 
   gait?, 
   fastest?
): number;

How fast a steady stride is played to go at a speed, its steps made as long as motionStrideFor says: 1 as performed, kept within MOTION_RATE_SLOWEST and MOTION_RATE_FASTEST (or the set's own most for the stride: motionRateFastest).

Parameters ​

ParameterTypeDefault valueDescription
rationumberundefinedThe speed wanted over the stride's own pace.
gaitnumberGAIT_WALKThe stride's gait (GAIT_WALK, the default, GAIT_RUN or GAIT_SPRINT).
fastestnumberMOTION_RATE_FASTESTThe most it is played faster. Default MOTION_RATE_FASTEST.

Returns ​

number

The rate.


motionRigFromSnapshot() ​

ts
function motionRigFromSnapshot(snapshot): Object3D;

A small rig made from a snapshot: the joints a motion table reads, standing at rest under a root of their own.

Parameters ​

ParameterTypeDescription
snapshotMotionRigSnapshotWhat snapshotMotionRig copied.

Returns ​

Object3D

The rig's root; hand it to buildMotionTable.

Example ​

ts
import { motionRigFromSnapshot, snapshotMotionRig } from 'gameable/animation';

const small = motionRigFromSnapshot(snapshotMotionRig(rigRoot));
console.log(small.getObjectByName('Hips')?.position.y);

motionStartScale() ​

ts
function motionStartScale(
   turn, 
   angle, 
   steer?
): number;

How much smaller or larger a move-off's own turn is made to serve an angle asked: 0 when it does not serve it. Its turn made between MOTION_START_TURN_LEAST and MOTION_START_TURN_MOST of itself must come to the angle, or, with steer, to within that of it (the rest is steered in its first strides). A turn nearly right round may be made either way round.

Parameters ​

ParameterTypeDefault valueDescription
turnnumberundefinedThe move-off's own turn, radians (left positive).
anglenumberundefinedThe way asked against the body's facing, radians (left positive).
steernumber0How far short of or past the angle its turn may come, radians (0: not at all).

Returns ​

number

The scale of its turn, or 0.


motionStrideFor() ​

ts
function motionStrideFor(ratio, gait?): number;

How long a steady stride's steps are made to go at a speed: the share of the stride's own length (1: as performed). The steps' length takes the difference first, with only a little of it left to the stride's rate (a quarter, never more than MOTION_RATE_NATURAL), within MOTION_STRIDE_SHORTEST and MOTION_STRIDE_LONGEST for a walk (a run and a sprint: MOTION_RUN_STRIDE_SHORTEST and MOTION_RUN_STRIDE_LONGEST); what the length does not reach is then the rate's, within MOTION_RATE_SLOWEST and MOTION_RATE_FASTEST (motionRateFor).

Parameters ​

ParameterTypeDefault valueDescription
rationumberundefinedThe speed wanted over the stride's own pace.
gaitnumberGAIT_WALKThe stride's gait (GAIT_WALK, the default, GAIT_RUN or GAIT_SPRINT).

Returns ​

number

The stride's length, as a share of its own.


motionStrideLongest() ​

ts
function motionStrideLongest(gait): number;

The longest a steady stride's steps are made, as a share of their own length.

Parameters ​

ParameterTypeDescription
gaitnumberThe stride's gait.

Returns ​

number

For a run and a sprint MOTION_RUN_STRIDE_LONGEST, else MOTION_STRIDE_LONGEST.


motionStrideShortest() ​

ts
function motionStrideShortest(gait): number;

The shortest a steady stride's steps are made, as a share of their own length.

Parameters ​

ParameterTypeDescription
gaitnumberThe stride's gait.

Returns ​

number

For a run and a sprint MOTION_RUN_STRIDE_SHORTEST, else MOTION_STRIDE_SHORTEST.


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.


parseActionSources() ​

ts
function parseActionSources(value): object;

Read the actions list of a motion set file. An action that breaks a rule is left out and said, never the whole file; a file without the list has no actions.

Parameters ​

ParameterTypeDescription
valueunknownThe parsed JSON of the whole motion set file.

Returns ​

object

The actions that can be read, and the ones refused.

actions ​
ts
actions: ActionSource[];
refused ​
ts
refused: object[];

Example ​

ts
import { parseActionSources } from 'gameable/animation';

const { actions, refused } = parseActionSources(await (await fetch(url)).json());
console.log(actions.map((a) => a.name), refused);

parseGetUpSources() ​

ts
function parseGetUpSources(value): object;

Read the get-ups a motion set file states: every take of the part getups that carries getup: { lying, standing } (seconds; style: 'quick' for a spring, air: [from, to] for a stretch off the floor). A take that ends in a run says style: 'run' and carries, beside the mark, run: { hipsUp85, footfalls: [{ t, foot: 'left' | 'right' }], endSpeed }; getup.hands: [{ hand: 'left' | 'right', from, to }] states where a hand is on the floor when the read floats it. One that breaks a rule is left out and said.

Parameters ​

ParameterTypeDescription
valueunknownThe file's own words (the parsed JSON, or what is kept of it once packed).

Returns ​

object

The get-ups that can be read, and the ones refused.

getups ​
ts
getups: GetUpSource[];
refused ​
ts
refused: object[];

Example ​

ts
import { parseGetUpSources } from 'gameable/animation';

const { getups, refused } = parseGetUpSources(await (await fetch(url)).json());
console.log(getups.map((g) => `${g.take}: ${g.style}`), refused);

parseMotionBytes() ​

ts
function parseMotionBytes(
   bytes, 
   parse, 
   options?
): object;

Read a motion set from the bytes of its file, whichever form the file is in: the compact binary (soma-motion-bin) or the studio's text (soma-motion JSON).

Parameters ​

ParameterTypeDescription
bytesUint8ArrayThe whole file.
parse(value, options?) => MotionDataparseMotionSet (handed in so this module stays free of the table's code).
optionsMotionDecodeOptionsWhich parts of the set: modules is handed to the parser too, and, as the parser does, a set asked for whole is read without its actions part (a binary set's takes that are not kept are not even unpacked).

Returns ​

object

The packed set, and the set as its file states it (the text file's own fields: its modules, its actions, what it stands on), for whatever else reads them.

binary ​
ts
binary: boolean;
data ​
ts
data: MotionData;
source ​
ts
source: MotionSetSource;

Throws ​

When the bytes are neither, or no take can be read.

Example ​

ts
import { parseMotionBytes, parseMotionSet } from 'gameable/animation';

const response = await fetch('/motion/everyday.motion.bin'); // or a .json
const { data, binary } = parseMotionBytes(new Uint8Array(await response.arrayBuffer()), parseMotionSet);
console.log(data.name, data.frames, binary ? 'from the binary' : 'from the text');

parseMotionSet() ​

ts
function parseMotionSet(value, options?): MotionData;

Validate and pack a motion set file. A take that breaks a rule is left out and said, never the whole file.

Parameters ​

ParameterTypeDescription
valueunknownThe parsed JSON.
optionsMotionParseOptionsWhich parts of the set to keep.

Returns ​

MotionData

The packed set.

Throws ​

When the file is not a soma-motion file, or no take can be read.

Example ​

ts
import { parseMotionSet } from 'gameable/animation';

const json = await (await fetch('/motion/third-person.motion.json')).json();
const data = parseMotionSet(json);
console.log(data.name, data.takes.length, data.frames, data.modules);
// a presenter who only walks: the standing and the walking, nothing else in memory
const walking = parseMotionSet(json, { modules: ['idle', 'walk'] });

parsePoseAdjust() ​

ts
function parsePoseAdjust(value): PoseAdjustRecord | null;

Read a package's poseAdjust.

Parameters ​

ParameterTypeDescription
valueunknownThe field as parsed from character.json (anything).

Returns ​

PoseAdjustRecord | null

The record with every turn at unit length, or null when the field is absent.

Throws ​

When the field is there and is not a version 1 record in the parent's frame, or a turn or a move is not numbers: the caller says so once and leaves the character as it is without it.

Example ​

ts
import { parsePoseAdjust } from 'gameable/animation';

const record = parsePoseAdjust({
  version: 1,
  space: 'parent',
  adjust: { Chest: [-0.0262, 0, 0, 0.9997] },
});
console.log(record?.adjust.Chest);

parseSeatedMoveSources() ​

ts
function parseSeatedMoveSources(value): object;

Read the seated takes a set's file states: every take of its riding part with a seated block.

json
{ "name": "kick_right", "module": "riding", "fps": 30, "frames": 40, "bones": {}, "root": [],
  "seated": { "move": "kick", "limb": "right-leg", "strikeFrame": 14, "reachM": 0.35, "trunk": 0.5 } }

limb is needed, but for a take in which no limb acts (kind: 'react', a hit or a jostle taken: the trunk and the head alone are turned, and a limb it states is kept but not posed); strikeFrame and releaseFrame are frames into the take as stored (its first frame is 0); reachM is metres (absent: the limb is never bent to a target); trunk is the share of the take's turn of the trunk and head the rider takes (absent: a half); firstMovesFrame is the frame the performer first moves on (kept in SECONDS as lead; absent, or not a frame of the take: 0). Anything else in the block is the studio's own. A take that breaks a rule is left out and said, never the whole file.

Parameters ​

ParameterTypeDescription
valueunknownThe file's own words (the parsed JSON, or what is kept of it once packed).

Returns ​

object

The seated takes that can be read, and the ones refused.

moves ​
ts
moves: SeatedMoveSource[];
refused ​
ts
refused: object[];

Example ​

ts
import { parseSeatedMoveSources } from 'gameable/animation';

const { moves, refused } = parseSeatedMoveSources(await (await fetch(url)).json());
console.log(moves.map((m) => `${m.move} (${m.limb}): ${m.take}`), refused);

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.


poseCost() ​

ts
function poseCost(
   table, 
   a, 
   b
): number;

How far apart two frames' bodies are, by the feet and the hips alone (their places and speeds against the root): the part of a search's cost that says whether the feet are in step. -1 for a stands for the rig standing at rest.

Parameters ​

ParameterTypeDescription
tableMotionTableThe table.
anumberThe first frame, or -1 for standing.
bnumberThe second frame.

Returns ​

number

The squared distance, in the table's own scaled units.

Example ​

ts
import { poseCost } from 'gameable/animation';

// is frame 120 in step with the frame playing?
console.log(poseCost(table, Math.floor(motion.cursor), 120));

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.


readAnimationIntent() ​

ts
function readAnimationIntent(raw, ownClips): AnimationIntent | null;

Read a package's animation. Absent, or without an intent the reader knows, null.

Parameters ​

ParameterTypeDescription
rawunknowncharacter.json's animation, or undefined.
ownClipsreadonly string[]The package's own clip names (character.json's clips), the default cover.

Returns ​

AnimationIntent | null

The intention, or null when the package carries none.

Example ​

ts
import { readAnimationIntent } from 'gameable/animation';

const a = readAnimationIntent({ intent: 'style', style: 'slow and broad' }, ['idle', 'walk']);
console.log(a?.intent, a?.clips, a?.life.idle); // 'style' ['idle', 'walk'] 'idle'
console.log(readAnimationIntent(undefined, [])); // null

readGetUpLie() ​

ts
function readGetUpLie(
   points, 
   offset, 
   out
): GetUpLieRead;

How a body lies, from its points.

Parameters ​

ParameterTypeDescription
pointsArrayLike<number>GETUP_POINTS points (x, y up, z), from offset.
offsetnumberWhere the points start in points.
outGetUpLieReadFilled and returned.

Returns ​

GetUpLieRead

out.

Example ​

ts
import { readGetUpLie, type GetUpLieRead } from 'gameable/animation';

const read: GetUpLieRead = { lie: null, heading: 0, faceUp: 0, leftUp: 0, upright: 0 };
readGetUpLie(bodyPoints, 0, read);
console.log(read.lie ?? 'not lying', 'the head points', read.heading, 'radians from +Z');

readHolds() ​

ts
function readHolds(raw): Holds | null;

Read a package's holds. A package without one, or with one that names no joints, holds nothing (null); a joint name that is not a string is left out.

Parameters ​

ParameterTypeDescription
rawunknowncharacter.json's holds, or undefined.

Returns ​

Holds | null

The holds, or null for none.

Example ​

ts
import { readHolds } from 'gameable/animation';

const holds = readHolds({ arms: true, at: 'rest', joints: ['LeftShoulder', 'LeftArm'] });
console.log(holds?.joints.length); // 2
console.log(readHolds(undefined)); // null

readLifeSetting() ​

ts
function readLifeSetting(raw): LifeSetting;

Read a package's life (or anything shaped like it) into a setting; what is missing or not understood is the default's. A package with no life at all reads as the default: the studio's package doc says a record without one gives the defaults.

Parameters ​

ParameterTypeDescription
rawunknowncharacter.json's life, or undefined.

Returns ​

LifeSetting

The setting.

Example ​

ts
import { readLifeSetting } from 'gameable/animation';

const life = readLifeSetting({ level: 'lively', blink: true, blinkRate: 2 });
console.log(life.level, life.blink, life.on); // 'lively' true true

readMotionBinaryHeader() ​

ts
function readMotionBinaryHeader(bytes): MotionBinaryIndex | null;

Read a binary set's header: what it holds and where each take ends, before (or without) reading any take. A file still arriving can be asked once its first bytes are here.

Parameters ​

ParameterTypeDescription
bytesUint8ArrayThe file's bytes from its start.

Returns ​

MotionBinaryIndex | null

The header, or null while the bytes at hand do not yet hold all of it.

Throws ​

When the bytes are not a binary motion set of this version.

Example ​

ts
import { readMotionBinaryHeader } from 'gameable/animation';

const index = readMotionBinaryHeader(bytes);
if (index !== null)
  console.log(index.header.takes.map((take) => take.name), 'in', index.fileBytes, 'bytes');

readMotionGaits() ​

ts
function readMotionGaits(
   data, 
   rootSpeed, 
   down, 
   body?
): MotionGaits;

Read the gaits of a set's takes.

Parameters ​

ParameterTypeDefault valueDescription
dataMotionDataundefinedThe packed set.
rootSpeedFloat32Arrayundefinedframes: the root's speed over the ground, metres a second.
downFloat32Arrayundefinedframes x 2: how much each foot (left, right) is down, 0 to 1.
bodyMotionBodyReading | nullnullThe hips' height and the ankles against the root, when they are known: a walk is then told from a run by where the hips are as a foot passes under them.

Returns ​

MotionGaits

The reading.

Example ​

ts
import { buildMotionTable, MOTION_GAIT_NAMES, parseMotionSet } from 'gameable/animation';

const table = buildMotionTable(parseMotionSet(json), rigRoot);
for (const band of table.gaits.bands)
  console.log(band.name, band.from.toFixed(1), 'to', band.to.toFixed(1), 'm/s');
console.log(MOTION_GAIT_NAMES[table.gaits.now[0]]); // 'stand'

readMotionSource() ​

ts
function readMotionSource(bytes, options?): object;

A motion set's file as its text parses, whichever form the file is in: the compact binary unpacked, or the studio's text parsed. Not yet packed: hand source to parseMotionSet (or lay one set's takes over another's first).

Parameters ​

ParameterTypeDescription
bytesUint8ArrayThe whole file.
optionsMotionDecodeOptionsWhich parts: modules as the parser keeps them (a set asked for whole is read without its actions part; a binary set's takes that are not kept are not unpacked).

Returns ​

object

The set as its file states it, and whether the file was the binary.

binary ​
ts
binary: boolean;
source ​
ts
source: MotionSetSource;

Throws ​

When the bytes are neither form.

Example ​

ts
import { parseMotionSet, readMotionSource } from 'gameable/animation';

const { source, binary } = readMotionSource(new Uint8Array(await response.arrayBuffer()));
console.log(binary, source.takes.map((take) => take.module));
const data = parseMotionSet(source);

readSeatedReference() ​

ts
function readSeatedReference(frame): SeatedReference | null;

Read a reference pose off one frame of a performed take, on the character's own skeleton: the same record a person would write. The take's joints are laid on the rig's own lengths, and every amount is measured as an angle against the performer's seat.

What is NOT read: where the hands, the feet and the hips are (the game's machine says that), how far the back leans forward (the reach to the grips decides it), the fingers.

Parameters ​

ParameterTypeDescription
frameSeatedReferenceFrameThe rig, and the frame's turns by bone name.

Returns ​

SeatedReference | null

The record, each amount rounded to a tenth of a degree, or null for a rig without the joints (a head by itself).

Example ​

ts
import { readSeatedReference } from 'gameable/animation';

const pose = readSeatedReference({ root: rig, rotation: (name, out) => turns.get(name) ?? null });
console.log(pose?.chestTurn, pose?.headTilt); // degrees

readSeatedReferenceOfTake() ​

ts
function readSeatedReferenceOfTake(
   root, 
   data, 
   take, 
   frame?, 
   facingDeg?
): SeatedReference | null;

Read a reference pose off a frame of a take of a motion set (a "sit" take of a riding set), on the character's own skeleton: readSeatedReference over the set's packed frames.

Parameters ​

ParameterTypeDescription
rootObject3DThe rig root, the bones under it at rest.
dataMotionDataThe set, read (its riding part).
takestringThe take's name in the set.
frame?numberThe frame into the take (its first frame is 0); left out, its last frame: the rider settled.
facingDeg?numberWhich way the performer's seat faces in the take, degrees; left out, read off the performer's feet and hands.

Returns ​

SeatedReference | null

The record, or null when the set has no such take or frame, or the rig no body.

Example ​

ts
import { parseMotionSet, readSeatedReferenceOfTake } from 'gameable/animation';

const data = parseMotionSet(json, { modules: ['riding'] });
const pose = readSeatedReferenceOfTake(rig, data, 'sit_pink_menace');
if (pose) seated?.apply({ seat, hands, feet, pose }, dt);

readStrides() ​

ts
function readStrides(contacts): StrideReading;

Read how a looping clip's steps sit in its cycle: how many strides it holds and where the left foot first lands. The walk blend's shared phase turns every gait's clip to that landing, so two clips cut at different moments of the step still put the same foot down together. Run once per clip at load.

Parameters ​

ParameterTypeDescription
contactsFootContactsThe clip's contacts.

Returns ​

StrideReading

The reading; one stride from the loop's start when the contacts say nothing.

Example ​

ts
import { readStrides } from 'gameable/animation';

// a loop of eight frames: the left foot lands at frame 2, the right at frame 6
const reading = readStrides({
  left: [0, 0, 1, 1, 1, 0, 0, 0],
  right: [1, 1, 0, 0, 0, 0, 1, 1],
  fps: 30,
  authored: true,
});
console.log(reading); // { strides: 1, offset: 0.25 }

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): number[] | Float32Array<ArrayBufferLike>;

Rebind a whole quaternion keyframe track in place.

Parameters ​

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

Returns ​

number[] | Float32Array<ArrayBufferLike>

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): number[] | Float32Array<ArrayBufferLike>;

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
valuesnumber[] | Float32Array<ArrayBufferLike>Flat xyz stream, three floats per key; rewritten in place.
rationumberdstHipHeight / srcHipHeight.

Returns ​

number[] | Float32Array<ArrayBufferLike>

values, for chaining.


searchMotion() ​

ts
function searchMotion(
   table, 
   query, 
   scaled, 
   out, 
   slowerThan?, 
   serves?, 
   steady?
): MotionMatch;

Find the frame whose features are nearest a query. Every matchable frame is a candidate, but the frames are looked at through the table's tree of boxes (MotionTable.tree): the leaf nearest the query first, and a branch is passed over whole when its box is already further from the query than the best frame found. The answer is the one a look at every frame gives (of two frames that cost the same, the earlier), many times sooner.

Parameters ​

ParameterTypeDefault valueDescription
tableMotionTableundefinedThe table.
queryArrayLike<number>undefinedThe query, raw (metres, metres a second, sines and cosines): MOTION_FEATURES numbers.
scaledFloat32ArrayundefinedScratch of MOTION_FEATURES numbers: the query as the table scales it.
outMotionMatchundefinedFilled with the best frame and its cost.
slowerThannumberInfinityOnly frames whose root moves slower than this (metres a second) are looked at: a body that stands may only land where a take is itself still standing or just moving off, never on a frame already in motion.
servesnumber0Only frames that serve this are looked at: bits of MOTION_SERVES (a request to walk is answered with frames heading to a walk, never with a run that passes through a walk's speed while it slows). 0, the default: every frame.
steadynumber0How much a frame with little steady going left costs (times gaits.unsteady): above 0 for a body asked to keep going as it is, so it settles on a take's long steady stretch. 0, the default: nothing.

Returns ​

MotionMatch

out.

Example ​

ts
import { MOTION_FEATURES, searchMotion } from 'gameable/animation';

const query = new Float32Array(MOTION_FEATURES); // a stand: nothing moves, the feet under the hips
const match = searchMotion(table, query, new Float32Array(MOTION_FEATURES), { frame: -1, cost: 0 });
console.log(table.data.takes[table.data.takeOf[match.frame]].name);

seatedJointsFor() ​

ts
function seatedJointsFor(root): SeatedJointNames | null;

Which of the skeletons the engine knows a rig has, probed rather than declared: the first set of names whose hips, head, arms and legs are all in the rig.

Parameters ​

ParameterTypeDescription
rootObject3DThe rig root.

Returns ​

SeatedJointNames | null

The names, or null for a rig that has no body to seat (a head by itself).

Example ​

ts
import { seatedJointsFor } from 'gameable/animation';

console.log(seatedJointsFor(rig)?.hips); // 'root' on the sample character

seededRandom() ​

ts
function seededRandom(seed): () => number;

A seeded uniform source (the studio's seeded: mulberry32), so a measurement replays.

Parameters ​

ParameterTypeDescription
seednumberAny integer.

Returns ​

[0, 1) numbers.

() => number


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,
});

snapshotMotionRig() ​

ts
function snapshotMotionRig(
   root, 
   names?, 
   more?
): MotionRigSnapshot;

Copy what a motion table reads off a rig: its pelvis, both legs down to the toes, and every joint between them and the root. Call while the rig stands at rest.

Parameters ​

ParameterTypeDefault valueDescription
rootObject3DundefinedThe rig's root (the character's own frame).
namesMotionRigNamesSOMA_MOTION_RIGWhat the rig calls its pelvis and legs.
morereadonly string[][]Other joints to copy with them, by name, each with every joint between it and the root (what a set's actions are read by: SOMA_ACTION_RIG.points). One the rig lacks is left out. A table read on the copy is the same with or without them.

Returns ​

MotionRigSnapshot

The copy: plain numbers, safe to keep or to send to another thread.

Throws ​

When the rig lacks the pelvis or a leg joint.

Example ​

ts
import { buildMotionTable, motionRigFromSnapshot, snapshotMotionRig } from 'gameable/animation';

const atRest = snapshotMotionRig(rigRoot); // at spawn, before anything poses the rig
// later, the character long since walking:
const table = buildMotionTable(data, motionRigFromSnapshot(atRest));

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.


springRing() ​

ts
function springRing(
   s, 
   to, 
   dt, 
   hertz, 
   damping
): number;

One step of the same spring let ring: under-damped, so it passes its target a little and comes back to rest (the exact step, as springTo's is). What a weight does that is brought up short: a lean coming off a curve, a chest over hips that have stopped. At a damping of 1 or more it is springTo at the half-life that frequency has.

Parameters ​

ParameterTypeDescription
sSprungThe spring's state, changed in place.
tonumberThe target.
dtnumberSeconds.
hertznumberIts own frequency, cycles a second (undamped).
dampingnumberIts damping ratio: 1 never passes the target; 0.5 passes it by 16 % of the way come, 0.6 by 9 %, 0.7 by 5 %.

Returns ​

number

The new value.


springTo() ​

ts
function springTo(
   s, 
   to, 
   dt, 
   halfLife
): number;

One step of a critically damped spring toward to (the studio's springTo, D. Holden's exact step): it leaves rest gently, is fastest part of the way there and arrives without overshoot, where an ease is at its fastest on the very frame its target changes.

Parameters ​

ParameterTypeDescription
sSprungThe spring's state, changed in place.
tonumberThe target.
dtnumberSeconds.
halfLifenumberSeconds for what is left to halve once it is under way.

Returns ​

number

The new value.


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.