Browse Source

[unity] Improved yield instructions for animation track events such as End, Complete, Interrupt. Added a generic version to wait for any combination of events. Closes #1457

Harald Csaszar 6 years ago
parent
commit
bf052f9a4e

+ 4 - 0
CHANGELOG.md

@@ -171,6 +171,10 @@
     * **Restrictions** As all Spine shaders, the LWRP shaders **do not support `Premultiply alpha` (PMA) atlas textures in Linear color space**. Please export your atlas textures as `straight alpha` textures with disabled `Premultiply alpha` setting when using Linear color space. You can check the current color space via `Project Settings - Player - Other Settings - Color Space.`.
     * **Example:** You can find an example scene in the package under `com.esotericsoftware.spine.lwrp-shaders-3.8/Examples/LWRP Shaders.unity` that demonstrates usage of the LWRP shaders.
   * Added `Spine/Skeleton Lit ZWrite` shader. This variant of the `Spine/Skeleton Lit` shader writes to the depth buffer with configurable depth alpha threshold. Apart from that it is identical to `Spine/Skeleton Lit`.
+  * Additional yield instructions to wait for animation track events `End`, `Complete` and `Interrupt`.
+    * `WaitForSpineAnimationComplete` now proves an additional `bool includeEndEvent` parameter, defaults to `false` (previous behaviour).
+    * Added a new `WaitForSpineAnimationEnd` yield instruction.
+    * Added a new generic `WaitForSpineAnimation` yield instruction which can be configured to wait for any combination of animation track events. It is now used as base class for `WaitForSpineAnimationComplete` and `WaitForSpineAnimationEnd`.
 
 * **Changes of default values**
   * `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.SpineStyle` instead of `MixMode.MixAlways`.

+ 108 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/YieldInstructions/WaitForSpineAnimation.cs

@@ -0,0 +1,108 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated May 1, 2019. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2019, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS
+ * INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+using UnityEngine;
+using System.Collections;
+using System;
+
+namespace Spine.Unity {
+	/// <summary>
+	/// Use this as a condition-blocking yield instruction for Unity Coroutines. 
+	/// The routine will pause until the AnimationState.TrackEntry fires any of the
+	/// configured events.
+	/// <p/>
+	/// See the <see cref="http://esotericsoftware.com/spine-unity-events">Spine Unity Events documentation page</see>
+	/// and <see cref="http://esotericsoftware.com/spine-api-reference#AnimationStateListener"/>
+	/// for more information on when track events will be triggered.</summary>
+	public class WaitForSpineAnimation : IEnumerator {
+		
+		[Flags]
+		public enum AnimationEventTypes
+		{
+			Start = 1,
+			Interrupt = 2,
+			End = 4,
+			Dispose = 8,
+			Complete = 16
+		}
+
+		bool m_WasFired = false;
+
+		public WaitForSpineAnimation (Spine.TrackEntry trackEntry, AnimationEventTypes eventsToWaitFor) {
+			SafeSubscribe(trackEntry, eventsToWaitFor);
+		}
+
+		#region Reuse
+		/// <summary>
+		/// One optimization high-frequency YieldInstruction returns is to cache instances to minimize GC pressure.
+		/// Use NowWaitFor to reuse the same instance of WaitForSpineAnimationComplete.</summary>
+		public WaitForSpineAnimation NowWaitFor (Spine.TrackEntry trackEntry, AnimationEventTypes eventsToWaitFor) {
+			SafeSubscribe(trackEntry, eventsToWaitFor);
+			return this;
+		}
+		#endregion
+		
+		#region IEnumerator
+		bool IEnumerator.MoveNext () {
+			if (m_WasFired) {
+				((IEnumerator)this).Reset();	// auto-reset for YieldInstruction reuse
+				return false;
+			}
+
+			return true;
+		}
+		void IEnumerator.Reset () { m_WasFired = false; }
+		object IEnumerator.Current { get { return null; } }
+		#endregion
+
+		protected void SafeSubscribe (Spine.TrackEntry trackEntry, AnimationEventTypes eventsToWaitFor) {
+			if (trackEntry == null) {
+				// Break immediately if trackEntry is null.
+				Debug.LogWarning("TrackEntry was null. Coroutine will continue immediately.");
+				m_WasFired = true;
+			}
+			else {
+				if ((eventsToWaitFor & AnimationEventTypes.Start) != 0)
+					trackEntry.Start += HandleComplete;
+				if ((eventsToWaitFor & AnimationEventTypes.Interrupt) != 0)
+					trackEntry.Interrupt += HandleComplete;
+				if ((eventsToWaitFor & AnimationEventTypes.End) != 0)
+					trackEntry.End += HandleComplete;
+				if ((eventsToWaitFor & AnimationEventTypes.Dispose) != 0)
+					trackEntry.Dispose += HandleComplete;
+				if ((eventsToWaitFor & AnimationEventTypes.Complete) != 0)
+					trackEntry.Complete += HandleComplete;
+			}
+		}
+
+		void HandleComplete (TrackEntry trackEntry) {
+			m_WasFired = true;
+		}
+	}
+}

