MotionHandleExtensions.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. using System;
  2. using System.Collections;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using UnityEngine;
  6. namespace LitMotion
  7. {
  8. /// <summary>
  9. /// Provides methods for manipulating the motion entity pointed to by MotionHandle.
  10. /// </summary>
  11. public static class MotionHandleExtensions
  12. {
  13. /// <summary>
  14. /// Checks if a motion is currently playing.
  15. /// </summary>
  16. /// <param name="handle">This motion handle</param>
  17. /// <returns>True if motion is active, otherwise false.</returns>
  18. public static bool IsActive(this MotionHandle handle)
  19. {
  20. return MotionStorageManager.IsActive(handle);
  21. }
  22. /// <summary>
  23. /// Complete motion.
  24. /// </summary>
  25. /// <param name="handle">This motion handle</param>
  26. public static void Complete(this MotionHandle handle)
  27. {
  28. MotionStorageManager.CompleteMotion(handle);
  29. }
  30. /// <summary>
  31. /// Cancel motion.
  32. /// </summary>
  33. /// <param name="handle">This motion handle</param>
  34. public static void Cancel(this MotionHandle handle)
  35. {
  36. MotionStorageManager.CancelMotion(handle);
  37. }
  38. /// <summary>
  39. /// Add this motion handle to CompositeMotionHandle.
  40. /// </summary>
  41. /// <param name="handle">This motion handle</param>
  42. /// <param name="compositeMotionHandle">target CompositeMotionHandle</param>
  43. public static MotionHandle AddTo(this MotionHandle handle, CompositeMotionHandle compositeMotionHandle)
  44. {
  45. compositeMotionHandle.Add(handle);
  46. return handle;
  47. }
  48. /// <summary>
  49. /// Link the motion lifecycle to the target object.
  50. /// </summary>
  51. /// <param name="handle">This motion handle</param>
  52. /// <param name="target">Target object</param>
  53. public static MotionHandle AddTo(this MotionHandle handle, GameObject target)
  54. {
  55. GetOrAddComponent<MotionHandleLinker>(target).Register(handle, LinkBehaviour.CancelOnDestroy);
  56. return handle;
  57. }
  58. /// <summary>
  59. /// Link the motion lifecycle to the target object.
  60. /// </summary>
  61. /// <param name="handle">This motion handle</param>
  62. /// <param name="target">Target object</param>
  63. /// <param name="linkBehaviour">Link behaviour</param>
  64. public static MotionHandle AddTo(this MotionHandle handle, GameObject target, LinkBehaviour linkBehaviour)
  65. {
  66. GetOrAddComponent<MotionHandleLinker>(target).Register(handle, linkBehaviour);
  67. return handle;
  68. }
  69. /// <summary>
  70. /// Link the motion lifecycle to the target object.
  71. /// </summary>
  72. /// <param name="handle">This motion handle</param>
  73. /// <param name="target">Target object</param>
  74. public static MotionHandle AddTo(this MotionHandle handle, Component target)
  75. {
  76. GetOrAddComponent<MotionHandleLinker>(target.gameObject).Register(handle, LinkBehaviour.CancelOnDestroy);
  77. return handle;
  78. }
  79. /// <summary>
  80. /// Link the motion lifecycle to the target object.
  81. /// </summary>
  82. /// <param name="handle">This motion handle</param>
  83. /// <param name="target">Target object</param>
  84. /// <param name="linkBehaviour">Link behaviour</param>
  85. public static MotionHandle AddTo(this MotionHandle handle, Component target, LinkBehaviour linkBehaviour)
  86. {
  87. GetOrAddComponent<MotionHandleLinker>(target.gameObject).Register(handle, linkBehaviour);
  88. return handle;
  89. }
  90. #if UNITY_2022_2_OR_NEWER
  91. /// <summary>
  92. /// Link the motion lifecycle to the target object.
  93. /// </summary>
  94. /// <param name="handle">This motion handle</param>
  95. /// <param name="target">Target object</param>
  96. public static MotionHandle AddTo(this MotionHandle handle, MonoBehaviour target)
  97. {
  98. target.destroyCancellationToken.Register(() =>
  99. {
  100. if (handle.IsActive()) handle.Cancel();
  101. }, false);
  102. return handle;
  103. }
  104. #endif
  105. static TComponent GetOrAddComponent<TComponent>(GameObject target) where TComponent : Component
  106. {
  107. if (!target.TryGetComponent<TComponent>(out var component))
  108. {
  109. component = target.AddComponent<TComponent>();
  110. }
  111. return component;
  112. }
  113. /// <summary>
  114. /// Convert MotionHandle to IDisposable.
  115. /// </summary>
  116. /// <param name="handle">This motion handle</param>
  117. /// <returns></returns>
  118. public static IDisposable ToDisposable(this MotionHandle handle)
  119. {
  120. return new MotionHandleDisposable(handle);
  121. }
  122. /// <summary>
  123. /// Wait for the motion to finish in a coroutine.
  124. /// </summary>
  125. /// <param name="handle">This motion handle</param>
  126. /// <returns></returns>
  127. public static IEnumerator ToYieldInteraction(this MotionHandle handle)
  128. {
  129. while (handle.IsActive())
  130. {
  131. yield return null;
  132. }
  133. }
  134. public static MotionAwaiter GetAwaiter(this MotionHandle handle)
  135. {
  136. return new MotionAwaiter(handle);
  137. }
  138. /// <summary>
  139. /// Convert motion handle to ValueTask.
  140. /// </summary>
  141. /// <param name="handle">This motion handle</param>
  142. /// <param name="cancellationToken">CancellationToken</param>
  143. /// <returns></returns>
  144. public static ValueTask ToValueTask(this MotionHandle handle, CancellationToken cancellationToken = default)
  145. {
  146. if (!handle.IsActive()) return default;
  147. var source = ValueTaskMotionConfiguredSource.Create(handle, CancelBehaviour.CancelAndCancelAwait, cancellationToken, out var token);
  148. return new ValueTask(source, token);
  149. }
  150. /// <summary>
  151. /// Convert motion handle to ValueTask.
  152. /// </summary>
  153. /// <param name="handle">This motion handle</param>
  154. /// <param name="cancelBehaviour">Behavior when canceling</param>
  155. /// <param name="cancellationToken">CancellationToken</param>
  156. /// <returns></returns>
  157. public static ValueTask ToValueTask(this MotionHandle handle, CancelBehaviour cancelBehaviour, CancellationToken cancellationToken = default)
  158. {
  159. if (!handle.IsActive()) return default;
  160. var source = ValueTaskMotionConfiguredSource.Create(handle, cancelBehaviour, cancellationToken, out var token);
  161. return new ValueTask(source, token);
  162. }
  163. #if UNITY_2023_1_OR_NEWER
  164. /// <summary>
  165. /// Convert motion handle to Awaitable.
  166. /// </summary>
  167. /// <param name="handle">This motion handle</param>
  168. /// <param name="cancellationToken">CancellationToken</param>
  169. /// <returns></returns>
  170. public static Awaitable ToAwaitable(this MotionHandle handle, CancellationToken cancellationToken = default)
  171. {
  172. if (!handle.IsActive()) return AwaitableMotionConfiguredSource.CompletedSource.Awaitable;
  173. return AwaitableMotionConfiguredSource.Create(handle, CancelBehaviour.CancelAndCancelAwait, cancellationToken).Awaitable;
  174. }
  175. /// <summary>
  176. /// Convert motion handle to Awaitable.
  177. /// </summary>
  178. /// <param name="handle">This motion handle</param>
  179. /// <param name="cancelBehaviour">Behavior when canceling</param>
  180. /// <param name="cancellationToken">CancellationToken</param>
  181. /// <returns></returns>
  182. public static Awaitable ToAwaitable(this MotionHandle handle, CancelBehaviour cancelBehaviour, CancellationToken cancellationToken = default)
  183. {
  184. if (!handle.IsActive()) return AwaitableMotionConfiguredSource.CompletedSource.Awaitable;
  185. return AwaitableMotionConfiguredSource.Create(handle, cancelBehaviour, cancellationToken).Awaitable;
  186. }
  187. #endif
  188. }
  189. internal sealed class MotionHandleDisposable : IDisposable
  190. {
  191. public MotionHandleDisposable(MotionHandle handle) => this.handle = handle;
  192. public readonly MotionHandle handle;
  193. public void Dispose()
  194. {
  195. if (handle.IsActive()) handle.Cancel();
  196. }
  197. }
  198. }