Sfoglia il codice sorgente

[unity] Fixed root motion components ignoring split translate timelines. Closes #1997.

Harald Csaszar 3 anni fa
parent
commit
7e765c1b5b

+ 40 - 4
spine-unity/Assets/Spine/Runtime/spine-unity/Components/RootMotion/SkeletonRootMotionBase.cs

@@ -202,6 +202,8 @@ namespace Spine.Unity {
 				return Vector2.zero;
 
 			TranslateTimeline translateTimeline = animation.FindTranslateTimelineForBone(rootMotionBoneIndex);
+			TranslateXTimeline xTimeline = animation.FindTimelineForBone<TranslateXTimeline>(rootMotionBoneIndex);
+			TranslateYTimeline yTimeline = animation.FindTimelineForBone<TranslateYTimeline>(rootMotionBoneIndex);
 
 			// Non-looped base
 			Vector2 endPos = Vector2.zero;
@@ -209,6 +211,9 @@ namespace Spine.Unity {
 			if (translateTimeline != null) {
 				endPos = translateTimeline.Evaluate(endTime);
 				startPos = translateTimeline.Evaluate(startTime);
+			} else if (xTimeline != null || yTimeline != null) {
+				endPos = TimelineExtensions.Evaluate(xTimeline, yTimeline, endTime);
+				startPos = TimelineExtensions.Evaluate(xTimeline, yTimeline, startTime);
 			}
 			var transformConstraintsItems = skeletonComponent.Skeleton.TransformConstraints.Items;
 			foreach (int constraintIndex in this.transformConstraintIndices) {
@@ -225,6 +230,9 @@ namespace Spine.Unity {
 				if (translateTimeline != null) {
 					loopPos = translateTimeline.Evaluate(animation.Duration);
 					zeroPos = translateTimeline.Evaluate(0);
+				} else if (xTimeline != null || yTimeline != null) {
+					loopPos = TimelineExtensions.Evaluate(xTimeline, yTimeline, animation.Duration);
+					zeroPos = TimelineExtensions.Evaluate(xTimeline, yTimeline, 0);
 				}
 				foreach (int constraintIndex in this.transformConstraintIndices) {
 					TransformConstraint constraint = transformConstraintsItems[constraintIndex];
@@ -266,15 +274,25 @@ namespace Spine.Unity {
 
 		public RootMotionInfo GetAnimationRootMotionInfo (Animation animation, float currentTime) {
 			RootMotionInfo rootMotion = new RootMotionInfo();
-			var timeline = animation.FindTranslateTimelineForBone(rootMotionBoneIndex);
+			float duration = animation.Duration;
+			float mid = duration * 0.5f;
+			rootMotion.timeIsPastMid = currentTime > mid;
+			TranslateTimeline timeline = animation.FindTranslateTimelineForBone(rootMotionBoneIndex);
 			if (timeline != null) {
-				float duration = animation.Duration;
-				float mid = duration * 0.5f;
 				rootMotion.start = timeline.Evaluate(0);
 				rootMotion.current = timeline.Evaluate(currentTime);
 				rootMotion.mid = timeline.Evaluate(mid);
 				rootMotion.end = timeline.Evaluate(duration);
-				rootMotion.timeIsPastMid = currentTime > mid;
+				return rootMotion;
+			}
+			TranslateXTimeline xTimeline = animation.FindTimelineForBone<TranslateXTimeline>(rootMotionBoneIndex);
+			TranslateYTimeline yTimeline = animation.FindTimelineForBone<TranslateYTimeline>(rootMotionBoneIndex);
+			if (xTimeline != null || yTimeline != null) {
+				rootMotion.start = TimelineExtensions.Evaluate(xTimeline, yTimeline, 0);
+				rootMotion.current = TimelineExtensions.Evaluate(xTimeline, yTimeline, currentTime);
+				rootMotion.mid = TimelineExtensions.Evaluate(xTimeline, yTimeline, mid);
+				rootMotion.end = TimelineExtensions.Evaluate(xTimeline, yTimeline, duration);
+				return rootMotion;
 			}
 			return rootMotion;
 		}
@@ -293,6 +311,24 @@ namespace Spine.Unity {
 			}
 		}
 
+		Vector2 GetTimelineMovementDelta (float startTime, float endTime,
+			TranslateXTimeline xTimeline, TranslateYTimeline yTimeline, Animation animation) {
+
+			Vector2 currentDelta;
+			if (startTime > endTime) // Looped
+				currentDelta =
+					(TimelineExtensions.Evaluate(xTimeline, yTimeline, animation.Duration)
+					- TimelineExtensions.Evaluate(xTimeline, yTimeline, startTime))
+					+ (TimelineExtensions.Evaluate(xTimeline, yTimeline, endTime)
+					- TimelineExtensions.Evaluate(xTimeline, yTimeline, 0));
+			else if (startTime != endTime) // Non-looped
+				currentDelta = TimelineExtensions.Evaluate(xTimeline, yTimeline, endTime)
+					- TimelineExtensions.Evaluate(xTimeline, yTimeline, startTime);
+			else
+				currentDelta = Vector2.zero;
+			return currentDelta;
+		}
+
 		void GatherTopLevelBones () {
 			topLevelBones.Clear();
 			var skeleton = skeletonComponent.Skeleton;

+ 34 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/TimelineExtensions.cs

@@ -52,6 +52,27 @@ namespace Spine.Unity.AnimationTools {
 			}
 		}
 
+		/// <summary>Evaluates the resulting value of a pair of split translate timelines at a given time.
+		/// SkeletonData can be accessed from Skeleton.Data or from SkeletonDataAsset.GetSkeletonData.
+		/// If no SkeletonData is given, values are returned as difference to setup pose
+		/// instead of absolute values.</summary>
+		public static Vector2 Evaluate (TranslateXTimeline xTimeline, TranslateYTimeline yTimeline,
+			float time, SkeletonData skeletonData = null) {
+
+			float x = 0, y = 0;
+			if (xTimeline != null && time > xTimeline.Frames[0]) x = xTimeline.GetCurveValue(time);
+			if (yTimeline != null && time > yTimeline.Frames[0]) y = yTimeline.GetCurveValue(time);
+
+			if (skeletonData == null) {
+				return new Vector2(x, y);
+			} else {
+				var bonesItems = skeletonData.Bones.Items;
+				BoneData boneDataX = bonesItems[xTimeline.BoneIndex];
+				BoneData boneDataY = bonesItems[yTimeline.BoneIndex];
+				return new Vector2(boneDataX.X + x, boneDataY.Y + y);
+			}
+		}
+
 		/// <summary>Evaluates the resulting X and Y translate mix values of a
 		/// TransformConstraintTimeline at a given time.</summary>
 		public static Vector2 EvaluateTranslateXYMix (this TransformConstraintTimeline timeline, float time) {
@@ -78,6 +99,19 @@ namespace Spine.Unity.AnimationTools {
 			return null;
 		}
 
+		/// <summary>Gets the IBoneTimeline timeline of a given type for a given boneIndex.
+		/// You can get the boneIndex using SkeletonData.FindBoneIndex.
+		/// The root bone is always boneIndex 0.
+		/// This will return null if a timeline of the given type is not found.</summary>
+		public static T FindTimelineForBone<T> (this Animation a, int boneIndex) where T : class, IBoneTimeline {
+			foreach (var timeline in a.Timelines) {
+				T translateTimeline = timeline as T;
+				if (translateTimeline != null && translateTimeline.BoneIndex == boneIndex)
+					return translateTimeline;
+			}
+			return null;
+		}
+
 		/// <summary>Gets the transform constraint timeline for a given boneIndex.
 		/// You can get the boneIndex using SkeletonData.FindBone().Index.
 		/// The root bone is always boneIndex 0.