+ 12 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/YieldInstructions/WaitForSpineAnimation.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d9be5adcaf0003849a1d181173c19635
+timeCreated: 1566289729
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 14 - 37
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/YieldInstructions/WaitForSpineAnimationComplete.cs

@@ -34,52 +34,29 @@ using Spine;
 namespace Spine.Unity {
 	/// <summary>
 	/// Use this as a condition-blocking yield instruction for Unity Coroutines. 
-	/// The routine will pause until the AnimationState.TrackEntry fires its Complete event.</summary>
-	public class WaitForSpineAnimationComplete : IEnumerator {
+	/// The routine will pause until the AnimationState.TrackEntry fires its Complete event.
+	/// It can be configured to trigger on the End event as well to cover interruption.
+	/// <p/>
+	/// See the <see cref="http://esotericsoftware.com/spine-unity-events">Spine Unity Events documentation page</see>
+	/// and <see cref="http://esotericsoftware.com/spine-api-reference#AnimationStateListener"/>
+	/// for more information on when track events will be triggered.</summary>
+	public class WaitForSpineAnimationComplete : WaitForSpineAnimation, IEnumerator {
 		
-		bool m_WasFired = false;
-
-		public WaitForSpineAnimationComplete (Spine.TrackEntry trackEntry) {
-			SafeSubscribe(trackEntry);
-		}
-
-		void HandleComplete (TrackEntry trackEntry) {
-			m_WasFired = true;
-		}
-
-		void SafeSubscribe (Spine.TrackEntry trackEntry) {
-			if (trackEntry == null) {
-				// Break immediately if trackEntry is null.
-				Debug.LogWarning("TrackEntry was null. Coroutine will continue immediately.");
-				m_WasFired = true;
-			} else {
-				trackEntry.Complete += HandleComplete;
-			}
+		public WaitForSpineAnimationComplete (Spine.TrackEntry trackEntry, bool includeEndEvent = false) :
+			base(trackEntry,
+				includeEndEvent ? (AnimationEventTypes.Complete | AnimationEventTypes.End) : AnimationEventTypes.Complete)
+		{
 		}
 
 		#region Reuse
 		/// <summary>
 		/// One optimization high-frequency YieldInstruction returns is to cache instances to minimize GC pressure. 
 		/// Use NowWaitFor to reuse the same instance of WaitForSpineAnimationComplete.</summary>
-		public WaitForSpineAnimationComplete NowWaitFor (Spine.TrackEntry trackEntry) {
-			SafeSubscribe(trackEntry);
+		public WaitForSpineAnimationComplete NowWaitFor (Spine.TrackEntry trackEntry, bool includeEndEvent = false) {
+			SafeSubscribe(trackEntry,
+				includeEndEvent ? (AnimationEventTypes.Complete | AnimationEventTypes.End) : AnimationEventTypes.Complete);
 			return this;
 		}
 		#endregion
-
-		#region IEnumerator
-		bool IEnumerator.MoveNext () {
-			if (m_WasFired) {
-				((IEnumerator)this).Reset();	// auto-reset for YieldInstruction reuse
-				return false;
-			}
-
-			return true;
-		}
-		void IEnumerator.Reset () { m_WasFired = false; }
-		object IEnumerator.Current { get { return null; } }
-		#endregion
-
 	}
-
 }

+ 59 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/YieldInstructions/WaitForSpineAnimationEnd.cs

@@ -0,0 +1,59 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated May 1, 2019. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2019, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS
+ * INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+using UnityEngine;
+using System.Collections;
+using Spine;
+
+namespace Spine.Unity {
+	/// <summary>
+	/// Use this as a condition-blocking yield instruction for Unity Coroutines. 
+	/// The routine will pause until the AnimationState.TrackEntry fires its End event.
+	/// <p/>
+	/// See the <see cref="http://esotericsoftware.com/spine-unity-events">Spine Unity Events documentation page</see>
+	/// and <see cref="http://esotericsoftware.com/spine-api-reference#AnimationStateListener"/>
+	/// for more information on when track events will be triggered.</summary>
+	public class WaitForSpineAnimationEnd : WaitForSpineAnimation, IEnumerator {
+		
+		public WaitForSpineAnimationEnd (Spine.TrackEntry trackEntry) :
+			base(trackEntry, AnimationEventTypes.End)
+		{
+		}
+		
+		#region Reuse
+		/// <summary>
+		/// One optimization high-frequency YieldInstruction returns is to cache instances to minimize GC pressure. 
+		/// Use NowWaitFor to reuse the same instance of WaitForSpineAnimationComplete.</summary>
+		public WaitForSpineAnimationEnd NowWaitFor (Spine.TrackEntry trackEntry) {
+			SafeSubscribe(trackEntry, AnimationEventTypes.End);
+			return this;
+		}
+		#endregion
+	}
+}

+ 12 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/YieldInstructions/WaitForSpineAnimationEnd.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 3c5a5fe930d1ab24da154d76b24c2747
+timeCreated: 1566288961
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: