mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[as3] Ported holdPrevious in AnimationState. See #1169.
This commit is contained in:
parent
4202fd1363
commit
018d3a9e3d
Binary file not shown.
@ -38,8 +38,8 @@ package spine.animation {
|
|||||||
public class AnimationState {
|
public class AnimationState {
|
||||||
public static var SUBSEQUENT : int = 0;
|
public static var SUBSEQUENT : int = 0;
|
||||||
public static var FIRST : int = 1;
|
public static var FIRST : int = 1;
|
||||||
public static var DIP : int = 2;
|
public static var HOLD : int = 2;
|
||||||
public static var DIP_MIX : int = 3;
|
public static var HOLD_MIX : int = 3;
|
||||||
internal static var emptyAnimation : Animation = new Animation("<empty>", new Vector.<Timeline>(), 0);
|
internal static var emptyAnimation : Animation = new Animation("<empty>", new Vector.<Timeline>(), 0);
|
||||||
public var data : AnimationStateData;
|
public var data : AnimationStateData;
|
||||||
public var tracks : Vector.<TrackEntry> = new Vector.<TrackEntry>();
|
public var tracks : Vector.<TrackEntry> = new Vector.<TrackEntry>();
|
||||||
@ -112,6 +112,7 @@ package spine.animation {
|
|||||||
// End mixing from entries once all have completed.
|
// End mixing from entries once all have completed.
|
||||||
var from : TrackEntry = current.mixingFrom;
|
var from : TrackEntry = current.mixingFrom;
|
||||||
current.mixingFrom = null;
|
current.mixingFrom = null;
|
||||||
|
if (from != null) from.mixingTo = null;
|
||||||
while (from != null) {
|
while (from != null) {
|
||||||
queue.end(from);
|
queue.end(from);
|
||||||
from = from.mixingFrom;
|
from = from.mixingFrom;
|
||||||
@ -138,6 +139,7 @@ package spine.animation {
|
|||||||
// Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame).
|
// Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame).
|
||||||
if (from.totalAlpha == 0 || to.mixDuration == 0) {
|
if (from.totalAlpha == 0 || to.mixDuration == 0) {
|
||||||
to.mixingFrom = from.mixingFrom;
|
to.mixingFrom = from.mixingFrom;
|
||||||
|
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
|
||||||
to.interruptAlpha = from.interruptAlpha;
|
to.interruptAlpha = from.interruptAlpha;
|
||||||
queue.end(from);
|
queue.end(from);
|
||||||
}
|
}
|
||||||
@ -174,11 +176,11 @@ package spine.animation {
|
|||||||
var timelineCount : int = current.animation.timelines.length;
|
var timelineCount : int = current.animation.timelines.length;
|
||||||
var timelines : Vector.<Timeline> = current.animation.timelines;
|
var timelines : Vector.<Timeline> = current.animation.timelines;
|
||||||
var ii : int = 0;
|
var ii : int = 0;
|
||||||
if (mix == 1 || blend == MixBlend.add) {
|
if (i == 0 && (mix == 1 || blend == MixBlend.add)) {
|
||||||
for (ii = 0; ii < timelineCount; ii++)
|
for (ii = 0; ii < timelineCount; ii++)
|
||||||
Timeline(timelines[ii]).apply(skeleton, animationLast, animationTime, events, mix, blend, MixDirection.In);
|
Timeline(timelines[ii]).apply(skeleton, animationLast, animationTime, events, mix, blend, MixDirection.In);
|
||||||
} else {
|
} else {
|
||||||
var timelineData : Vector.<int> = current.timelineData;
|
var timelineMode : Vector.<int> = current.timelineMode;
|
||||||
|
|
||||||
var firstFrame : Boolean = current.timelinesRotation.length == 0;
|
var firstFrame : Boolean = current.timelinesRotation.length == 0;
|
||||||
if (firstFrame) current.timelinesRotation.length = timelineCount << 1;
|
if (firstFrame) current.timelinesRotation.length = timelineCount << 1;
|
||||||
@ -186,7 +188,7 @@ package spine.animation {
|
|||||||
|
|
||||||
for (ii = 0; ii < timelineCount; ii++) {
|
for (ii = 0; ii < timelineCount; ii++) {
|
||||||
var timeline : Timeline = timelines[ii];
|
var timeline : Timeline = timelines[ii];
|
||||||
var timelineBlend : MixBlend = timelineData[ii] == AnimationState.SUBSEQUENT ? blend : MixBlend.setup;
|
var timelineBlend : MixBlend = timelineMode[ii] == AnimationState.SUBSEQUENT ? blend : MixBlend.setup;
|
||||||
if (timeline is RotateTimeline) {
|
if (timeline is RotateTimeline) {
|
||||||
applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
|
applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
|
||||||
} else
|
} else
|
||||||
@ -222,15 +224,15 @@ package spine.animation {
|
|||||||
var animationLast : Number = from.animationLast, animationTime : Number = from.getAnimationTime();
|
var animationLast : Number = from.animationLast, animationTime : Number = from.getAnimationTime();
|
||||||
var timelineCount : int = from.animation.timelines.length;
|
var timelineCount : int = from.animation.timelines.length;
|
||||||
var timelines : Vector.<Timeline> = from.animation.timelines;
|
var timelines : Vector.<Timeline> = from.animation.timelines;
|
||||||
var alphaDip : Number = from.alpha * to.interruptAlpha;
|
var alphaHold : Number = from.alpha * to.interruptAlpha;
|
||||||
var alphaMix : Number = alphaDip * (1 - mix);
|
var alphaMix : Number = alphaHold * (1 - mix);
|
||||||
var i : int = 0;
|
var i : int = 0;
|
||||||
if (blend == MixBlend.add) {
|
if (blend == MixBlend.add) {
|
||||||
for (i = 0; i < timelineCount; i++)
|
for (i = 0; i < timelineCount; i++)
|
||||||
timelines[i].apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.Out);
|
timelines[i].apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.Out);
|
||||||
} else {
|
} else {
|
||||||
var timelineData : Vector.<int> = from.timelineData;
|
var timelineMode : Vector.<int> = from.timelineMode;
|
||||||
var timelineDipMix : Vector.<TrackEntry> = from.timelineDipMix;
|
var timelineHoldMix : Vector.<TrackEntry> = from.timelineHoldMix;
|
||||||
|
|
||||||
var firstFrame : Boolean = from.timelinesRotation.length == 0;
|
var firstFrame : Boolean = from.timelinesRotation.length == 0;
|
||||||
if (firstFrame) from.timelinesRotation.length = timelineCount << 1;
|
if (firstFrame) from.timelinesRotation.length = timelineCount << 1;
|
||||||
@ -241,7 +243,7 @@ package spine.animation {
|
|||||||
var timeline : Timeline = timelines[i];
|
var timeline : Timeline = timelines[i];
|
||||||
var timelineBlend: MixBlend;
|
var timelineBlend: MixBlend;
|
||||||
var alpha : Number = 0;
|
var alpha : Number = 0;
|
||||||
switch (timelineData[i]) {
|
switch (timelineMode[i]) {
|
||||||
case SUBSEQUENT:
|
case SUBSEQUENT:
|
||||||
if (!attachments && timeline is AttachmentTimeline) continue;
|
if (!attachments && timeline is AttachmentTimeline) continue;
|
||||||
if (!drawOrder && timeline is DrawOrderTimeline) continue;
|
if (!drawOrder && timeline is DrawOrderTimeline) continue;
|
||||||
@ -252,14 +254,14 @@ package spine.animation {
|
|||||||
timelineBlend = MixBlend.setup;
|
timelineBlend = MixBlend.setup;
|
||||||
alpha = alphaMix;
|
alpha = alphaMix;
|
||||||
break;
|
break;
|
||||||
case DIP:
|
case HOLD:
|
||||||
timelineBlend = MixBlend.setup;
|
timelineBlend = MixBlend.setup;
|
||||||
alpha = alphaDip;
|
alpha = alphaHold;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
timelineBlend = MixBlend.setup;
|
timelineBlend = MixBlend.setup;
|
||||||
var dipMix : TrackEntry = timelineDipMix[i];
|
var holdMix : TrackEntry = timelineHoldMix[i];
|
||||||
alpha = alphaDip * Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration);
|
alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
from.totalAlpha += alpha;
|
from.totalAlpha += alpha;
|
||||||
@ -399,6 +401,7 @@ package spine.animation {
|
|||||||
if (from == null) break;
|
if (from == null) break;
|
||||||
queue.end(from);
|
queue.end(from);
|
||||||
entry.mixingFrom = null;
|
entry.mixingFrom = null;
|
||||||
|
entry.mixingTo = null;
|
||||||
entry = from;
|
entry = from;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,6 +417,7 @@ package spine.animation {
|
|||||||
if (from != null) {
|
if (from != null) {
|
||||||
if (interrupt) queue.interrupt(from);
|
if (interrupt) queue.interrupt(from);
|
||||||
current.mixingFrom = from;
|
current.mixingFrom = from;
|
||||||
|
from.mixingTo = current;
|
||||||
current.mixTime = 0;
|
current.mixTime = 0;
|
||||||
|
|
||||||
// Store the interrupted mix percentage.
|
// Store the interrupted mix percentage.
|
||||||
@ -529,6 +533,7 @@ package spine.animation {
|
|||||||
entry.trackIndex = trackIndex;
|
entry.trackIndex = trackIndex;
|
||||||
entry.animation = animation;
|
entry.animation = animation;
|
||||||
entry.loop = loop;
|
entry.loop = loop;
|
||||||
|
entry.holdPrevious = false;
|
||||||
|
|
||||||
entry.eventThreshold = 0;
|
entry.eventThreshold = 0;
|
||||||
entry.attachmentThreshold = 0;
|
entry.attachmentThreshold = 0;
|
||||||
@ -565,15 +570,70 @@ package spine.animation {
|
|||||||
private function _animationsChanged() : void {
|
private function _animationsChanged() : void {
|
||||||
animationsChanged = false;
|
animationsChanged = false;
|
||||||
|
|
||||||
var propertyIDs : Dictionary = this.propertyIDs = new Dictionary();
|
propertyIDs = new Dictionary();
|
||||||
var mixingTo : Vector.<TrackEntry> = this.mixingTo;
|
|
||||||
for (var i : int = 0, n : int = tracks.length; i < n; i++) {
|
for (var i : int = 0, n : int = tracks.length; i < n; i++) {
|
||||||
var entry : TrackEntry = tracks[i];
|
var entry : TrackEntry = tracks[i];
|
||||||
if (entry != null && (i == 0 || entry.mixBlend != MixBlend.add))
|
if (entry == null) continue;
|
||||||
entry.setTimelineData(null, mixingTo, propertyIDs);
|
while (entry.mixingFrom != null)
|
||||||
|
entry = entry.mixingFrom;
|
||||||
|
do {
|
||||||
|
if (entry.mixingTo == null || entry.mixBlend != MixBlend.add) setTimelineModes(entry);
|
||||||
|
entry = entry.mixingTo;
|
||||||
|
} while (entry != null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function setTimelineModes (entry: TrackEntry) {
|
||||||
|
var to: TrackEntry = entry.mixingTo;
|
||||||
|
var timelines : Vector.<Timeline> = entry.animation.timelines;
|
||||||
|
var timelinesCount : int = entry.animation.timelines.length;
|
||||||
|
var timelineMode : Vector.<int> = entry.timelineMode;
|
||||||
|
timelineMode.length = timelinesCount;
|
||||||
|
var timelineHoldMix : Vector.<TrackEntry> = entry.timelineHoldMix;
|
||||||
|
timelineHoldMix.length = 0;
|
||||||
|
var propertyIDs: Dictionary = this.propertyIDs;
|
||||||
|
|
||||||
|
if (to != null && to.holdPrevious) {
|
||||||
|
for (var i : int = 0; i < timelinesCount; i++) {
|
||||||
|
propertyIDs[timelines[i].getPropertyId().toString()] = true;
|
||||||
|
timelineMode[i] = HOLD;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
outer:
|
||||||
|
for (var i : int = 0; i < timelinesCount; i++) {
|
||||||
|
var intId : int = timelines[i].getPropertyId();
|
||||||
|
var id : String = intId.toString();
|
||||||
|
var contained: Object = propertyIDs[id];
|
||||||
|
propertyIDs[id] = true;
|
||||||
|
if (contained != null) {
|
||||||
|
timelineMode[i] = AnimationState.SUBSEQUENT;
|
||||||
|
} else if (to == null || !hasTimeline(to, intId)) {
|
||||||
|
timelineMode[i] = AnimationState.FIRST;
|
||||||
|
} else {
|
||||||
|
for (var next : TrackEntry = to.mixingTo; next != null; next = next.mixingTo) {
|
||||||
|
if (hasTimeline(next, intId)) continue;
|
||||||
|
if (entry.mixDuration > 0) {
|
||||||
|
timelineMode[i] = AnimationState.HOLD_MIX;
|
||||||
|
timelineHoldMix[i] = entry;
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
timelineMode[i] = AnimationState.HOLD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function hasTimeline (entry: TrackEntry, id : int) : Boolean {
|
||||||
|
var timelines : Vector.<Timeline> = entry.animation.timelines;
|
||||||
|
for (var i : int = 0, n : int = entry.animation.timelines.length; i < n; i++)
|
||||||
|
if (timelines[i].getPropertyId() == id) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function getCurrent(trackIndex : int) : TrackEntry {
|
public function getCurrent(trackIndex : int) : TrackEntry {
|
||||||
if (trackIndex >= tracks.length) return null;
|
if (trackIndex >= tracks.length) return null;
|
||||||
return tracks[trackIndex];
|
return tracks[trackIndex];
|
||||||
|
|||||||
@ -34,7 +34,7 @@ package spine.animation {
|
|||||||
|
|
||||||
public class TrackEntry implements Poolable {
|
public class TrackEntry implements Poolable {
|
||||||
public var animation : Animation;
|
public var animation : Animation;
|
||||||
public var next : TrackEntry, mixingFrom : TrackEntry;
|
public var next : TrackEntry, mixingFrom : TrackEntry, mixingTo: TrackEntry;
|
||||||
public var onStart : Listeners = new Listeners();
|
public var onStart : Listeners = new Listeners();
|
||||||
public var onInterrupt : Listeners = new Listeners();
|
public var onInterrupt : Listeners = new Listeners();
|
||||||
public var onEnd : Listeners = new Listeners();
|
public var onEnd : Listeners = new Listeners();
|
||||||
@ -42,14 +42,14 @@ package spine.animation {
|
|||||||
public var onComplete : Listeners = new Listeners();
|
public var onComplete : Listeners = new Listeners();
|
||||||
public var onEvent : Listeners = new Listeners();
|
public var onEvent : Listeners = new Listeners();
|
||||||
public var trackIndex : int;
|
public var trackIndex : int;
|
||||||
public var loop : Boolean;
|
public var loop : Boolean, holdPrevious: Boolean;
|
||||||
public var eventThreshold : Number, attachmentThreshold : Number, drawOrderThreshold : Number;
|
public var eventThreshold : Number, attachmentThreshold : Number, drawOrderThreshold : Number;
|
||||||
public var animationStart : Number, animationEnd : Number, animationLast : Number, nextAnimationLast : Number;
|
public var animationStart : Number, animationEnd : Number, animationLast : Number, nextAnimationLast : Number;
|
||||||
public var delay : Number, trackTime : Number, trackLast : Number, nextTrackLast : Number, trackEnd : Number, timeScale : Number;
|
public var delay : Number, trackTime : Number, trackLast : Number, nextTrackLast : Number, trackEnd : Number, timeScale : Number;
|
||||||
public var alpha : Number, mixTime : Number, mixDuration : Number, interruptAlpha : Number, totalAlpha : Number = 0;
|
public var alpha : Number, mixTime : Number, mixDuration : Number, interruptAlpha : Number, totalAlpha : Number = 0;
|
||||||
public var mixBlend: MixBlend = MixBlend.replace;
|
public var mixBlend: MixBlend = MixBlend.replace;
|
||||||
public var timelineData : Vector.<int> = new Vector.<int>();
|
public var timelineMode : Vector.<int> = new Vector.<int>();
|
||||||
public var timelineDipMix : Vector.<TrackEntry> = new Vector.<TrackEntry>();
|
public var timelineHoldMix : Vector.<TrackEntry> = new Vector.<TrackEntry>();
|
||||||
public var timelinesRotation : Vector.<Number> = new Vector.<Number>();
|
public var timelinesRotation : Vector.<Number> = new Vector.<Number>();
|
||||||
|
|
||||||
public function TrackEntry() {
|
public function TrackEntry() {
|
||||||
@ -67,6 +67,7 @@ package spine.animation {
|
|||||||
public function reset() : void {
|
public function reset() : void {
|
||||||
next = null;
|
next = null;
|
||||||
mixingFrom = null;
|
mixingFrom = null;
|
||||||
|
mixingTo = null;
|
||||||
animation = null;
|
animation = null;
|
||||||
onStart.listeners.length = 0;
|
onStart.listeners.length = 0;
|
||||||
onInterrupt.listeners.length = 0;
|
onInterrupt.listeners.length = 0;
|
||||||
@ -74,61 +75,11 @@ package spine.animation {
|
|||||||
onDispose.listeners.length = 0;
|
onDispose.listeners.length = 0;
|
||||||
onComplete.listeners.length = 0;
|
onComplete.listeners.length = 0;
|
||||||
onEvent.listeners.length = 0;
|
onEvent.listeners.length = 0;
|
||||||
timelineData.length = 0;
|
timelineMode.length = 0;
|
||||||
timelineDipMix.length = 0;
|
timelineHoldMix.length = 0;
|
||||||
timelinesRotation.length = 0;
|
timelinesRotation.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTimelineData (to: TrackEntry, mixingToArray : Vector.<TrackEntry>, propertyIDs : Dictionary) : TrackEntry {
|
|
||||||
if (to != null) mixingToArray.push(to);
|
|
||||||
var lastEntry : TrackEntry = mixingFrom != null ? mixingFrom.setTimelineData(this, mixingToArray, propertyIDs) : this;
|
|
||||||
if (to != null) mixingToArray.pop();
|
|
||||||
|
|
||||||
var mixingTo : Vector.<TrackEntry> = mixingToArray;
|
|
||||||
var mixingToLast : int = mixingToArray.length - 1;
|
|
||||||
var timelines : Vector.<Timeline> = animation.timelines;
|
|
||||||
var timelinesCount : int = animation.timelines.length;
|
|
||||||
var timelineData : Vector.<int> = this.timelineData;
|
|
||||||
timelineData.length = timelinesCount;
|
|
||||||
this.timelineDipMix.length = 0;
|
|
||||||
var timelineDipMix : Vector.<TrackEntry> = this.timelineDipMix;
|
|
||||||
timelineDipMix.length = timelinesCount;
|
|
||||||
|
|
||||||
outer:
|
|
||||||
for (var i : int = 0; i < timelinesCount; i++) {
|
|
||||||
var intId : int = timelines[i].getPropertyId();
|
|
||||||
var id : String = intId.toString();
|
|
||||||
var contained: Object = propertyIDs[id];
|
|
||||||
propertyIDs[id] = true;
|
|
||||||
if (contained != null) {
|
|
||||||
timelineData[i] = AnimationState.SUBSEQUENT;
|
|
||||||
} else if (to == null || !to.hasTimeline(intId)) {
|
|
||||||
timelineData[i] = AnimationState.FIRST;
|
|
||||||
} else {
|
|
||||||
for (var ii : int = mixingToLast; ii >= 0; ii--) {
|
|
||||||
var entry : TrackEntry = mixingTo[ii];
|
|
||||||
if (!entry.hasTimeline(intId)) {
|
|
||||||
if (entry.mixDuration > 0) {
|
|
||||||
timelineData[i] = AnimationState.DIP_MIX;
|
|
||||||
timelineDipMix[i] = entry;
|
|
||||||
continue outer;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timelineData[i] = AnimationState.DIP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lastEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function hasTimeline (id : int) : Boolean {
|
|
||||||
var timelines : Vector.<Timeline> = animation.timelines;
|
|
||||||
for (var i : int = 0, n : int = animation.timelines.length; i < n; i++)
|
|
||||||
if (timelines[i].getPropertyId() == id) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resetRotationDirection() : void {
|
public function resetRotationDirection() : void {
|
||||||
timelinesRotation.length = 0;
|
timelinesRotation.length = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@ -69,6 +69,7 @@ package spine.examples {
|
|||||||
var skeletonData : SkeletonData = json.readSkeletonData(new SpineboyJson());
|
var skeletonData : SkeletonData = json.readSkeletonData(new SpineboyJson());
|
||||||
|
|
||||||
var stateData : AnimationStateData = new AnimationStateData(skeletonData);
|
var stateData : AnimationStateData = new AnimationStateData(skeletonData);
|
||||||
|
stateData.setMixByName("walk", "run", 0.4);
|
||||||
stateData.setMixByName("run", "jump", 0.4);
|
stateData.setMixByName("run", "jump", 0.4);
|
||||||
stateData.setMixByName("jump", "run", 0.4);
|
stateData.setMixByName("jump", "run", 0.4);
|
||||||
stateData.setMixByName("jump", "jump", 0.4);
|
stateData.setMixByName("jump", "jump", 0.4);
|
||||||
|
|||||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user