Browse Source

[unity] Update calls to Timeline/Animation.Apply. And other cleanup.

pharan 8 years ago
parent
commit
7481a05931

+ 1 - 1
spine-unity/Assets/Examples/Scripts/SpineGauge.cs

@@ -65,7 +65,7 @@ namespace Spine.Unity.Examples {
 				if (fillAnimation == null) return;
 			}
 
-			fillAnimation.Apply(skeleton, 0, percent, false, null, 1f, true, false);
+			fillAnimation.Apply(skeleton, 0, percent, false, null, 1f, MixPose.Setup, MixDirection.In);
 
 			skeleton.Update(Time.deltaTime);
 			skeleton.UpdateWorldTransform();

+ 2 - 2
spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs

@@ -115,8 +115,8 @@ namespace Spine.Unity.Editor {
 					Spine.Animation animationToUse = skeletonAnimation.skeleton.Data.FindAnimation(animationName.stringValue);
 
 					if (!Application.isPlaying) {
-						if (animationToUse != null) animationToUse.Apply(skeletonAnimation.skeleton, 0f, 0f, false, null, 1f, true, false);
-						skeletonAnimation.Update();
+						if (animationToUse != null) animationToUse.PoseSkeleton(skeletonAnimation.Skeleton, 0f);
+						skeletonAnimation.Update(0);
 						skeletonAnimation.LateUpdate();
 						requireRepaint = true;
 					} else {

+ 14 - 20
spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs

@@ -931,7 +931,7 @@ namespace Spine.Unity.Editor {
 			Skeleton skeleton = bone.Skeleton;
 			bool inheritRotation = bone.Data.TransformMode.InheritsRotation();
 
-			animation.Apply(skeleton, 0, 0, true, null, 1f, true, false);
+			animation.PoseSkeleton(skeleton, 0);
 			skeleton.UpdateWorldTransform();
 			float duration = animation.Duration;
 
@@ -952,7 +952,6 @@ namespace Spine.Unity.Editor {
 			int steps = Mathf.CeilToInt(duration / bakeIncrement);
 
 			float currentTime = 0;
-			float lastTime = 0;
 			float angle = rotation;
 
 			for (int i = 1; i <= steps; i++) {
@@ -960,7 +959,7 @@ namespace Spine.Unity.Editor {
 				if (i == steps)
 					currentTime = duration;
 
-				animation.Apply(skeleton, lastTime, currentTime, true, null, 1f, true, false);
+				animation.PoseSkeleton(skeleton, currentTime, true);
 				skeleton.UpdateWorldTransform();
 
 				int pIndex = listIndex - 1;
@@ -969,11 +968,7 @@ namespace Spine.Unity.Editor {
 
 				pk = keys[pIndex];
 
-				if (inheritRotation)
-					rotation = bone.AppliedRotation;
-				else {
-					rotation = GetUninheritedRotation(bone);
-				}
+				rotation = inheritRotation ? bone.AppliedRotation : GetUninheritedRotation(bone);
 
 				angle += Mathf.DeltaAngle(angle, rotation);
 
@@ -988,7 +983,6 @@ namespace Spine.Unity.Editor {
 				keys[pIndex] = pk;
 
 				listIndex++;
-				lastTime = currentTime;
 			}
 
 			curve = EnsureCurveKeyCount(new AnimationCurve(keys.ToArray()));
@@ -1058,7 +1052,7 @@ namespace Spine.Unity.Editor {
 
 					currentTime = time;
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 
 					lastTime = time;
 					listIndex++;
@@ -1085,7 +1079,7 @@ namespace Spine.Unity.Editor {
 
 					currentTime = time;
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 
 					lastTime = time;
 					listIndex++;
@@ -1104,7 +1098,7 @@ namespace Spine.Unity.Editor {
 						if (i == steps)
 							currentTime = time;
 
-						timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 
 						px = xKeys[listIndex - 1];
 						py = yKeys[listIndex - 1];
@@ -1201,7 +1195,7 @@ namespace Spine.Unity.Editor {
 
 					currentTime = time;
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 
 					lastTime = time;
 					listIndex++;
@@ -1228,7 +1222,7 @@ namespace Spine.Unity.Editor {
 
 					currentTime = time;
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 
 					lastTime = time;
 					listIndex++;
@@ -1246,7 +1240,7 @@ namespace Spine.Unity.Editor {
 						if (i == steps)
 							currentTime = time;
 
-						timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 
 						px = xKeys[listIndex - 1];
 						py = yKeys[listIndex - 1];
@@ -1330,7 +1324,7 @@ namespace Spine.Unity.Editor {
 
 					currentTime = time;
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 
 					lastTime = time;
 					listIndex++;
@@ -1355,7 +1349,7 @@ namespace Spine.Unity.Editor {
 
 					currentTime = time;
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 
 					lastTime = time;
 					listIndex++;
@@ -1365,7 +1359,7 @@ namespace Spine.Unity.Editor {
 
 					float time = frames[f];
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 					skeleton.UpdateWorldTransform();
 
 					rotation = frames[f + 1] + boneData.Rotation;
@@ -1379,7 +1373,7 @@ namespace Spine.Unity.Editor {
 						if (i == steps)
 							currentTime = time;
 
-						timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
+						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
 						skeleton.UpdateWorldTransform();
 						pk = keys[listIndex - 1];
 
@@ -1407,7 +1401,7 @@ namespace Spine.Unity.Editor {
 			curve = EnsureCurveKeyCount(new AnimationCurve(keys.ToArray()));
 
 			string path = GetPath(boneData);
-			string propertyName = "localEulerAnglesBaked";
+			const string propertyName = "localEulerAnglesBaked";
 
 			EditorCurveBinding xBind = EditorCurveBinding.FloatCurve(path, typeof(Transform), propertyName + ".x");
 			AnimationUtility.SetEditorCurve(clip, xBind, new AnimationCurve());

+ 1 - 1
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs

@@ -242,7 +242,7 @@ namespace Spine.Unity {
 					// Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
 					var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(startingAnimation);
 					if (animationObject != null)
-						animationObject.Apply(skeleton, 0f, 0f, false, null, 1f, true, false);
+						animationObject.PoseSkeleton(skeleton, 0);
 				}
 				Update(0);
 			}

+ 3 - 2
spine-unity/Assets/spine-unity/SkeletonAnimation.cs

@@ -150,7 +150,7 @@ namespace Spine.Unity {
 					// Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
 					var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(_animationName);
 					if (animationObject != null)
-						animationObject.Apply(skeleton, 0f, 0f, false, null, 1f, true, false);
+						animationObject.PoseSkeleton(skeleton, 0f);
 				}
 				Update(0);
 			}
@@ -162,10 +162,11 @@ namespace Spine.Unity {
 			#endif
 		}
 
-		public void Update () {
+		void Update () {
 			Update(Time.deltaTime);
 		}
 
+		/// <summary>Progresses the AnimationState according to the given deltaTime, and applies it to the Skeleton. Use Time.deltaTime to update manually. Use deltaTime 0 to update without progressing the time.</summary>
 		public void Update (float deltaTime) {
 			if (!valid)
 				return;

+ 135 - 121
spine-unity/Assets/spine-unity/SkeletonAnimator.cs

@@ -40,9 +40,6 @@ namespace Spine.Unity {
 		public enum MixMode { AlwaysMix, MixNext, SpineStyle }
 		public MixMode[] layerMixModes = new MixMode[0];
 
-		public bool autoReset = true;
-		List<Animation> previousAnimations = new List<Animation>();
-
 		#region Bone Callbacks (ISkeletonAnimation)
 		protected event UpdateBonesDelegate _UpdateLocal;
 		protected event UpdateBonesDelegate _UpdateWorld;
@@ -66,123 +63,165 @@ namespace Spine.Unity {
 		public event UpdateBonesDelegate UpdateComplete { add { _UpdateComplete += value; } remove { _UpdateComplete -= value; } }
 		#endregion
 
-		readonly Dictionary<int, Spine.Animation> animationTable = new Dictionary<int, Spine.Animation>();
-		readonly Dictionary<AnimationClip, int> clipNameHashCodeTable = new Dictionary<AnimationClip, int>();
-		Animator animator;
+		public class SpineMecanimTranslator {
+			readonly Dictionary<int, Spine.Animation> animationTable = new Dictionary<int, Spine.Animation>();
+			readonly Dictionary<AnimationClip, int> clipNameHashCodeTable = new Dictionary<AnimationClip, int>();
+			Animator animator;
+
+			List<Animation> previousAnimations = new List<Animation>();
+			public bool autoReset = true;
+
+			public void Initialize (Animator animator, SkeletonDataAsset skeletonDataAsset) {
+				this.animator = animator;
+				animationTable.Clear();
+				clipNameHashCodeTable.Clear();
+				var data = skeletonDataAsset.GetSkeletonData(true);
+				foreach (var a in data.Animations)
+					animationTable.Add(a.Name.GetHashCode(), a);	
+			}
 
-		public override void Initialize (bool overwrite) {
-			if (valid && !overwrite) return;
-			base.Initialize(overwrite);
-			if (!valid) return;
+			public void Apply (Skeleton skeleton, ref MixMode[] layerMixModes) {
 
-			animationTable.Clear();
-			clipNameHashCodeTable.Clear();
-			animator = GetComponent<Animator>();
-			var data = skeletonDataAsset.GetSkeletonData(true);
-			foreach (var a in data.Animations)
-				animationTable.Add(a.Name.GetHashCode(), a);
-		}
+				if (layerMixModes.Length < animator.layerCount)
+					System.Array.Resize<MixMode>(ref layerMixModes, animator.layerCount);
+				
+				//skeleton.Update(Time.deltaTime); // Doesn't actually do anything, currently. (Spine 3.5).
 
-		public void Update () {
-			if (!valid) return;
+				// Clear Previous
+				if (autoReset) {
+					var previousAnimations = this.previousAnimations;
+					for (int i = 0, n = previousAnimations.Count; i < n; i++)
+						previousAnimations[i].SetKeyedItemsToSetupPose(skeleton);
 
-			if (layerMixModes.Length < animator.layerCount)
-				System.Array.Resize<MixMode>(ref layerMixModes, animator.layerCount);
+					previousAnimations.Clear();
+					for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
+						float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
+						if (layerWeight <= 0) continue;
 
-			//skeleton.Update(Time.deltaTime); // Doesn't actually do anything, currently. (Spine 3.5).
+						AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
 
-			// Clear Previous
-			if (autoReset) {
-				var previousAnimations = this.previousAnimations;
-				for (int i = 0, n = previousAnimations.Count; i < n; i++)
-					previousAnimations[i].SetKeyedItemsToSetupPose(skeleton);
+						bool hasNext = nextStateInfo.fullPathHash != 0;
+						AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
+						AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
+
+						for (int c = 0; c < clipInfo.Length; c++) {
+							var info = clipInfo[c];
+							float weight = info.weight * layerWeight; if (weight == 0) continue;
+							previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
+						}
+						if (hasNext) {
+							for (int c = 0; c < nextClipInfo.Length; c++) {
+								var info = nextClipInfo[c];
+								float weight = info.weight * layerWeight; if (weight == 0) continue;
+								previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
+							}
+						}
+					}
+				}
 
-				previousAnimations.Clear();
+				// Apply
 				for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
 					float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
-					if (layerWeight <= 0) continue;
-
+					AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(layer);
 					AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
 
 					bool hasNext = nextStateInfo.fullPathHash != 0;
 					AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
 					AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
-
-					for (int c = 0; c < clipInfo.Length; c++) {
-						var info = clipInfo[c];
-						float weight = info.weight * layerWeight; if (weight == 0) continue;
-						previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
-					}
-					if (hasNext) {
-						for (int c = 0; c < nextClipInfo.Length; c++) {
-							var info = nextClipInfo[c];
-							float weight = info.weight * layerWeight; if (weight == 0) continue;
-							previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
+					//UNITY 4
+					//bool hasNext = nextStateInfo.nameHash != 0;
+					//var clipInfo = animator.GetCurrentAnimationClipState(i);
+					//var nextClipInfo = animator.GetNextAnimationClipState(i);
+
+					MixMode mode = layerMixModes[layer];
+					if (mode == MixMode.AlwaysMix) {
+						// Always use Mix instead of Applying the first non-zero weighted clip.
+						for (int c = 0; c < clipInfo.Length; c++) {
+							var info = clipInfo[c];	float weight = info.weight * layerWeight; if (weight == 0) continue;
+							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed <0), stateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
 						}
-					}
-				}
-			}
-
-			// Apply
-			for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
-				float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
-				AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(layer);
-				AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
-
-				bool hasNext = nextStateInfo.fullPathHash != 0;
-				AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
-				AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
-				//UNITY 4
-				//bool hasNext = nextStateInfo.nameHash != 0;
-				//var clipInfo = animator.GetCurrentAnimationClipState(i);
-				//var nextClipInfo = animator.GetNextAnimationClipState(i);
-
-				MixMode mode = layerMixModes[layer];
-				if (mode == MixMode.AlwaysMix) {
-					// Always use Mix instead of Applying the first non-zero weighted clip.
-					for (int c = 0; c < clipInfo.Length; c++) {
-						var info = clipInfo[c];	float weight = info.weight * layerWeight; if (weight == 0) continue;
-						animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed <0), stateInfo.loop, null, weight, false, false);
-					}
-					if (hasNext) {
-						for (int c = 0; c < nextClipInfo.Length; c++) {
-							var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
-							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, false, false);
-						}
-					}
-				} else { // case MixNext || SpineStyle
-					// Apply first non-zero weighted clip
-					int c = 0;
-					for (; c < clipInfo.Length; c++) {
-						var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
-						animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed <0), stateInfo.loop, null, 1f, false, false);
-						break;
-					}
-					// Mix the rest
-					for (; c < clipInfo.Length; c++) {
-						var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
-						animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed <0), stateInfo.loop, null, weight, false, false);
-					}
-
-					c = 0;
-					if (hasNext) {
-						// Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
-						if (mode == MixMode.SpineStyle) {
-							for (; c < nextClipInfo.Length; c++) {
+						if (hasNext) {
+							for (int c = 0; c < nextClipInfo.Length; c++) {
 								var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
-								animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, 1f, false, false);
-								break;
+								animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
 							}
 						}
+					} else { // case MixNext || SpineStyle
+						// Apply first non-zero weighted clip
+						int c = 0;
+						for (; c < clipInfo.Length; c++) {
+							var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
+							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed <0), stateInfo.loop, null, 1f, MixPose.Current, MixDirection.In);
+							break;
+						}
 						// Mix the rest
-						for (; c < nextClipInfo.Length; c++) {
-							var info = nextClipInfo[c];	float weight = info.weight * layerWeight; if (weight == 0) continue;
-							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, false, false);
+						for (; c < clipInfo.Length; c++) {
+							var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
+							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed <0), stateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
+						}
+
+						c = 0;
+						if (hasNext) {
+							// Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
+							if (mode == MixMode.SpineStyle) {
+								for (; c < nextClipInfo.Length; c++) {
+									var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
+									animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, 1f, MixPose.Current, MixDirection.In);
+									break;
+								}
+							}
+							// Mix the rest
+							for (; c < nextClipInfo.Length; c++) {
+								var info = nextClipInfo[c];	float weight = info.weight * layerWeight; if (weight == 0) continue;
+								animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
+							}
 						}
 					}
 				}
 			}
 
+			static float AnimationTime (float normalizedTime, float clipLength, bool loop, bool reversed) {
+				if (reversed)
+					normalizedTime = (1-normalizedTime + (int)normalizedTime) + (int)normalizedTime;
+				float time = normalizedTime * clipLength;
+				if (loop) return time;
+				const float EndSnapEpsilon = 1f/30f; // Workaround for end-duration keys not being applied.
+				return (clipLength - time < EndSnapEpsilon) ? clipLength : time; // return a time snapped to clipLength;
+			}
+
+			static float AnimationTime (float normalizedTime, float clipLength, bool reversed) {
+				if (reversed)
+					normalizedTime = (1-normalizedTime + (int)normalizedTime) + (int)normalizedTime;
+
+				return normalizedTime * clipLength;
+			}
+
+			int NameHashCode (AnimationClip clip) {
+				int clipNameHashCode;
+				if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
+					clipNameHashCode = clip.name.GetHashCode();
+					clipNameHashCodeTable.Add(clip, clipNameHashCode);
+				}
+				return clipNameHashCode;
+			}
+		}
+
+		public SpineMecanimTranslator translator;
+
+		public override void Initialize (bool overwrite) {
+			if (valid && !overwrite) return;
+			base.Initialize(overwrite);
+			if (!valid) return;
+
+			translator = new SpineMecanimTranslator();
+			translator.Initialize(GetComponent<Animator>(), this.skeletonDataAsset);
+		}
+
+		public void Update () {
+			if (!valid) return;
+
+			translator.Apply(skeleton, ref layerMixModes);
+
 			// UpdateWorldTransform and Bone Callbacks
 			{
 				if (_UpdateLocal != null)
@@ -199,30 +238,5 @@ namespace Spine.Unity {
 					_UpdateComplete(this);	
 			}
 		}
-
-		static float AnimationTime (float normalizedTime, float clipLength, bool loop, bool reversed) {
-			if (reversed)
-				normalizedTime = (1-normalizedTime + (int)normalizedTime) + (int)normalizedTime;
-			float time = normalizedTime * clipLength;
-			if (loop) return time;
-			const float EndSnapEpsilon = 1f/30f; // Workaround for end-duration keys not being applied.
-			return (clipLength - time < EndSnapEpsilon) ? clipLength : time; // return a time snapped to clipLength;
-		}
-
-		static float AnimationTime (float normalizedTime, float clipLength, bool reversed) {
-			if (reversed)
-				normalizedTime = (1-normalizedTime + (int)normalizedTime) + (int)normalizedTime;
-
-			return normalizedTime * clipLength;
-		}
-
-		int NameHashCode (AnimationClip clip) {
-			int clipNameHashCode;
-			if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
-				clipNameHashCode = clip.name.GetHashCode();
-				clipNameHashCodeTable.Add(clip, clipNameHashCode);
-			}
-			return clipNameHashCode;
-		}
 	}
 }

+ 18 - 8
spine-unity/Assets/spine-unity/SkeletonExtensions.cs

@@ -283,11 +283,6 @@ namespace Spine {
 		#endregion
 
 		#region Posing
-		[System.Obsolete("Old Animation.Apply method signature. Please use the 8 parameter signature. See summary to learn about the extra arguments.")]
-		public static void Apply (this Spine.Animation animation, Skeleton skeleton, float lastTime, float time, bool loop, ExposedList<Event> events) {
-			animation.Apply(skeleton, lastTime, time, loop, events, 1f, false, false);
-		}
-
 		internal static void SetPropertyToSetupPose (this Skeleton skeleton, int propertyID) {
 			int tt = propertyID >> 24;
 			var timelineType = (TimelineType)tt;
@@ -326,6 +321,9 @@ namespace Spine {
 			case TimelineType.Color:
 				skeleton.slots.Items[i].SetColorToSetupPose();
 				break;
+			case TimelineType.TwoColor:
+				skeleton.slots.Items[i].SetColorToSetupPose();
+				break;
 			case TimelineType.Deform:
 				skeleton.slots.Items[i].attachmentVertices.Clear();
 				break;
@@ -341,6 +339,8 @@ namespace Spine {
 				ikc.mix = ikc.data.mix;
 				ikc.bendDirection = ikc.data.bendDirection;
 				break;
+
+			// TransformConstraint
 			case TimelineType.TransformConstraint:
 				var tc = skeleton.transformConstraints.Items[i];
 				var tcData = tc.data;
@@ -384,6 +384,9 @@ namespace Spine {
 			slot.g = slot.data.g;
 			slot.b = slot.data.b;
 			slot.a = slot.data.a;
+			slot.r2 = slot.data.r2;
+			slot.g2 = slot.data.g2;
+			slot.b2 = slot.data.b2;
 		}
 
 		/// <summary>Sets a slot's attachment to setup pose. If you have the slotIndex, Skeleton.SetSlotAttachmentToSetupPose is faster.</summary>
@@ -411,17 +414,24 @@ namespace Spine {
 		/// <param name="animationName">The name of the animation to use.</param>
 		/// <param name = "time">The time of the pose within the animation.</param>
 		/// <param name = "loop">Wraps the time around if it is longer than the duration of the animation.</param>
-		public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop) {
+		public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop = false) {
 			// Fail loud when skeleton.data is null.
 			Spine.Animation animation = skeleton.data.FindAnimation(animationName);
 			if (animation == null) return;
-			animation.Apply(skeleton, 0, time, loop, null, 1f, false, false);
+			animation.Apply(skeleton, 0, time, loop, null, 1f, MixPose.Setup, MixDirection.In);
+		}
+
+		/// <summary>Pose a skeleton according to a given time in an animation.</summary>
+		public static void PoseSkeleton (this Animation animation, Skeleton skeleton, float time, bool loop = false) {
+			animation.Apply(skeleton, 0, time, loop, null, 1f, MixPose.Setup, MixDirection.In);
 		}
 
 		/// <summary>Resets Skeleton parts to Setup Pose according to a Spine.Animation's keyed items.</summary>
 		public static void SetKeyedItemsToSetupPose (this Animation animation, Skeleton skeleton) {
-			animation.Apply(skeleton, 0, 0, false, null, 0, true, true);
+			animation.Apply(skeleton, 0, 0, false, null, 0, MixPose.Setup, MixDirection.Out);
 		}
+
+
 		#endregion
 
 		#region Skins