|
@@ -1,8 +1,27 @@
|
|
|
module BABYLON {
|
|
|
+ /**
|
|
|
+ * Represents the range of an animation
|
|
|
+ */
|
|
|
export class AnimationRange {
|
|
|
- constructor(public name: string, public from: number, public to: number) {
|
|
|
+ /**
|
|
|
+ * Initializes the range of an animation
|
|
|
+ * @param name The name of the animation range
|
|
|
+ * @param from The starting frame of the animation
|
|
|
+ * @param to The ending frame of the animation
|
|
|
+ */
|
|
|
+ constructor(
|
|
|
+ /**The name of the animation range**/
|
|
|
+ public name: string,
|
|
|
+ /**The starting frame of the animation */
|
|
|
+ public from: number,
|
|
|
+ /**The ending frame of the animation*/
|
|
|
+ public to: number) {
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Makes a copy of the animation range
|
|
|
+ * @returns A copy of the animation range
|
|
|
+ */
|
|
|
public clone(): AnimationRange {
|
|
|
return new AnimationRange(this.name, this.from, this.to);
|
|
|
}
|
|
@@ -12,37 +31,90 @@
|
|
|
* Composed of a frame, and an action function
|
|
|
*/
|
|
|
export class AnimationEvent {
|
|
|
+ /**
|
|
|
+ * Specifies if the animation event is done
|
|
|
+ */
|
|
|
public isDone: boolean = false;
|
|
|
- constructor(public frame: number, public action: () => void, public onlyOnce?: boolean) {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Initializes the animation event
|
|
|
+ * @param frame The frame for which the event is triggered
|
|
|
+ * @param action The event to perform when triggered
|
|
|
+ * @param onlyOnce Specifies if the event should be triggered only once
|
|
|
+ */
|
|
|
+ constructor(
|
|
|
+ /** The frame for which the event is triggered **/
|
|
|
+ public frame: number,
|
|
|
+ /** The event to perform when triggered **/
|
|
|
+ public action: () => void ,
|
|
|
+ /** Specifies if the event should be triggered only once**/
|
|
|
+ public onlyOnce?: boolean ) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * A cursor which tracks a point on a path
|
|
|
+ */
|
|
|
export class PathCursor {
|
|
|
+ /**
|
|
|
+ * Stores path cursor callbacks for when an onchange event is triggered
|
|
|
+ */
|
|
|
private _onchange = new Array<(cursor: PathCursor) => void>();
|
|
|
|
|
|
+ /**
|
|
|
+ * The value of the path cursor
|
|
|
+ */
|
|
|
value: number = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The animation array of the path cursor
|
|
|
+ */
|
|
|
animations = new Array<Animation>();
|
|
|
|
|
|
+ /**
|
|
|
+ * Initializes the path cursor
|
|
|
+ * @param path The path to track
|
|
|
+ */
|
|
|
constructor(private path: Path2) {
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Gets the cursor point on the path
|
|
|
+ * @returns A point on the path cursor at the cursor location
|
|
|
+ */
|
|
|
public getPoint(): Vector3 {
|
|
|
var point = this.path.getPointAtLengthPosition(this.value);
|
|
|
return new Vector3(point.x, 0, point.y);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Moves the cursor ahead by the step amount
|
|
|
+ * @param step The amount to move the cursor forward
|
|
|
+ * @returns This path cursor
|
|
|
+ */
|
|
|
public moveAhead(step: number = 0.002): PathCursor {
|
|
|
this.move(step);
|
|
|
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Moves the cursor behind by the step amount
|
|
|
+ * @param step The amount to move the cursor back
|
|
|
+ * @returns This path cursor
|
|
|
+ */
|
|
|
public moveBack(step: number = 0.002): PathCursor {
|
|
|
this.move(-step);
|
|
|
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Moves the cursor by the step amount
|
|
|
+ * If the step amount is greater than one, an exception is thrown
|
|
|
+ * @param step The amount to move the cursor
|
|
|
+ * @returns This path cursor
|
|
|
+ */
|
|
|
public move(step: number): PathCursor {
|
|
|
|
|
|
if (Math.abs(step) > 1) {
|
|
@@ -56,6 +128,10 @@
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Ensures that the value is limited between zero and one
|
|
|
+ * @returns This path cursor
|
|
|
+ */
|
|
|
private ensureLimits(): PathCursor {
|
|
|
while (this.value > 1) {
|
|
|
this.value -= 1;
|
|
@@ -67,13 +143,21 @@
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
- // used by animation engine
|
|
|
+ /**
|
|
|
+ * Runs onchange callbacks on change (used by the animation engine)
|
|
|
+ * @returns This path cursor
|
|
|
+ */
|
|
|
private raiseOnChange(): PathCursor {
|
|
|
this._onchange.forEach(f => f(this));
|
|
|
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Executes a function on change
|
|
|
+ * @param f A path cursor onchange callback
|
|
|
+ * @returns This path cursor
|
|
|
+ */
|
|
|
public onchange(f: (cursor: PathCursor) => void): PathCursor {
|
|
|
this._onchange.push(f);
|
|
|
|
|
@@ -81,17 +165,38 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Defines an interface which represents an animation key frame
|
|
|
+ */
|
|
|
export interface IAnimationKey {
|
|
|
+ /**
|
|
|
+ * Frame of the key frame
|
|
|
+ */
|
|
|
frame: number;
|
|
|
+ /**
|
|
|
+ * Value at the specifies key frame
|
|
|
+ */
|
|
|
value: any;
|
|
|
+ /**
|
|
|
+ * The input tangent for the cubic hermite spline
|
|
|
+ */
|
|
|
inTangent?: any;
|
|
|
+ /**
|
|
|
+ * The output tangent for the cubic hermite spline
|
|
|
+ */
|
|
|
outTangent?: any;
|
|
|
+ /**
|
|
|
+ * The animation interpolation type
|
|
|
+ */
|
|
|
interpolation?: AnimationKeyInterpolation;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Enum for the animation key frame interpolation type
|
|
|
+ */
|
|
|
export enum AnimationKeyInterpolation {
|
|
|
/**
|
|
|
- * Do not interpolate between keys and use the start key value only. Tangents are ignored.
|
|
|
+ * Do not interpolate between keys and use the start key value only. Tangents are ignored
|
|
|
*/
|
|
|
STEP = 1
|
|
|
}
|
|
@@ -110,21 +215,45 @@
|
|
|
*/
|
|
|
public static AllowMatrixDecomposeForInterpolation = true;
|
|
|
|
|
|
+ /**
|
|
|
+ * Stores the key frames of the animation
|
|
|
+ */
|
|
|
private _keys: Array<IAnimationKey>;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Stores the easing function of the animation
|
|
|
+ */
|
|
|
private _easingFunction: IEasingFunction;
|
|
|
|
|
|
+ /**
|
|
|
+ * @ignore Internal use only
|
|
|
+ */
|
|
|
public _runtimeAnimations = new Array<RuntimeAnimation>();
|
|
|
|
|
|
- // The set of event that will be linked to this animation
|
|
|
+ /**
|
|
|
+ * The set of event that will be linked to this animation
|
|
|
+ */
|
|
|
private _events = new Array<AnimationEvent>();
|
|
|
|
|
|
+ /**
|
|
|
+ * Stores an array of target property paths
|
|
|
+ */
|
|
|
public targetPropertyPath: string[];
|
|
|
|
|
|
+ /**
|
|
|
+ * Stores the blending speed of the animation
|
|
|
+ */
|
|
|
public blendingSpeed = 0.01;
|
|
|
|
|
|
+ /**
|
|
|
+ * Stores the animation ranges for the animation
|
|
|
+ */
|
|
|
private _ranges: { [name: string]: Nullable<AnimationRange> } = {};
|
|
|
|
|
|
- static _PrepareAnimation(name: string, targetProperty: string, framePerSecond: number, totalFrame: number,
|
|
|
+ /**
|
|
|
+ * @ignore Internal use
|
|
|
+ */
|
|
|
+ public static _PrepareAnimation(name: string, targetProperty: string, framePerSecond: number, totalFrame: number,
|
|
|
from: any, to: any, loopMode?: number, easingFunction?: EasingFunction): Nullable<Animation> {
|
|
|
var dataType = undefined;
|
|
|
|
|
@@ -159,10 +288,11 @@
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Sets up an animation.
|
|
|
- * @param property the property to animate
|
|
|
- * @param animationType the animation type to apply
|
|
|
- * @param easingFunction the easing function used in the animation
|
|
|
+ * Sets up an animation
|
|
|
+ * @param property The property to animate
|
|
|
+ * @param animationType The animation type to apply
|
|
|
+ * @param framePerSecond The frames per second of the animation
|
|
|
+ * @param easingFunction The easing function used in the animation
|
|
|
* @returns The created animation
|
|
|
*/
|
|
|
public static CreateAnimation(property: string, animationType: number, framePerSecond: number, easingFunction: EasingFunction): Animation {
|
|
@@ -179,15 +309,15 @@
|
|
|
|
|
|
/**
|
|
|
* Create and start an animation on a node
|
|
|
- * @param {string} name defines the name of the global animation that will be run on all nodes
|
|
|
- * @param {BABYLON.Node} node defines the root node where the animation will take place
|
|
|
- * @param {string} targetProperty defines property to animate
|
|
|
- * @param {number} framePerSecond defines the number of frame per second yo use
|
|
|
- * @param {number} totalFrame defines the number of frames in total
|
|
|
- * @param {any} from defines the initial value
|
|
|
- * @param {any} to defines the final value
|
|
|
- * @param {number} loopMode defines which loop mode you want to use (off by default)
|
|
|
- * @param {BABYLON.EasingFunction} easingFunction defines the easing function to use (linear by default)
|
|
|
+ * @param name defines the name of the global animation that will be run on all nodes
|
|
|
+ * @param node defines the root node where the animation will take place
|
|
|
+ * @param targetProperty defines property to animate
|
|
|
+ * @param framePerSecond defines the number of frame per second yo use
|
|
|
+ * @param totalFrame defines the number of frames in total
|
|
|
+ * @param from defines the initial value
|
|
|
+ * @param to defines the final value
|
|
|
+ * @param loopMode defines which loop mode you want to use (off by default)
|
|
|
+ * @param easingFunction defines the easing function to use (linear by default)
|
|
|
* @param onAnimationEnd defines the callback to call when animation end
|
|
|
* @returns the animatable created for this animation
|
|
|
*/
|
|
@@ -206,16 +336,16 @@
|
|
|
|
|
|
/**
|
|
|
* Create and start an animation on a node and its descendants
|
|
|
- * @param {string} name defines the name of the global animation that will be run on all nodes
|
|
|
- * @param {BABYLON.Node} node defines the root node where the animation will take place
|
|
|
- * @param {boolean} directDescendantsOnly if true only direct descendants will be used, if false direct and also indirect (children of children, an so on in a recursive manner) descendants will be used.
|
|
|
- * @param {string} targetProperty defines property to animate
|
|
|
- * @param {number} framePerSecond defines the number of frame per second yo use
|
|
|
- * @param {number} totalFrame defines the number of frames in total
|
|
|
- * @param {any} from defines the initial value
|
|
|
- * @param {any} to defines the final value
|
|
|
- * @param {number} loopMode defines which loop mode you want to use (off by default)
|
|
|
- * @param {BABYLON.EasingFunction} easingFunction defines the easing function to use (linear by default)
|
|
|
+ * @param name defines the name of the global animation that will be run on all nodes
|
|
|
+ * @param node defines the root node where the animation will take place
|
|
|
+ * @param directDescendantsOnly if true only direct descendants will be used, if false direct and also indirect (children of children, an so on in a recursive manner) descendants will be used
|
|
|
+ * @param targetProperty defines property to animate
|
|
|
+ * @param framePerSecond defines the number of frame per second to use
|
|
|
+ * @param totalFrame defines the number of frames in total
|
|
|
+ * @param from defines the initial value
|
|
|
+ * @param to defines the final value
|
|
|
+ * @param loopMode defines which loop mode you want to use (off by default)
|
|
|
+ * @param easingFunction defines the easing function to use (linear by default)
|
|
|
* @param onAnimationEnd defines the callback to call when an animation ends (will be called once per node)
|
|
|
* @returns the list of animatables created for all nodes
|
|
|
* @example https://www.babylonjs-playground.com/#MH0VLI
|
|
@@ -234,6 +364,20 @@
|
|
|
return scene.beginDirectHierarchyAnimation(node, directDescendantsOnly, [animation], 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Creates a new animation, merges it with the existing animations and starts it
|
|
|
+ * @param name Name of the animation
|
|
|
+ * @param node Node which contains the scene that begins the animations
|
|
|
+ * @param targetProperty Specifies which property to animate
|
|
|
+ * @param framePerSecond The frames per second of the animation
|
|
|
+ * @param totalFrame The total number of frames
|
|
|
+ * @param from The frame at the beginning of the animation
|
|
|
+ * @param to The frame at the end of the animation
|
|
|
+ * @param loopMode Specifies the loop mode of the animation
|
|
|
+ * @param easingFunction (Optional) The easing function of the animation, which allow custom mathematical formulas for animations
|
|
|
+ * @param onAnimationEnd Callback to run once the animation is complete
|
|
|
+ * @returns Nullable animation
|
|
|
+ */
|
|
|
public static CreateMergeAndStartAnimation(name: string, node: Node, targetProperty: string,
|
|
|
framePerSecond: number, totalFrame: number,
|
|
|
from: any, to: any, loopMode?: number, easingFunction?: EasingFunction, onAnimationEnd?: () => void): Nullable<Animatable> {
|
|
@@ -250,7 +394,7 @@
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Transition property of the Camera to the target Value.
|
|
|
+ * Transition property of the Camera to the target Value
|
|
|
* @param property The property to transition
|
|
|
* @param targetValue The target Value of the property
|
|
|
* @param host The object where the property to animate belongs
|
|
@@ -258,10 +402,10 @@
|
|
|
* @param frameRate Framerate (in frame/s) to use
|
|
|
* @param transition The transition type we want to use
|
|
|
* @param duration The duration of the animation, in milliseconds
|
|
|
- * @param onAnimationEnd Call back trigger at the end of the animation.
|
|
|
+ * @param onAnimationEnd Callback trigger at the end of the animation
|
|
|
+ * @returns Nullable animation
|
|
|
*/
|
|
|
public static TransitionTo(property: string, targetValue: any, host: any, scene: Scene, frameRate: number, transition: Animation, duration: number, onAnimationEnd: Nullable<() => void> = null): Nullable<Animatable> {
|
|
|
-
|
|
|
if (duration <= 0) {
|
|
|
host[property] = targetValue;
|
|
|
if (onAnimationEnd) {
|
|
@@ -299,6 +443,9 @@
|
|
|
return this._runtimeAnimations;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Specifies if any of the runtime animations are currently running
|
|
|
+ */
|
|
|
public get hasRunningRuntimeAnimations(): boolean {
|
|
|
for (var runtimeAnimation of this._runtimeAnimations) {
|
|
|
if (!runtimeAnimation.isStopped) {
|
|
@@ -309,7 +456,28 @@
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- constructor(public name: string, public targetProperty: string, public framePerSecond: number, public dataType: number, public loopMode?: number, public enableBlending?: boolean) {
|
|
|
+ /**
|
|
|
+ * Initializes the animation
|
|
|
+ * @param name Name of the animation
|
|
|
+ * @param targetProperty Property to animate
|
|
|
+ * @param framePerSecond The frames per second of the animation
|
|
|
+ * @param dataType The data type of the animation
|
|
|
+ * @param loopMode The loop mode of the animation
|
|
|
+ * @param enableBlendings Specifies if blending should be enabled
|
|
|
+ */
|
|
|
+ constructor(
|
|
|
+ /**Name of the animation */
|
|
|
+ public name: string,
|
|
|
+ /**Property to animate */
|
|
|
+ public targetProperty: string,
|
|
|
+ /**The frames per second of the animation */
|
|
|
+ public framePerSecond: number,
|
|
|
+ /**The data type of the animation */
|
|
|
+ public dataType: number,
|
|
|
+ /**The loop mode of the animation */
|
|
|
+ public loopMode?: number,
|
|
|
+ /**Specifies if blending should be enabled */
|
|
|
+ public enableBlending?: boolean) {
|
|
|
this.targetPropertyPath = targetProperty.split(".");
|
|
|
this.dataType = dataType;
|
|
|
this.loopMode = loopMode === undefined ? Animation.ANIMATIONLOOPMODE_CYCLE : loopMode;
|
|
@@ -317,7 +485,9 @@
|
|
|
|
|
|
// Methods
|
|
|
/**
|
|
|
- * @param {boolean} fullDetails - support for multiple levels of logging within scene loading
|
|
|
+ * Converts the animation to a string
|
|
|
+ * @param fullDetails support for multiple levels of logging within scene loading
|
|
|
+ * @returns String form of the animation
|
|
|
*/
|
|
|
public toString(fullDetails?: boolean): string {
|
|
|
var ret = "Name: " + this.name + ", property: " + this.targetProperty;
|
|
@@ -340,7 +510,8 @@
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Add an event to this animation.
|
|
|
+ * Add an event to this animation
|
|
|
+ * @param event Event to add
|
|
|
*/
|
|
|
public addEvent(event: AnimationEvent): void {
|
|
|
this._events.push(event);
|
|
@@ -348,7 +519,7 @@
|
|
|
|
|
|
/**
|
|
|
* Remove all events found at the given frame
|
|
|
- * @param frame
|
|
|
+ * @param frame The frame to remove events from
|
|
|
*/
|
|
|
public removeEvents(frame: number): void {
|
|
|
for (var index = 0; index < this._events.length; index++) {
|
|
@@ -359,10 +530,20 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Retrieves all the events from the animation
|
|
|
+ * @returns Events from the animation
|
|
|
+ */
|
|
|
public getEvents(): AnimationEvent[] {
|
|
|
return this._events;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Creates an animation range
|
|
|
+ * @param name Name of the animation range
|
|
|
+ * @param from Starting frame of the animation range
|
|
|
+ * @param to Ending frame of the animation
|
|
|
+ */
|
|
|
public createRange(name: string, from: number, to: number): void {
|
|
|
// check name not already in use; could happen for bones after serialized
|
|
|
if (!this._ranges[name]) {
|
|
@@ -370,6 +551,11 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Deletes an animation range by name
|
|
|
+ * @param name Name of the animation range to delete
|
|
|
+ * @param deleteFrames Specifies if the key frames for the range should also be deleted (true) or not (false)
|
|
|
+ */
|
|
|
public deleteRange(name: string, deleteFrames = true): void {
|
|
|
let range = this._ranges[name];
|
|
|
if (!range) {
|
|
@@ -391,15 +577,27 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Gets the animation range by name, or null if not defined
|
|
|
+ * @param name Name of the animation range
|
|
|
+ * @returns Nullable animation range
|
|
|
+ */
|
|
|
public getRange(name: string): Nullable<AnimationRange> {
|
|
|
return this._ranges[name];
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Gets the key frames from the animation
|
|
|
+ * @returns The key frames of the animation
|
|
|
+ */
|
|
|
public getKeys(): Array<IAnimationKey> {
|
|
|
return this._keys;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Gets the highest frame rate of the animation
|
|
|
+ * @returns Highest frame rate of the animation
|
|
|
+ */
|
|
|
public getHighestFrame(): number {
|
|
|
var ret = 0;
|
|
|
|
|
@@ -411,55 +609,279 @@
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- public getEasingFunction() {
|
|
|
+ /**
|
|
|
+ * Gets the easing function of the animation
|
|
|
+ * @returns Easing function of the animation
|
|
|
+ */
|
|
|
+ public getEasingFunction(): IEasingFunction {
|
|
|
return this._easingFunction;
|
|
|
}
|
|
|
|
|
|
- public setEasingFunction(easingFunction: EasingFunction) {
|
|
|
+ /**
|
|
|
+ * Sets the easing function of the animation
|
|
|
+ * @param easingFunction A custom mathematical formula for animation
|
|
|
+ */
|
|
|
+ public setEasingFunction(easingFunction: EasingFunction): void {
|
|
|
this._easingFunction = easingFunction;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a scalar linearly
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated scalar value
|
|
|
+ */
|
|
|
public floatInterpolateFunction(startValue: number, endValue: number, gradient: number): number {
|
|
|
return Scalar.Lerp(startValue, endValue, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a scalar cubically
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param outTangent End tangent of the animation
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param inTangent Start tangent of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated scalar value
|
|
|
+ */
|
|
|
public floatInterpolateFunctionWithTangents(startValue: number, outTangent: number, endValue: number, inTangent: number, gradient: number): number {
|
|
|
return Scalar.Hermite(startValue, outTangent, endValue, inTangent, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a quaternion using a spherical linear interpolation
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated quaternion value
|
|
|
+ */
|
|
|
public quaternionInterpolateFunction(startValue: Quaternion, endValue: Quaternion, gradient: number): Quaternion {
|
|
|
return Quaternion.Slerp(startValue, endValue, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a quaternion cubically
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param outTangent End tangent of the animation curve
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param inTangent Start tangent of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated quaternion value
|
|
|
+ */
|
|
|
public quaternionInterpolateFunctionWithTangents(startValue: Quaternion, outTangent: Quaternion, endValue: Quaternion, inTangent: Quaternion, gradient: number): Quaternion {
|
|
|
return Quaternion.Hermite(startValue, outTangent, endValue, inTangent, gradient).normalize();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a Vector3 linearl
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated scalar value
|
|
|
+ */
|
|
|
public vector3InterpolateFunction(startValue: Vector3, endValue: Vector3, gradient: number): Vector3 {
|
|
|
return Vector3.Lerp(startValue, endValue, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a Vector3 cubically
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param outTangent End tangent of the animation
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param inTangent Start tangent of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns InterpolatedVector3 value
|
|
|
+ */
|
|
|
public vector3InterpolateFunctionWithTangents(startValue: Vector3, outTangent: Vector3, endValue: Vector3, inTangent: Vector3, gradient: number): Vector3 {
|
|
|
return Vector3.Hermite(startValue, outTangent, endValue, inTangent, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a Vector2 linearly
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated Vector2 value
|
|
|
+ */
|
|
|
public vector2InterpolateFunction(startValue: Vector2, endValue: Vector2, gradient: number): Vector2 {
|
|
|
return Vector2.Lerp(startValue, endValue, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a Vector2 cubically
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param outTangent End tangent of the animation
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param inTangent Start tangent of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated Vector2 value
|
|
|
+ */
|
|
|
public vector2InterpolateFunctionWithTangents(startValue: Vector2, outTangent: Vector2, endValue: Vector2, inTangent: Vector2, gradient: number): Vector2 {
|
|
|
return Vector2.Hermite(startValue, outTangent, endValue, inTangent, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a size linearly
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated Size value
|
|
|
+ */
|
|
|
public sizeInterpolateFunction(startValue: Size, endValue: Size, gradient: number): Size {
|
|
|
return Size.Lerp(startValue, endValue, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Interpolates a Color3 linearly
|
|
|
+ * @param startValue Start value of the animation curve
|
|
|
+ * @param endValue End value of the animation curve
|
|
|
+ * @param gradient Scalar amount to interpolate
|
|
|
+ * @returns Interpolated Color3 value
|
|
|
+ */
|
|
|
public color3InterpolateFunction(startValue: Color3, endValue: Color3, gradient: number): Color3 {
|
|
|
return Color3.Lerp(startValue, endValue, gradient);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * @ignore Internal use only
|
|
|
+ */
|
|
|
+ public _getKeyValue(value: any): any {
|
|
|
+ if (typeof value === "function") {
|
|
|
+ return value();
|
|
|
+ }
|
|
|
+
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @ignore Internal use only
|
|
|
+ */
|
|
|
+ public _interpolate(currentFrame: number, repeatCount: number, workValue?: any, loopMode?: number, offsetValue?: any, highLimitValue?: any): any {
|
|
|
+ if (loopMode === Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
|
|
|
+ return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
|
|
|
+ }
|
|
|
+
|
|
|
+ let keys = this.getKeys();
|
|
|
+
|
|
|
+ // Try to get a hash to find the right key
|
|
|
+ var startKeyIndex = Math.max(0, Math.min(keys.length - 1, Math.floor(keys.length * (currentFrame - keys[0].frame) / (keys[keys.length - 1].frame - keys[0].frame)) - 1));
|
|
|
+
|
|
|
+ if (keys[startKeyIndex].frame >= currentFrame) {
|
|
|
+ while (startKeyIndex - 1 >= 0 && keys[startKeyIndex].frame >= currentFrame) {
|
|
|
+ startKeyIndex--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (var key = startKeyIndex; key < keys.length; key++) {
|
|
|
+ var endKey = keys[key + 1];
|
|
|
+
|
|
|
+ if (endKey.frame >= currentFrame) {
|
|
|
+
|
|
|
+ var startKey = keys[key];
|
|
|
+ var startValue = this._getKeyValue(startKey.value);
|
|
|
+ if (startKey.interpolation === AnimationKeyInterpolation.STEP) {
|
|
|
+ return startValue;
|
|
|
+ }
|
|
|
+
|
|
|
+ var endValue = this._getKeyValue(endKey.value);
|
|
|
+
|
|
|
+ var useTangent = startKey.outTangent !== undefined && endKey.inTangent !== undefined;
|
|
|
+ var frameDelta = endKey.frame - startKey.frame;
|
|
|
+
|
|
|
+ // gradient : percent of currentFrame between the frame inf and the frame sup
|
|
|
+ var gradient = (currentFrame - startKey.frame) / frameDelta;
|
|
|
+
|
|
|
+ // check for easingFunction and correction of gradient
|
|
|
+ let easingFunction = this.getEasingFunction();
|
|
|
+ if (easingFunction != null) {
|
|
|
+ gradient = easingFunction.ease(gradient);
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (this.dataType) {
|
|
|
+ // Float
|
|
|
+ case Animation.ANIMATIONTYPE_FLOAT:
|
|
|
+ var floatValue = useTangent ? this.floatInterpolateFunctionWithTangents(startValue, startKey.outTangent * frameDelta, endValue, endKey.inTangent * frameDelta, gradient) : this.floatInterpolateFunction(startValue, endValue, gradient);
|
|
|
+ switch (loopMode) {
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CYCLE:
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CONSTANT:
|
|
|
+ return floatValue;
|
|
|
+ case Animation.ANIMATIONLOOPMODE_RELATIVE:
|
|
|
+ return offsetValue * repeatCount + floatValue;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ // Quaternion
|
|
|
+ case Animation.ANIMATIONTYPE_QUATERNION:
|
|
|
+ var quatValue = useTangent ? this.quaternionInterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.quaternionInterpolateFunction(startValue, endValue, gradient);
|
|
|
+ switch (loopMode) {
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CYCLE:
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CONSTANT:
|
|
|
+ return quatValue;
|
|
|
+ case Animation.ANIMATIONLOOPMODE_RELATIVE:
|
|
|
+ return quatValue.addInPlace(offsetValue.scale(repeatCount));
|
|
|
+ }
|
|
|
+
|
|
|
+ return quatValue;
|
|
|
+ // Vector3
|
|
|
+ case Animation.ANIMATIONTYPE_VECTOR3:
|
|
|
+ var vec3Value = useTangent ? this.vector3InterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.vector3InterpolateFunction(startValue, endValue, gradient);
|
|
|
+ switch (loopMode) {
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CYCLE:
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CONSTANT:
|
|
|
+ return vec3Value;
|
|
|
+ case Animation.ANIMATIONLOOPMODE_RELATIVE:
|
|
|
+ return vec3Value.add(offsetValue.scale(repeatCount));
|
|
|
+ }
|
|
|
+ // Vector2
|
|
|
+ case Animation.ANIMATIONTYPE_VECTOR2:
|
|
|
+ var vec2Value = useTangent ? this.vector2InterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.vector2InterpolateFunction(startValue, endValue, gradient);
|
|
|
+ switch (loopMode) {
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CYCLE:
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CONSTANT:
|
|
|
+ return vec2Value;
|
|
|
+ case Animation.ANIMATIONLOOPMODE_RELATIVE:
|
|
|
+ return vec2Value.add(offsetValue.scale(repeatCount));
|
|
|
+ }
|
|
|
+ // Size
|
|
|
+ case Animation.ANIMATIONTYPE_SIZE:
|
|
|
+ switch (loopMode) {
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CYCLE:
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CONSTANT:
|
|
|
+ return this.sizeInterpolateFunction(startValue, endValue, gradient);
|
|
|
+ case Animation.ANIMATIONLOOPMODE_RELATIVE:
|
|
|
+ return this.sizeInterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount));
|
|
|
+ }
|
|
|
+ // Color3
|
|
|
+ case Animation.ANIMATIONTYPE_COLOR3:
|
|
|
+ switch (loopMode) {
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CYCLE:
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CONSTANT:
|
|
|
+ return this.color3InterpolateFunction(startValue, endValue, gradient);
|
|
|
+ case Animation.ANIMATIONLOOPMODE_RELATIVE:
|
|
|
+ return this.color3InterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount));
|
|
|
+ }
|
|
|
+ // Matrix
|
|
|
+ case Animation.ANIMATIONTYPE_MATRIX:
|
|
|
+ switch (loopMode) {
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CYCLE:
|
|
|
+ case Animation.ANIMATIONLOOPMODE_CONSTANT:
|
|
|
+ if (Animation.AllowMatricesInterpolation) {
|
|
|
+ workValue = this.matrixInterpolateFunction(startValue, endValue, gradient, workValue);
|
|
|
+ return workValue;
|
|
|
+ }
|
|
|
+ case Animation.ANIMATIONLOOPMODE_RELATIVE:
|
|
|
+ return startValue;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this._getKeyValue(keys[keys.length - 1].value);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* Defines the function to use to interpolate matrices
|
|
|
* @param startValue defines the start matrix
|
|
|
* @param endValue defines the end matrix
|
|
@@ -483,6 +905,10 @@
|
|
|
return Matrix.Lerp(startValue, endValue, gradient);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Makes a copy of the animation
|
|
|
+ * @returns Cloned animation
|
|
|
+ */
|
|
|
public clone(): Animation {
|
|
|
var clone = new Animation(this.name, this.targetPropertyPath.join("."), this.framePerSecond, this.dataType, this.loopMode);
|
|
|
|
|
@@ -507,10 +933,18 @@
|
|
|
return clone;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Sets the key frames of the animation
|
|
|
+ * @param values The animation key frames to set
|
|
|
+ */
|
|
|
public setKeys(values: Array<IAnimationKey>): void {
|
|
|
this._keys = values.slice(0);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Serializes the animation to an object
|
|
|
+ * @returns Serialized object
|
|
|
+ */
|
|
|
public serialize(): any {
|
|
|
var serializationObject: any = {};
|
|
|
|
|
@@ -564,57 +998,122 @@
|
|
|
}
|
|
|
|
|
|
// Statics
|
|
|
+ /**
|
|
|
+ * Float animation type
|
|
|
+ */
|
|
|
private static _ANIMATIONTYPE_FLOAT = 0;
|
|
|
+ /**
|
|
|
+ * Vector3 animation type
|
|
|
+ */
|
|
|
private static _ANIMATIONTYPE_VECTOR3 = 1;
|
|
|
+ /**
|
|
|
+ * Quaternion animation type
|
|
|
+ */
|
|
|
private static _ANIMATIONTYPE_QUATERNION = 2;
|
|
|
+ /**
|
|
|
+ * Matrix animation type
|
|
|
+ */
|
|
|
private static _ANIMATIONTYPE_MATRIX = 3;
|
|
|
+ /**
|
|
|
+ * Color3 animation type
|
|
|
+ */
|
|
|
private static _ANIMATIONTYPE_COLOR3 = 4;
|
|
|
+ /**
|
|
|
+ * Vector2 animation type
|
|
|
+ */
|
|
|
private static _ANIMATIONTYPE_VECTOR2 = 5;
|
|
|
+ /**
|
|
|
+ * Size animation type
|
|
|
+ */
|
|
|
private static _ANIMATIONTYPE_SIZE = 6;
|
|
|
+ /**
|
|
|
+ * Relative Loop Mode
|
|
|
+ */
|
|
|
private static _ANIMATIONLOOPMODE_RELATIVE = 0;
|
|
|
+ /**
|
|
|
+ * Cycle Loop Mode
|
|
|
+ */
|
|
|
private static _ANIMATIONLOOPMODE_CYCLE = 1;
|
|
|
+ /**
|
|
|
+ * Constant Loop Mode
|
|
|
+ */
|
|
|
private static _ANIMATIONLOOPMODE_CONSTANT = 2;
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the float animation type
|
|
|
+ */
|
|
|
public static get ANIMATIONTYPE_FLOAT(): number {
|
|
|
return Animation._ANIMATIONTYPE_FLOAT;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Vector3 animation type
|
|
|
+ */
|
|
|
public static get ANIMATIONTYPE_VECTOR3(): number {
|
|
|
return Animation._ANIMATIONTYPE_VECTOR3;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Vectpr2 animation type
|
|
|
+ */
|
|
|
public static get ANIMATIONTYPE_VECTOR2(): number {
|
|
|
return Animation._ANIMATIONTYPE_VECTOR2;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Size animation type
|
|
|
+ */
|
|
|
public static get ANIMATIONTYPE_SIZE(): number {
|
|
|
return Animation._ANIMATIONTYPE_SIZE;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Quaternion animation type
|
|
|
+ */
|
|
|
public static get ANIMATIONTYPE_QUATERNION(): number {
|
|
|
return Animation._ANIMATIONTYPE_QUATERNION;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Matrix animation type
|
|
|
+ */
|
|
|
public static get ANIMATIONTYPE_MATRIX(): number {
|
|
|
return Animation._ANIMATIONTYPE_MATRIX;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Color3 animation type
|
|
|
+ */
|
|
|
public static get ANIMATIONTYPE_COLOR3(): number {
|
|
|
return Animation._ANIMATIONTYPE_COLOR3;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Relative Loop Mode
|
|
|
+ */
|
|
|
public static get ANIMATIONLOOPMODE_RELATIVE(): number {
|
|
|
return Animation._ANIMATIONLOOPMODE_RELATIVE;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Cycle Loop Mode
|
|
|
+ */
|
|
|
public static get ANIMATIONLOOPMODE_CYCLE(): number {
|
|
|
return Animation._ANIMATIONLOOPMODE_CYCLE;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the Constant Loop Mode
|
|
|
+ */
|
|
|
public static get ANIMATIONLOOPMODE_CONSTANT(): number {
|
|
|
return Animation._ANIMATIONLOOPMODE_CONSTANT;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Parses an animation object and creates an animation
|
|
|
+ * @param parsedAnimation Parsed animation object
|
|
|
+ * @returns Animation object
|
|
|
+ */
|
|
|
public static Parse(parsedAnimation: any): Animation {
|
|
|
var animation = new Animation(parsedAnimation.name, parsedAnimation.property, parsedAnimation.framePerSecond, parsedAnimation.dataType, parsedAnimation.loopBehavior);
|
|
|
|
|
@@ -698,7 +1197,12 @@
|
|
|
return animation;
|
|
|
}
|
|
|
|
|
|
- public static AppendSerializedAnimations(source: IAnimatable, destination: any): any {
|
|
|
+ /**
|
|
|
+ * Appends the serialized animations from the source animations
|
|
|
+ * @param source Source containing the animations
|
|
|
+ * @param destination Target to store the animations
|
|
|
+ */
|
|
|
+ public static AppendSerializedAnimations(source: IAnimatable, destination: any): void {
|
|
|
if (source.animations) {
|
|
|
destination.animations = [];
|
|
|
for (var animationIndex = 0; animationIndex < source.animations.length; animationIndex++) {
|