Jelajahi Sumber

[as3] Ported holdPrevious in AnimationState. See #1169.

badlogic 7 tahun lalu
induk
melakukan
018d3a9e3d

TEMPAT SAMPAH
spine-as3/spine-as3-example/lib/spine-as3.swc


+ 78 - 18
spine-as3/spine-as3/src/spine/animation/AnimationState.as

@@ -38,8 +38,8 @@ package spine.animation {
 	public class AnimationState {
 		public static var SUBSEQUENT : int = 0;
 		public static var FIRST : int = 1;
-		public static var DIP : int = 2;
-		public static var DIP_MIX : int = 3;
+		public static var HOLD : int = 2;
+		public static var HOLD_MIX : int = 3;
 		internal static var emptyAnimation : Animation = new Animation("<empty>", new Vector.<Timeline>(), 0);
 		public var data : AnimationStateData;
 		public var tracks : Vector.<TrackEntry> = new Vector.<TrackEntry>();
@@ -112,6 +112,7 @@ package spine.animation {
 					// End mixing from entries once all have completed.
 					var from : TrackEntry = current.mixingFrom;
 					current.mixingFrom = null;
+					if (from != null) from.mixingTo = null;
 					while (from != null) {
 						queue.end(from);
 						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).
 				if (from.totalAlpha == 0 || to.mixDuration == 0) {
 					to.mixingFrom = from.mixingFrom;
+					if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
 					to.interruptAlpha = from.interruptAlpha;
 					queue.end(from);					
 				}
@@ -174,11 +176,11 @@ package spine.animation {
 				var timelineCount : int = current.animation.timelines.length;
 				var timelines : Vector.<Timeline> = current.animation.timelines;
 				var ii : int = 0;
-				if (mix == 1 || blend == MixBlend.add) {
+				if (i == 0 && (mix == 1 || blend == MixBlend.add)) {
 					for (ii = 0; ii < timelineCount; ii++)
 						Timeline(timelines[ii]).apply(skeleton, animationLast, animationTime, events, mix, blend, MixDirection.In);
 				} else {
-					var timelineData : Vector.<int> = current.timelineData;
+					var timelineMode : Vector.<int> = current.timelineMode;
 					
 					var firstFrame : Boolean = current.timelinesRotation.length == 0;
 					if (firstFrame) current.timelinesRotation.length = timelineCount << 1;
@@ -186,7 +188,7 @@ package spine.animation {
 					
 					for (ii = 0; ii < timelineCount; 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) {
 							applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
 						} else
@@ -222,15 +224,15 @@ package spine.animation {
 			var animationLast : Number = from.animationLast, animationTime : Number = from.getAnimationTime();
 			var timelineCount : int = from.animation.timelines.length;
 			var timelines : Vector.<Timeline> = from.animation.timelines;
-			var alphaDip : Number = from.alpha * to.interruptAlpha;
-			var alphaMix : Number = alphaDip * (1 - mix);
+			var alphaHold : Number = from.alpha * to.interruptAlpha;
+			var alphaMix : Number = alphaHold * (1 - mix);
 			var i : int = 0;
 			if (blend == MixBlend.add) {
 				for (i = 0; i < timelineCount; i++)
 					timelines[i].apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.Out);
 			} else {
-				var timelineData : Vector.<int> = from.timelineData;
-				var timelineDipMix : Vector.<TrackEntry> = from.timelineDipMix;
+				var timelineMode : Vector.<int> = from.timelineMode;
+				var timelineHoldMix : Vector.<TrackEntry> = from.timelineHoldMix;
 	
 				var firstFrame : Boolean = from.timelinesRotation.length == 0;
 				if (firstFrame) from.timelinesRotation.length = timelineCount << 1;
@@ -241,7 +243,7 @@ package spine.animation {
 					var timeline : Timeline = timelines[i];
 					var timelineBlend: MixBlend;
 					var alpha : Number = 0;
-					switch (timelineData[i]) {
+					switch (timelineMode[i]) {
 					case SUBSEQUENT:
 						if (!attachments && timeline is AttachmentTimeline) continue;
 						if (!drawOrder && timeline is DrawOrderTimeline) continue;
@@ -252,14 +254,14 @@ package spine.animation {
 						timelineBlend = MixBlend.setup;
 						alpha = alphaMix;
 						break;
-					case DIP:
+					case HOLD:
 						timelineBlend = MixBlend.setup;
-						alpha = alphaDip;
+						alpha = alphaHold;
 						break;
 					default:
 						timelineBlend = MixBlend.setup;						
-						var dipMix : TrackEntry = timelineDipMix[i];
-						alpha = alphaDip * Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration);
+						var holdMix : TrackEntry = timelineHoldMix[i];
+						alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);
 						break;
 					}
 					from.totalAlpha += alpha;
@@ -399,6 +401,7 @@ package spine.animation {
 				if (from == null) break;
 				queue.end(from);
 				entry.mixingFrom = null;
+				entry.mixingTo = null;
 				entry = from;
 			}
 
@@ -414,6 +417,7 @@ package spine.animation {
 			if (from != null) {
 				if (interrupt) queue.interrupt(from);
 				current.mixingFrom = from;
+				from.mixingTo = current;
 				current.mixTime = 0;
 	
 				// Store the interrupted mix percentage.
@@ -529,6 +533,7 @@ package spine.animation {
 			entry.trackIndex = trackIndex;
 			entry.animation = animation;
 			entry.loop = loop;
+			entry.holdPrevious = false;
 
 			entry.eventThreshold = 0;
 			entry.attachmentThreshold = 0;
@@ -565,13 +570,68 @@ package spine.animation {
 		private function _animationsChanged() : void {
 			animationsChanged = false;
 
-			var propertyIDs : Dictionary = this.propertyIDs = new Dictionary();					
-			var mixingTo : Vector.<TrackEntry> = this.mixingTo;			
+			propertyIDs = new Dictionary();					
+				
 			for (var i : int = 0, n : int = tracks.length; i < n; i++) {
 				var entry : TrackEntry = tracks[i];
-				if (entry != null && (i == 0 || entry.mixBlend != MixBlend.add)) 
-					entry.setTimelineData(null, mixingTo, propertyIDs);				
+				if (entry == null) continue;
+				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 {

+ 8 - 57
spine-as3/spine-as3/src/spine/animation/TrackEntry.as

@@ -34,7 +34,7 @@ package spine.animation {
 
 	public class TrackEntry implements Poolable {
 		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 onInterrupt : Listeners = new Listeners();
 		public var onEnd : Listeners = new Listeners();
@@ -42,14 +42,14 @@ package spine.animation {
 		public var onComplete : Listeners = new Listeners();
 		public var onEvent : Listeners = new Listeners();
 		public var trackIndex : int;
-		public var loop : Boolean;
+		public var loop : Boolean, holdPrevious: Boolean;
 		public var eventThreshold : Number, attachmentThreshold : Number, drawOrderThreshold : 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 alpha : Number, mixTime : Number, mixDuration : Number, interruptAlpha : Number, totalAlpha : Number = 0;
 		public var mixBlend: MixBlend = MixBlend.replace;
-		public var timelineData : Vector.<int> = new Vector.<int>();
-		public var timelineDipMix : Vector.<TrackEntry> = new Vector.<TrackEntry>();
+		public var timelineMode : Vector.<int> = new Vector.<int>();
+		public var timelineHoldMix : Vector.<TrackEntry> = new Vector.<TrackEntry>();
 		public var timelinesRotation : Vector.<Number> = new Vector.<Number>();
 
 		public function TrackEntry() {
@@ -67,6 +67,7 @@ package spine.animation {
 		public function reset() : void {
 			next = null;
 			mixingFrom = null;
+			mixingTo = null;
 			animation = null;
 			onStart.listeners.length = 0;
 			onInterrupt.listeners.length = 0;
@@ -74,60 +75,10 @@ package spine.animation {
 			onDispose.listeners.length = 0;
 			onComplete.listeners.length = 0;
 			onEvent.listeners.length = 0;
-			timelineData.length = 0;
-			timelineDipMix.length = 0;
+			timelineMode.length = 0;
+			timelineHoldMix.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 {
 			timelinesRotation.length = 0;

TEMPAT SAMPAH
spine-starling/spine-starling-example/lib/spine-as3.swc


+ 1 - 0
spine-starling/spine-starling-example/src/spine/examples/SpineboyExample.as

@@ -69,6 +69,7 @@ package spine.examples {
 			var skeletonData : SkeletonData = json.readSkeletonData(new SpineboyJson());
 
 			var stateData : AnimationStateData = new AnimationStateData(skeletonData);
+			stateData.setMixByName("walk", "run", 0.4);
 			stateData.setMixByName("run", "jump", 0.4);
 			stateData.setMixByName("jump", "run", 0.4);
 			stateData.setMixByName("jump", "jump", 0.4);

TEMPAT SAMPAH
spine-starling/spine-starling/lib/spine-as3.swc