ngx-spine
Version:
[](https://travis-ci.org/PoiScript/ngx-spine)
1,453 lines • 141 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions.
*
* Copyright (c) 2013-2019, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { MathUtils, Utils, IntSet, Pool } from "./Utils";
import { Animation, MixBlend, AttachmentTimeline, MixDirection, DrawOrderTimeline, RotateTimeline, EventTimeline } from "./Animation";
var AnimationState = /** @class */ (function () {
function AnimationState(data) {
this.tracks = new Array();
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
this.propertyIDs = new IntSet();
this.animationsChanged = false;
this.timeScale = 1;
this.trackEntryPool = new Pool((/**
* @return {?}
*/
function () { return new TrackEntry(); }));
this.data = data;
}
/**
* @param {?} delta
* @return {?}
*/
AnimationState.prototype.update = /**
* @param {?} delta
* @return {?}
*/
function (delta) {
delta *= this.timeScale;
/** @type {?} */
var tracks = this.tracks;
for (var i = 0, n = tracks.length; i < n; i++) {
/** @type {?} */
var current = tracks[i];
if (current == null)
continue;
current.animationLast = current.nextAnimationLast;
current.trackLast = current.nextTrackLast;
/** @type {?} */
var currentDelta = delta * current.timeScale;
if (current.delay > 0) {
current.delay -= currentDelta;
if (current.delay > 0)
continue;
currentDelta = -current.delay;
current.delay = 0;
}
/** @type {?} */
var next = current.next;
if (next != null) {
// When the next entry's delay is passed, change to the next entry, preserving leftover time.
/** @type {?} */
var nextTime = current.trackLast - next.delay;
if (nextTime >= 0) {
next.delay = 0;
next.trackTime +=
current.timeScale == 0
? 0
: (nextTime / current.timeScale + delta) * next.timeScale;
current.trackTime += currentDelta;
this.setCurrent(i, next, true);
while (next.mixingFrom != null) {
next.mixTime += delta;
next = next.mixingFrom;
}
continue;
}
}
else if (current.trackLast >= current.trackEnd &&
current.mixingFrom == null) {
tracks[i] = null;
this.queue.end(current);
this.disposeNext(current);
continue;
}
if (current.mixingFrom != null && this.updateMixingFrom(current, delta)) {
// End mixing from entries once all have completed.
/** @type {?} */
var from = current.mixingFrom;
current.mixingFrom = null;
if (from != null)
from.mixingTo = null;
while (from != null) {
this.queue.end(from);
from = from.mixingFrom;
}
}
current.trackTime += currentDelta;
}
this.queue.drain();
};
/**
* @param {?} to
* @param {?} delta
* @return {?}
*/
AnimationState.prototype.updateMixingFrom = /**
* @param {?} to
* @param {?} delta
* @return {?}
*/
function (to, delta) {
/** @type {?} */
var from = to.mixingFrom;
if (from == null)
return true;
/** @type {?} */
var finished = this.updateMixingFrom(from, delta);
from.animationLast = from.nextAnimationLast;
from.trackLast = from.nextTrackLast;
// Require mixTime > 0 to ensure the mixing from entry was applied at least once.
if (to.mixTime > 0 && to.mixTime >= to.mixDuration) {
// Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame).
if (from.totalAlpha == 0 || to.mixDuration == 0) {
to.mixingFrom = from.mixingFrom;
if (from.mixingFrom != null)
from.mixingFrom.mixingTo = to;
to.interruptAlpha = from.interruptAlpha;
this.queue.end(from);
}
return finished;
}
from.trackTime += delta * from.timeScale;
to.mixTime += delta;
return false;
};
/**
* @param {?} skeleton
* @return {?}
*/
AnimationState.prototype.apply = /**
* @param {?} skeleton
* @return {?}
*/
function (skeleton) {
if (skeleton == null)
throw new Error("skeleton cannot be null.");
if (this.animationsChanged)
this._animationsChanged();
/** @type {?} */
var events = this.events;
/** @type {?} */
var tracks = this.tracks;
/** @type {?} */
var applied = false;
for (var i = 0, n = tracks.length; i < n; i++) {
/** @type {?} */
var current = tracks[i];
if (current == null || current.delay > 0)
continue;
applied = true;
/** @type {?} */
var blend = i == 0 ? MixBlend.first : current.mixBlend;
// Apply mixing from entries first.
/** @type {?} */
var mix = current.alpha;
if (current.mixingFrom != null)
mix *= this.applyMixingFrom(current, skeleton, blend);
else if (current.trackTime >= current.trackEnd && current.next == null)
mix = 0;
// Apply current entry.
/** @type {?} */
var animationLast = current.animationLast;
/** @type {?} */
var animationTime = current.getAnimationTime();
/** @type {?} */
var timelineCount = current.animation.timelines.length;
/** @type {?} */
var timelines = current.animation.timelines;
if ((i == 0 && mix == 1) || blend == MixBlend.add) {
for (var ii = 0; ii < timelineCount; ii++) {
// Fixes issue #302 on IOS9 where mix, blend sometimes became undefined and caused assets
// to sometimes stop rendering when using color correction, as their RGBA values become NaN.
// (https://github.com/pixijs/pixi-spine/issues/302)
Utils.webkit602BugfixHelper(mix, blend);
timelines[ii].apply(skeleton, animationLast, animationTime, events, mix, blend, MixDirection.mixIn);
}
}
else {
/** @type {?} */
var timelineMode = current.timelineMode;
/** @type {?} */
var firstFrame = current.timelinesRotation.length == 0;
if (firstFrame)
Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null);
/** @type {?} */
var timelinesRotation = current.timelinesRotation;
for (var ii = 0; ii < timelineCount; ii++) {
/** @type {?} */
var timeline = timelines[ii];
/** @type {?} */
var timelineBlend = (timelineMode[ii] & (AnimationState.NOT_LAST - 1)) ==
AnimationState.SUBSEQUENT
? blend
: MixBlend.setup;
if (timeline instanceof RotateTimeline) {
this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
}
else {
// This fixes the WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109
Utils.webkit602BugfixHelper(mix, blend);
timeline.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, MixDirection.mixIn);
}
}
}
this.queueEvents(current, animationTime);
events.length = 0;
current.nextAnimationLast = animationTime;
current.nextTrackLast = current.trackTime;
}
this.queue.drain();
return applied;
};
/**
* @param {?} to
* @param {?} skeleton
* @param {?} blend
* @return {?}
*/
AnimationState.prototype.applyMixingFrom = /**
* @param {?} to
* @param {?} skeleton
* @param {?} blend
* @return {?}
*/
function (to, skeleton, blend) {
/** @type {?} */
var from = to.mixingFrom;
if (from.mixingFrom != null)
this.applyMixingFrom(from, skeleton, blend);
/** @type {?} */
var mix = 0;
if (to.mixDuration == 0) {
// Single frame mix to undo mixingFrom changes.
mix = 1;
if (blend == MixBlend.first)
blend = MixBlend.setup;
}
else {
mix = to.mixTime / to.mixDuration;
if (mix > 1)
mix = 1;
if (blend != MixBlend.first)
blend = from.mixBlend;
}
/** @type {?} */
var events = mix < from.eventThreshold ? this.events : null;
/** @type {?} */
var attachments = mix < from.attachmentThreshold;
/** @type {?} */
var drawOrder = mix < from.drawOrderThreshold;
/** @type {?} */
var animationLast = from.animationLast;
/** @type {?} */
var animationTime = from.getAnimationTime();
/** @type {?} */
var timelineCount = from.animation.timelines.length;
/** @type {?} */
var timelines = from.animation.timelines;
/** @type {?} */
var alphaHold = from.alpha * to.interruptAlpha;
/** @type {?} */
var alphaMix = alphaHold * (1 - mix);
if (blend == MixBlend.add) {
for (var i = 0; i < timelineCount; i++)
timelines[i].apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.mixOut);
}
else {
/** @type {?} */
var timelineMode = from.timelineMode;
/** @type {?} */
var timelineHoldMix = from.timelineHoldMix;
/** @type {?} */
var firstFrame = from.timelinesRotation.length == 0;
if (firstFrame)
Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null);
/** @type {?} */
var timelinesRotation = from.timelinesRotation;
from.totalAlpha = 0;
for (var i = 0; i < timelineCount; i++) {
/** @type {?} */
var timeline = timelines[i];
/** @type {?} */
var direction = MixDirection.mixOut;
/** @type {?} */
var timelineBlend = void 0;
/** @type {?} */
var alpha = 0;
switch (timelineMode[i] & (AnimationState.NOT_LAST - 1)) {
case AnimationState.SUBSEQUENT:
timelineBlend = blend;
if (!attachments && timeline instanceof AttachmentTimeline) {
if ((timelineMode[i] & AnimationState.NOT_LAST) ==
AnimationState.NOT_LAST)
continue;
timelineBlend = MixBlend.setup;
}
if (!drawOrder && timeline instanceof DrawOrderTimeline)
continue;
alpha = alphaMix;
break;
case AnimationState.FIRST:
timelineBlend = MixBlend.setup;
alpha = alphaMix;
break;
case AnimationState.HOLD:
timelineBlend = MixBlend.setup;
alpha = alphaHold;
break;
default:
timelineBlend = MixBlend.setup;
/** @type {?} */
var holdMix = timelineHoldMix[i];
alpha =
alphaHold *
Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);
break;
}
from.totalAlpha += alpha;
if (timeline instanceof RotateTimeline)
this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame);
else {
// This fixes the WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109
Utils.webkit602BugfixHelper(alpha, blend);
if (timelineBlend == MixBlend.setup) {
if (timeline instanceof AttachmentTimeline) {
if (attachments ||
(timelineMode[i] & AnimationState.NOT_LAST) ==
AnimationState.NOT_LAST)
direction = MixDirection.mixIn;
}
else if (timeline instanceof DrawOrderTimeline) {
if (drawOrder)
direction = MixDirection.mixIn;
}
}
timeline.apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, direction);
}
}
}
if (to.mixDuration > 0)
this.queueEvents(from, animationTime);
this.events.length = 0;
from.nextAnimationLast = animationTime;
from.nextTrackLast = from.trackTime;
return mix;
};
/**
* @param {?} timeline
* @param {?} skeleton
* @param {?} time
* @param {?} alpha
* @param {?} blend
* @param {?} timelinesRotation
* @param {?} i
* @param {?} firstFrame
* @return {?}
*/
AnimationState.prototype.applyRotateTimeline = /**
* @param {?} timeline
* @param {?} skeleton
* @param {?} time
* @param {?} alpha
* @param {?} blend
* @param {?} timelinesRotation
* @param {?} i
* @param {?} firstFrame
* @return {?}
*/
function (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) {
if (firstFrame)
timelinesRotation[i] = 0;
if (alpha == 1) {
timeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.mixIn);
return;
}
/** @type {?} */
var rotateTimeline = (/** @type {?} */ (timeline));
/** @type {?} */
var frames = rotateTimeline.frames;
/** @type {?} */
var bone = skeleton.bones[rotateTimeline.boneIndex];
if (!bone.active)
return;
/** @type {?} */
var r1 = 0;
/** @type {?} */
var r2 = 0;
if (time < frames[0]) {
switch (blend) {
case MixBlend.setup:
bone.rotation = bone.data.rotation;
default:
return;
case MixBlend.first:
r1 = bone.rotation;
r2 = bone.data.rotation;
}
}
else {
r1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation;
if (time >= frames[frames.length - RotateTimeline.ENTRIES])
// Time is after last frame.
r2 =
bone.data.rotation +
frames[frames.length + RotateTimeline.PREV_ROTATION];
else {
// Interpolate between the previous frame and the current frame.
/** @type {?} */
var frame = Animation.binarySearch(frames, time, RotateTimeline.ENTRIES);
/** @type {?} */
var prevRotation = frames[frame + RotateTimeline.PREV_ROTATION];
/** @type {?} */
var frameTime = frames[frame];
/** @type {?} */
var percent = rotateTimeline.getCurvePercent((frame >> 1) - 1, 1 -
(time - frameTime) /
(frames[frame + RotateTimeline.PREV_TIME] - frameTime));
r2 = frames[frame + RotateTimeline.ROTATION] - prevRotation;
r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360;
r2 = prevRotation + r2 * percent + bone.data.rotation;
r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360;
}
}
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
/** @type {?} */
var total = 0;
/** @type {?} */
var diff = r2 - r1;
diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360;
if (diff == 0) {
total = timelinesRotation[i];
}
else {
/** @type {?} */
var lastTotal = 0;
/** @type {?} */
var lastDiff = 0;
if (firstFrame) {
lastTotal = 0;
lastDiff = diff;
}
else {
lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops.
lastDiff = timelinesRotation[i + 1]; // Difference between bones.
}
/** @type {?} */
var current = diff > 0;
/** @type {?} */
var dir = lastTotal >= 0;
// Detect cross at 0 (not 180).
if (MathUtils.signum(lastDiff) != MathUtils.signum(diff) &&
Math.abs(lastDiff) <= 90) {
// A cross after a 360 rotation is a loop.
if (Math.abs(lastTotal) > 180)
lastTotal += 360 * MathUtils.signum(lastTotal);
dir = current;
}
total = diff + lastTotal - (lastTotal % 360); // Store loops as part of lastTotal.
if (dir != current)
total += 360 * MathUtils.signum(lastTotal);
timelinesRotation[i] = total;
}
timelinesRotation[i + 1] = diff;
r1 += total * alpha;
bone.rotation = r1 - (16384 - ((16384.499999999996 - r1 / 360) | 0)) * 360;
};
/**
* @param {?} entry
* @param {?} animationTime
* @return {?}
*/
AnimationState.prototype.queueEvents = /**
* @param {?} entry
* @param {?} animationTime
* @return {?}
*/
function (entry, animationTime) {
/** @type {?} */
var animationStart = entry.animationStart;
/** @type {?} */
var animationEnd = entry.animationEnd;
/** @type {?} */
var duration = animationEnd - animationStart;
/** @type {?} */
var trackLastWrapped = entry.trackLast % duration;
// Queue events before complete.
/** @type {?} */
var events = this.events;
/** @type {?} */
var i = 0;
/** @type {?} */
var n = events.length;
for (; i < n; i++) {
/** @type {?} */
var event_1 = events[i];
if (event_1.time < trackLastWrapped)
break;
if (event_1.time > animationEnd)
continue; // Discard events outside animation start/end.
this.queue.event(entry, event_1);
}
// Queue complete if completed a loop iteration or the animation.
/** @type {?} */
var complete = false;
if (entry.loop)
complete = duration == 0 || trackLastWrapped > entry.trackTime % duration;
else
complete =
animationTime >= animationEnd && entry.animationLast < animationEnd;
if (complete)
this.queue.complete(entry);
// Queue events after complete.
for (; i < n; i++) {
/** @type {?} */
var event_2 = events[i];
if (event_2.time < animationStart)
continue; // Discard events outside animation start/end.
this.queue.event(entry, events[i]);
}
};
/**
* @return {?}
*/
AnimationState.prototype.clearTracks = /**
* @return {?}
*/
function () {
/** @type {?} */
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
/**
* @param {?} trackIndex
* @return {?}
*/
AnimationState.prototype.clearTrack = /**
* @param {?} trackIndex
* @return {?}
*/
function (trackIndex) {
if (trackIndex >= this.tracks.length)
return;
/** @type {?} */
var current = this.tracks[trackIndex];
if (current == null)
return;
this.queue.end(current);
this.disposeNext(current);
/** @type {?} */
var entry = current;
while (true) {
/** @type {?} */
var from = entry.mixingFrom;
if (from == null)
break;
this.queue.end(from);
entry.mixingFrom = null;
entry.mixingTo = null;
entry = from;
}
this.tracks[current.trackIndex] = null;
this.queue.drain();
};
/**
* @param {?} index
* @param {?} current
* @param {?} interrupt
* @return {?}
*/
AnimationState.prototype.setCurrent = /**
* @param {?} index
* @param {?} current
* @param {?} interrupt
* @return {?}
*/
function (index, current, interrupt) {
/** @type {?} */
var from = this.expandToIndex(index);
this.tracks[index] = current;
if (from != null) {
if (interrupt)
this.queue.interrupt(from);
current.mixingFrom = from;
from.mixingTo = current;
current.mixTime = 0;
// Store the interrupted mix percentage.
if (from.mixingFrom != null && from.mixDuration > 0)
current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration);
from.timelinesRotation.length = 0; // Reset rotation for mixing out, in case entry was mixed in.
}
this.queue.start(current);
};
/**
* @param {?} trackIndex
* @param {?} animationName
* @param {?} loop
* @return {?}
*/
AnimationState.prototype.setAnimation = /**
* @param {?} trackIndex
* @param {?} animationName
* @param {?} loop
* @return {?}
*/
function (trackIndex, animationName, loop) {
/** @type {?} */
var animation = this.data.skeletonData.findAnimation(animationName);
if (animation == null)
throw new Error("Animation not found: " + animationName);
return this.setAnimationWith(trackIndex, animation, loop);
};
/**
* @param {?} trackIndex
* @param {?} animation
* @param {?} loop
* @return {?}
*/
AnimationState.prototype.setAnimationWith = /**
* @param {?} trackIndex
* @param {?} animation
* @param {?} loop
* @return {?}
*/
function (trackIndex, animation, loop) {
if (animation == null)
throw new Error("animation cannot be null.");
/** @type {?} */
var interrupt = true;
/** @type {?} */
var current = this.expandToIndex(trackIndex);
if (current != null) {
if (current.nextTrackLast == -1) {
// Don't mix from an entry that was never applied.
this.tracks[trackIndex] = current.mixingFrom;
this.queue.interrupt(current);
this.queue.end(current);
this.disposeNext(current);
current = current.mixingFrom;
interrupt = false;
}
else
this.disposeNext(current);
}
/** @type {?} */
var entry = this.trackEntry(trackIndex, animation, loop, current);
this.setCurrent(trackIndex, entry, interrupt);
this.queue.drain();
return entry;
};
/**
* @param {?} trackIndex
* @param {?} animationName
* @param {?} loop
* @param {?} delay
* @return {?}
*/
AnimationState.prototype.addAnimation = /**
* @param {?} trackIndex
* @param {?} animationName
* @param {?} loop
* @param {?} delay
* @return {?}
*/
function (trackIndex, animationName, loop, delay) {
/** @type {?} */
var animation = this.data.skeletonData.findAnimation(animationName);
if (animation == null)
throw new Error("Animation not found: " + animationName);
return this.addAnimationWith(trackIndex, animation, loop, delay);
};
/**
* @param {?} trackIndex
* @param {?} animation
* @param {?} loop
* @param {?} delay
* @return {?}
*/
AnimationState.prototype.addAnimationWith = /**
* @param {?} trackIndex
* @param {?} animation
* @param {?} loop
* @param {?} delay
* @return {?}
*/
function (trackIndex, animation, loop, delay) {
if (animation == null)
throw new Error("animation cannot be null.");
/** @type {?} */
var last = this.expandToIndex(trackIndex);
if (last != null) {
while (last.next != null)
last = last.next;
}
/** @type {?} */
var entry = this.trackEntry(trackIndex, animation, loop, last);
if (last == null) {
this.setCurrent(trackIndex, entry, true);
this.queue.drain();
}
else {
last.next = entry;
if (delay <= 0) {
/** @type {?} */
var duration = last.animationEnd - last.animationStart;
if (duration != 0) {
if (last.loop)
delay += duration * (1 + ((last.trackTime / duration) | 0));
else
delay += Math.max(duration, last.trackTime);
delay -= this.data.getMix(last.animation, animation);
}
else
delay = last.trackTime;
}
}
entry.delay = delay;
return entry;
};
/**
* @param {?} trackIndex
* @param {?} mixDuration
* @return {?}
*/
AnimationState.prototype.setEmptyAnimation = /**
* @param {?} trackIndex
* @param {?} mixDuration
* @return {?}
*/
function (trackIndex, mixDuration) {
/** @type {?} */
var entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation, false);
entry.mixDuration = mixDuration;
entry.trackEnd = mixDuration;
return entry;
};
/**
* @param {?} trackIndex
* @param {?} mixDuration
* @param {?} delay
* @return {?}
*/
AnimationState.prototype.addEmptyAnimation = /**
* @param {?} trackIndex
* @param {?} mixDuration
* @param {?} delay
* @return {?}
*/
function (trackIndex, mixDuration, delay) {
if (delay <= 0)
delay -= mixDuration;
/** @type {?} */
var entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation, false, delay);
entry.mixDuration = mixDuration;
entry.trackEnd = mixDuration;
return entry;
};
/**
* @param {?} mixDuration
* @return {?}
*/
AnimationState.prototype.setEmptyAnimations = /**
* @param {?} mixDuration
* @return {?}
*/
function (mixDuration) {
/** @type {?} */
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++) {
/** @type {?} */
var current = this.tracks[i];
if (current != null)
this.setEmptyAnimation(current.trackIndex, mixDuration);
}
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
/**
* @param {?} index
* @return {?}
*/
AnimationState.prototype.expandToIndex = /**
* @param {?} index
* @return {?}
*/
function (index) {
if (index < this.tracks.length)
return this.tracks[index];
Utils.ensureArrayCapacity(this.tracks, index + 1, null);
this.tracks.length = index + 1;
return null;
};
/**
* @param {?} trackIndex
* @param {?} animation
* @param {?} loop
* @param {?} last
* @return {?}
*/
AnimationState.prototype.trackEntry = /**
* @param {?} trackIndex
* @param {?} animation
* @param {?} loop
* @param {?} last
* @return {?}
*/
function (trackIndex, animation, loop, last) {
/** @type {?} */
var entry = this.trackEntryPool.obtain();
entry.trackIndex = trackIndex;
entry.animation = animation;
entry.loop = loop;
entry.holdPrevious = false;
entry.eventThreshold = 0;
entry.attachmentThreshold = 0;
entry.drawOrderThreshold = 0;
entry.animationStart = 0;
entry.animationEnd = animation.duration;
entry.animationLast = -1;
entry.nextAnimationLast = -1;
entry.delay = 0;
entry.trackTime = 0;
entry.trackLast = -1;
entry.nextTrackLast = -1;
entry.trackEnd = Number.MAX_VALUE;
entry.timeScale = 1;
entry.alpha = 1;
entry.interruptAlpha = 1;
entry.mixTime = 0;
entry.mixDuration =
last == null ? 0 : this.data.getMix(last.animation, animation);
return entry;
};
/**
* @param {?} entry
* @return {?}
*/
AnimationState.prototype.disposeNext = /**
* @param {?} entry
* @return {?}
*/
function (entry) {
/** @type {?} */
var next = entry.next;
while (next != null) {
this.queue.dispose(next);
next = next.next;
}
entry.next = null;
};
/**
* @return {?}
*/
AnimationState.prototype._animationsChanged = /**
* @return {?}
*/
function () {
this.animationsChanged = false;
this.propertyIDs.clear();
for (var i = 0, n = this.tracks.length; i < n; i++) {
/** @type {?} */
var entry = this.tracks[i];
if (entry == null)
continue;
while (entry.mixingFrom != null)
entry = entry.mixingFrom;
do {
if (entry.mixingFrom == null || entry.mixBlend != MixBlend.add)
this.computeHold(entry);
entry = entry.mixingTo;
} while (entry != null);
}
this.propertyIDs.clear();
for (var i = this.tracks.length - 1; i >= 0; i--) {
/** @type {?} */
var entry = this.tracks[i];
while (entry != null) {
this.computeNotLast(entry);
entry = entry.mixingFrom;
}
}
};
/**
* @param {?} entry
* @return {?}
*/
AnimationState.prototype.computeHold = /**
* @param {?} entry
* @return {?}
*/
function (entry) {
/** @type {?} */
var to = entry.mixingTo;
/** @type {?} */
var timelines = entry.animation.timelines;
/** @type {?} */
var timelinesCount = entry.animation.timelines.length;
/** @type {?} */
var timelineMode = Utils.setArraySize(entry.timelineMode, timelinesCount);
entry.timelineHoldMix.length = 0;
/** @type {?} */
var timelineDipMix = Utils.setArraySize(entry.timelineHoldMix, timelinesCount);
/** @type {?} */
var propertyIDs = this.propertyIDs;
if (to != null && to.holdPrevious) {
for (var i = 0; i < timelinesCount; i++) {
propertyIDs.add(timelines[i].getPropertyId());
timelineMode[i] = AnimationState.HOLD;
}
return;
}
outer: for (var i = 0; i < timelinesCount; i++) {
/** @type {?} */
var timeline = timelines[i];
/** @type {?} */
var id = timeline.getPropertyId();
if (!propertyIDs.add(id))
timelineMode[i] = AnimationState.SUBSEQUENT;
else if (to == null ||
timeline instanceof AttachmentTimeline ||
timeline instanceof DrawOrderTimeline ||
timeline instanceof EventTimeline ||
!to.animation.hasTimeline(id)) {
timelineMode[i] = AnimationState.FIRST;
}
else {
for (var next = to.mixingTo; next != null; next = next.mixingTo) {
if (next.animation.hasTimeline(id))
continue;
if (entry.mixDuration > 0) {
timelineMode[i] = AnimationState.HOLD_MIX;
timelineDipMix[i] = next;
continue outer;
}
break;
}
timelineMode[i] = AnimationState.HOLD;
}
}
};
/**
* @param {?} entry
* @return {?}
*/
AnimationState.prototype.computeNotLast = /**
* @param {?} entry
* @return {?}
*/
function (entry) {
/** @type {?} */
var timelines = entry.animation.timelines;
/** @type {?} */
var timelinesCount = entry.animation.timelines.length;
/** @type {?} */
var timelineMode = entry.timelineMode;
/** @type {?} */
var propertyIDs = this.propertyIDs;
for (var i = 0; i < timelinesCount; i++) {
if (timelines[i] instanceof AttachmentTimeline) {
/** @type {?} */
var timeline = (/** @type {?} */ (timelines[i]));
if (!propertyIDs.add(timeline.slotIndex))
timelineMode[i] |= AnimationState.NOT_LAST;
}
}
};
/**
* @param {?} trackIndex
* @return {?}
*/
AnimationState.prototype.getCurrent = /**
* @param {?} trackIndex
* @return {?}
*/
function (trackIndex) {
if (trackIndex >= this.tracks.length)
return null;
return this.tracks[trackIndex];
};
/**
* @param {?} listener
* @return {?}
*/
AnimationState.prototype.addListener = /**
* @param {?} listener
* @return {?}
*/
function (listener) {
if (listener == null)
throw new Error("listener cannot be null.");
this.listeners.push(listener);
};
/** Removes the listener added with {@link #addListener(AnimationStateListener)}. */
/**
* Removes the listener added with {\@link #addListener(AnimationStateListener)}.
* @param {?} listener
* @return {?}
*/
AnimationState.prototype.removeListener = /**
* Removes the listener added with {\@link #addListener(AnimationStateListener)}.
* @param {?} listener
* @return {?}
*/
function (listener) {
/** @type {?} */
var index = this.listeners.indexOf(listener);
if (index >= 0)
this.listeners.splice(index, 1);
};
/**
* @return {?}
*/
AnimationState.prototype.clearListeners = /**
* @return {?}
*/
function () {
this.listeners.length = 0;
};
/**
* @return {?}
*/
AnimationState.prototype.clearListenerNotifications = /**
* @return {?}
*/
function () {
this.queue.clear();
};
AnimationState.emptyAnimation = new Animation("<empty>", [], 0);
AnimationState.SUBSEQUENT = 0;
AnimationState.FIRST = 1;
AnimationState.HOLD = 2;
AnimationState.HOLD_MIX = 3;
AnimationState.NOT_LAST = 4;
return AnimationState;
}());
export { AnimationState };
if (false) {
/** @type {?} */
AnimationState.emptyAnimation;
/** @type {?} */
AnimationState.SUBSEQUENT;
/** @type {?} */
AnimationState.FIRST;
/** @type {?} */
AnimationState.HOLD;
/** @type {?} */
AnimationState.HOLD_MIX;
/** @type {?} */
AnimationState.NOT_LAST;
/** @type {?} */
AnimationState.prototype.data;
/** @type {?} */
AnimationState.prototype.tracks;
/** @type {?} */
AnimationState.prototype.events;
/** @type {?} */
AnimationState.prototype.listeners;
/** @type {?} */
AnimationState.prototype.queue;
/** @type {?} */
AnimationState.prototype.propertyIDs;
/** @type {?} */
AnimationState.prototype.animationsChanged;
/** @type {?} */
AnimationState.prototype.timeScale;
/** @type {?} */
AnimationState.prototype.trackEntryPool;
}
var TrackEntry = /** @class */ (function () {
function TrackEntry() {
this.mixBlend = MixBlend.replace;
this.timelineMode = new Array();
this.timelineHoldMix = new Array();
this.timelinesRotation = new Array();
}
/**
* @return {?}
*/
TrackEntry.prototype.reset = /**
* @return {?}
*/
function () {
this.next = null;
this.mixingFrom = null;
this.mixingTo = null;
this.animation = null;
this.listener = null;
this.timelineMode.length = 0;
this.timelineHoldMix.length = 0;
this.timelinesRotation.length = 0;
};
/**
* @return {?}
*/
TrackEntry.prototype.getAnimationTime = /**
* @return {?}
*/
function () {
if (this.loop) {
/** @type {?} */
var duration = this.animationEnd - this.animationStart;
if (duration == 0)
return this.animationStart;
return (this.trackTime % duration) + this.animationStart;
}
return Math.min(this.trackTime + this.animationStart, this.animationEnd);
};
/**
* @param {?} animationLast
* @return {?}
*/
TrackEntry.prototype.setAnimationLast = /**
* @param {?} animationLast
* @return {?}
*/
function (animationLast) {
this.animationLast = animationLast;
this.nextAnimationLast = animationLast;
};
/**
* @return {?}
*/
TrackEntry.prototype.isComplete = /**
* @return {?}
*/
function () {
return this.trackTime >= this.animationEnd - this.animationStart;
};
/**
* @return {?}
*/
TrackEntry.prototype.resetRotationDirections = /**
* @return {?}
*/
function () {
this.timelinesRotation.length = 0;
};
return TrackEntry;
}());
export { TrackEntry };
if (false) {
/** @type {?} */
TrackEntry.prototype.animation;
/** @type {?} */
TrackEntry.prototype.next;
/** @type {?} */
TrackEntry.prototype.mixingFrom;
/** @type {?} */
TrackEntry.prototype.mixingTo;
/** @type {?} */
TrackEntry.prototype.listener;
/** @type {?} */
TrackEntry.prototype.trackIndex;
/** @type {?} */
TrackEntry.prototype.loop;
/** @type {?} */
TrackEntry.prototype.holdPrevious;
/** @type {?} */
TrackEntry.prototype.eventThreshold;
/** @type {?} */
TrackEntry.prototype.attachmentThreshold;
/** @type {?} */
TrackEntry.prototype.drawOrderThreshold;
/** @type {?} */
TrackEntry.prototype.animationStart;
/** @type {?} */
TrackEntry.prototype.animationEnd;
/** @type {?} */
TrackEntry.prototype.animationLast;
/** @type {?} */
TrackEntry.prototype.nextAnimationLast;
/** @type {?} */
TrackEntry.prototype.delay;
/** @type {?} */
TrackEntry.prototype.trackTime;
/** @type {?} */
TrackEntry.prototype.trackLast;
/** @type {?} */
TrackEntry.prototype.nextTrackLast;
/** @type {?} */
TrackEntry.prototype.trackEnd;
/** @type {?} */
TrackEntry.prototype.timeScale;
/** @type {?} */
TrackEntry.prototype.alpha;
/** @type {?} */
TrackEntry.prototype.mixTime;
/** @type {?} */
TrackEntry.prototype.mixDuration;
/** @type {?} */
TrackEntry.prototype.interruptAlpha;
/** @type {?} */
TrackEntry.prototype.totalAlpha;
/** @type {?} */
TrackEntry.prototype.mixBlend;
/** @type {?} */
TrackEntry.prototype.timelineMode;
/** @type {?} */
TrackEntry.prototype.timelineHoldMix;
/** @type {?} */
TrackEntry.prototype.timelinesRotation;
}
var EventQueue = /** @class */ (function () {
function EventQueue(animState) {
this.objects = [];
this.drainDisabled = false;
this.animState = animState;
}
/**
* @param {?} entry
* @return {?}
*/
EventQueue.prototype.start = /**
* @param {?} entry
* @return {?}
*/
function (entry) {
this.objects.push(EventType.start);
this.objects.push(entry);
this.animState.animationsChanged = true;
};
/**
* @param {?} entry
* @return {?}
*/
EventQueue.prototype.interrupt = /**
* @param {?} entry
* @return {?}
*/
function (entry) {
this.objects.push(EventType.interrupt);
this.objects.push(entry);
};
/**
* @param {?} entry
* @return {?}
*/
EventQueue.prototype.end = /**
* @param {?} entry
* @return {?}
*/
function (entry) {
this.objects.push(EventType.end);
this.objects.push(entry);
this.animState.animationsChanged = true;
};
/**
* @param {?} entry
* @return {?}
*/
EventQueue.prototype.dispose = /**
* @param {?} entry
* @return {?}
*/
function (entry) {
this.objects.push(EventType.dispose);
this.objects.push(entry);
};
/**
* @param {?} entry
* @return {?}
*/
EventQueue.prototype.complete = /**
* @param {?} entry
* @return {?}
*/
function (entry) {
this.objects.push(EventType.complete);
this.objects.push(entry);
};
/**
* @param {?} entry
* @param {?} event
* @return {?}
*/
EventQueue.prototype.event = /**
* @param {?} entry
* @param {?} event
* @return {?}
*/
function (entry, event) {
this.objects.push(EventType.event);
this.objects.push(entry);
this.objects.push(event);
};
/**
* @return {?}
*/
EventQueue.prototype.drain = /**
* @return {?}
*/
function () {
if (this.drainDisabled)
return;
this.drainDisabled = true;
/** @type {?} */
var objects = this.objects;
/** @type {?} */
var listeners = this.animState.listeners;
for (var i = 0; i < objects.length; i += 2) {
/** @type {?} */
var type = (/** @type {?} */ (objects[i]));
/** @type {?} */
var entry = (/** @type {?} */ (objects[i + 1]));
switch (type) {
case EventType.start:
if (entry.listener != null && entry.listener.start)
entry.listener.start(entry);
for (var ii = 0; ii < listeners.length; ii++)
if (listeners[ii].start)
listeners[ii].start(entry);
break;
case EventType.interrupt:
if (entry.listener != null && entry.listener.interrupt)
entry.listener.interrupt(entry);
for (var ii = 0; ii < listeners.length; ii++)
if (listeners[ii].interrupt)
listeners[ii].interrupt(entry);
break;
case EventType.end:
if (entry.listener != null && entry.listener.end)
entry.listener.end(entry);
for (var ii = 0; ii < listeners.length; ii++)
if (listeners[ii].end)
listeners[ii].end(entry);
// Fall through.
case EventType.dispose:
if (entry.listener != null && entry.listener.dispose)
entry.listener.dispose(entry);
for (var ii = 0; ii < listeners.length; ii++)
if (listeners[ii].dispose)
listeners[ii].dispose(entry);
this.animState.trackEntryPool.free(entry);
break;
case EventType.complete:
if (entry.listener != null && entry.listener.complete)
entry.listener.complete(entry);
for (var ii = 0; ii < listeners.length; ii++)
if (listeners[ii].complete)
listeners[ii].complete(entry);
break;
case EventType.event:
/** @type {?} */
var event_3 = (/** @type {?} */ (objects[i++ + 2]));
if (entry.listener != null && entry.listener.event)
entry.listener.event(entry, event_3);
for (var ii = 0; ii < listeners.length; ii++)
if (listeners[ii].event)
listeners[ii].event(entry, event_3);
break;
}
}
this.clear();
this.drainDisabled = false;
};
/**
* @return {?}
*/
EventQueue.prototype.clear = /**
* @return {?}
*/
function () {
this.objects.length = 0;
};
return EventQueue;
}());
export { EventQueue };
if (false) {
/** @type {?} */
EventQueue.prototype.objects;
/** @type {?} */
EventQueue.prototype.drainDisabled;
/** @type {?} */
EventQueue.prototype.animState;
}
/** @enum {number} */
var EventType = {
start: 0,
interrupt: 1,
end: 2,
dispose: 3,
complete: 4,
event: 5,
};
export { EventType };
EventType[EventType.start] = 'start';
EventType[EventType.interrupt] = 'interrupt';
EventType[EventType.end] = 'end';
EventType[EventType.dispose] = 'dispose';
EventType[EventType.complete] = 'complete';
EventType[EventType.event] = 'event';
/**
* @record
*/
export function AnimationStateListener2() { }
if (false) {
/**
* Invoked when this entry has been set as the current entry.
* @param {?} entry
* @return {?}
*/
AnimationStateListener2.prototype.start = function (entry) { };
/**
* Invoked when another entry has replaced this entry as the current entry. This entry may continue being applied for
* mixing.
* @param {?} entry
* @return {?}
*/
AnimationStateListener2.prototype.interrupt = function (entry) { };
/**
* Invoked when this entry is no longer the current entry and will never be applied again.
* @param {?} entry
* @return {?}
*/
AnimationStateListener2.prototype.end = function (entry) { };
/**
* Invoked when this entry will be disposed. This may occur without the entry ever being set as the current en