# @ferret/animation: API

Animation graphs: state machines, blend spaces, layers, notifies, retargeting and a stand-in puppet.

100 exports. Generated from the source (`packages/animation/src`), so it matches the code.

## Classes

### Animator

*class* · `packages/animation/src/animator.ts:32`

```ts
class Animator extends Component<AnimatorParams>
```

Plays an animation graph on an entity. Parameters come from the entity's motion source (or from game code through
`graph.set` / `graph.trigger`), the pose is applied once per rendered frame (the world hands over dt scaled by the entity's time dilation).
Notifies are emitted on the world's event bus as `anim:notify` { entity, name, clip }.

- `graph: AnimGraph`
- `backend: GroupBackend`
- `rootDelta: RootDelta` — root motion of the last frame, in the entity's own space (zero without `rootMotion`)
- `onAttach()`
- `onFixedUpdate()`
- `onUpdate(dt: number)`
- `playMontage(def: MontageDef)` — Play a one-shot clip over the base animation (a gesture, an attack, a pick-up).
- `onDetach()`

### AnimGraph

*class* · `packages/animation/src/graph.ts:235`

```ts
class AnimGraph
```

Runtime of one graph on one character.

- `readonly values: Record<string, number>`
- `notifyThreshold: number` — a clip whose weight in the output is at least this fires its notifies
- `constructor(readonly def: GraphDef, readonly clips: ClipLibrary, readonly events: GraphEvents = {})`
- `get state(): string`
- `get activeMontages(): readonly Montage[]`
- `set(param: string, value: number | boolean)`
- `get(param: string): number`
- `trigger(name: string)`
- `playMontage(def: MontageDef): Montage`
- `stopMontage(m: Montage)`
- `update(dt: number): Pose` — Advance by dt seconds (already multiplied by the entity's time dilation).

### ClipEditError

*class* · `packages/animation/src/clip.ts:234`

```ts
class ClipEditError extends Error
```

### ClipEditor

*class* · `packages/animation/src/clip.ts:258`

```ts
class ClipEditor
```

- `readonly rest: Rest`
- `constructor(clip: ClipJson, private readonly o: ClipEditorOptions)`
- `static create(o: ClipEditorOptions & { skeleton: string; name: string; duration?: number; base?: string; loop?: boolean; fps?: number }): ClipEditor` — A new clip: empty (the rest pose), or a copy of a library clip.
- `get json(): ClipJson`
- `get canUndo()`
- `get canRedo()`
- `history(): string[]`
- `undo(): boolean`
- `redo(): boolean`
- `setKey(a: { bone: string; time: number; rotation?: Quat; euler?: Vec3; position?: Vec3; interp?: Interp; absolute?: boolean }): void` — Set a key of a bone at a time (replaces the key there). `rotation` (quaternion) or `euler` (degrees) is the change from rest; with `absolute` it is the bone's own rotation (the change is worked out from the rest pose). `position` is the offset from the rest position (root and pelvis only).
- `removeKey(a: { bone: string; time: number; channel?: 'rotation' | 'position' }): number` — Remove the key of a bone at a time (`channel` limits it to `rotation` or `position`). Returns how many were removed.
- `copyKey(a: { from: number; to: number; bone?: string }): number` — Copy the keys at a time to another time: of one bone, or of every bone that has one (a pose). The values are what the clip is at `from` (held keys, or sampled between).
- `mirror(a: { time?: number } = {}): number` — Mirror left and right (partners are found by the `_l` / `_r` ending of the bone name; bones on the middle line are mirrored in place). With `time`, only the pose at that time is mirrored (the keys there); without, the whole clip.
- `ik(a: { chain: [string, string, string]; target: Vec3 | { bone: string; offset?: Vec3 }; pole?: Vec3 | { bone: string; offset?: Vec3 }; time: number; endRotation?: Quat; weight?: number; interp?: Interp }): { error: number; stretched: boolean }` — Set keys by solving a limb to a target at a time: `chain` is [root bone, middle bone, end bone] (shoulder, elbow, hand), `target` a point in the skeleton frame or a point on another bone (`{bone, offset}`, the offset in that bone's frame: a grip on the sword is an offset of the right hand), `pole` the same for the point the elbow or knee bends toward. The chain's three bones get rotation keys at `time`; the end bone keeps its rotation in the world unless `endRotation` (a rotation in the skeleton frame) is given. Returns how far the end is from the target afterwards (a limb too short stretches).
- `hold(a: { time: number; side?: 'r' | 'l'; grip: Grip; position: Vec3; direction: Vec3; roll?: number | 'auto'; both?: boolean; poleMain?: Vec3; poleOff?: Vec3; wrapToward?: Vec3; edge?: Vec3; edgeWeight?: number; interp?: Interp }): ReturnType<typeof holdWeapon>` — Put a weapon in the hands at a time (see `holdWeapon`): the grip's middle at `position`, the blade along `direction`, both hands if the grip has a spacing. The arms, the hands' turn and the fingers get rotation keys at `time`; returns the solve's errors.
- `holdRun(holds: Parameters<ClipEditor['hold']>[0][], o: { loop?: boolean; step?: number } = {}): ReturnType<typeof holdWeapon>[]` — Hold a weapon at many times at once (frames of a move, in any order): the turns of the hands about the blade left as `'auto'` (or absent) are chosen for the whole run together (`holdRolls`: wrists least bent, hands moving least between the times; `loop` joins the last to the first), then each is set as `hold` does. The poses the run is solved on are the clip's at those times before the hands are set. One undo step per time. Returns one result per hold, in the order given.
- `setNotify(a: { name: string; time: number }): void`
- `removeNotify(a: { name: string; time?: number }): number`
- `retime(a: { scale?: number; curve?: [number, number][] }): void` — Change the length: `scale` multiplies every time, or `curve` maps old times to new ones with straight lines between the pairs (first pair 0 -> 0 added if missing).
- `setInfo(a: { duration?: number; loop?: boolean; fps?: number; name?: string }): void`
- `validate(): { ok: boolean; issues: ClipIssue[]; skipped: string[] }` — Checks of the clip: what a hand-made clip gets wrong. Errors are what cannot play; warnings are joints bent past their limit (`limits`), sudden jumps between keys (pops), a loop whose end does not meet its start, and tracks for bones the skeleton lacks. Foot sliding and ground penetration need the bodies' bones in space and are not checked here (`skipped`).

### GroupBackend

*class* · `packages/animation/src/backend.ts:66`

```ts
class GroupBackend
```

Applies a pose request to Babylon animation groups without Babylon's own animation clock: every targeted animation is
sampled at the requested time (`Animation.evaluate`), the samples of one property are blended by weight (vectors and
floats linearly, rotations by normalised lerp) and written to the target. A masked item (a montage on the upper body)
counts only for targets under its bones, and takes its weight from the base clips there. Targets the pose does not
mention keep their value, and a property whose weights sum to less than 1 keeps the rest of its current value.
The groups are plain containers of animations: never started, so they cost nothing between frames.

- `constructor(readonly groups: Record<string, BABYLON.AnimationGroup>, readonly rootMotion?: RootMotionOptions)`
- `apply(pose: Pose): RootDelta` — Apply a pose; returns the root motion the clips made this call (all zero without `rootMotion`).
- `dispose()`

### IkRig

*class* · `packages/animation/src/ik-babylon.ts:83`

```ts
class IkRig
```

IK for one body. Add parts (`limb`, `lookAt`, `footPlacement`), then `attach()` to run it after each frame's animation (or call `update(dt)` yourself).
Parts run in the order: feet, look-at, limbs (so a hand that follows a sword held by an animated hand sees the body as placed).

- `readonly frame: Node`
- `readonly rest: Rest`
- `readonly state: { pelvisDrop: number; footOffsets: number[]; limbError: Record<string, number> }` — what the last update did, for tests and the inspector
- `constructor(readonly scene: BABYLON.Scene, readonly bones: Record<string, Node>, o: IkRigOptions = {})`
- `limb(spec: LimbSpec): this`
- `lookAt(spec: LookAtSpec): this`
- `footPlacement(spec: FootPlacementSpec): this`
- `attach(): this` — run after the scene's animations every frame
- `dispose()`
- `frameT(n: Node): { p: Vec3; q: Quat }` — frame position and rotation of a node, from the local values of it and its parents up to the frame
- `axisOf(bone: string, worldDir: BABYLON.Vector3): Vec3` — a world direction as an axis of a bone's own frame, with the skeleton as it is now (for `lookAt.forward`: build the rig with the body at rest, facing `worldDir`)
- `update(dt: number): void`

### Montage

*class* · `packages/animation/src/graph.ts:104`

```ts
class Montage
```

- `time: number`
- `weight: number`
- `stopping: boolean`
- `finished: boolean`
- `constructor(readonly def: MontageDef, readonly id: number)`

## Functions

### alignFrames

*function* · `packages/animation/src/hold.ts:30`

```ts
function alignFrames(la: Vec3, lb: Vec3, wa: Vec3, wb: Vec3): Quat
```

The rotation that turns the orthonormal frame made of (la, lb) onto the one made of (wa, wb): `la` onto `wa` exactly, `lb` as near to `wb` as it can be.

### applyClipPose

*function* · `packages/animation/src/clip-babylon.ts:128`

```ts
function applyClipPose(bones: Record<string, Node>, rest: Rest, pose: Record<string, { q?: Quat; p?: Vec3 }>): void
```

Put the pose of a clip at a time on a body's nodes (rest where the clip has no key): for scrubbing in a panel, without an animation group.

### bindClips

*function* · `packages/animation/src/character.ts:25`

```ts
function bindClips(scene: BABYLON.Scene, bodyRoot: BABYLON.TransformNode, source: Record<string, BABYLON.AnimationGroup>, map: Record<string, string>, o: BindClipsOptions = {}): BoundClips
```

Puts the clips of a skeleton on a body made of parts: `source` is the animation groups of a loaded clips file (by their names in the file),
`map` says which of them each name of the animation graph is (`{ idle: 'Idle', walk: 'Walk_Fwd' }`), `bodyRoot` is the loaded character.
Every bound clip is a copy of the source targeting the body's bones by name, so one clips file serves any number of bodies.
A character made by tools/ue-export/characters.mjs has the bone names of its clips; a body with other names passes a bone map in `retarget`.

### bonesOf

*function* · `packages/animation/src/clip-babylon.ts:11`

```ts
function bonesOf(root: Node, bones?: Iterable<string>): Record<string, Node>
```

The bones of a model by name: the transform nodes below a root (a body made by the library has them named `<model>/<bone>`).

### buildPuppet

*function* · `packages/animation/src/puppet.ts:48`

```ts
function buildPuppet(scene: BABYLON.Scene, opts: PuppetOptions = {}): Puppet
```

### chain2Pose

*function* · `packages/animation/src/ik.ts:39`

```ts
function chain2Pose(c: Chain2): Chain2Pose
```

### clipFromJson

*function* · `packages/animation/src/clip-babylon.ts:69`

```ts
function clipFromJson(scene: BABYLON.Scene, clip: ClipJson, bones: Record<string, Node>, rest: Rest, o: { name?: string } = {}): BuiltClip
```

Make an AnimationGroup of a clip for a body: one animation per bone that has keys, targeting that bone's node. `bones` are the body's nodes by bone name and
`rest` its rest pose (`restOf`). Bones the body lacks are listed in `missing` and skipped. The group has the clip's name (or `name`) and is not started.

### clipInfo

*function* · `packages/animation/src/backend.ts:4`

```ts
function clipInfo(group: BABYLON.AnimationGroup, opts: { loop?: boolean; notifies?: Notify[] } = {}): ClipInfo
```

The length and frame rate of an AnimationGroup, as a graph clip.

### clipLibrary

*function* · `packages/animation/src/backend.ts:8`

```ts
function clipLibrary(groups: Record<string, BABYLON.AnimationGroup>, extra: Record<string, { loop?: boolean; notifies?: Notify[] }> = {}): ClipLibrary
```

### clipToJson

*function* · `packages/animation/src/clip-babylon.ts:98`

```ts
function clipToJson(group: BABYLON.AnimationGroup, rest: Rest, o: { name?: string; skeleton: string; loop?: boolean; fps?: number; positionBones?: (b: string) => boolean }): { clip: ClipJson; skipped: string[] }
```

The clip file of any AnimationGroup of a body, with the skeleton's `rest` (the library's clips are such groups): every animation of a bone's rotation and
position becomes keys at the animation's own frames, as the change from rest (linear between keys, as Babylon plays them). Tracks of other properties and of
nodes that are not bones are left out and named in `skipped`.

### holdCost

*function* · `packages/animation/src/hold.ts:121`

```ts
function holdCost(a: HoldArgs, r: HoldResult, near = false): number
```

How awkward a hold leaves the arms: the wrists' bend counts in full, the turn of the forearm they carry much less, the elbows and shoulders less; a hand off its
place or a joint past its range costs much more. With `near`, also how far the hands moved from where `a.pose` has them.

### holdRolls

*function* · `packages/animation/src/hold.ts:141`

```ts
function holdRolls(holds: HoldArgs[], o: { step?: number; smooth?: number; loop?: boolean } = {}): number[]
```

The turns of the hands about the blade for a whole run of holds (one per frame of a clip, in time order): the run that is least awkward over all its frames and
whose hands move least between frames (each frame tries every turn in `step` degrees, the best path through them is found at once, then each is refined by a
degree). `loop`: the last frame joins the first. Returns one turn per hold, degrees, to pass as `roll`.

### holdWeapon

*function* · `packages/animation/src/hold.ts:106`

```ts
function holdWeapon(a: HoldArgs): HoldResult
```

Put a weapon in the hands: the grip's middle at `position`, the blade along `direction`, the main hand's frame turned so the weapon sits as its socket places it, the second hand
mirrored on the grip `spacing` toward the pommel, the arms solved to them (two-bone IK on the pose, elbows toward the poles), and the fingers closed round the grip.
The thumb is left as it is (it rests on the grip in the library's hands).

### locomotionGraph

*function* · `packages/animation/src/puppet.ts:165`

```ts
function locomotionGraph(opts: { walkSpeed?: number; runSpeed?: number; points?: { at: number; clip: string }[]; crouch?: boolean; swim?: { at: number; clip: string }[]; swim2d?: { x: number; y: number; clip: string }[] } = {})
```

A ready-made locomotion graph for a puppet (or any character with the same clip names): a blend of idle and gaits by speed, jump, fall,
and with `crouch` a crouch state (the clips `crouch` and `crouchWalk`) entered while the `crouching` parameter is true.
`swim` (blend1d points on the speed, e.g. Swim_Idle and Swim_Fwd) adds a swim state entered while the `swimming` parameter is true (CharacterMovement in a dense medium) and left when it is false.
`swim2d` (blend2d points on `swimX` = m/s to the right and `swimY` = m/s forward, e.g. Swim_Idle at 0,0, Swim_Fwd 0,3, Swim_Bwd 0,-3, Swim_Left -3,0, Swim_Right 3,0) replaces the speed blend of the swim state; the Animator feeds both from the motion source.
`points` replaces the idle/walk/run blend: `[{ at: 0, clip: 'idle' }, { at: 2, clip: 'walk' }, { at: 3.5, clip: 'jog' }, { at: 6, clip: 'sprint' }]`.

### mirrorName

*function* · `packages/animation/src/clip.ts:208`

```ts
function mirrorName(name: string): string | null
```

`upperarm_l` -> `upperarm_r` and back (case kept: `Wing_01_L` -> `Wing_01_R`); null for a bone on the middle line

### mirrorPosition

*function* · `packages/animation/src/clip.ts:227`

```ts
function mirrorPosition(p: Vec3, from: BoneRest, to: BoneRest): Vec3
```

### mirrorRotation

*function* · `packages/animation/src/clip.ts:220`

```ts
function mirrorRotation(q: Quat, from: BoneRest, to: BoneRest): Quat
```

The mirror of a rotation change of a bone as the change of its partner, for a skeleton that is symmetric about the plane x = 0 in its own frame: the change
is taken into the skeleton frame with the bone's rest rotation, reflected (the axis of a rotation keeps its component along the plane's normal and flips the
others), and taken into the partner's frame. A bone on the middle line is its own partner.

### motionClips

*function* · `packages/animation/src/graph.ts:149`

```ts
function motionClips(m: Motion): string[]
```

### poseFk

*function* · `packages/animation/src/clip.ts:145`

```ts
function poseFk(rest: Rest, pose: Record<string, { q?: Quat; p?: Vec3 }>, bone: string): { p: Vec3; q: Quat }
```

The frame position and rotation of a bone in a pose of the clip (the change from rest per bone, as `samplePose` gives), the skeleton frame being the top bone's parent.

### qAngle

*function* · `packages/animation/src/clip.ts:68`

```ts
function qAngle(q: Quat): number
```

the angle of a rotation in degrees, 0 to 180

### qDistance

*function* · `packages/animation/src/clip.ts:70`

```ts
function qDistance: (a: Quat, b: Quat) => number
```

angle between two rotations in degrees

### qFromEuler

*function* · `packages/animation/src/clip.ts:93`

```ts
function qFromEuler(deg: Vec3): Quat
```

Euler angles in degrees, rotating about x, then y, then z of the parent frame's axes taken in the XYZ order of three.js (q = qx * qy * qz).

### qIdentity

*function* · `packages/animation/src/clip.ts:55`

```ts
function qIdentity: () => Quat
```

### qInv

*function* · `packages/animation/src/clip.ts:64`

```ts
function qInv: (q: Quat) => Quat
```

### qMul

*function* · `packages/animation/src/clip.ts:56`

```ts
function qMul(a: Quat, b: Quat): Quat
```

### qNorm

*function* · `packages/animation/src/clip.ts:65`

```ts
function qNorm(q: Quat): Quat
```

### qRotate

*function* · `packages/animation/src/clip.ts:66`

```ts
function qRotate(q: Quat, v: Vec3): Vec3
```

### qSlerp

*function* · `packages/animation/src/clip.ts:84`

```ts
function qSlerp(a: Quat, b: Quat, t: number): Quat
```

### qToEuler

*function* · `packages/animation/src/clip.ts:98`

```ts
function qToEuler(q: Quat): Vec3
```

### restOf

*function* · `packages/animation/src/clip-babylon.ts:25`

```ts
function restOf(bones: Record<string, Node>): Rest
```

The rest pose of a skeleton as the editor wants it: local position and rotation of every bone, and the rest rotations in the skeleton's frame (every parent
multiplied in; the loader's mirror above the skeleton is not part of it). Read from the nodes as they are: call it before any clip has played, or with the
skeleton returned to rest.

### retargetGroup

*function* · `packages/animation/src/retarget.ts:25`

```ts
function retargetGroup(scene: BABYLON.Scene, source: BABYLON.AnimationGroup, targetRoot: BABYLON.TransformNode, opts: RetargetOptions = {}): RetargetResult
```

Copy an animation group from one skeleton onto another with different bone names, proportions and rest pose.
Targets are found by name below `targetRoot`. Rotations keep their change from the rest pose
(target = targetRest * inverse(sourceRest) * source); positions are scaled.

### samplePose

*function* · `packages/animation/src/clip.ts:133`

```ts
function samplePose(clip: ClipJson, t: number): Record<string, { q?: Quat; p?: Vec3 }>
```

A pose of the clip at a time: per bone the change from rest. Bones without keys are not in it.

### samplePosition

*function* · `packages/animation/src/clip.ts:124`

```ts
function samplePosition(keys: PosKey[], t: number): Vec3
```

### sampleRotation

*function* · `packages/animation/src/clip.ts:118`

```ts
function sampleRotation(keys: RotKey[], t: number): Quat
```

The rotation key track at a time (held before the first and after the last key).

### solveLookAt

*function* · `packages/animation/src/ik.ts:107`

```ts
function solveLookAt(bones: LookBone[], forward: Vec3, toward: Vec3, o: { maxAngle?: number; weight?: number } = {}): Quat[]
```

Turn a chain of bones (root-ward first, the head last) so the axis `forward` of the last bone (in its own frame) points along `toward`, within `maxAngle` degrees
of where it points now. Every bone takes its share of the turn; the last one takes what is left so the whole comes out exact. Parents' rotations are taken from
`parentQ` of the first bone and the bones above each other.

### solveTwoBone

*function* · `packages/animation/src/ik.ts:61`

```ts
function solveTwoBone(c: Chain2, target: Vec3, o: TwoBoneOptions = {}): TwoBoneResult
```

Solve a two-bone chain so its end is at `target` (law of cosines), bending toward `pole`. The bone lengths are kept.

### swing

*function* · `packages/animation/src/ik.ts:15`

```ts
function swing(a: Vec3, b: Vec3): Quat
```

The shortest rotation taking direction `a` to direction `b` (any lengths).

### swingTwist

*function* · `packages/animation/src/clip.ts:72`

```ts
function swingTwist(q: Quat, axis: Vec3): { swing: number; twist: number; twistQ: Quat }
```

Split a rotation into a turn about `axis` (twist, signed degrees) and the rest (swing, degrees): q = swing * twist.

### twistAxis

*function* · `packages/animation/src/clip.ts:83`

```ts
function twistAxis(rest: Rest, bone: string): Vec3
```

The axis a bone twists about, in its own frame: the line from its parent's joint to its own (its rest offset seen from itself).

### validateClipJson

*function* · `packages/animation/src/clip.ts:165`

```ts
function validateClipJson(clip: unknown): ClipIssue[]
```

The problems of a clip file (JSON path and message). Empty when it can be played.

### validateGraphDef

*function* · `packages/animation/src/graph.ts:161`

```ts
function validateGraphDef(def: unknown): { path: string; message: string }[]
```

Check a graph definition without any clips: the initial state exists, transitions join existing states, every condition names a
declared parameter of the right kind, motions have clips and sensible numbers. Returns the problems with their paths (relative to
the graph); an empty list means `new AnimGraph` will accept it as long as the clips exist.

## Interfaces

### AnimatorParams

*interface* · `packages/animation/src/animator.ts:10`

```ts
interface AnimatorParams
```

- `graph: GraphDef`
- `groups: Record<string, BABYLON.AnimationGroup>` — one AnimationGroup per clip name used by the graph
- `notifies?: Record<string, Notify[]>` — notifies per clip, and clips that do not loop (default: all loop)
- `loops?: Record<string, boolean>`
- `fromMovement?: boolean` — Feed `speed`, `verticalSpeed`, `grounded`, `crouching` from the entity's motion source (a component with `motionState()`: CharacterMovement, NavAgent) and the `jump` trigger from `character:jump` (default true)
- `rootMotion?: RootMotionOptions & { apply?: 'node' | 'none' }` — Take the movement the clips author on a bone off the skeleton (see `RootMotionOptions`). Each frame it is reported as `Animator.rootDelta` and the `anim:rootmotion` event { entity, x, y, z, yaw } in the entity's own space. `apply: 'node'` also moves and turns the entity's node by it (for entities nothing else drives: a prop, a cutscene actor); the default `'none'` leaves that to the game, e.g. to feed a character controller.

### BindClipsOptions

*interface* · `packages/animation/src/character.ts:3`

```ts
interface BindClipsOptions
```

- `retarget?: RetargetOptions` — `retargetGroup` options (the bones are matched by name; `restRotation` re-bases the rotations when the two rest poses differ)
- `oneShot?: string[]` — clip names (the keys of `map`) that do not loop (default: all loop)

### BoneRest

*interface* · `packages/animation/src/clip.ts:40`

```ts
interface BoneRest
```

What the editor must know about one bone of the skeleton: its rest pose (local), and the rest rotations in the skeleton frame for mirroring.

- `p: Vec3`
- `q: Quat`
- `wq?: Quat` — the bone's rest rotation in the skeleton's frame (all parents multiplied in); needed to mirror left to right
- `pwq?: Quat` — the same for its parent (identity at the root)
- `parent?: string` — the parent bone's name (absent at the top of the skeleton); needed to work in space (ik)

### BoundClips

*interface* · `packages/animation/src/character.ts:10`

```ts
interface BoundClips
```

- `groups: Record<string, BABYLON.AnimationGroup>` — one AnimationGroup per graph clip name, targeting this body's bones: what `Animator` takes as `groups`
- `loops: Record<string, boolean>`
- `missingClips: string[]` — graph clip names whose source clip does not exist, and the source bones without a bone on the body (per clip, once)
- `missingBones: string[]`

### BuiltClip

*interface* · `packages/animation/src/clip-babylon.ts:63`

```ts
interface BuiltClip
```

- `group: BABYLON.AnimationGroup`
- `info: ClipInfo`
- `missing: string[]`

### Chain2

*interface* · `packages/animation/src/ik.ts:28`

```ts
interface Chain2
```

A two-bone chain a -> b -> c: the local rotations and positions of the three bones, and the rotation of a's parent in the frame the target is given in.

- `pa: Quat` — world (frame) rotation of the parent of `a`, and the frame position of `a`
- `posA: Vec3`
- `qa: Quat`
- `pb: Vec3` — local position of b in a, and of c in b
- `pc: Vec3`
- `qb: Quat`
- `qc: Quat`

### Chain2Pose

*interface* · `packages/animation/src/ik.ts:37`

```ts
interface Chain2Pose
```

- `A: Vec3`
- `B: Vec3`
- `C: Vec3`
- `wa: Quat`
- `wb: Quat`
- `wc: Quat`

### ClipBone

*interface* · `packages/animation/src/clip.ts:17`

```ts
interface ClipBone
```

- `rotation?: RotKey[]`
- `position?: PosKey[]`

### ClipEditorOptions

*interface* · `packages/animation/src/clip.ts:236`

```ts
interface ClipEditorOptions
```

- `rest: Rest`
- `positionBones?: (bone: string) => boolean` — which bones may carry position keys (default: the root and the pelvis)
- `library?: (name: string) => ClipJson | undefined` — a clip of the library by name, for `base` (its keys are copied)
- `limits?: [RegExp, number][]` — largest change from rest, in degrees, per bone matcher; the first match counts (default: a table for a human)
- `twistLimits?: [RegExp, number][]` — bones whose turn about their own length is checked apart (degrees): for these `limits` holds the bend (the swing) and this the twist; the default: the hands, which turn with the forearm (from a T-pose, palm down, a forearm turns some 170 degrees, a wrist bends no more than 90)

### ClipInfo

*interface* · `packages/animation/src/graph.ts:7`

```ts
interface ClipInfo
```

- `duration: number`
- `loop?: boolean`
- `notifies?: Notify[]`

### ClipIssue

*interface* · `packages/animation/src/clip.ts:52`

```ts
interface ClipIssue
```

- `level: 'error' | 'warning'`
- `path: string`
- `message: string`

### ClipJson

*interface* · `packages/animation/src/clip.ts:20`

```ts
interface ClipJson
```

- `format: 1`
- `name: string`
- `skeleton: string` — skeleton id of the library (`gw-68`, `viking-73`, `dragon-62`)
- `duration: number` — seconds
- `loop?: boolean`
- `fps?: number` — frame rate the clip is played and sampled at when it becomes an animation group (default 30)
- `base?: string` — the library clip this one was made from (its keys were copied in; informational)
- `additive?: boolean` — an additive clip (UE's additive animations): its keys are the change itself (rotation from identity, position from zero), to be put on top of another pose, not relative to rest
- `bones: Record<string, ClipBone>`
- `notifies?: ClipNotify[]`

### ClipNotify

*interface* · `packages/animation/src/clip.ts:18`

```ts
interface ClipNotify
```

- `name: string`
- `time: number`

### FootPlacementSpec

*interface* · `packages/animation/src/ik-babylon.ts:55`

```ts
interface FootPlacementSpec
```

- `feet: FootSpec[]`
- `pelvis?: string` — the bone that carries the body and is lowered when a foot finds the ground lower (default `pelvis`)
- `isGround: (mesh: BABYLON.AbstractMesh) => boolean` — which meshes are ground
- `probeUp?: number` — how far above the foot the probe starts and how far below it ends, in metres (default 0.6 and 1.0)
- `probeDown?: number`
- `smooth?: number` — how quickly the offsets follow the ground, 1/s (default 14)
- `maxDrop?: number` — the largest the body is lowered, in metres (default 0.45)
- `tilt?: number` — tilt the foot to the ground normal, up to this many degrees (default 25; 0 leaves it)
- `weight?: Live<number>`

### FootSpec

*interface* · `packages/animation/src/ik-babylon.ts:51`

```ts
interface FootSpec
```

- `chain: [string, string, string]` — [thigh, calf, foot]

### GraphDef

*interface* · `packages/animation/src/graph.ts:65`

```ts
interface GraphDef
```

- `params?: Record<string, 'float' | 'bool' | 'trigger'>`
- `states: Record<string, StateDef>`
- `initial: string`
- `transitions?: TransitionDef[]`
- `seed?: number` — seed of the random players, so a run can be repeated (default: not seeded)

### GraphEvents

*interface* · `packages/animation/src/graph.ts:97`

```ts
interface GraphEvents
```

- `notify?(name: string, clip: string): void`
- `stateEnter?(state: string): void`
- `stateExit?(state: string): void`
- `montageEnd?(handle: Montage): void`

### Grip

*interface* · `packages/animation/src/hold.ts:18`

```ts
interface Grip
```

A grip of a weapon in the frame of the bone that holds it (the socket's bone): `point` is the middle of the grip, `axis` runs along it toward the blade.

- `point: Vec3`
- `axis: Vec3`
- `radius: number` — radius of the grip, metres
- `spacing?: number` — distance from the hand on the grip to the second hand, toward the pommel (metres; 0 or absent: one hand)
- `edge?: Vec3` — for a blade: the way its edge faces, across `axis` (a two-edged blade cuts along it either way)

### HoldArgs

*interface* · `packages/animation/src/hold.ts:49`

```ts
interface HoldArgs
```

- `rest: Rest`
- `pose: Pose` — the pose the clip has at this time (the other bones; the held hands and fingers are replaced)
- `side: 'r' | 'l'` — the hand that holds the weapon: its bone is `hand_<side>`
- `grip: Grip`
- `position: Vec3` — where the middle of the grip (the main hand) goes, in the skeleton frame
- `direction: Vec3` — where the blade points
- `roll?: number | 'auto'` — turn of the hands about the blade, degrees (0: the fingers wrap toward the holder's left for a right hand); `'auto'`: the turn that bends the wrists and forearms least and moves the hands least from where `pose` has them (searched all round; a clip made frame by frame has the previous frame's hands there, so it stays smooth)
- `both?: boolean` — hold with both hands (needs `grip.spacing`; default: when the grip has a spacing)
- `poleMain?: Vec3` — points the elbows bend toward, in the skeleton frame; default: down and out, a little back
- `poleOff?: Vec3`
- `names?: { upper?: string; lower?: string; hand?: string; twist?: string; finger?: (finger: string, joint: number, side: string) => string }` — names, default `upperarm_<side>`, `lowerarm_<side>`, `hand_<side>`
- `elbows?: 'auto' | 'fixed'` — where the elbows go when no pole is given: `'auto'` (default) round the shoulder-wrist line where the wrists and upper arms turn least; `'fixed'`: down, out to the side and a little back
- `hinge?: boolean` — keep the elbows hinges (default true): the forearm bends about one axis only and the hand carries the forearm's turn
- `wrapToward?: Vec3` — a direction in the skeleton frame the fingers wrap toward before `roll` (default: to the left of the holder, -x for a right hand)
- `edge?: Vec3` — for a blade with `grip.edge`: the way the edge should lead (the way the blade moves; skeleton frame), and how much that counts against the arms' comfort when the turn is chosen (`roll: 'auto'`, `holdRolls`; default 1, 0: not at all). A cut gives the blade's motion with a weight that grows with its speed.
- `edgeWeight?: number`

### HoldResult

*interface* · `packages/animation/src/hold.ts:80`

```ts
interface HoldResult
```

- `rotations: Record<string, Quat>` — keys to set: bone -> rotation change from rest (quaternion)
- `error: { main: number; off?: number }` — how far each hand's solve is from its place (metres), and whether the arm had to stretch
- `stretched: { main: boolean; off?: boolean }`
- `roll: number` — the turn of the hands about the blade used, degrees (the one chosen with `roll: 'auto'`)
- `edgeOff?: number` — with `edge`: how far the blade's edge (either one) is from leading, degrees

### IkRigOptions

*interface* · `packages/animation/src/ik-babylon.ts:72`

```ts
interface IkRigOptions
```

- `frame?: Node` — the node that holds the skeleton: the parent of the `root` bone (default found by name)
- `rest?: Rest` — the rest pose of the bodies skeleton (default: read from the nodes now, so build the rig before any clip has played)

### LimbSpec

*interface* · `packages/animation/src/ik-babylon.ts:21`

```ts
interface LimbSpec
```

- `name: string`
- `chain: [string, string, string]` — [root bone, middle bone, end bone] by name: shoulder, elbow, hand / thigh, calf, foot
- `target: () => BABYLON.Vector3 | null` — where the end goes, in the world; null: the limb is left as animated this frame
- `pole?: () => BABYLON.Vector3 | null` — the point the elbow or knee bends toward, in the world (default: the way the animation bends it)
- `weight?: Live<number>` — 0 to 1 (default 1)
- `fade?: number` — seconds to fade the weight in and out (default 0.1)
- `maxStretch?: number` — how far past the limb's full length the target may be before the limb is let go back to the animation (a fraction of the length; the weight falls to 0 over the next 0.15). Default: never let go, the limb stretches toward the target.

### LookAtSpec

*interface* · `packages/animation/src/ik-babylon.ts:37`

```ts
interface LookAtSpec
```

- `bones: { bone: string; share: number }[]` — root-ward bone first, head last, with the share of the turn each takes (spine 0.2, neck 0.3, head 0.5)
- `forward: Vec3` — the head's axis that looks forward, in the head bone's own frame (the glTF/UE mannequins look along +Z... measure with `forwardOf`)
- `target: () => BABYLON.Vector3 | null` — what to look at, in the world; null: look as animated
- `maxAngle?: number` — how far the head may leave where the animation looks, degrees (default 70)
- `weight?: Live<number>`
- `smooth?: number` — how quickly the look follows, 1/s (default 8)

### LookBone

*interface* · `packages/animation/src/ik.ts:94`

```ts
interface LookBone
```

- `parentQ: Quat` — world (frame) rotation of this bone's parent
- `q: Quat` — local rotation
- `share: number` — share of the turn this bone takes, 0 to 1 (shares are normalised)

### MontageDef

*interface* · `packages/animation/src/graph.ts:74`

```ts
interface MontageDef
```

- `clip: string`
- `blendIn?: number`
- `blendOut?: number`
- `rate?: number`
- `loop?: boolean`
- `mask?: string[]` — only these bones (and everything below them) are animated; the rest keeps the base pose
- `additive?: boolean | { reference?: number }` — Add the clip's change from a reference pose on top of the result instead of replacing it (breathing, leaning, a flinch over any locomotion). `reference` is the time in seconds of the clip's own reference pose (default 0, its first frame). The weight scales the change; an additive montage never takes weight from the base. Combines with `mask` and `loop`.

### MotionSource

*interface* · `packages/animation/src/animator.ts:6`

```ts
interface MotionSource
```

Anything that moves an entity and can say how: CharacterMovement (players, NPCs on the capsule) and NavAgent (crowd).

- `motionState(): { velocity: { x: number; y: number; z: number }; grounded: boolean; crouching?: boolean; swimming?: boolean }`

### Notify

*interface* · `packages/animation/src/graph.ts:5`

```ts
interface Notify
```

- `time: number`
- `name: string`

### Pose

*interface* · `packages/animation/src/graph.ts:92`

```ts
interface Pose
```

- `items: PoseItem[]` — the weights of the items without `mask` or `additive` sum to 1; a masked item blends over the base on its bones only; an additive item adds its change from the reference time on top of that

### PoseItem

*interface* · `packages/animation/src/graph.ts:91`

```ts
interface PoseItem
```

- `clip: string`
- `time: number`
- `weight: number`
- `mask?: string[]`
- `additive?: { reference: number }`

### PosKey

*interface* · `packages/animation/src/clip.ts:16`

```ts
interface PosKey
```

- `t: number`
- `p: Vec3`
- `i?: Interp`

### Puppet

*interface* · `packages/animation/src/puppet.ts:18`

```ts
interface Puppet
```

- `root: BABYLON.TransformNode`
- `mesh: BABYLON.Mesh`
- `skeleton: BABYLON.Skeleton`
- `bones: Record<string, BABYLON.TransformNode>`
- `groups: Record<string, BABYLON.AnimationGroup>`
- `notifies: Record<string, Notify[]>` — notifies authored with the clips (footsteps, take-off)
- `loops: Record<string, boolean>`

### PuppetOptions

*interface* · `packages/animation/src/puppet.ts:8`

```ts
interface PuppetOptions
```

A procedural skinned character with a skeleton and a set of clips: the stand-in for a character exported from Unreal
(a GLB with a skeleton and animations) in samples and tests. Bones are TransformNodes linked to a Babylon Skeleton, the way
the glTF loader makes them, and the clips are AnimationGroups that target those nodes.

- `scale?: number` — overall size factor (1 = 1.8 m tall)
- `armRest?: number` — angle of the arms from straight down at rest, radians (a T-pose or A-pose authoring difference)
- `prefix?: string` — bone name prefix, to tell two puppets in one scene apart
- `color?: [number, number, number]`

### RandomEntry

*interface* · `packages/animation/src/graph.ts:23`

```ts
interface RandomEntry
```

- `clip: string`
- `weight?: number` — chance to be picked relative to the others (default 1)
- `loops?: [number, number]` — how many times the clip loops before the next pick: [min, max] (default [1, 1])
- `rate?: [number, number]` — playback rate range: [min, max] (default [1, 1])
- `blendIn?: number` — seconds to cross-fade from the previous entry (default 0.2)

### RetargetOptions

*interface* · `packages/animation/src/retarget.ts:1`

```ts
interface RetargetOptions
```

- `map?: Record<string, string> | ((source: string) => string | null)` — source bone name -> target bone name; a function, a table, or nothing when the names are equal after `stripPrefix`
- `stripPrefix?: string` — removed from the front of the source names (and `addPrefix` put on the target names) before the lookup
- `addPrefix?: string`
- `positionScale?: number` — position tracks are multiplied by this (the target is taller or shorter than the source)
- `restRotation?: boolean` — rotation tracks are re-based from the source rest rotation to the target one (different T-/A-poses)
- `name?: string`

### RetargetResult

*interface* · `packages/animation/src/retarget.ts:14`

```ts
interface RetargetResult
```

- `group: BABYLON.AnimationGroup`
- `missing: string[]` — source bones that have an animation but no target bone

### RootDelta

*interface* · `packages/animation/src/backend.ts:56`

```ts
interface RootDelta
```

What the clips moved the root bone by during one `apply`, in the bone's parent space (the entity's own space for a skeleton under it).

- `x: number`
- `y: number`
- `z: number`
- `yaw: number`

### RootMotionOptions

*interface* · `packages/animation/src/backend.ts:46`

```ts
interface RootMotionOptions
```

Root motion: the movement a clip authors on one bone (usually the root or hips) is taken off the skeleton and handed to the game, so the
character's body moves by what the animation says (a dodge roll, a lunge, a climb) instead of the skeleton sliding away from its entity.

- `bone: string` — name of the bone whose position track (and yaw) carries the motion
- `axes?: ('x' | 'y' | 'z')[]` — position axes taken off the bone and reported (default x and z: the bone keeps its own height bob)
- `yaw?: boolean` — also take the bone's turn about the vertical axis (default true)

### RotKey

*interface* · `packages/animation/src/clip.ts:15`

```ts
interface RotKey
```

- `t: number`
- `q: Quat`
- `i?: Interp`

### StateDef

*interface* · `packages/animation/src/graph.ts:46`

```ts
interface StateDef
```

- `motion: Motion`
- `speed?: number` — playback rate (1 = as authored)
- `loop?: boolean` — override the loop flag of the clips: a state that plays once and holds the last pose

### TransitionDef

*interface* · `packages/animation/src/graph.ts:54`

```ts
interface TransitionDef
```

- `from: string | '*'`
- `to: string`
- `when?: Condition[]` — all must hold
- `duration?: number` — cross-fade seconds
- `interruptible?: boolean` — may start while the state is still fading in (default true)

### TwoBoneOptions

*interface* · `packages/animation/src/ik.ts:44`

```ts
interface TwoBoneOptions
```

- `pole?: Vec3` — a point the knee or elbow bends toward (default: the way it bends now)
- `weight?: number` — 0 to 1: how much of the solved pose is used (default 1)
- `endRotation?: Quat` — a world (frame) rotation for the end bone (the hand turned onto a grip, the foot onto the ground); default: it keeps its world rotation

### TwoBoneResult

*interface* · `packages/animation/src/ik.ts:52`

```ts
interface TwoBoneResult
```

- `qa: Quat`
- `qb: Quat`
- `qc: Quat`
- `stretched: boolean` — the chain was too short to reach: it is stretched straight toward the target
- `error: number` — distance of the end bone from the target after the solve

## Types

### ClipLibrary

*type* · `packages/animation/src/graph.ts:13`

```ts
type ClipLibrary = Record<string, ClipInfo>
```

### Condition

*type* · `packages/animation/src/graph.ts:35`

```ts
type Condition = | { param: string; op: '>' | '<' | '>=' | '<=' | '==' | '!='; value: number } | { param: string; is: boolean } | { trigger: string } /** the state has played at least this many seconds */ | { stateTime: number } /** a non-looping state has reached its end */ | { finished: true } /** less than this fraction of the state's clip is left to play (Unreal's TimeRemaining (ratio) < value) */ | { remaining: number }
```

### Interp

*type* · `packages/animation/src/clip.ts:12`

```ts
type Interp = 'step' | 'linear' | 'smooth'
```

### Motion

*type* · `packages/animation/src/graph.ts:16`

```ts
type Motion = | { clip: string } | { blend1d: { param: string; points: { at: number; clip: string }[] } } | { blend2d: { x: string; y: string; points: { x: number; y: number; clip: string }[] } } /** plays one entry for a random number of loops, then cross-fades to another (Unreal's Random Player) */ | { random: { entries: RandomEntry[] } }
```

### Quat

*type* · `packages/animation/src/clip.ts:11`

```ts
type Quat = [number, number, number, number]
```

### Rest

*type* · `packages/animation/src/clip.ts:50`

```ts
type Rest = Record<string, BoneRest>
```

### Vec3

*type* · `packages/animation/src/clip.ts:10`

```ts
type Vec3 = [number, number, number]
```

## Constants

### DEFAULT_LIMITS

*const* · `packages/animation/src/clip.ts:249`

```ts
const DEFAULT_LIMITS: [RegExp, number][]
```

### DEFAULT_TWIST_LIMITS

*const* · `packages/animation/src/clip.ts:253`

```ts
const DEFAULT_TWIST_LIMITS: [RegExp, number][]
```

### INTERPS

*const* · `packages/animation/src/clip.ts:13`

```ts
const INTERPS: readonly Interp[]
```

