Transition.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using Animancer.Units;
  3. using System;
  4. using UnityEngine;
  5. using Object = UnityEngine.Object;
  6. namespace Animancer
  7. {
  8. /// <summary>
  9. /// A serializable <see cref="ITransition"/> which can create a particular type of
  10. /// <see cref="AnimancerState"/> when passed into <see cref="AnimancerLayer.Play(ITransition)"/>.
  11. /// </summary>
  12. /// <remarks>
  13. /// <strong>Documentation:</strong>
  14. /// <see href="https://kybernetik.com.au/animancer/docs/manual/transitions">
  15. /// Transitions</see>
  16. /// </remarks>
  17. /// https://kybernetik.com.au/animancer/api/Animancer/Transition_1
  18. [Serializable]
  19. public abstract class Transition<TState> :
  20. IPolymorphic,
  21. ITransition<TState>,
  22. ITransitionDetailed,
  23. ITransitionWithEvents,
  24. ICopyable<Transition<TState>>,
  25. ICloneable<Transition<TState>>
  26. where TState : AnimancerState
  27. {
  28. /************************************************************************************************************************/
  29. [SerializeField]
  30. [Tooltip(Strings.Tooltips.FadeDuration)]
  31. [AnimationTime(AnimationTimeAttribute.Units.Seconds, Rule = Validate.Value.IsNotNegative)]
  32. [DefaultFadeValue]
  33. private float _FadeDuration = AnimancerGraph.DefaultFadeDuration;
  34. /// <inheritdoc/>
  35. /// <remarks>[<see cref="SerializeField"/>]</remarks>
  36. /// <exception cref="ArgumentOutOfRangeException">Thrown when setting the value to a negative number.</exception>
  37. public float FadeDuration
  38. {
  39. get => _FadeDuration;
  40. set
  41. {
  42. if (value < 0)
  43. throw new ArgumentOutOfRangeException(
  44. nameof(value),
  45. $"{nameof(FadeDuration)} must not be negative");
  46. _FadeDuration = value;
  47. }
  48. }
  49. /************************************************************************************************************************/
  50. [SerializeField]
  51. [Tooltip(Strings.Tooltips.OptionalSpeed)]
  52. [AnimationSpeed(DisabledText = Strings.Tooltips.SpeedDisabled)]
  53. [DefaultValue(1f, -1f)]
  54. private float _Speed = 1;
  55. /// <summary>[<see cref="SerializeField"/>]
  56. /// Determines how fast the animation plays (1x = normal speed, 2x = double speed).
  57. /// </summary>
  58. /// <remarks>
  59. /// This sets the <see cref="AnimancerNodeBase.Speed"/> when this transition is played.
  60. /// </remarks>
  61. public float Speed
  62. {
  63. get => _Speed;
  64. set => _Speed = value;
  65. }
  66. /************************************************************************************************************************/
  67. /// <inheritdoc/>
  68. /// <remarks>Returns <c>false</c> unless overridden.</remarks>
  69. public virtual bool IsLooping => false;
  70. /// <inheritdoc/>
  71. public virtual float NormalizedStartTime
  72. {
  73. get => float.NaN;
  74. set { }
  75. }
  76. /// <inheritdoc/>
  77. public abstract float MaximumDuration { get; }
  78. /************************************************************************************************************************/
  79. [SerializeField, Tooltip(Strings.ProOnlyTag + "Events which will be triggered as the animation plays")]
  80. private AnimancerEvent.Sequence.Serializable _Events;
  81. /// <inheritdoc/>
  82. /// <remarks>This property returns the <see cref="AnimancerEvent.Sequence.Serializable.Events"/>.</remarks>
  83. public virtual AnimancerEvent.Sequence Events
  84. {
  85. get => (_Events ??= new()).Events;
  86. set => (_Events ??= new()).Events = value;
  87. }
  88. /// <inheritdoc/>
  89. public ref AnimancerEvent.Sequence.Serializable SerializedEvents
  90. => ref _Events;
  91. /************************************************************************************************************************/
  92. /// <summary>
  93. /// The state that was created by this object. Specifically, this is the state that was most recently
  94. /// passed into <see cref="Apply"/> (usually by <see cref="AnimancerGraph.Play(ITransition)"/>).
  95. /// <para></para>
  96. /// You can use <see cref="AnimancerStateDictionary.GetOrCreate(ITransition)"/> or
  97. /// <see cref="AnimancerLayer.GetOrCreateState(ITransition)"/> to get or create the state for a
  98. /// specific object.
  99. /// <para></para>
  100. /// <see cref="State"/> is simply a shorthand for casting this to <typeparamref name="TState"/>.
  101. /// </summary>
  102. public AnimancerState BaseState { get; private set; }
  103. /************************************************************************************************************************/
  104. private TState _State;
  105. /// <summary>
  106. /// The state that was created by this object. Specifically, this is the state that was most recently
  107. /// passed into <see cref="Apply"/> (usually by <see cref="AnimancerGraph.Play(ITransition)"/>).
  108. /// </summary>
  109. ///
  110. /// <remarks>
  111. /// You can use <see cref="AnimancerStateDictionary.GetOrCreate(ITransition)"/> or
  112. /// <see cref="AnimancerLayer.GetOrCreateState(ITransition)"/>
  113. /// to get or create the state for a specific object.
  114. /// <para></para>
  115. /// This property is shorthand for casting the <see cref="BaseState"/> to <typeparamref name="TState"/>.
  116. /// </remarks>
  117. ///
  118. /// <exception cref="InvalidCastException">
  119. /// The <see cref="BaseState"/> is not actually a <typeparamref name="TState"/>.
  120. /// This should only happen if a different type of state was created by something else
  121. /// and registered using the <see cref="Key"/>,
  122. /// causing this <see cref="AnimancerGraph.Play(ITransition)"/> to pass that state into
  123. /// <see cref="Apply"/> instead of calling <see cref="CreateState"/>
  124. /// to make the correct type of state.
  125. /// </exception>
  126. public TState State
  127. {
  128. get => _State ??= (TState)BaseState;
  129. protected set => BaseState = _State = value;
  130. }
  131. /************************************************************************************************************************/
  132. /// <inheritdoc/>
  133. /// <remarks>Returns <c>true</c> unless overridden.</remarks>
  134. public virtual bool IsValid
  135. => true;
  136. /// <summary>The <see cref="AnimancerState.Key"/> which the created state will be registered with.</summary>
  137. /// <remarks>Returns <c>this</c> unless overridden.</remarks>
  138. public virtual object Key
  139. => this;
  140. /// <inheritdoc/>
  141. /// <remarks>Returns <see cref="FadeMode.FixedSpeed"/> unless overridden.</remarks>
  142. public virtual FadeMode FadeMode
  143. => FadeMode.FixedSpeed;
  144. /************************************************************************************************************************/
  145. /// <inheritdoc/>
  146. public abstract TState CreateState();
  147. /// <inheritdoc/>
  148. AnimancerState ITransition.CreateState()
  149. => CreateAndInitializeState();
  150. /// <summary>Calls <see cref="CreateState"/> and assigns the <see cref="Events"/> to the state.</summary>
  151. public TState CreateAndInitializeState()
  152. {
  153. var state = CreateState();
  154. AnimancerState.SetExpectFade(state, _FadeDuration);
  155. State = state;
  156. state.SharedEvents = _Events;
  157. return state;
  158. }
  159. /************************************************************************************************************************/
  160. /// <inheritdoc/>
  161. public virtual void Apply(AnimancerState state)
  162. {
  163. if (_State != state)
  164. {
  165. _State = null;
  166. BaseState = state;
  167. }
  168. if (!float.IsNaN(_Speed))
  169. state.Speed = _Speed;
  170. }
  171. /************************************************************************************************************************/
  172. /// <summary>Applies the `normalizedStartTime` to the `state`.</summary>
  173. public static void ApplyNormalizedStartTime(AnimancerState state, float normalizedStartTime)
  174. {
  175. if (!float.IsNaN(normalizedStartTime))
  176. state.NormalizedTime = normalizedStartTime;
  177. else if (state.Weight == 0)
  178. state.NormalizedTime = AnimancerEvent.Sequence.GetDefaultNormalizedStartTime(state.Speed);
  179. }
  180. /************************************************************************************************************************/
  181. /// <summary>The <see cref="AnimancerState.MainObject"/> that the created state will have.</summary>
  182. public virtual Object MainObject { get; }
  183. /// <summary>The display name of this transition.</summary>
  184. public virtual string Name
  185. {
  186. get
  187. {
  188. var mainObject = MainObject;
  189. return mainObject != null ? mainObject.name : null;
  190. }
  191. }
  192. /// <summary>Returns the <see cref="Name"/> and type of this transition.</summary>
  193. public override string ToString()
  194. {
  195. var type = GetType().FullName;
  196. var name = Name;
  197. return name is null
  198. ? type :
  199. $"{name} ({type})";
  200. }
  201. /************************************************************************************************************************/
  202. /// <inheritdoc/>
  203. public abstract Transition<TState> Clone(CloneContext context);
  204. /// <inheritdoc/>
  205. public virtual void CopyFrom(Transition<TState> copyFrom, CloneContext context)
  206. {
  207. if (copyFrom == null)
  208. {
  209. _FadeDuration = AnimancerGraph.DefaultFadeDuration;
  210. _Events = default;
  211. _Speed = 1;
  212. return;
  213. }
  214. _FadeDuration = copyFrom._FadeDuration;
  215. _Speed = copyFrom._Speed;
  216. _Events = copyFrom._Events.Clone();
  217. }
  218. /************************************************************************************************************************/
  219. }
  220. }