@gameable/animation
Classes
LifeModel
The life as plain numbers.
Constructors
Constructor
ts
new LifeModel(seed?): LifeModel;Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
seed | number | 1 | The seed of every choice made here. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
i | LifeIn | This frame's inputs. |
Returns
The outputs, reused in place.
MovementComponent
Navmesh path following for one character.
Constructors
Constructor
ts
new MovementComponent(options?): MovementComponent;Build a component.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | MovementOptions | See MovementOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
patch | Partial<MovementConfig> | Fields to change. |
Returns
void
moveToActor()
ts
moveToActor(target, acceptanceRadius?): boolean;Unreal's MoveToActor: follows a possibly-moving target.
Parameters
| Parameter | Type | Description |
|---|---|---|
target | MovementTarget | The target. |
acceptanceRadius? | number | Override for this move, in metres. |
Returns
boolean
Whether a path was found.
moveToLocation()
ts
moveToLocation(point, acceptanceRadius?): boolean;Unreal's MoveToLocation.
Parameters
| Parameter | Type | Description |
|---|---|---|
point | Vec3 | The destination. |
acceptanceRadius? | number | Override for this move, in metres. |
Returns
boolean
Whether a path was found.
moveToRandomPoint()
ts
moveToRandomPoint(
center,
radius,
rng?
): boolean;Unreal's MoveToRandomPoint.
Parameters
| Parameter | Type | Description |
|---|---|---|
center | Vec3 | Search centre. |
radius | number | Search radius in metres. |
rng? | () => number | Uniform [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
| Parameter | Type | Description |
|---|---|---|
fn | MovementEventSink | null | The sink, or null. |
Returns
void
setGroup()
ts
setGroup(g): void;Set the transform to drive.
Parameters
| Parameter | Type | Description |
|---|---|---|
g | MovementGroupLike | null | The transform, or null. |
Returns
void
setNavMesh()
ts
setNavMesh(nm): void;Set the navmesh.
Parameters
| Parameter | Type | Description |
|---|---|---|
nm | NavMeshLike | null | The navmesh, or null. |
Returns
void
tick()
ts
tick(dt): void;Advance one frame.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds 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
| Parameter | Type |
|---|---|
limb | number |
x | number |
y | number |
z | number |
Returns
void
release()
ts
release(limb): void;Parameters
| Parameter | Type |
|---|---|
limb | number |
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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds. |
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
| Parameter | Type | Description |
|---|---|---|
frame | Readonly<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
| Parameter | Type | Description |
|---|---|---|
name | string | The action's name in the set. |
target? | Readonly<ActionTarget> | null | The object, as the game has it. |
options? | ActionRequestOptions | How 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
| Parameter | Type | Description |
|---|---|---|
actions | ActionSet | The 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
blink
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
| Parameter | Type | Description |
|---|---|---|
name | string | Runtime name; how state.clips and the graph address it. |
clip | AnimationClip | The clip, already bound to this rig's bone names. |
options? | AddClipOptions | See AddClipOptions. |
Returns
void
addFaceClip()
ts
addFaceClip(name, clip): void;Register a face clip.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Runtime name. |
clip | FaceClipData | ARKit-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
| Parameter | Type | Description |
|---|---|---|
listener | ClipEndListener | What 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
| Parameter | Type | Description |
|---|---|---|
graph | BodyGraph | null | The 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
| Parameter | Type | Description |
|---|---|---|
index | LocomotionIndex | null | The 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
| Parameter | Type | Description |
|---|---|---|
layer | MotionLayer | null | The layer, or null for none. |
extras? | AnimatorMotionExtras | null | The 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
| Parameter | Type | Description |
|---|---|---|
state | CharacterState | The state; validate untrusted input with validateCharacterState. |
Returns
void
update()
ts
update(dt, context?): void;Advance every layer by dt.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds since the last update. |
context? | AnimatorUpdateContext | See 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
| Parameter | Type |
|---|---|
dt | number |
Returns
void
before?
ts
optional before?: (frame) => void;Before the motion layer: its direction for this frame.
Parameters
| Parameter | Type |
|---|---|
frame | MotionFrame |
Returns
void
last?
ts
optional last?: (dt) => void;After the feet: the last word on the pose.
Parameters
| Parameter | Type |
|---|---|
dt | number |
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
blink?
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
| Parameter | Type | Description |
|---|---|---|
out | Float32Array | ARKit-52 weight vector, written in place and clamped to 1. |
gate? | number | Sentinel 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
| Parameter | Type | Description |
|---|---|---|
gate? | number | Sentinel 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
| Parameter | Type | Description |
|---|---|---|
patch | Partial<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
| Parameter | Type |
|---|---|
boneName | string |
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
| Parameter | Type | Description |
|---|---|---|
facing | number | Radians about +Y. |
walker | Readonly<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
| Parameter | Type | Description |
|---|---|---|
request | WalkRequest | Where, facing which way, at what pace, by when. |
walker | Readonly<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
| Parameter | Type | Description |
|---|---|---|
pace | number | Metres 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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds since the last frame. |
walker | Walker | The 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
| Parameter | Type | Description |
|---|---|---|
arkit | Float32Array | 52 ARKit weights. |
out | Float32Array | dim 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
| Parameter | Type | Description |
|---|---|---|
name | string | Runtime key the drive weights address it by. |
clip | FaceClipData | The 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
| Parameter | Type | Description |
|---|---|---|
alias | string | The new key. |
sourceName | string | The 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
| Parameter | Type | Description |
|---|---|---|
weights | ReadonlyMap<string, number> | null | Drive 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
| Parameter | Type | Description |
|---|---|---|
name | string | Runtime 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
| Parameter | Type | Description |
|---|---|---|
name | string | Runtime 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
| Parameter | Type | Description |
|---|---|---|
name | string | Runtime 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.
right
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
| Parameter | Type | Description |
|---|---|---|
context | FootPlantContext | The 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
foot
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
| Parameter | Type |
|---|---|
leg | number |
x | number |
y | number |
z | number |
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
| Parameter | Type | Description |
|---|---|---|
weight | number | Weight in [0, 1]. |
Returns
void
setLoop()
ts
setLoop(mode, count): void;Set the loop style.
Parameters
| Parameter | Type | Description |
|---|---|---|
mode | number | Loop style, e.g. LOOP_ONCE. |
count | number | Repetition 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
| Parameter | Type | Description |
|---|---|---|
actions | ReadonlyMap<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
| Parameter | Type | Description |
|---|---|---|
clipName | string | Name the clip was registered under. |
options? | GestureOptions | Envelope 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
| Parameter | Type | Description |
|---|---|---|
active | boolean | Whether 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
| Parameter | Type |
|---|---|
limb | number |
out | Float32Array |
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
| Parameter | Type |
|---|---|
limb | number |
x | number |
y | number |
z | number |
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
| Parameter | Type |
|---|---|
limb | number |
y | number |
fresh? | boolean |
Returns
void
release()
ts
release(limb): void;Parameters
| Parameter | Type |
|---|---|
limb | number |
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
| Parameter | Type | Description |
|---|---|---|
style? | GetUpStyle | The style asked; the layer's own when absent. |
way? | GetUpWay | For '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
| Parameter | Type | Description |
|---|---|---|
way? | GetUpWay | Where 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
| Parameter | Type | Description |
|---|---|---|
set | GetUpSet | The 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
| Parameter | Type | Description |
|---|---|---|
style | GetUpStyle | The style asked. |
way? | GetUpWay | For '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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds. |
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.statedGapstill 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.
head
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
| Parameter | Type |
|---|---|
on | boolean |
Returns
void
setSetting()
ts
setSetting(setting): void;A new setting (a page's Calm / Natural / Lively), in force from the next frame.
Parameters
| Parameter | Type |
|---|---|
setting | LifeSetting |
Returns
void
setState()
ts
setState(state, voice?): void;The conversation's state and the voice's loudness (0..1), from the host.
Parameters
| Parameter | Type |
|---|---|
state | LifeState |
voice? | number |
Returns
void
update()
ts
update(context): void;Lay the life over the posed bones.
Parameters
| Parameter | Type |
|---|---|
context | LifeUpdateContext |
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
blink
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
| Parameter | Type | Description |
|---|---|---|
limb | number | The limb's number. |
out | Float32Array | Three 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
| Parameter | Type | Description |
|---|---|---|
limb | number | The limb's number in LimbHoldOptions.limbs. |
x | number | The point, world metres. |
y | number | The point's height. |
z | number | The point's depth. |
orient? | ArrayLike<number> | null | The 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? | boolean | True 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
| Parameter | Type | Description |
|---|---|---|
limb | number | The limb's number. |
y | number | The height, world metres; NaN for none. |
fresh? | boolean | True 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
| Parameter | Type | Description |
|---|---|---|
limb | number | The 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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds 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.
header
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
| Parameter | Type |
|---|---|
joint | string |
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";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
| Parameter | Type | Description |
|---|---|---|
foot | number | The foot that comes down next: 0 the left, 1 the right. |
ahead | number | Seconds until it does. |
speed | number | Metres 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
| Parameter | Type | Description |
|---|---|---|
frame | number | The 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
| Parameter | Type | Description |
|---|---|---|
table | MotionTable | The 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
| Parameter | Type | Description |
|---|---|---|
frame | MotionFrame | The 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
| Parameter | Type | Description |
|---|---|---|
frame | MotionFrame | The 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
| Parameter | Type |
|---|---|
must | boolean |
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
| Parameter | Type |
|---|---|
x | number |
z | number |
turn | number |
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 (feetFlatabsent, 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.
NavMeshLike
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
| Parameter | Type | Description |
|---|---|---|
from | Vec3 | Start point. |
to | Vec3 | Goal 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
| Parameter | Type | Description |
|---|---|---|
center | Vec3 | Search centre. |
radius | number | Search radius in metres. |
rng? | () => number | Uniform [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
| Parameter | Type | Description |
|---|---|---|
slot | number | 0: the acting limb; 1: the also. |
sample | number | Which sample, or under 0 for none at all. |
x | number | Metres in the seat's own frame. |
y | number | Metres. |
z | number | Metres. |
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
| Parameter | Type | Description |
|---|---|---|
sample | number | Which sample, or under 0 to put the bones back. |
spots | Readonly<SeatedSpots> | Where the seat, the grips and the rests are this frame. |
slot | number | 0: the overlay's acting limb; 1: its also. |
give | Readonly<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
| Parameter | Type | Description |
|---|---|---|
slot | number | 0: the acting limb; 1: the also. |
more | Readonly<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
| Parameter | Type | Description |
|---|---|---|
which | number | The limb. |
more | Readonly<Vector3> | How much further, metres in the seat's own frame. |
middle? | boolean | Whether 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
| Parameter | Type | Description |
|---|---|---|
which | number | The 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
| Parameter | Type | Description |
|---|---|---|
sample | number | Which sample, 0 to samples - 1. |
spots | Readonly<SeatedSpots> | Where the seat, the grips and the rests are this frame. |
pelvis | Quaternion | Written: 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
| Parameter | Type | Description |
|---|---|---|
limb | number | The limb's number. |
first | number | The take's first frame in the set. |
last | number | Its last. |
neutral | number | The set's frame of the performer's neutral for it (its own first frame, or another take's). |
endsRiding | boolean | Whether it ends riding (its hand or foot back on its rest). |
change? | boolean | Whether it was performed from the riding posture: laid as a change at every distance (SeatedFitTake.change). Left out: false. |
strike? | number | The 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? | boolean | For 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
| Parameter | Type | Description |
|---|---|---|
limb | number | The limb's number. |
take | SeatedFitTake | The take's measure. |
frame | number | The set's frame (a float). |
seat | Quaternion | How the seat is turned, world. |
wanted | Vector3 | Written, 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
| Parameter | Type | Description |
|---|---|---|
limb | number | The limb's number. |
take | SeatedFitTake | The take's measure. |
frame | number | The set's frame (a float). |
seat | Quaternion | How the seat is turned, world. |
pose | Float32Array | columns x 4 numbers at offset: the limb's columns are written. |
offset | number | Where the pose starts in pose. |
wanted | Vector3 | Written: 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
| Parameter | Type | Description |
|---|---|---|
limb | number | The 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
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
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
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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds 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
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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds since the last frame. |
spots | Readonly<SeatedSpots> | Where the seat, the grips and the rests are this frame. |
out | Quaternion | Written: the turn, in the pelvis' own frame. |
Returns
boolean
Whether the pelvis is turned at all this frame.
Inherited from
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
| Parameter | Type | Description |
|---|---|---|
request | SeatedMoveRequest | The 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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds 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
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:
- 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);
- 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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds 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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds since the last frame. |
spots | Readonly<SeatedSpots> | Where the seat, the grips and the rests are this frame. |
out | Quaternion | Written: 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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds 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
| Parameter | Type | Description |
|---|---|---|
spots | SeatedSpots | Where the seat, the grips and the rests are, world. |
dt | number | Seconds since the last frame. |
over? | SeatedOverlay | null | Something 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
| Parameter | Type | Description |
|---|---|---|
middle | Vector3 | The ball's middle, world. |
radius | number | Its 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
| Parameter | Type | Description |
|---|---|---|
part | SeatedBodyPart | Which 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
| Parameter | Type | Description |
|---|---|---|
name | string | The bone's name. |
out | Quaternion | Written. |
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
| Parameter | Type | Description |
|---|---|---|
request | UpperBodyPlay | The 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
| Parameter | Type | Description |
|---|---|---|
table | Pick<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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds 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
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds. |
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
| Parameter | Type | Description |
|---|---|---|
weight | number | Weight in [0, 1]. |
Returns
void
setLoop()
ts
setLoop(mode, count): void;Set the loop style.
Parameters
| Parameter | Type | Description |
|---|---|---|
mode | number | Loop style. |
count | number | Repetition 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
| Parameter | Type | Description |
|---|---|---|
wanted | ReadonlyMap<string, number> | The weights the game wants, by clip name. Names absent want 0. |
dt | number | Seconds 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
| Parameter | Type | Description |
|---|---|---|
name | string | The clip's runtime name. |
kind | ClipEndKind | 'ended' (a once-only clip finished) or 'loop' (a looping clip wrapped). |
time | number | The 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
| Parameter | Type |
|---|---|
x | number |
y | number |
z | number |
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
| Parameter | Type | Description |
|---|---|---|
type | string | Event name; only onMoveCompleted is emitted today. |
data | MoveCompletedEvent | Event 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.
ARKIT_EYE_BLINK_LEFT
ts
const ARKIT_EYE_BLINK_LEFT: 0 = 0;Index of EyeBlinkLeft, the left half of the procedural blink overlay.
ARKIT_EYE_BLINK_RIGHT
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.
BLINK_DEFAULTS
ts
const BLINK_DEFAULTS: Readonly<BlinkConfig>;The Unreal DynamicBlinkSM timings the POC shipped with.
BLINK_RATE_RANGE
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 asprintpart (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 ofturn), 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 ledgeSOMA_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
| Parameter | Type | Description |
|---|---|---|
kind | string | What 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
| Parameter | Type | Description |
|---|---|---|
blend | LocomotionBlend | The blend this frame. |
speed | number | The ground speed, metres a second. |
speeds | ReadonlyMap<string, number> | Clip name to the clip's speed (its planted feet's travel at rate 1). |
durations | ReadonlyMap<string, number> | Clip name to the clip's duration in seconds. |
dt | number | Seconds since the last advance. |
phase | LocomotionPhase | The phase, advanced in place. |
times | Map<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
| Parameter | Type | Description |
|---|---|---|
weights | ReadonlyMap<string, number> | null | Clip name to weight, or null to stop everything. |
loop | ReadonlyMap<string, boolean> | null | Clip name to loop flag; a missing entry means "loop". |
speed | ReadonlyMap<string, number> | null | Clip name to time scale; a missing entry means 1. |
actions | ReadonlyMap<string, WeightedActionLike> | Registered actions by clip name. |
constants | LoopConstants | three'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
| Parameter | Type | Description |
|---|---|---|
current | number | Current angle in radians. |
target | number | Target angle in radians. |
rate | number | Follow rate in 1/seconds; larger is snappier. |
dt | number | Delta 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
| Parameter | Type | Description |
|---|---|---|
name | string | Channel 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
| Parameter | Type | Description |
|---|---|---|
clip | AnimationClip | The clip, mutated in place. |
settings | AdditiveSettings | null | The authored additive settings, or null for the historical local-space / own-frame-0 default. |
ctx | AdditiveBakeContext | What 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
record | PoseAdjustRecord | undefined | The record (parsePoseAdjust). |
joints | readonly string[] | undefined | The layer's joints, by name. |
hips | string | 'Hips' | The hips' name among them, for the record's move. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
sorted | readonly LocomotionClipMeta[] | Clips ordered by ascending speed, from sortLocomotionClips. |
speed | number | Planar ground speed in metres per second. |
out | LocomotionBlend | Result written in place, from createLocomotionBlend. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
s | LifeSetting | The 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 }))); // nullboneMapFromJson()
ts
function boneMapFromJson(table): BoneNameMap;Turn a JSON { source: target } table into a BoneNameMap.
Parameters
| Parameter | Type | Description |
|---|---|---|
table | unknown | Parsed mixamo_to_mh.json. |
Returns
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
sources | readonly ActionSource[] | undefined | The actions as the file states them. |
table | MotionTable | undefined | The set, read on this rig. |
root | Object3D | undefined | The rig's root. |
names | ActionRigNames | SOMA_ACTION_RIG | What the rig calls the joints an action is read by. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
tracks | BodyMotionTracks | The payload; see BodyMotionTracks. |
options | BuildBodyMotionClipOptions | See 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
| Parameter | Type | Description |
|---|---|---|
root | Object3D | The 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
data | MotionData | undefined | The set, read with its getups part. |
sources | readonly GetUpSource[] | undefined | The get-ups as the file states them (parseGetUpSources). |
root | Object3D | undefined | The rig's root (the character's own frame, its origin on the floor). |
names | GetUpRigNames | SOMA_GETUP_RIG | What the rig calls the joints a get-up is read by. |
Returns
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
data | MotionData | undefined | The packed set. |
root | Object3D | undefined | The rig's root (the character's own frame, its origin on the floor). |
names | MotionRigNames | SOMA_MOTION_RIG | What the rig calls its pelvis and legs. |
weights | Readonly<MotionWeights> | MOTION_WEIGHTS | How much each group of features counts. |
options | Readonly<MotionTableOptions> | {} | How the takes are stood on the floor (MotionTableOptions.stand); absent, the table is what it always was. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
root | Object3D | The rig root, freshly loaded and not yet posed. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
set | GetUpSet | The set's get-ups. |
body | ArrayLike<number> | The body's GETUP_POINTS points in the world (x, y over its floor, z). |
lie | GetUpLie | How the body lies (readGetUpLie). |
style | GetUpStyle | The style asked. |
most | number | The furthest a pose distance may be, metres. |
out | GetUpFit | The 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
| Parameter | Type | Description |
|---|---|---|
r | unknown | The 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
| Parameter | Type | Description |
|---|---|---|
rawPitch | number | Desired look pitch in radians; positive looks up. |
maxPitch | number | Max 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
| Parameter | Type | Description |
|---|---|---|
rawYaw | number | Desired look yaw in world space (radians; 0 = +Z). |
bodyYaw | number | Body forward yaw in world space (radians). |
maxYaw | number | Max 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
values | Float32Array | undefined | Packed positions, mutated in place. |
blendFrames | number | 6 | Tail 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
values | Float32Array | undefined | Packed xyzw samples; must contain unit rotations. |
blendFrames | number | 6 | Tail 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
| Parameter | Type | Description |
|---|---|---|
tracks? | | Pick<BodyMotionTracks, "frames" | "root"> | null | A 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
| Parameter | Type | Description |
|---|---|---|
options | ActionLayerOptions | See ActionLayerOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | AnimatorOptions | See AnimatorOptions. |
Returns
The Animator.
createBlinkRuntime()
ts
function createBlinkRuntime(options?): BlinkRuntime;Create a procedural blink channel.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | BlinkRuntimeOptions | See BlinkRuntimeOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | DirectedWalkOptions | See DirectedWalkOptions. |
Returns
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
Empty accumulators, ready to be reused every frame.
createFaceClipPlayer()
ts
function createFaceClipPlayer(options?): FaceClipPlayer;Create a face-clip blender.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | FaceClipPlayerOptions | See FaceClipPlayerOptions. |
Returns
createFootPlant()
ts
function createFootPlant(options): FootPlant;Create the feet's layer on a rig.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | FootPlantOptions | See FootPlantOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | GestureChannelOptions | See GestureChannelOptions. |
Returns
createGetUpLayer()
ts
function createGetUpLayer(options): GetUpLayer;Put a get-up on a character.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | GetUpLayerOptions | See GetUpLayerOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | GraphRuntimeOptions | See GraphRuntimeOptions. |
Returns
A fresh GraphRuntime.
createLifeLayer()
ts
function createLifeLayer(options): LifeLayer;Create the life on a rig.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | LifeLayerOptions | See LifeLayerOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | LimbHoldOptions | See LimbHoldOptions. |
Returns
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
A zeroed LocomotionBlend.
createLocomotionPhase()
ts
function createLocomotionPhase(): LocomotionPhase;Create a phase to reuse every frame.
Returns
A phase at 0.
createMotionLayer()
ts
function createMotionLayer(options): MotionLayer;Put a character under a motion set.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | MotionLayerOptions | See MotionLayerOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | MovementOptions | See MovementOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | SeatedFitOptions | See SeatedFitOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | SeatedMovesOptions | See 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
| Parameter | Type | Description |
|---|---|---|
options | SeatedPoseOptions | The 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
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
| Parameter | Type | Description |
|---|---|---|
options | UpperBodyLayerOptions | See UpperBodyLayerOptions. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
options | WalkFeelLayerOptions | See WalkFeelLayerOptions. |
Returns
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
seconds | number | DEFAULT_FADE_SECONDS | How long a weight takes to go from 0 to 1 (or back). Default 0.4. |
Returns
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.5decodeMotionSet()
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
| Parameter | Type | Description |
|---|---|---|
bytes | Uint8Array | The file's bytes from its start (all of them, or as many as have arrived). |
options | MotionDecodeOptions | Which takes. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
need | ArrayLike<number> | The need on each sample, 0 or more. |
rate | ArrayLike<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). |
count | number | How many samples. |
out | Float64Array | Written: the curve, one value a sample. |
work | Float64Array | Scratch, at least count long. |
options | EaseAheadOptions | The 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 5edgeList()
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
| Parameter | Type | Description |
|---|---|---|
data | Readonly<Record<string, unknown>> | undefined | Authored payload, possibly undefined. |
key | string | Field 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
| Parameter | Type | Description |
|---|---|---|
source | MotionSetSource | The set, as its text file parses. |
options | MotionEncodeOptions | How 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
graph | BodyGraph | undefined | The 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. |
rt | GraphRuntime | undefined | Runtime context; valueCache is cleared here, because one call is one logical frame and stale cache entries would freeze a wired alpha. |
out | EvalAccumulator | ... | Accumulators to fill. Cleared first. Omit to allocate fresh ones. |
handlers | NodeHandlers | DEFAULT_HANDLERS | Node-type overrides; defaults to the built-in state machine. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
graph | RuleGraph | The rule graph. |
ctx | RuleContext | What 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
| Parameter | Type | Description |
|---|---|---|
clip | GetUpClip | The get-up. |
body | ArrayLike<number> | The body's GETUP_POINTS points in the world (x, y over ITS floor, z). |
out | GetUpFit | Filled and returned. |
Returns
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
furthest | number | undefined | Metres the furthest point travels. |
turn | number | 0 | Radians 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.047hipHeightRatio()
ts
function hipHeightRatio(srcHipHeight, dstHipHeight): number;Hip-height ratio between two rigs.
Parameters
| Parameter | Type | Description |
|---|---|---|
srcHipHeight | number | Source pelvis height above the floor, in metres. |
dstHipHeight | number | Target 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
| Parameter | Type | Description |
|---|---|---|
bytes | Uint8Array | The 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
| Parameter | Type | Description |
|---|---|---|
data | Readonly<Record<string, unknown>> | undefined | Authored payload, possibly undefined. |
key | string | Field 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
| Parameter | Type | Description |
|---|---|---|
bound | BoundPoseAdjust | The bound record. |
j | number | The joint's place in the list it was bound to. |
q | Float32Array | Quaternions, x y z w. |
o | number | The 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 recordlookSharesOf()
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
| Parameter | Type | Description |
|---|---|---|
s | LifeSetting | The setting. |
Returns
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 0mapTrackName()
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
| Parameter | Type | Description |
|---|---|---|
trackName | string | Source track name, e.g. mixamorig:LeftArm.quaternion. |
boneMap | BoneNameMap | Source 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
| Parameter | Type | Description |
|---|---|---|
pose | Readonly<SeatedReference> | The pose. |
Returns
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
poses | Readonly<SeatedPoses> | undefined | The set. |
speed | number | undefined | How far from the upright pose to the pose at speed, 0 to 1 (with no upright pose it changes nothing). |
turn | number | undefined | How far into a turn's pose: toward the left turn's when positive, the right turn's when negative. |
first | number | undefined | The same for the hips and the head. |
out | SeatedReference | undefined | Written (every numeric amount, and both knees); a scratch record to keep. |
brake | number | 0 | How 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
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
| Parameter | Type | Description |
|---|---|---|
from | Readonly<SeatedReference> | The first pose. |
to | Readonly<SeatedReference> | The second pose, for everything but the hips and the head. |
share | number | How far toward to: 0 the first pose, 1 the second (a spring may carry it a little past). |
firstTo | Readonly<SeatedReference> | The second pose for the hips and the head. |
firstShare | number | How far the hips and the head are toward firstTo. |
out | SeatedReference | Written (every numeric amount, and both knees); a scratch record to keep. |
Returns
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
| Parameter | Type | Default value | Description |
|---|---|---|---|
table | MotionTable | undefined | The table. |
frame | number | undefined | The frame. |
scaled | ArrayLike<number> | undefined | The query as the table scales it (what searchMotion left in its scratch). |
steady | number | 0 | As 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
| Parameter | Type | Description |
|---|---|---|
gaits | MotionGaits | The set's reading. |
asked | number | The speed asked for, metres a second. |
current | number | The gait the body is in now. |
out | MotionPace | Filled in place. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
gaits | MotionGaits | The set's reading. |
gait | number | The stride's gait. |
fallback | boolean | Whether 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
ratio | number | undefined | The speed wanted over the stride's own pace. |
gait | number | GAIT_WALK | The stride's gait (GAIT_WALK, the default, GAIT_RUN or GAIT_SPRINT). |
fastest | number | MOTION_RATE_FASTEST | The 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
| Parameter | Type | Description |
|---|---|---|
snapshot | MotionRigSnapshot | What 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
turn | number | undefined | The move-off's own turn, radians (left positive). |
angle | number | undefined | The way asked against the body's facing, radians (left positive). |
steer | number | 0 | How 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
ratio | number | undefined | The speed wanted over the stride's own pace. |
gait | number | GAIT_WALK | The 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
| Parameter | Type | Description |
|---|---|---|
gait | number | The 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
| Parameter | Type | Description |
|---|---|---|
gait | number | The 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
| Parameter | Type | Description |
|---|---|---|
data | Readonly<Record<string, unknown>> | undefined | Authored payload, possibly undefined. |
key | string | Field 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
| Parameter | Type | Description |
|---|---|---|
angle | number | Angle 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
| Parameter | Type | Description |
|---|---|---|
data | Readonly<Record<string, unknown>> | undefined | Authored payload, possibly undefined. |
key | string | Field name. |
fallback | number | Value 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
| Parameter | Type | Description |
|---|---|---|
value | unknown | The 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
| Parameter | Type | Description |
|---|---|---|
value | unknown | The 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
| Parameter | Type | Description |
|---|---|---|
bytes | Uint8Array | The whole file. |
parse | (value, options?) => MotionData | parseMotionSet (handed in so this module stays free of the table's code). |
options | MotionDecodeOptions | Which 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
| Parameter | Type | Description |
|---|---|---|
value | unknown | The parsed JSON. |
options | MotionParseOptions | Which parts of the set to keep. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
value | unknown | The 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
| Parameter | Type | Description |
|---|---|---|
value | unknown | The 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
| Parameter | Type | Description |
|---|---|---|
dx | number | World-space X offset from the head to the look target. |
dy | number | World-space Y offset from the head to the look target. |
dz | number | World-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
| Parameter | Type | Description |
|---|---|---|
state | CharacterState | The 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
| Parameter | Type | Description |
|---|---|---|
table | MotionTable | The table. |
a | number | The first frame, or -1 for standing. |
b | number | The 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
| Parameter | Type | Description |
|---|---|---|
clip | PrunableClip | Clip whose tracks array is replaced in place with the kept subset. |
sceneNodes | ReadonlySet<string> | Leaf node names present on the rig. |
options | PruneOptions | Prune options; see PruneOptions. |
Returns
A PruneReport describing what was kept and dropped.
quatInvert()
ts
function quatInvert(q): Quat;Conjugate of a unit quaternion, i.e. its inverse.
Parameters
| Parameter | Type | Description |
|---|---|---|
q | Quat | The quaternion; assumed normalised, as every rest rotation is. |
Returns
A new quaternion.
quatMultiply()
ts
function quatMultiply(
a,
b,
out
): number[];Hamilton product a * b.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | Quat | Left quaternion. |
b | Quat | Right quaternion. |
out | number[] | 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
| Parameter | Type | Description |
|---|---|---|
raw | unknown | character.json's animation, or undefined. |
ownClips | readonly 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, [])); // nullreadGetUpLie()
ts
function readGetUpLie(
points,
offset,
out
): GetUpLieRead;How a body lies, from its points.
Parameters
| Parameter | Type | Description |
|---|---|---|
points | ArrayLike<number> | GETUP_POINTS points (x, y up, z), from offset. |
offset | number | Where the points start in points. |
out | GetUpLieRead | Filled and returned. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
raw | unknown | character.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)); // nullreadLifeSetting()
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
| Parameter | Type | Description |
|---|---|---|
raw | unknown | character.json's life, or undefined. |
Returns
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 truereadMotionBinaryHeader()
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
| Parameter | Type | Description |
|---|---|---|
bytes | Uint8Array | The 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
data | MotionData | undefined | The packed set. |
rootSpeed | Float32Array | undefined | frames: the root's speed over the ground, metres a second. |
down | Float32Array | undefined | frames x 2: how much each foot (left, right) is down, 0 to 1. |
body | MotionBodyReading | null | null | The 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
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
| Parameter | Type | Description |
|---|---|---|
bytes | Uint8Array | The whole file. |
options | MotionDecodeOptions | Which 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
| Parameter | Type | Description |
|---|---|---|
frame | SeatedReferenceFrame | The 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); // degreesreadSeatedReferenceOfTake()
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
| Parameter | Type | Description |
|---|---|---|
root | Object3D | The rig root, the bones under it at rest. |
data | MotionData | The set, read (its riding part). |
take | string | The take's name in the set. |
frame? | number | The frame into the take (its first frame is 0); left out, its last frame: the rider settled. |
facingDeg? | number | Which 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
| Parameter | Type | Description |
|---|---|---|
contacts | FootContacts | The clip's contacts. |
Returns
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_dstwhere 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
| Parameter | Type | Description |
|---|---|---|
qSource | Quat | Local rotation from the source clip. |
frames | RestFrames | Rest orientations of the bone in both skeletons. |
out | number[] | 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
| Parameter | Type | Description |
|---|---|---|
values | number[] | Float32Array<ArrayBufferLike> | Flat xyzw stream, four floats per key; rewritten in place. |
frames | RestFrames | Rest 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
| Parameter | Type | Description |
|---|---|---|
settings? | AdditiveSettings | null | The authored settings, or null. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
name | string | Clip/gesture id. |
motion | PreparedMotion | Source local quaternion samples. |
source | RestSkeleton | Source rest skeleton, including unanimated ancestors. |
target | RestSkeleton | Target rest skeleton, including unanimated ancestors. |
boneMap | Readonly<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
| Parameter | Type | Description |
|---|---|---|
values | number[] | Float32Array<ArrayBufferLike> | Flat xyz stream, three floats per key; rewritten in place. |
ratio | number | dstHipHeight / 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
table | MotionTable | undefined | The table. |
query | ArrayLike<number> | undefined | The query, raw (metres, metres a second, sines and cosines): MOTION_FEATURES numbers. |
scaled | Float32Array | undefined | Scratch of MOTION_FEATURES numbers: the query as the table scales it. |
out | MotionMatch | undefined | Filled with the best frame and its cost. |
slowerThan | number | Infinity | Only 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. |
serves | number | 0 | Only 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. |
steady | number | 0 | How 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
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
| Parameter | Type | Description |
|---|---|---|
root | Object3D | The 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 characterseededRandom()
ts
function seededRandom(seed): () => number;A seeded uniform source (the studio's seeded: mulberry32), so a measurement replays.
Parameters
| Parameter | Type | Description |
|---|---|---|
seed | number | Any 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
| Parameter | Type | Description |
|---|---|---|
take | LocomotionTake | Source sampled motion. |
options | GaitCycleOptions | Search 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
| Parameter | Type | Default value | Description |
|---|---|---|---|
root | Object3D | undefined | The rig's root (the character's own frame). |
names | MotionRigNames | SOMA_MOTION_RIG | What the rig calls its pelvis and legs. |
more | readonly 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
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
| Parameter | Type | Description |
|---|---|---|
index | LocomotionIndex | The index. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
s | Sprung | The spring's state, changed in place. |
to | number | The target. |
dt | number | Seconds. |
hertz | number | Its own frequency, cycles a second (undamped). |
damping | number | Its 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
| Parameter | Type | Description |
|---|---|---|
s | Sprung | The spring's state, changed in place. |
to | number | The target. |
dt | number | Seconds. |
halfLife | number | Seconds 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
| Parameter | Type | Description |
|---|---|---|
targetFloors | ArrayLike<number> | Minimum foot/toe world height per frame at the target rest root height. |
restY | number | Target 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
| Parameter | Type | Description |
|---|---|---|
data | Readonly<Record<string, unknown>> | undefined | Authored payload, possibly undefined. |
key | string | Field 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
| Parameter | Type | Description |
|---|---|---|
data | Readonly<Record<string, unknown>> | undefined | Authored payload, possibly undefined. |
key | string | Field 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
| Parameter | Type | Description |
|---|---|---|
speed | number | Actual ground speed. |
clipSpeed | number | The 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
| Parameter | Type | Description |
|---|---|---|
value | unknown | The candidate, typically decoded from the guest's frame output. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
value | unknown | Parsed JSON. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
blend | LocomotionBlend | A result from blendLocomotion. |
weights | Map<string, number> | Cleared and filled with clip name to weight. |
speeds | Map<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
| Parameter | Type | Description |
|---|---|---|
dx | number | World-space X offset from the head to the look target. |
dz | number | World-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.