ClipTransitionAsset.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
  2. using Animancer.Units;
  3. using System;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using Object = UnityEngine.Object;
  7. namespace Animancer
  8. {
  9. /// <inheritdoc/>
  10. /// https://kybernetik.com.au/animancer/api/Animancer/ClipTransitionAsset
  11. [CreateAssetMenu(menuName = Strings.MenuPrefix + "Clip Transition", order = Strings.AssetMenuOrder + 1)]
  12. [HelpURL(Strings.DocsURLs.APIDocumentation + "/" + nameof(ClipTransitionAsset))]
  13. public class ClipTransitionAsset : AnimancerTransitionAsset<ClipTransition>
  14. {
  15. /// <inheritdoc/>
  16. [Serializable]
  17. public new class UnShared :
  18. UnShared<ClipTransitionAsset, ClipTransition, ClipState>,
  19. ClipState.ITransition
  20. { }
  21. }
  22. /// <inheritdoc/>
  23. /// https://kybernetik.com.au/animancer/api/Animancer/ClipTransition
  24. [Serializable]
  25. public class ClipTransition : AnimancerTransition<ClipState>,
  26. ClipState.ITransition, IMotion, IAnimationClipCollection, ICopyable<ClipTransition>
  27. {
  28. /************************************************************************************************************************/
  29. [SerializeField, Tooltip("The animation to play")]
  30. private AnimationClip _Clip;
  31. /// <summary>[<see cref="SerializeField"/>] The animation to play.</summary>
  32. public AnimationClip Clip
  33. {
  34. get => _Clip;
  35. set
  36. {
  37. #if UNITY_ASSERTIONS
  38. if (value != null)
  39. Validate.AssertNotLegacy(value);
  40. #endif
  41. _Clip = value;
  42. }
  43. }
  44. /// <inheritdoc/>
  45. public override Object MainObject => _Clip;
  46. /// <summary>Returns the <see cref="Clip"/> to use as the <see cref="AnimancerState.Key"/>.</summary>
  47. public override object Key => _Clip;
  48. /************************************************************************************************************************/
  49. [SerializeField]
  50. [Tooltip(Strings.Tooltips.OptionalSpeed)]
  51. [AnimationSpeed]
  52. [DefaultValue(1f, -1f)]
  53. private float _Speed = 1;
  54. /// <inheritdoc/>
  55. public override float Speed
  56. {
  57. get => _Speed;
  58. set => _Speed = value;
  59. }
  60. /************************************************************************************************************************/
  61. [SerializeField]
  62. [Tooltip(Strings.Tooltips.NormalizedStartTime)]
  63. [AnimationTime(AnimationTimeAttribute.Units.Normalized)]
  64. [DefaultValue(float.NaN, 0f)]
  65. private float _NormalizedStartTime = float.NaN;
  66. /// <inheritdoc/>
  67. public override float NormalizedStartTime
  68. {
  69. get => _NormalizedStartTime;
  70. set => _NormalizedStartTime = value;
  71. }
  72. /// <summary>
  73. /// If this transition will set the <see cref="AnimancerState.Time"/>, then it needs to use
  74. /// <see cref="FadeMode.FromStart"/>.
  75. /// </summary>
  76. public override FadeMode FadeMode => float.IsNaN(_NormalizedStartTime) ? FadeMode.FixedSpeed : FadeMode.FromStart;
  77. /************************************************************************************************************************/
  78. /// <summary>
  79. /// The length of the <see cref="Clip"/> (in seconds), accounting for the <see cref="NormalizedStartTime"/> and
  80. /// <see cref="AnimancerEvent.Sequence.NormalizedEndTime"/> (but not <see cref="Speed"/>).
  81. /// </summary>
  82. public virtual float Length
  83. {
  84. get
  85. {
  86. if (!IsValid)
  87. return 0;
  88. var normalizedEndTime = Events.NormalizedEndTime;
  89. normalizedEndTime = !float.IsNaN(normalizedEndTime)
  90. ? normalizedEndTime
  91. : AnimancerEvent.Sequence.GetDefaultNormalizedEndTime(_Speed);
  92. var normalizedStartTime = !float.IsNaN(_NormalizedStartTime)
  93. ? _NormalizedStartTime
  94. : AnimancerEvent.Sequence.GetDefaultNormalizedStartTime(_Speed);
  95. return _Clip.length * (normalizedEndTime - normalizedStartTime);
  96. }
  97. }
  98. /************************************************************************************************************************/
  99. /// <inheritdoc/>
  100. public override bool IsValid => _Clip != null && !_Clip.legacy;
  101. /// <summary>[<see cref="ITransitionDetailed"/>] Is the <see cref="Clip"/> looping?</summary>
  102. public override bool IsLooping => _Clip != null && _Clip.isLooping;
  103. /// <inheritdoc/>
  104. public override float MaximumDuration => _Clip != null ? _Clip.length : 0;
  105. /// <inheritdoc/>
  106. public virtual float AverageAngularSpeed => _Clip != null ? _Clip.averageAngularSpeed : default;
  107. /// <inheritdoc/>
  108. public virtual Vector3 AverageVelocity => _Clip != null ? _Clip.averageSpeed : default;
  109. /************************************************************************************************************************/
  110. /// <inheritdoc/>
  111. public override ClipState CreateState()
  112. {
  113. #if UNITY_ASSERTIONS
  114. if (_Clip == null)
  115. throw new ArgumentException(
  116. $"Unable to create {nameof(ClipState)} because the {nameof(ClipTransition)}.{nameof(Clip)} is null.");
  117. #endif
  118. return State = new ClipState(_Clip);
  119. }
  120. /************************************************************************************************************************/
  121. /// <inheritdoc/>
  122. public override void Apply(AnimancerState state)
  123. {
  124. ApplyDetails(state, _Speed, _NormalizedStartTime);
  125. base.Apply(state);
  126. }
  127. /************************************************************************************************************************/
  128. /// <summary>[<see cref="IAnimationClipCollection"/>] Adds the <see cref="Clip"/> to the collection.</summary>
  129. public virtual void GatherAnimationClips(ICollection<AnimationClip> clips) => clips.Gather(_Clip);
  130. /************************************************************************************************************************/
  131. /// <inheritdoc/>
  132. public virtual void CopyFrom(ClipTransition copyFrom)
  133. {
  134. CopyFrom((AnimancerTransition<ClipState>)copyFrom);
  135. if (copyFrom == null)
  136. {
  137. _Clip = default;
  138. _Speed = 1;
  139. _NormalizedStartTime = float.NaN;
  140. return;
  141. }
  142. _Clip = copyFrom._Clip;
  143. _Speed = copyFrom._Speed;
  144. _NormalizedStartTime = copyFrom._NormalizedStartTime;
  145. }
  146. /************************************************************************************************************************/
  147. #if UNITY_EDITOR
  148. /************************************************************************************************************************/
  149. /// <inheritdoc/>
  150. [UnityEditor.CustomPropertyDrawer(typeof(ClipTransition), true)]
  151. public class Drawer : Editor.TransitionDrawer
  152. {
  153. /************************************************************************************************************************/
  154. /// <summary>Creates a new <see cref="Drawer"/>.</summary>
  155. public Drawer() : base(nameof(_Clip)) { }
  156. /************************************************************************************************************************/
  157. }
  158. /************************************************************************************************************************/
  159. #endif
  160. /************************************************************************************************************************/
  161. }
  162. }