From 89e759a8f51bc7fec3acf8b210d9b0a97b59140f Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Thu, 25 Apr 2019 18:41:56 +0200 Subject: [PATCH] [unity] Fixed initial animation not being mixed out in some circumstances due to PoseSkeleton call. Removed PoseSkeleton and PoseWithAnimation extension methods to prevent related issues on user side. Fixed incorrect random Nth frame preview in Scene view for SkeletonAnimation and SkeletonGraphic. Closes #1340. --- .../Spine Examples/Scripts/SpineGauge.cs | 2 +- .../Editor/SkeletonAnimationInspector.cs | 50 +++++++------------ .../spine-unity/Editor/SkeletonBaker.cs | 4 +- .../Components/SkeletonAnimation.cs | 21 ++++---- .../SkeletonGraphic/SkeletonGraphic.cs | 34 ++++++------- .../SpineAnimationStateMixerBehaviour.cs | 2 +- .../Runtime/spine-unity/SkeletonExtensions.cs | 19 ------- 7 files changed, 49 insertions(+), 83 deletions(-) diff --git a/spine-unity/Assets/Spine Examples/Scripts/SpineGauge.cs b/spine-unity/Assets/Spine Examples/Scripts/SpineGauge.cs index a145d2150..4f327461e 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/SpineGauge.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/SpineGauge.cs @@ -56,7 +56,7 @@ namespace Spine.Unity.Examples { if (skeletonRenderer == null) return; var skeleton = skeletonRenderer.skeleton; if (skeleton == null) return; - fillAnimation.Animation.PoseSkeleton(skeleton, percent); + fillAnimation.Animation.Apply(skeleton, 0, percent, false, null, 1f, MixBlend.Setup, MixDirection.In); skeleton.Update(Time.deltaTime); skeleton.UpdateWorldTransform(); } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonAnimationInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonAnimationInspector.cs index 4f9d5d189..94b56a756 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonAnimationInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonAnimationInspector.cs @@ -55,38 +55,26 @@ namespace Spine.Unity.Editor { if (!TargetIsValid) return; bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject); - if (multi) { - foreach (var o in targets) - TrySetAnimation(o as SkeletonAnimation, multi); - - EditorGUILayout.Space(); - if (!sameData) { - EditorGUILayout.DelayedTextField(animationName); - } else { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(animationName); - wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update. - } - EditorGUILayout.PropertyField(loop); - EditorGUILayout.PropertyField(timeScale); - foreach (var o in targets) { - var component = o as SkeletonAnimation; - component.timeScale = Mathf.Max(component.timeScale, 0); - } - } else { - TrySetAnimation(target as SkeletonAnimation, multi); + foreach (var o in targets) + TrySetAnimation(o as SkeletonAnimation, multi); + wasAnimationNameChanged = false; - EditorGUILayout.Space(); + EditorGUILayout.Space(); + if (!sameData) { + EditorGUILayout.DelayedTextField(animationName); + } else { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(animationName); wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update. - EditorGUILayout.PropertyField(loop, LoopLabel); - EditorGUILayout.PropertyField(timeScale, TimeScaleLabel); - var component = (SkeletonAnimation)target; - component.timeScale = Mathf.Max(component.timeScale, 0); - EditorGUILayout.Space(); } - + EditorGUILayout.PropertyField(loop, LoopLabel); + EditorGUILayout.PropertyField(timeScale, TimeScaleLabel); + foreach (var o in targets) { + var component = o as SkeletonAnimation; + component.timeScale = Mathf.Max(component.timeScale, 0); + } + EditorGUILayout.Space(); + if (!isInspectingPrefab) { if (requireRepaint) { SceneView.RepaintAll(); @@ -113,7 +101,9 @@ namespace Spine.Unity.Editor { Spine.Animation animationToUse = skeleton.Data.FindAnimation(animationName.stringValue); if (!Application.isPlaying) { - if (animationToUse != null) animationToUse.PoseSkeleton(skeleton, 0f); + if (animationToUse != null) { + skeletonAnimation.AnimationState.SetAnimation(0, animationToUse, loop.boolValue); + } skeleton.UpdateWorldTransform(); skeletonAnimation.LateUpdate(); requireRepaint = true; @@ -123,12 +113,10 @@ namespace Spine.Unity.Editor { else state.ClearTrack(0); } - - wasAnimationNameChanged = false; } // Reflect animationName serialized property in the inspector even if SetAnimation API was used. - if (!multi && Application.isPlaying) { + if (Application.isPlaying) { TrackEntry current = skeletonAnimation.AnimationState.GetCurrent(0); if (current != null) { if (skeletonAnimation.AnimationName != animationName.stringValue) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs index 8a6ddb540..4f1215463 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs @@ -831,7 +831,7 @@ namespace Spine.Unity.Editor { Skeleton skeleton = bone.Skeleton; bool inheritRotation = bone.Data.TransformMode.InheritsRotation(); - animation.PoseSkeleton(skeleton, 0); + animation.Apply(skeleton, 0, 0, false, null, 1f, MixBlend.Setup, MixDirection.In); skeleton.UpdateWorldTransform(); float duration = animation.Duration; @@ -859,7 +859,7 @@ namespace Spine.Unity.Editor { if (i == steps) currentTime = duration; - animation.PoseSkeleton(skeleton, currentTime, true); + animation.Apply(skeleton, 0, currentTime, true, null, 1f, MixBlend.Setup, MixDirection.In); skeleton.UpdateWorldTransform(); int pIndex = listIndex - 1; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs index 9d41ffae4..f2eed8cbe 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs @@ -158,24 +158,23 @@ namespace Spine.Unity { if (!string.IsNullOrEmpty(_animationName)) { var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(_animationName); if (animationObject != null) { - animationObject.PoseSkeleton(skeleton, 0f); - skeleton.UpdateWorldTransform(); - + state.SetAnimation(0, animationObject, loop); #if UNITY_EDITOR - if (Application.isPlaying) { - #endif - - // In Unity Editor edit mode, make this block not run. - state.SetAnimation(0, animationObject, loop); - - #if UNITY_EDITOR - } + if (!Application.isPlaying) + Update(0f); #endif } } } void Update () { + #if UNITY_EDITOR + if (!Application.isPlaying) { + Update(0f); + return; + } + #endif + Update(Time.deltaTime); } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs index a0976b2fe..7be3831ff 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs @@ -92,12 +92,14 @@ namespace Spine.Unity { if (!Application.isPlaying) { skeleton.scaleX = this.initialFlipX ? -1 : 1; skeleton.scaleY = this.initialFlipY ? -1 : 1; - + + state.ClearTrack(0); skeleton.SetToSetupPose(); - if (!string.IsNullOrEmpty(startingAnimation)) - skeleton.PoseWithAnimation(startingAnimation, 0f, false); + if (!string.IsNullOrEmpty(startingAnimation)) { + state.SetAnimation(0, startingAnimation, startingLoop); + Update(0f); + } } - } } else { // Under some circumstances (e.g. sometimes on the first import) OnValidate is called @@ -181,6 +183,13 @@ namespace Spine.Unity { } public virtual void Update () { + #if UNITY_EDITOR + if (!Application.isPlaying) { + Update(0f); + return; + } + #endif + if (freeze) return; Update(unscaledTime ? Time.unscaledDeltaTime : Time.deltaTime); } @@ -273,22 +282,11 @@ namespace Spine.Unity { if (!string.IsNullOrEmpty(startingAnimation)) { var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(startingAnimation); if (animationObject != null) { - animationObject.PoseSkeleton(skeleton, 0f); - skeleton.UpdateWorldTransform(); - + state.SetAnimation(0, animationObject, startingLoop); #if UNITY_EDITOR - if (Application.isPlaying) { + if (!Application.isPlaying) + Update(0f); #endif - - // Make this block not run in Unity Editor edit mode. - state.SetAnimation(0, animationObject, startingLoop); - - #if UNITY_EDITOR - } - #endif - } - else { - startingAnimation = string.Empty; } } } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs index 9e8604bd4..1aba237e4 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs @@ -181,7 +181,7 @@ namespace Spine.Unity.Playables { } else { skeleton.SetToSetupPose(); if (toAnimation != null) - toAnimation.PoseSkeleton(skeleton, toClipTime, clipData.loop); + toAnimation.Apply(skeleton, 0, toClipTime, clipData.loop, null, 1f, MixBlend.Setup, MixDirection.In); } } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs index 9c1e958f9..ecfb21fcd 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs @@ -601,25 +601,6 @@ namespace Spine { } } - /// - /// Shortcut for posing a skeleton at a specific time. Time is in seconds. (frameNumber / 30f) will give you seconds. - /// If you need to do this often, you should get the Animation object yourself using skeleton.data.FindAnimation. and call Apply on that. - /// The skeleton to pose. - /// The name of the animation to use. - /// The time of the pose within the animation. - /// Wraps the time around if it is longer than the duration of the animation. - 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, MixBlend.Setup, MixDirection.In); - } - - /// Pose a skeleton according to a given time in an animation. This is the simplified version of Animation.Apply(skeleton). - public static void PoseSkeleton (this Animation animation, Skeleton skeleton, float time, bool loop = false) { - animation.Apply(skeleton, 0, time, loop, null, 1f, MixBlend.Setup, MixDirection.In); - } - /// Resets Skeleton parts to Setup Pose according to a Spine.Animation's keyed items. public static void SetKeyedItemsToSetupPose (this Animation animation, Skeleton skeleton) { animation.Apply(skeleton, 0, 0, false, null, 0, MixBlend.Setup, MixDirection.Out);