Просмотр исходного кода

Docs: More JSDoc. (#30624)

* Docs: More JSDoc.

* AnimationUtils: Fix `if`.
Michael Herzog 1 год назад
Родитель
Сommit
ba08cab76a

+ 262 - 30
src/animation/AnimationAction.js

@@ -1,13 +1,31 @@
 import { WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, LoopPingPong, LoopOnce, LoopRepeat, NormalAnimationBlendMode, AdditiveAnimationBlendMode } from '../constants.js';
 
-
+/**
+ * An instance of `AnimationAction` schedules the playback of an animation which is
+ * stored in {@link AnimationClip}.
+ */
 class AnimationAction {
 
+	/**
+	 * Constructs a new animation action.
+	 *
+	 * @param {AnimationMixer} mixer - The mixer that is controlled by this action.
+	 * @param {AnimationClip} clip - The animation clip that holds the actual keyframes.
+	 * @param {?Object3D} [localRoot=null] - The root object on which this action is performed.
+	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode] - The blend mode.
+	 */
 	constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
 
 		this._mixer = mixer;
 		this._clip = clip;
 		this._localRoot = localRoot;
+
+		/**
+		 * Defines how the animation is blended/combined when two or more animations
+		 * are simultaneously played.
+		 *
+		 * @type {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)}
+		 */
 		this.blendMode = blendMode;
 
 		const tracks = clip.tracks,
@@ -40,6 +58,12 @@ class AnimationAction {
 		this._timeScaleInterpolant = null;
 		this._weightInterpolant = null;
 
+		/**
+		 * The loop mode, set via {@link AnimationAction#setLoop}.
+		 *
+		 * @type {(LoopRepeat|LoopOnce|LoopPingPong)}
+		 * @default LoopRepeat
+		 */
 		this.loop = LoopRepeat;
 		this._loopCount = - 1;
 
@@ -47,30 +71,107 @@ class AnimationAction {
 		// it's set back to 'null' upon start of the action
 		this._startTime = null;
 
-		// scaled local time of the action
-		// gets clamped or wrapped to 0..clip.duration according to loop
+		/**
+		 * The local time of this action (in seconds, starting with `0`).
+		 *
+		 * The value gets clamped or wrapped to `[0,clip.duration]` (according to the
+		 * loop state).
+		 *
+		 * @type {number}
+		 * @default Infinity
+		 */
 		this.time = 0;
 
+		/**
+		 * Scaling factor for the {@link AnimationAction#time}. A value of `0` causes the
+		 * animation to pause. Negative values cause the animation to play backwards.
+		 *
+		 * @type {number}
+		 * @default 1
+		 */
 		this.timeScale = 1;
 		this._effectiveTimeScale = 1;
 
+		/**
+		 * The degree of influence of this action (in the interval `[0, 1]`). Values
+		 * between `0` (no impact) and `1` (full impact) can be used to blend between
+		 * several actions.
+		 *
+		 * @type {number}
+		 * @default 1
+		 */
 		this.weight = 1;
 		this._effectiveWeight = 1;
 
-		this.repetitions = Infinity; // no. of repetitions when looping
-
-		this.paused = false; // true -> zero effective time scale
-		this.enabled = true; // false -> zero effective weight
+		/**
+		 * The number of repetitions of the performed clip over the course of this action.
+		 * Can be set via {@link AnimationAction#setLoop}.
+		 *
+		 * Setting this number has no effect if {@link AnimationAction#loop} is set to
+		 * `THREE:LoopOnce`.
+		 *
+		 * @type {number}
+		 * @default Infinity
+		 */
+		this.repetitions = Infinity;
+
+		/**
+		 * If set to `true`, the playback of the action is paused.
+		 *
+		 * @type {boolean}
+		 * @default false
+		 */
+		this.paused = false;
 
-		this.clampWhenFinished = false;// keep feeding the last frame?
+		/**
+		 * If set to `false`, the action is disabeled so it has no impact.
+		 *
+		 * When the action is re-enabled, the animation continues from its current
+		 * time (setting `enabled` to `false` doesn't reset the action).
+		 *
+		 * @type {boolean}
+		 * @default true
+		 */
+		this.enabled = true;
 
-		this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
-		this.zeroSlopeAtEnd = true;// clips for start, loop and end
+		/**
+		 * If set to true the animation will automatically be paused on its last frame.
+		 *
+		 * If set to false, {@link AnimationAction#enabled} will automatically be switched
+		 * to `false` when the last loop of the action has finished, so that this action has
+		 * no further impact.
+		 *
+		 * Note: This member has no impact if the action is interrupted (it
+		 * has only an effect if its last loop has really finished).
+		 *
+		 * @type {boolean}
+		 * @default false
+		 */
+		this.clampWhenFinished = false;
+
+		/**
+		 * Enables smooth interpolation without separate clips for start, loop and end.
+		 *
+		 * @type {boolean}
+		 * @default true
+		 */
+		this.zeroSlopeAtStart = true;
+
+		/**
+		 * Enables smooth interpolation without separate clips for start, loop and end.
+		 *
+		 * @type {boolean}
+		 * @default true
+		 */
+		this.zeroSlopeAtEnd = true;
 
 	}
 
-	// State & Scheduling
-
+	/**
+	 * Starts the playback of the animation.
+	 *
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	play() {
 
 		this._mixer._activateAction( this );
@@ -79,6 +180,11 @@ class AnimationAction {
 
 	}
 
+	/**
+	 * Stops the playback of the animation.
+	 *
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	stop() {
 
 		this._mixer._deactivateAction( this );
@@ -87,6 +193,11 @@ class AnimationAction {
 
 	}
 
+	/**
+	 * Resets the playback of the animation.
+	 *
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	reset() {
 
 		this.paused = false;
@@ -100,6 +211,11 @@ class AnimationAction {
 
 	}
 
+	/**
+	 * Returns `true` if the animation is running.
+	 *
+	 * @return {boolean} Whether the animation is running or not.
+	 */
 	isRunning() {
 
 		return this.enabled && ! this.paused && this.timeScale !== 0 &&
@@ -107,13 +223,23 @@ class AnimationAction {
 
 	}
 
-	// return true when play has been called
+	/**
+	 * Returns `true` when {@link AnimationAction#play} has been called.
+	 *
+	 * @return {boolean} Whether the animation is scheduled or not.
+	 */
 	isScheduled() {
 
 		return this._mixer._isActiveAction( this );
 
 	}
 
+	/**
+	 * Defines the time when the animation should start.
+	 *
+	 * @param {number} time - The start time in seconds.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	startAt( time ) {
 
 		this._startTime = time;
@@ -122,6 +248,13 @@ class AnimationAction {
 
 	}
 
+	/**
+	 * Configures the loop settings for this action.
+	 *
+	 * @param {(LoopRepeat|LoopOnce|LoopPingPong)} mode - The loop mode.
+	 * @param {number} repetitions - The number of repetitions.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	setLoop( mode, repetitions ) {
 
 		this.loop = mode;
@@ -131,11 +264,15 @@ class AnimationAction {
 
 	}
 
-	// Weight
-
-	// set the weight stopping any scheduled fading
-	// although .enabled = false yields an effective weight of zero, this
-	// method does *not* change .enabled, because it would be confusing
+	/**
+	 * Sets the effective weight of this action.
+	 *
+	 * An action has no effect and thus an effective weight of zero when the
+	 * action is disabled.
+	 *
+	 * @param {number} weight - The weight to set.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	setEffectiveWeight( weight ) {
 
 		this.weight = weight;
@@ -147,31 +284,58 @@ class AnimationAction {
 
 	}
 
-	// return the weight considering fading and .enabled
+	/**
+	 * Returns the effective weight of this action.
+	 *
+	 * @return {number} The effective weight.
+	 */
 	getEffectiveWeight() {
 
 		return this._effectiveWeight;
 
 	}
 
+	/**
+	 * Fades the animation in by increasing its weight gradually from `0` to `1`,
+	 * within the passed time interval.
+	 *
+	 * @param {number} duration - The duration of the fade.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	fadeIn( duration ) {
 
 		return this._scheduleFading( duration, 0, 1 );
 
 	}
 
+	/**
+	 * Fades the animation out by decreasing its weight gradually from `1` to `0`,
+	 * within the passed time interval.
+	 *
+	 * @param {number} duration - The duration of the fade.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	fadeOut( duration ) {
 
 		return this._scheduleFading( duration, 1, 0 );
 
 	}
 
-	crossFadeFrom( fadeOutAction, duration, warp ) {
+	/**
+	 * Causes this action to fade in and the given action to fade out,
+	 * within the passed time interval.
+	 *
+	 * @param {AnimationAction} fadeOutAction - The animation action to fade out.
+	 * @param {number} duration - The duration of the fade.
+	 * @param {boolean} [warp=false] - Whether warping should be used or not.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
+	crossFadeFrom( fadeOutAction, duration, warp = false ) {
 
 		fadeOutAction.fadeOut( duration );
 		this.fadeIn( duration );
 
-		if ( warp ) {
+		if ( warp === true ) {
 
 			const fadeInDuration = this._clip.duration,
 				fadeOutDuration = fadeOutAction._clip.duration,
@@ -188,12 +352,26 @@ class AnimationAction {
 
 	}
 
-	crossFadeTo( fadeInAction, duration, warp ) {
+	/**
+	 * Causes this action to fade out and the given action to fade in,
+	 * within the passed time interval.
+	 *
+	 * @param {AnimationAction} fadeInAction - The animation action to fade in.
+	 * @param {number} duration - The duration of the fade.
+	 * @param {boolean} [warp=false] - Whether warping should be used or not.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
+	crossFadeTo( fadeInAction, duration, warp = false ) {
 
 		return fadeInAction.crossFadeFrom( this, duration, warp );
 
 	}
 
+	/**
+	 * Stops any fading which is applied to this action.
+	 *
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	stopFading() {
 
 		const weightInterpolant = this._weightInterpolant;
@@ -209,11 +387,15 @@ class AnimationAction {
 
 	}
 
-	// Time Scale Control
-
-	// set the time scale stopping any scheduled warping
-	// although .paused = true yields an effective time scale of zero, this
-	// method does *not* change .paused, because it would be confusing
+	/**
+	 * Sets the effective time scale of this action.
+	 *
+	 * An action has no effect and thus an effective time scale of zero when the
+	 * action is paused.
+	 *
+	 * @param {number} timeScale - The time scale to set.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	setEffectiveTimeScale( timeScale ) {
 
 		this.timeScale = timeScale;
@@ -223,13 +405,23 @@ class AnimationAction {
 
 	}
 
-	// return the time scale considering warping and .paused
+	/**
+	 * Returns the effective time scale of this action.
+	 *
+	 * @return {number} The effective time scale.
+	 */
 	getEffectiveTimeScale() {
 
 		return this._effectiveTimeScale;
 
 	}
 
+	/**
+	 * Sets the duration for a single loop of this action.
+	 *
+	 * @param {number} duration - The duration to set.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	setDuration( duration ) {
 
 		this.timeScale = this._clip.duration / duration;
@@ -238,6 +430,12 @@ class AnimationAction {
 
 	}
 
+	/**
+	 * Synchronizes this action with the passed other action.
+	 *
+	 * @param {AnimationAction} action - The action to sync with.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	syncWith( action ) {
 
 		this.time = action.time;
@@ -247,12 +445,28 @@ class AnimationAction {
 
 	}
 
+	/**
+	 * Decelerates this animation's speed to `0` within the passed time interval.
+	 *
+	 * @param {number} duration - The duration.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	halt( duration ) {
 
 		return this.warp( this._effectiveTimeScale, 0, duration );
 
 	}
 
+	/**
+	 * Changes the playback speed, within the passed time interval, by modifying
+	 * {@link AnimationAction#timeScale} gradually from `startTimeScale` to
+	 * `endTimeScale`.
+	 *
+	 * @param {number} startTimeScale - The start time scale.
+	 * @param {number} endTimeScale - The end time scale.
+	 * @param {number} duration - The duration.
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	warp( startTimeScale, endTimeScale, duration ) {
 
 		const mixer = this._mixer,
@@ -281,6 +495,11 @@ class AnimationAction {
 
 	}
 
+	/**
+	 * Stops any scheduled warping which is applied to this action.
+	 *
+	 * @return {AnimationAction} A reference to this animation action.
+	 */
 	stopWarping() {
 
 		const timeScaleInterpolant = this._timeScaleInterpolant;
@@ -296,20 +515,33 @@ class AnimationAction {
 
 	}
 
-	// Object Accessors
-
+	/**
+	 * Returns the animation mixer of this animation action.
+	 *
+	 * @return {AnimationMixer} The animation mixer.
+	 */
 	getMixer() {
 
 		return this._mixer;
 
 	}
 
+	/**
+	 * Returns the animation clip of this animation action.
+	 *
+	 * @return {AnimationClip} The animation clip.
+	 */
 	getClip() {
 
 		return this._clip;
 
 	}
 
+	/**
+	 * Returns the root object of this animation action.
+	 *
+	 * @return {Object3D} The root object.
+	 */
 	getRoot() {
 
 		return this._localRoot || this._mixer._root;

+ 138 - 2
src/animation/AnimationClip.js

@@ -9,15 +9,62 @@ import { VectorKeyframeTrack } from './tracks/VectorKeyframeTrack.js';
 import { generateUUID } from '../math/MathUtils.js';
 import { NormalAnimationBlendMode } from '../constants.js';
 
+/**
+ * A reusable set of keyframe tracks which represent an animation.
+ */
 class AnimationClip {
 
+	/**
+	 * Constructs a new animation clip.
+	 *
+	 * Note: Instead of instantiating an AnimationClip directly with the constructor, you can
+	 * use the static interface of this class for creating clips. In most cases though, animation clips
+	 * will automatically be created by loaders when importing animated 3D assets.
+	 *
+	 * @param {string} [name=''] - The clip's name.
+	 * @param {number} [duration=-1] - The clip's duration in seconds. If a negative value is passed,
+	 * the duration will be calculated from the passed keyframes.
+	 * @param {Array<KeyframeTrack>} tracks - An array of keyframe tracks.
+	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode=NormalAnimationBlendMode] - Defines how the animation
+	 * is blended/combined when two or more animations are simultaneously played.
+	 */
 	constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) {
 
+		/**
+		 * The clip's name.
+		 *
+		 * @type {string}
+		 */
 		this.name = name;
+
+		/**
+		 *  An array of keyframe tracks.
+		 *
+		 * @type {Array<KeyframeTrack>}
+		 */
 		this.tracks = tracks;
+
+		/**
+		 * The clip's duration in seconds.
+		 *
+		 * @type {number}
+		 */
 		this.duration = duration;
+
+		/**
+		 * Defines how the animation is blended/combined when two or more animations
+		 * are simultaneously played.
+		 *
+		 * @type {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)}
+		 */
 		this.blendMode = blendMode;
 
+		/**
+		 * The UUID of the animation clip.
+		 *
+		 * @type {string}
+		 * @readonly
+		 */
 		this.uuid = generateUUID();
 
 		// this means it should figure out its duration by scanning the tracks
@@ -29,7 +76,13 @@ class AnimationClip {
 
 	}
 
-
+	/**
+	 * Factory method for creating an animation clip from the given JSON.
+	 *
+	 * @static
+	 * @param {Object} json - The serialized animation clip.
+	 * @return {AnimationClip} The new animation clip.
+	 */
 	static parse( json ) {
 
 		const tracks = [],
@@ -49,6 +102,13 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Serializes the given animation clip into JSON.
+	 *
+	 * @static
+	 * @param {AnimationClip} clip - The animation clip to serialize.
+	 * @return {Object} The JSON object.
+	 */
 	static toJSON( clip ) {
 
 		const tracks = [],
@@ -74,6 +134,20 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Returns a new animation clip from the passed morph targets array of a
+	 * geometry, taking a name and the number of frames per second.
+	 *
+	 * Note: The fps parameter is required, but the animation speed can be
+	 * overridden via {@link AnimationAction#setDuration}.
+	 *
+	 * @static
+	 * @param {string} name - The name of the animation clip.
+	 * @param {Array<Object>} morphTargetSequence - A sequence of morph targets.
+	 * @param {number} fps - The Frames-Per-Second value.
+	 * @param {boolean} noLoop - Whether the clip should be no loop or not.
+	 * @return {AnimationClip} The new animation clip.
+	 */
 	static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {
 
 		const numMorphTargets = morphTargetSequence.length;
@@ -116,6 +190,16 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Searches for an animation clip by name, taking as its first parameter
+	 * either an array of clips, or a mesh or geometry that contains an
+	 * array named "animations" property.
+	 *
+	 * @static
+	 * @param {(Array<AnimationClip>|Object3D)} objectOrClipArray - The array or object to search through.
+	 * @param {string} name - The name to search for.
+	 * @return {?AnimationClip} The found animation clip. Returns `null` if no clip has been found.
+	 */
 	static findByName( objectOrClipArray, name ) {
 
 		let clipArray = objectOrClipArray;
@@ -141,6 +225,19 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Returns an array of new AnimationClips created from the morph target
+	 * sequences of a geometry, trying to sort morph target names into
+	 * animation-group-based patterns like "Walk_001, Walk_002, Run_001, Run_002...".
+	 *
+	 * See {@link MD2Loader#parse} as an example for how the method should be used.
+	 *
+	 * @static
+	 * @param {Array<Object>} morphTargets - A sequence of morph targets.
+	 * @param {number} fps - The Frames-Per-Second value.
+	 * @param {boolean} noLoop - Whether the clip should be no loop or not.
+	 * @return {Array<AnimationClip>} An array of new animation clips.
+	 */
 	static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {
 
 		const animationToMorphTargets = {};
@@ -186,7 +283,14 @@ class AnimationClip {
 
 	}
 
-	// parse the animation.hierarchy format
+	/**
+	 * Parses the `animation.hierarchy` format and returns a new animation clip.
+	 *
+	 * @static
+	 * @param {Object} animation - A serialized animation clip as JSON.
+	 * @param {Array<Bones>} bones - An array of bones.
+	 * @return {AnimationClip} The new animation clip.
+	 */
 	static parseAnimation( animation, bones ) {
 
 		if ( ! animation ) {
@@ -314,6 +418,11 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Sets the duration of this clip to the duration of its longest keyframe track.
+	 *
+	 * @return {AnimationClip} A reference to this animation clip.
+	 */
 	resetDuration() {
 
 		const tracks = this.tracks;
@@ -333,6 +442,11 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Trims all tracks to the clip's duration.
+	 *
+	 * @return {AnimationClip} A reference to this animation clip.
+	 */
 	trim() {
 
 		for ( let i = 0; i < this.tracks.length; i ++ ) {
@@ -345,6 +459,12 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Performs minimal validation on each track in the clip. Returns `true` if all
+	 * tracks are valid.
+	 *
+	 * @return {boolean} Whether the clip's keyframes are valid or not.
+	 */
 	validate() {
 
 		let valid = true;
@@ -359,6 +479,12 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Optimizes each track by removing equivalent sequential keys (which are
+	 * common in morph target sequences).
+	 *
+	 * @return {AnimationClip} A reference to this animation clip.
+	 */
 	optimize() {
 
 		for ( let i = 0; i < this.tracks.length; i ++ ) {
@@ -371,6 +497,11 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Returns a new animation clip with copied values from this instance.
+	 *
+	 * @return {AnimationClip} A clone of this instance.
+	 */
 	clone() {
 
 		const tracks = [];
@@ -385,6 +516,11 @@ class AnimationClip {
 
 	}
 
+	/**
+	 * Serializes this animation clip into JSON.
+	 *
+	 * @return {Object} The JSON object.
+	 */
 	toJSON() {
 
 		return this.constructor.toJSON( this );

+ 99 - 15
src/animation/AnimationMixer.js

@@ -6,12 +6,20 @@ import { PropertyMixer } from './PropertyMixer.js';
 import { AnimationClip } from './AnimationClip.js';
 import { NormalAnimationBlendMode } from '../constants.js';
 
-
 const _controlInterpolantsResultBuffer = new Float32Array( 1 );
 
-
+/**
+ * `AnimationMixer` is a player for animations on a particular object in
+ * the scene. When multiple objects in the scene are animated independently,
+ * one `AnimationMixer` may be used for each object.
+ */
 class AnimationMixer extends EventDispatcher {
 
+	/**
+	 * Constructs a new animation mixer.
+	 *
+	 * @param {Object3D} root - The object whose animations shall be played by this mixer.
+	 */
 	constructor( root ) {
 
 		super();
@@ -19,7 +27,25 @@ class AnimationMixer extends EventDispatcher {
 		this._root = root;
 		this._initMemoryManager();
 		this._accuIndex = 0;
+
+		/**
+		 * The global mixer time (in seconds; starting with `0` on the mixer's creation).
+		 *
+		 * @type {number}
+		 * @default 0
+		 */
 		this.time = 0;
+
+		/**
+		 * A scaling factor for the global time.
+		 *
+		 * Note: Setting this member to `0` and later back to `1` is a
+		 * possibility to pause/unpause all actions that are controlled by this
+		 * mixer.
+		 *
+		 * @type {number}
+		 * @default 1
+		 */
 		this.timeScale = 1.0;
 
 	}
@@ -510,9 +536,18 @@ class AnimationMixer extends EventDispatcher {
 
 	}
 
-	// return an action for a clip optionally using a custom root target
-	// object (this method allocates a lot of dynamic memory in case a
-	// previously unknown clip/root combination is specified)
+	/**
+	 * Returns an instance of {@link AnimationAction} for the passed clip.
+	 *
+	 * If an action fitting the clip and root parameters doesn't yet exist, it
+	 * will be created by this method. Calling this method several times with the
+	 * same clip and root parameters always returns the same action.
+	 *
+	 * @param {AnimationClip|string} clip - An animaion clip or alternatively the name of the animation clip.
+	 * @param {Object3D} [optionalRoot] - An alternative root object.
+	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode] - The blend mode.
+	 * @return {AnimationAction} The animation action.
+	 */
 	clipAction( clip, optionalRoot, blendMode ) {
 
 		const root = optionalRoot || this._root,
@@ -574,7 +609,13 @@ class AnimationMixer extends EventDispatcher {
 
 	}
 
-	// get an existing action
+	/**
+	 * Returns an existing animation action for the passed clip.
+	 *
+	 * @param {AnimationClip|string} clip - An animaion clip or alternatively the name of the animation clip.
+	 * @param {Object3D} [optionalRoot] - An alternative root object.
+	 * @return {?AnimationAction} The animation action. Returns `null` if no action was found.
+	 */
 	existingAction( clip, optionalRoot ) {
 
 		const root = optionalRoot || this._root,
@@ -597,7 +638,11 @@ class AnimationMixer extends EventDispatcher {
 
 	}
 
-	// deactivates all previously scheduled actions
+	/**
+	 * Deactivates all previously scheduled actions on this mixer.
+	 *
+	 * @return {AnimationMixer} A reference to thi animation mixer.
+	 */
 	stopAllAction() {
 
 		const actions = this._actions,
@@ -613,7 +658,15 @@ class AnimationMixer extends EventDispatcher {
 
 	}
 
-	// advance the time and update apply the animation
+	/**
+	 * Advances the global mixer time and updates the animation.
+	 *
+	 * This is usually done in the render loop by passing the delta
+	 * time from {@link Clock} or {@link Timer}.
+	 *
+	 * @param {number} deltaTime - The delta time in seconds.
+	 * @return {AnimationMixer} A reference to thi animation mixer.
+	 */
 	update( deltaTime ) {
 
 		deltaTime *= this.timeScale;
@@ -651,8 +704,16 @@ class AnimationMixer extends EventDispatcher {
 
 	}
 
-	// Allows you to seek to a specific time in an animation.
-	setTime( timeInSeconds ) {
+	/**
+	 * Sets the global mixer to a specific time and updates the animation accordingly.
+	 *
+	 * This is useful when you need to jump to an exact time in an animation. The
+	 * input parameter will be scaled by {@link AnimationMixer#timeScale}
+	 *
+	 * @param {number} time - The time to set in seconds.
+	 * @return {AnimationMixer} A reference to thi animation mixer.
+	 */
+	setTime( time ) {
 
 		this.time = 0; // Zero out time attribute for AnimationMixer object;
 		for ( let i = 0; i < this._actions.length; i ++ ) {
@@ -661,18 +722,27 @@ class AnimationMixer extends EventDispatcher {
 
 		}
 
-		return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
+		return this.update( time ); // Update used to set exact time. Returns "this" AnimationMixer object.
 
 	}
 
-	// return this mixer's root target object
+	/**
+	 * Returns this mixer's root object.
+	 *
+	 * @return {Object3D} The mixer's root object.
+	 */
 	getRoot() {
 
 		return this._root;
 
 	}
 
-	// free all resources specific to a particular clip
+	/**
+	 * Deallocates all memory resources for a clip. Before using this method make
+	 * sure to call {@link AnimationAction#stop} for all related actions.
+	 *
+	 * @param {AnimationClip} clip - The clip to uncache.
+	 */
 	uncacheClip( clip ) {
 
 		const actions = this._actions,
@@ -714,7 +784,14 @@ class AnimationMixer extends EventDispatcher {
 
 	}
 
-	// free all resources specific to a particular root target object
+	/**
+	 * Deallocates all memory resources for a root object. Before using this
+	 * method make sure to call {@link AnimationAction#stop} for all related
+	 * actions or alternatively {@link AnimationMixer#stopAllAction} when the
+	 * mixer operates on a single root.
+	 *
+	 * @param {Object3D} root - The root object to uncache.
+	 */
 	uncacheRoot( root ) {
 
 		const rootUuid = root.uuid,
@@ -751,7 +828,14 @@ class AnimationMixer extends EventDispatcher {
 
 	}
 
-	// remove a targeted clip from the cache
+	/**
+	 * Deallocates all memory resources for an action. The action is identified by the
+	 * given clip and an optional root object. Before using this method make
+	 * sure to call {@link AnimationAction#stop} to deactivate the action.
+	 *
+	 * @param {AnimationClip|string} clip - An animaion clip or alternatively the name of the animation clip.
+	 * @param {Object3D} [optionalRoot] - An alternative root object.
+	 */
 	uncacheAction( clip, optionalRoot ) {
 
 		const action = this.existingAction( clip, optionalRoot );

+ 41 - 18
src/animation/AnimationObjectGroup.js

@@ -2,40 +2,49 @@ import { PropertyBinding } from './PropertyBinding.js';
 import { generateUUID } from '../math/MathUtils.js';
 
 /**
- *
  * A group of objects that receives a shared animation state.
  *
  * Usage:
  *
- *  - Add objects you would otherwise pass as 'root' to the
- *    constructor or the .clipAction method of AnimationMixer.
- *
- *  - Instead pass this object as 'root'.
- *
- *  - You can also add and remove objects later when the mixer
- *    is running.
+ * - Add objects you would otherwise pass as 'root' to the
+ * constructor or the .clipAction method of AnimationMixer.
+ * - Instead pass this object as 'root'.
+ * - You can also add and remove objects later when the mixer is running.
  *
  * Note:
  *
- *    Objects of this class appear as one object to the mixer,
- *    so cache control of the individual objects must be done
- *    on the group.
+ * - Objects of this class appear as one object to the mixer,
+ * so cache control of the individual objects must be done on the group.
  *
  * Limitation:
  *
- *  - The animated properties must be compatible among the
- *    all objects in the group.
- *
- *  - A single property can either be controlled through a
- *    target group or directly, but not both.
+ * - The animated properties must be compatible among the all objects in the group.
+ * - A single property can either be controlled through a target group or directly, but not both.
  */
-
 class AnimationObjectGroup {
 
+	/**
+	 * Constructs a new animation group.
+	 *
+	 * @param {...Object3D} arguments - An arbitrary number of 3D objects that share the same animation state.
+	 */
 	constructor() {
 
+		/**
+		 * This flag can be used for type testing.
+		 *
+		 * @type {boolean}
+		 * @readonly
+		 * @default true
+		 */
 		this.isAnimationObjectGroup = true;
 
+		/**
+		 * The UUID of the 3D object.
+		 *
+		 * @type {string}
+		 * @readonly
+		 */
 		this.uuid = generateUUID();
 
 		// cached objects followed by the active ones
@@ -84,6 +93,11 @@ class AnimationObjectGroup {
 
 	}
 
+	/**
+	 * Adds an arbitrary number of objects to this animation group.
+	 *
+	 * @param {...Object3D} arguments - The 3D objects to add.
+	 */
 	add() {
 
 		const objects = this._objects,
@@ -172,6 +186,11 @@ class AnimationObjectGroup {
 
 	}
 
+	/**
+	 * Removes an arbitrary number of objects to this animation group
+	 *
+	 * @param {...Object3D} arguments - The 3D objects to remove.
+	 */
 	remove() {
 
 		const objects = this._objects,
@@ -221,7 +240,11 @@ class AnimationObjectGroup {
 
 	}
 
-	// remove & forget
+	/**
+	 * Deallocates all memory resources for the passed 3D objects of this animation group.
+	 *
+	 * @param {...Object3D} arguments - The 3D objects to uncache.
+	 */
 	uncache() {
 
 		const objects = this._objects,

+ 168 - 18
src/animation/AnimationUtils.js

@@ -1,11 +1,16 @@
 import { Quaternion } from '../math/Quaternion.js';
 import { AdditiveAnimationBlendMode } from '../constants.js';
 
-// converts an array to a specific type
-function convertArray( array, type, forceClone ) {
+/**
+ * Converts an array to a specific type.
+ *
+ * @param {TypedArray|Array} array - The array to convert.
+ * @param {TypedArray.constructor} type - The constructor of a typed array that defines the new type.
+ * @return {TypedArray} The converted array.
+ */
+function convertArray( array, type ) {
 
-	if ( ! array || // let 'undefined' and 'null' pass
-		! forceClone && array.constructor === type ) return array;
+	if ( ! array || array.constructor === type ) return array;
 
 	if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
 
@@ -17,14 +22,24 @@ function convertArray( array, type, forceClone ) {
 
 }
 
+/**
+ * Returns `true` if the given object is a typed array.
+ *
+ * @param {any} object - The object to check.
+ * @return {boolean} Whether the given object is a typed array.
+ */
 function isTypedArray( object ) {
 
-	return ArrayBuffer.isView( object ) &&
-		! ( object instanceof DataView );
+	return ArrayBuffer.isView( object ) && ! ( object instanceof DataView );
 
 }
 
-// returns an array by which times and values can be sorted
+/**
+ * Returns an array by which times and values can be sorted.
+ *
+ * @param {Array<number>} times - The keyframe time values.
+ * @return {Array<number>} The array.
+ */
 function getKeyframeOrder( times ) {
 
 	function compareTime( i, j ) {
@@ -43,7 +58,14 @@ function getKeyframeOrder( times ) {
 
 }
 
-// uses the array previously returned by 'getKeyframeOrder' to sort data
+/**
+ * Sorts the given array by the previously computed order via `getKeyframeOrder()`.
+ *
+ * @param {Array<number>} values - The values to sort.
+ * @param {number} stride - The stride.
+ * @param {Array<number>} order - The sort order.
+ * @return {Array<number>} The sorted values.
+ */
 function sortedArray( values, stride, order ) {
 
 	const nValues = values.length;
@@ -65,7 +87,14 @@ function sortedArray( values, stride, order ) {
 
 }
 
-// function for parsing AOS keyframe formats
+/**
+ * Used for parsing AOS keyframe formats.
+ *
+ * @param {Array<number>} jsonKeys - A list of JSON keyframes.
+ * @param {Array<number>} times - This array will be filled with keyframe times by this function.
+ * @param {Array<number>} values - This array will be filled with keyframe values by this function.
+ * @param {Object<string, any>} valuePropertyName - A dictionary assigning values to property names.
+ */
 function flattenJSON( jsonKeys, times, values, valuePropertyName ) {
 
 	let i = 1, key = jsonKeys[ 0 ];
@@ -140,6 +169,16 @@ function flattenJSON( jsonKeys, times, values, valuePropertyName ) {
 
 }
 
+/**
+ * Creates a new clip, containing only the segment of the original clip between the given frames.
+ *
+ * @param {AnimationClip} sourceClip - The values to sort.
+ * @param {string} name - The name of the clip.
+ * @param {number} startFrame - The start frame.
+ * @param {number} endFrame - The end frame.
+ * @param {number} [fps=30] - The FPS.
+ * @return {AnimationClip} The new sub clip.
+ */
 function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
 
 	const clip = sourceClip.clone();
@@ -211,6 +250,15 @@ function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
 
 }
 
+/**
+ * Converts the keyframes of the given animation clip to an additive format.
+ *
+ * @param {AnimationClip} targetClip - The clip to make additive.
+ * @param {number} [referenceFrame=0] - The reference frame.
+ * @param {AnimationClip} [referenceClip=targetClip] - The reference clip.
+ * @param {number} [fps=30] - The FPS.
+ * @return {AnimationClip} The updated clip which is now additive.
+ */
 function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
 
 	if ( fps <= 0 ) fps = 30;
@@ -334,15 +382,117 @@ function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targe
 
 }
 
-const AnimationUtils = {
-	convertArray: convertArray,
-	isTypedArray: isTypedArray,
-	getKeyframeOrder: getKeyframeOrder,
-	sortedArray: sortedArray,
-	flattenJSON: flattenJSON,
-	subclip: subclip,
-	makeClipAdditive: makeClipAdditive
-};
+/**
+ * A class with various methods to assist with animations.
+ *
+ * @hideconstructor
+ */
+class AnimationUtils {
+
+	/**
+	 * Converts an array to a specific type
+	 *
+	 * @static
+	 * @param {TypedArray|Array} array - The array to convert.
+	 * @param {TypedArray.constructor} type - The constructor of a type array.
+	 * @return {TypedArray} The converted array
+	 */
+	static convertArray( array, type ) {
+
+		return convertArray( array, type );
+
+	}
+
+	/**
+	 * Returns `true` if the given object is a typed array.
+	 *
+	 * @static
+	 * @param {any} object - The object to check.
+	 * @return {boolean} Whether the given object is a typed array.
+	 */
+	static isTypedArray( object ) {
+
+		return isTypedArray( object );
+
+	}
+
+	/**
+	 * Returns an array by which times and values can be sorted.
+	 *
+	 * @static
+	 * @param {Array<number>} times - The keyframe time values.
+	 * @return {Array<number>} The array.
+	 */
+	static getKeyframeOrder( times ) {
+
+		return getKeyframeOrder( times );
+
+	}
+
+	/**
+	 * Sorts the given array by the previously computed order via `getKeyframeOrder()`.
+	 *
+	 * @static
+	 * @param {Array<number>} values - The values to sort.
+	 * @param {number} stride - The stride.
+	 * @param {Array<number>} order - The sort order.
+	 * @return {Array<number>} The sorted values.
+	 */
+	static sortedArray( values, stride, order ) {
+
+		return sortedArray( values, stride, order );
+
+	}
+
+	/**
+	 * Used for parsing AOS keyframe formats.
+	 *
+	 * @static
+	 * @param {Array<number>} jsonKeys - A list of JSON keyframes.
+	 * @param {Array<number>} times - This array will be filled with keyframe times by this method.
+	 * @param {Array<number>} values - This array will be filled with keyframe values by this method.
+	 * @param {Object<string, any>} valuePropertyName - A dictionary assigning values to property names.
+	 */
+	static flattenJSON( jsonKeys, times, values, valuePropertyName ) {
+
+		flattenJSON( jsonKeys, times, values, valuePropertyName );
+
+	}
+
+	/**
+	 * Creates a new clip, containing only the segment of the original clip between the given frames.
+	 *
+	 * @static
+	 * @param {AnimationClip} sourceClip - The values to sort.
+	 * @param {string} name - The name of the clip.
+	 * @param {number} startFrame - The start frame.
+	 * @param {number} endFrame - The end frame.
+	 * @param {number} [fps=30] - The FPS.
+	 * @return {AnimationClip} The new sub clip.
+	 */
+	static subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
+
+		return subclip( sourceClip, name, startFrame, endFrame, fps );
+
+	}
+
+	/**
+	 * Converts the keyframes of the given animation clip to an additive format.
+	 *
+	 * @static
+	 * @param {AnimationClip} targetClip - The clip to make additive.
+	 * @param {number} [referenceFrame=0] - The reference frame.
+	 * @param {AnimationClip} [referenceClip=targetClip] - The reference clip.
+	 * @param {number} [fps=30] - The FPS.
+	 * @return {AnimationClip} The updated clip which is now additive.
+	 */
+	static makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
+
+		return makeClipAdditive( targetClip, referenceFrame, referenceClip, fps );
+
+	}
+
+}
 
 export {
 	convertArray,

+ 144 - 10
src/animation/KeyframeTrack.js

@@ -8,25 +8,60 @@ import { LinearInterpolant } from '../math/interpolants/LinearInterpolant.js';
 import { DiscreteInterpolant } from '../math/interpolants/DiscreteInterpolant.js';
 import * as AnimationUtils from './AnimationUtils.js';
 
+/**
+ * Represents s a timed sequence of keyframes, which are composed of lists of
+ * times and related values, and which are used to animate a specific property
+ * of an object.
+ */
 class KeyframeTrack {
 
+	/**
+	 * Constructs a new keyframe track.
+	 *
+	 * @param {string} name - The keyframe track's name.
+	 * @param {Array<number>} times - A list of keyframe times.
+	 * @param {Array<number>} values - A list of keyframe values.
+	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
+	 */
 	constructor( name, times, values, interpolation ) {
 
 		if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
 		if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
 
+		/**
+		 * The track's name can refer to morph targets or bones or
+		 * possibly other values within an animated object. See {@link PropertyBinding#parseTrackName}
+		 * for the forms of strings that can be parsed for property binding.
+		 *
+		 * @type {string}
+		 */
 		this.name = name;
 
+		/**
+		 * The keyframe times.
+		 *
+		 * @type {Float32Array}
+		 */
 		this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
+
+		/**
+		 * The keyframe values.
+		 *
+		 * @type {Float32Array}
+		 */
 		this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
 
 		this.setInterpolation( interpolation || this.DefaultInterpolation );
 
 	}
 
-	// Serialization (in static context, because of constructor invocation
-	// and automatic invocation of .toJSON):
-
+	/**
+	 * Converts the keyframe track to JSON.
+	 *
+	 * @static
+	 * @param {KeyframeTrack} track - The keyframe track to serialize.
+	 * @return {Object} The serialized keyframe track as JSON.
+	 */
 	static toJSON( track ) {
 
 		const trackType = track.constructor;
@@ -65,24 +100,51 @@ class KeyframeTrack {
 
 	}
 
+	/**
+	 * Factory method for creating a new discrete interpolant.
+	 *
+	 * @static
+	 * @param {TypedArray} [result] - The result buffer.
+	 * @return {DiscreteInterpolant} The new interpolant.
+	 */
 	InterpolantFactoryMethodDiscrete( result ) {
 
 		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
 
 	}
 
+	/**
+	 * Factory method for creating a new linear interpolant.
+	 *
+	 * @static
+	 * @param {TypedArray} [result] - The result buffer.
+	 * @return {LinearInterpolant} The new interpolant.
+	 */
 	InterpolantFactoryMethodLinear( result ) {
 
 		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
 
 	}
 
+	/**
+	 * Factory method for creating a new smooth interpolant.
+	 *
+	 * @static
+	 * @param {TypedArray} [result] - The result buffer.
+	 * @return {CubicInterpolant} The new interpolant.
+	 */
 	InterpolantFactoryMethodSmooth( result ) {
 
 		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
 
 	}
 
+	/**
+	 * Defines the interpolation factor method for this keyframe track.
+	 *
+	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} interpolation - The interpolation type.
+	 * @return {KeyframeTrack} A reference to this keyframe track.
+	 */
 	setInterpolation( interpolation ) {
 
 		let factoryMethod;
@@ -140,6 +202,11 @@ class KeyframeTrack {
 
 	}
 
+	/**
+	 * Returns the current interpolation type.
+	 *
+	 * @return {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} The interpolation type.
+	 */
 	getInterpolation() {
 
 		switch ( this.createInterpolant ) {
@@ -160,13 +227,23 @@ class KeyframeTrack {
 
 	}
 
+	/**
+	 * Returns the value size.
+	 *
+	 * @return {number} The value size.
+	 */
 	getValueSize() {
 
 		return this.values.length / this.times.length;
 
 	}
 
-	// move all keyframes either forwards or backwards in time
+	/**
+	 * Moves all keyframes either forward or backward in time.
+	 *
+	 * @param {number} timeOffset - The offset to move the time values.
+	 * @return {KeyframeTrack} A reference to this keyframe track.
+	 */
 	shift( timeOffset ) {
 
 		if ( timeOffset !== 0.0 ) {
@@ -185,7 +262,12 @@ class KeyframeTrack {
 
 	}
 
-	// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
+	/**
+	 * Scale all keyframe times by a factor (useful for frame - seconds conversions).
+	 *
+	 * @param {number} timeScale - The time scale.
+	 * @return {KeyframeTrack} A reference to this keyframe track.
+	 */
 	scale( timeScale ) {
 
 		if ( timeScale !== 1.0 ) {
@@ -204,8 +286,16 @@ class KeyframeTrack {
 
 	}
 
-	// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
-	// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
+	/**
+	 * Removes keyframes before and after animation without changing any values within the defined time range.
+	 *
+	 * Note: The method does not shift around keys to the start of the track time, because for interpolated
+	 * keys this will change their values
+	 *
+	 * @param {number} startTime - The start time.
+	 * @param {number} endTime - The end time.
+	 * @return {KeyframeTrack} A reference to this keyframe track.
+	 */
 	trim( startTime, endTime ) {
 
 		const times = this.times,
@@ -248,7 +338,12 @@ class KeyframeTrack {
 
 	}
 
-	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
+	/**
+	 * Performs minimal validation on the keyframe track. Returns `true` if the values
+	 * are valid.
+	 *
+	 * @return {boolean} Whether the keyframes are valid or not.
+	 */
 	validate() {
 
 		let valid = true;
@@ -325,10 +420,16 @@ class KeyframeTrack {
 
 	}
 
-	// removes equivalent sequential keys as common in morph target sequences
-	// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
+	/**
+	 * Optimizes this keyframe track by removing equivalent sequential keys (which are
+	 * common in morph target sequences).
+	 *
+	 * @return {AnimationClip} A reference to this animation clip.
+	 */
 	optimize() {
 
+		// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
+
 		// times or values may be shared with other tracks, so overwriting is unsafe
 		const times = this.times.slice(),
 			values = this.values.slice(),
@@ -438,6 +539,11 @@ class KeyframeTrack {
 
 	}
 
+	/**
+	 * Returns a new keyframe track with copied values from this instance.
+	 *
+	 * @return {KeyframeTrack} A clone of this instance.
+	 */
 	clone() {
 
 		const times = this.times.slice();
@@ -455,8 +561,36 @@ class KeyframeTrack {
 
 }
 
+/**
+ * The value type name.
+ *
+ * @type {String}
+ * @default ''
+ */
+KeyframeTrack.prototype.ValueTypeName = '';
+
+/**
+ * The time buffer type of this keyframe track.
+ *
+ * @type {TypedArray|Array}
+ * @default Float32Array.constructor
+ */
 KeyframeTrack.prototype.TimeBufferType = Float32Array;
+
+/**
+ * The value buffer type of this keyframe track.
+ *
+ * @type {TypedArray|Array}
+ * @default Float32Array.constructor
+ */
 KeyframeTrack.prototype.ValueBufferType = Float32Array;
+
+/**
+ * The default interpolation type of this keyframe track.
+ *
+ * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
+ * @default InterpolateLinear
+ */
 KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
 
 export { KeyframeTrack };

+ 77 - 3
src/animation/PropertyBinding.js

@@ -100,15 +100,48 @@ class Composite {
 // prototype version of these methods with one that represents
 // the bound state. When the property is not found, the methods
 // become no-ops.
+
+
+/**
+ * This holds a reference to a real property in the scene graph; used internally.
+ */
 class PropertyBinding {
 
+	/**
+	 * Constructs a new property binding.
+	 *
+	 * @param {Object} rootNode - The root node.
+	 * @param {string} path - The path.
+	 * @param {?Object} [parsedPath] - The parsed path.
+	 */
 	constructor( rootNode, path, parsedPath ) {
 
+		/**
+		 * The object path to the animated property.
+		 *
+		 * @type {PropertyBinding}
+		 */
 		this.path = path;
+
+		/**
+		 * An object holding information about the path.
+		 *
+		 * @type {Object}
+		 */
 		this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
 
+		/**
+		 * The object owns the animated property.
+		 *
+		 * @type {Object}
+		 */
 		this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName );
 
+		/**
+		 * The root node.
+		 *
+		 * @type {Object3D|Skeleton}
+		 */
 		this.rootNode = rootNode;
 
 		// initial state of these methods that calls 'bind'
@@ -118,6 +151,15 @@ class PropertyBinding {
 	}
 
 
+	/**
+	 * Factory method for creating a property binding from the given parameters.
+	 *
+	 * @static
+	 * @param {Object} root - The root node.
+	 * @param {string} path - The path.
+	 * @param {?Object} [parsedPath] - The parsed path.
+	 * @return {PropertyBinding|Composite} The created property binding or composite.
+	 */
 	static create( root, path, parsedPath ) {
 
 		if ( ! ( root && root.isAnimationObjectGroup ) ) {
@@ -136,8 +178,8 @@ class PropertyBinding {
 	 * Replaces spaces with underscores and removes unsupported characters from
 	 * node names, to ensure compatibility with parseTrackName().
 	 *
-	 * @param {string} name Node name to be sanitized.
-	 * @return {string}
+	 * @param {string} name - Node name to be sanitized.
+	 * @return {string} The sanitized node name.
 	 */
 	static sanitizeNodeName( name ) {
 
@@ -145,6 +187,24 @@ class PropertyBinding {
 
 	}
 
+	/**
+	 * Parses the given track name (an object path to an animated property) and
+	 * returns an object with information about the path. Matches strings in the following forms:
+	 *
+	 * - nodeName.property
+	 * - nodeName.property[accessor]
+	 * - nodeName.material.property[accessor]
+	 * - uuid.property[accessor]
+	 * - uuid.objectName[objectIndex].propertyName[propertyIndex]
+	 * - parentName/nodeName.property
+	 * - parentName/parentName/nodeName.property[index]
+	 * - .bone[Armature.DEF_cog].position
+	 * - scene:helium_balloon_model:helium_balloon_model.position
+	 *
+	 * @static
+	 * @param {string} trackName - The track name to parse.
+	 * @return {Object} The parsed track name as an object.
+	 */
 	static parseTrackName( trackName ) {
 
 		const matches = _trackRe.exec( trackName );
@@ -193,6 +253,15 @@ class PropertyBinding {
 
 	}
 
+	/**
+	 * Searches for a node in the hierarchy of the given root object by the given
+	 * node name.
+	 *
+	 * @static
+	 * @param {Object} root - The root object.
+	 * @param {string} nodeName - The name of the node.
+	 * @return {?Object} The found node. Returns `null` if no object was found.
+	 */
 	static findNode( root, nodeName ) {
 
 		if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
@@ -411,7 +480,9 @@ class PropertyBinding {
 
 	}
 
-	// create getter / setter pair for a property in the scene graph
+	/**
+	 * Creates a getter / setter pair for the property tracked by this binding.
+	 */
 	bind() {
 
 		let targetObject = this.node;
@@ -644,6 +715,9 @@ class PropertyBinding {
 
 	}
 
+	/**
+	 * Unbinds the property.
+	 */
 	unbind() {
 
 		this.node = null;

+ 72 - 5
src/animation/PropertyMixer.js

@@ -1,10 +1,31 @@
 import { Quaternion } from '../math/Quaternion.js';
 
+/**
+ * Buffered scene graph property that allows weighted accumulation; used internally.
+ */
 class PropertyMixer {
 
+	/**
+	 * Constructs a new property mixer.
+	 *
+	 * @param {PropertyBinding} binding - The property binding.
+	 * @param {string} typeName - The keyframe track type name.
+	 * @param {number} valueSize - The keyframe track value size.
+	 */
 	constructor( binding, typeName, valueSize ) {
 
+		/**
+		 * The property binding.
+		 *
+		 * @type {PropertyBinding}
+		 */
 		this.binding = binding;
+
+		/**
+		 * The keyframe track value size.
+		 *
+		 * @type {number}
+		 */
 		this.valueSize = valueSize;
 
 		let mixFunction,
@@ -66,15 +87,46 @@ class PropertyMixer {
 		this._origIndex = 3;
 		this._addIndex = 4;
 
+		/**
+		 * TODO
+		 *
+		 * @type {number}
+		 * @default 0
+		 */
 		this.cumulativeWeight = 0;
+
+		/**
+		 * TODO
+		 *
+		 * @type {number}
+		 * @default 0
+		 */
 		this.cumulativeWeightAdditive = 0;
 
+		/**
+		 * TODO
+		 *
+		 * @type {number}
+		 * @default 0
+		 */
 		this.useCount = 0;
+
+		/**
+		 * TODO
+		 *
+		 * @type {number}
+		 * @default 0
+		 */
 		this.referenceCount = 0;
 
 	}
 
-	// accumulate data in the 'incoming' region into 'accu<i>'
+	/**
+	 * Accumulates data in the `incoming` region into `accu<i>`.
+	 *
+	 * @param {number} accuIndex - The accumulation index.
+	 * @param {number} weight - The weight.
+	 */
 	accumulate( accuIndex, weight ) {
 
 		// note: happily accumulating nothing when weight = 0, the caller knows
@@ -112,7 +164,11 @@ class PropertyMixer {
 
 	}
 
-	// accumulate data in the 'incoming' region into 'add'
+	/**
+	 * Accumulates data in the `incoming` region into `add`.
+	 *
+	 * @param {number} weight - The weight.
+	 */
 	accumulateAdditive( weight ) {
 
 		const buffer = this.buffer,
@@ -134,7 +190,11 @@ class PropertyMixer {
 
 	}
 
-	// apply the state of 'accu<i>' to the binding when accus differ
+	/**
+	 * Applies the state of `accu<i>` to the binding when accus differ.
+	 *
+	 * @param {number} accuIndex - The accumulation index.
+	 */
 	apply( accuIndex ) {
 
 		const stride = this.valueSize,
@@ -183,7 +243,10 @@ class PropertyMixer {
 
 	}
 
-	// remember the state of the bound property and copy it to both accus
+
+	/**
+	 * Remembers the state of the bound property and copy it to both accus.
+	 */
 	saveOriginalState() {
 
 		const binding = this.binding;
@@ -210,7 +273,9 @@ class PropertyMixer {
 
 	}
 
-	// apply the state previously taken via 'saveOriginalState' to the binding
+	/**
+	 * Applies the state previously taken via {@link PropertyMixer#saveOriginalState} to the binding.
+	 */
 	restoreOriginalState() {
 
 		const originalValueOffset = this.valueSize * 3;
@@ -218,6 +283,8 @@ class PropertyMixer {
 
 	}
 
+	// internals
+
 	_setAdditiveIdentityNumeric() {
 
 		const startIndex = this._addIndex * this.valueSize;

+ 33 - 6
src/animation/tracks/BooleanKeyframeTrack.js

@@ -2,11 +2,22 @@ import { InterpolateDiscrete } from '../../constants.js';
 import { KeyframeTrack } from '../KeyframeTrack.js';
 
 /**
- * A Track of Boolean keyframe values.
+ * A track for boolean keyframe values.
+ *
+ * @augments KeyframeTrack
  */
 class BooleanKeyframeTrack extends KeyframeTrack {
 
-	// No interpolation parameter because only InterpolateDiscrete is valid.
+	/**
+	 * Constructs a new boolean keyframe track.
+	 *
+	 * This keyframe track type has no `interpolation` parameter because the
+	 * interpolation is always discrete.
+	 *
+	 * @param {string} name - The keyframe track's name.
+	 * @param {Array<number>} times - A list of keyframe times.
+	 * @param {Array<number>} values - A list of keyframe values.
+	 */
 	constructor( name, times, values ) {
 
 		super( name, times, values );
@@ -15,14 +26,30 @@ class BooleanKeyframeTrack extends KeyframeTrack {
 
 }
 
+/**
+ * The value type name.
+ *
+ * @type {String}
+ * @default 'bool'
+ */
 BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
+
+/**
+ * The value buffer type of this keyframe track.
+ *
+ * @type {TypedArray|Array}
+ * @default Array.constructor
+ */
 BooleanKeyframeTrack.prototype.ValueBufferType = Array;
+
+/**
+ * The default interpolation type of this keyframe track.
+ *
+ * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
+ * @default InterpolateDiscrete
+ */
 BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
 BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
 BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
 
-// Note: Actually this track could have a optimized / compressed
-// representation of a single value and a custom interpolant that
-// computes "firstValue ^ isOdd( index )".
-
 export { BooleanKeyframeTrack };

+ 26 - 5
src/animation/tracks/ColorKeyframeTrack.js

@@ -1,15 +1,36 @@
 import { KeyframeTrack } from '../KeyframeTrack.js';
 
 /**
- * A Track of keyframe values that represent color.
+ * A track for color keyframe values.
+ *
+ * @augments KeyframeTrack
  */
-class ColorKeyframeTrack extends KeyframeTrack {}
+class ColorKeyframeTrack extends KeyframeTrack {
 
+	/**
+	 * Constructs a new color keyframe track.
+	 *
+	 * @param {string} name - The keyframe track's name.
+	 * @param {Array<number>} times - A list of keyframe times.
+	 * @param {Array<number>} values - A list of keyframe values.
+	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
+	 */
+	constructor( name, times, values, interpolation ) {
+
+		super( name, times, values, interpolation );
+
+	}
+
+}
+
+/**
+ * The value type name.
+ *
+ * @type {String}
+ * @default 'color'
+ */
 ColorKeyframeTrack.prototype.ValueTypeName = 'color';
 // ValueBufferType is inherited
 // DefaultInterpolation is inherited
 
-// Note: Very basic implementation and nothing special yet.
-// However, this is the place for color space parameterization.
-
 export { ColorKeyframeTrack };

+ 26 - 2
src/animation/tracks/NumberKeyframeTrack.js

@@ -1,10 +1,34 @@
 import { KeyframeTrack } from '../KeyframeTrack.js';
 
 /**
- * A Track of numeric keyframe values.
+ * A track for numeric keyframe values.
+ *
+ * @augments KeyframeTrack
  */
-class NumberKeyframeTrack extends KeyframeTrack {}
+class NumberKeyframeTrack extends KeyframeTrack {
 
+	/**
+	 * Constructs a new number keyframe track.
+	 *
+	 * @param {string} name - The keyframe track's name.
+	 * @param {Array<number>} times - A list of keyframe times.
+	 * @param {Array<number>} values - A list of keyframe values.
+	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
+	 */
+	constructor( name, times, values, interpolation ) {
+
+		super( name, times, values, interpolation );
+
+	}
+
+}
+
+/**
+ * The value type name.
+ *
+ * @type {String}
+ * @default 'number'
+ */
 NumberKeyframeTrack.prototype.ValueTypeName = 'number';
 // ValueBufferType is inherited
 // DefaultInterpolation is inherited

+ 30 - 1
src/animation/tracks/QuaternionKeyframeTrack.js

@@ -2,10 +2,33 @@ import { KeyframeTrack } from '../KeyframeTrack.js';
 import { QuaternionLinearInterpolant } from '../../math/interpolants/QuaternionLinearInterpolant.js';
 
 /**
- * A Track of quaternion keyframe values.
+ * A track for Quaternion keyframe values.
+ *
+ * @augments KeyframeTrack
  */
 class QuaternionKeyframeTrack extends KeyframeTrack {
 
+	/**
+	 * Constructs a new Quaternion keyframe track.
+	 *
+	 * @param {string} name - The keyframe track's name.
+	 * @param {Array<number>} times - A list of keyframe times.
+	 * @param {Array<number>} values - A list of keyframe values.
+	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
+	 */
+	constructor( name, times, values, interpolation ) {
+
+		super( name, times, values, interpolation );
+
+	}
+
+	/**
+	 * Overwritten so the method returns Quaternion based interpolant.
+	 *
+	 * @static
+	 * @param {TypedArray} [result] - The result buffer.
+	 * @return {QuaternionLinearInterpolant} The new interpolant.
+	 */
 	InterpolantFactoryMethodLinear( result ) {
 
 		return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
@@ -14,6 +37,12 @@ class QuaternionKeyframeTrack extends KeyframeTrack {
 
 }
 
+/**
+ * The value type name.
+ *
+ * @type {String}
+ * @default 'quaternion'
+ */
 QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
 // ValueBufferType is inherited
 // DefaultInterpolation is inherited;

+ 33 - 2
src/animation/tracks/StringKeyframeTrack.js

@@ -2,11 +2,22 @@ import { InterpolateDiscrete } from '../../constants.js';
 import { KeyframeTrack } from '../KeyframeTrack.js';
 
 /**
- * A Track that interpolates Strings
+ * A track for string keyframe values.
+ *
+ * @augments KeyframeTrack
  */
 class StringKeyframeTrack extends KeyframeTrack {
 
-	// No interpolation parameter because only InterpolateDiscrete is valid.
+	/**
+	 * Constructs a new string keyframe track.
+	 *
+	 * This keyframe track type has no `interpolation` parameter because the
+	 * interpolation is always discrete.
+	 *
+	 * @param {string} name - The keyframe track's name.
+	 * @param {Array<number>} times - A list of keyframe times.
+	 * @param {Array<number>} values - A list of keyframe values.
+	 */
 	constructor( name, times, values ) {
 
 		super( name, times, values );
@@ -15,8 +26,28 @@ class StringKeyframeTrack extends KeyframeTrack {
 
 }
 
+/**
+ * The value type name.
+ *
+ * @type {String}
+ * @default 'string'
+ */
 StringKeyframeTrack.prototype.ValueTypeName = 'string';
+
+/**
+ * The value buffer type of this keyframe track.
+ *
+ * @type {TypedArray|Array}
+ * @default Array.constructor
+ */
 StringKeyframeTrack.prototype.ValueBufferType = Array;
+
+/**
+ * The default interpolation type of this keyframe track.
+ *
+ * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
+ * @default InterpolateDiscrete
+ */
 StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
 StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
 StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;

+ 26 - 2
src/animation/tracks/VectorKeyframeTrack.js

@@ -1,10 +1,34 @@
 import { KeyframeTrack } from '../KeyframeTrack.js';
 
 /**
- * A Track of vectored keyframe values.
+ * A track for vector keyframe values.
+ *
+ * @augments KeyframeTrack
  */
-class VectorKeyframeTrack extends KeyframeTrack {}
+class VectorKeyframeTrack extends KeyframeTrack {
 
+	/**
+	 * Constructs a new vector keyframe track.
+	 *
+	 * @param {string} name - The keyframe track's name.
+	 * @param {Array<number>} times - A list of keyframe times.
+	 * @param {Array<number>} values - A list of keyframe values.
+	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
+	 */
+	constructor( name, times, values, interpolation ) {
+
+		super( name, times, values, interpolation );
+
+	}
+
+}
+
+/**
+ * The value type name.
+ *
+ * @type {String}
+ * @default 'vector'
+ */
 VectorKeyframeTrack.prototype.ValueTypeName = 'vector';
 // ValueBufferType is inherited
 // DefaultInterpolation is inherited

+ 1 - 0
utils/docs/jsdoc.config.json

@@ -13,6 +13,7 @@
     "source": {
         "include": [
             "examples/jsm/tsl",
+            "src/animation",
             "src/audio",
             "src/cameras",
             "src/core/Object3D.js",

粤ICP备19079148号