animouse
Version:
lightweight animation state machine for three js
99 lines (98 loc) • 4.36 kB
TypeScript
import type { AnimationAction } from "three";
import { AnimationTree } from "./AnimationTree";
/**
* Configuration for a linear animation action in the blend tree.
* Associates an animation action with a position value on the linear blend axis.
*/
export interface LinearAction {
/** The animation action to be played */
action: AnimationAction;
/** Position value on the linear blend axis where this action is positioned */
value: number;
}
/**
* Linear blend tree implementation for 1D animation blending.
*
* Manages a collection of animation actions positioned along a linear axis,
* automatically blending between adjacent animations based on a blend value.
* The blend tree interpolates weights between the two closest animations
* to create smooth transitions across the linear space.
*
* Note: Action values are not limited to the 0-1 range. You can use any
* numeric values, including negative values, that make sense for your
* application (e.g., speed in m/s, or any custom metric). However, all
* values must be finite numbers within JavaScript's safe range and must
* be unique (no duplicate values allowed).
*
* @example
* ```typescript
* const idleAction = mixer.clipAction(idleClip);
* const walkAction = mixer.clipAction(walkClip);
* const runAction = mixer.clipAction(runClip);
*
* const blendTree = new LinearBlendTree([
* { action: idleAction, value: 0 },
* { action: walkAction, value: 0.5 },
* { action: runAction, value: 1 }
* ]);
*
* // Set blend to 0.3 - results in:
* // idleAction weight: 0.4 (40%)
* // walkAction weight: 0.6 (60%)
* // runAction weight: 0.0 (0%)
* blendTree.setBlend(0.3);
* ```
*/
export declare class LinearBlendTree extends AnimationTree {
private readonly anchors;
private lastLeftAnchor?;
private lastRightAnchor?;
private currentBlend;
/**
* Creates a new linear blend tree with the specified animation actions.
* Actions are automatically sorted by their value along the linear axis.
* Initializes all actions to stopped state and validates clip durations.
*
* @param linearActions - Array of linear actions defining the blend space.
* Must contain at least 2 actions with unique, finite values.
* @throws {Error} When fewer than 2 actions are provided
* @throws {Error} When any action has a non-finite value (NaN, ±Infinity)
* @throws {Error} When any action has a value outside JavaScript's safe integer range
* @throws {Error} When multiple actions have the same value (duplicate values)
* @throws {Error} When any animation clip duration is not a positive finite number
* @see {@link assertValidNumber} for value validation details
* @see {@link assertValidPositiveNumber} for duration validation details
*/
constructor(linearActions: LinearAction[]);
get blendValue(): number;
/**
* Sets the blend value to determine animation weights along the linear axis.
* When the blend changes, animation weights are recalculated to interpolate
* between the two closest actions. Values outside the action range are
* handled by giving full weight to the nearest boundary action.
*
* @param value - The target blend value (finite number)
* @throws {Error} When the blend value is not a finite number
* @see {@link assertValidNumber} for value validation details
*/
setBlend(value: number): void;
protected ["onEnterInternal"](): void;
/**
* Updates the influence for all anchors in the linear blend tree.
* Called when the tree's influence changes but relative weights remain the same.
* Applies the current tree influence to all anchors while maintaining
* their existing weight distribution from the linear blending.
*/
protected updateAnchorsInfluence(): void;
/**
* Recalculates and updates animation weights based on the current blend value.
* Performs linear interpolation between the two actions closest to the blend point.
* Actions outside the interpolation range receive zero weight.
*
* The interpolation uses the formula:
* - Left weight = 1 - difference
* - Right weight = difference
* Where difference = (blend - leftValue) / (rightValue - leftValue)
*/
private updateAnchors;
}