ManualMixerState.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.Playables;
  6. using Object = UnityEngine.Object;
  7. namespace Animancer
  8. {
  9. /// <summary>[Pro-Only]
  10. /// An <see cref="AnimancerState"/> which blends multiple child states. Unlike other mixers, this class does not
  11. /// perform any automatic weight calculations, it simple allows you to control the weight of all states manually.
  12. /// </summary>
  13. /// <remarks>
  14. /// This mixer type is similar to the Direct Blend Type in Mecanim Blend Trees.
  15. /// The official <see href="https://learn.unity.com/tutorial/5c5152bcedbc2a001fd5c696">Direct Blend Trees</see>
  16. /// tutorial explains their general concepts and purpose which apply to <see cref="ManualMixerState"/>s as well.
  17. /// <para></para>
  18. /// Documentation: <see href="https://kybernetik.com.au/animancer/docs/manual/blending/mixers">Mixers</see>
  19. /// </remarks>
  20. /// https://kybernetik.com.au/animancer/api/Animancer/ManualMixerState
  21. ///
  22. public partial class ManualMixerState : MixerState
  23. {
  24. /************************************************************************************************************************/
  25. /// <summary>An <see cref="ITransition{TState}"/> that creates a <see cref="ManualMixerState"/>.</summary>
  26. public interface ITransition : ITransition<ManualMixerState> { }
  27. /************************************************************************************************************************/
  28. #region Properties
  29. /************************************************************************************************************************/
  30. /// <summary>The states managed by this mixer.</summary>
  31. private AnimancerState[] _Children = Array.Empty<AnimancerState>();
  32. /// <summary>Returns the array of <see cref="_Children"/>.</summary>
  33. public override IList<AnimancerState> ChildStates => _Children;
  34. /************************************************************************************************************************/
  35. /// <inheritdoc/>
  36. public override int ChildCount => _Children.Length;
  37. /// <inheritdoc/>
  38. public override AnimancerState GetChild(int index) => _Children[index];
  39. /// <inheritdoc/>
  40. public override FastEnumerator<AnimancerState> GetEnumerator()
  41. => new FastEnumerator<AnimancerState>(_Children, _Children.Length);
  42. /************************************************************************************************************************/
  43. #endregion
  44. /************************************************************************************************************************/
  45. #region Initialisation
  46. /************************************************************************************************************************/
  47. /// <summary>
  48. /// Initializes this mixer with the specified number of children which can be set individually by
  49. /// <see cref="MixerState.CreateChild(int, AnimationClip)"/> and <see cref="MixerState.SetChild"/>.
  50. /// </summary>
  51. /// <remarks><see cref="AnimancerState.Destroy"/> will be called on any existing children.</remarks>
  52. public virtual void Initialize(int childCount)
  53. {
  54. #if UNITY_ASSERTIONS
  55. if (childCount <= 1 && OptionalWarning.MixerMinChildren.IsEnabled())
  56. OptionalWarning.MixerMinChildren.Log(
  57. $"{this} is being initialized with {nameof(childCount)} <= 1." +
  58. $" The purpose of a mixer is to mix multiple child states.", Root?.Component);
  59. #endif
  60. for (int i = _Children.Length - 1; i >= 0; i--)
  61. {
  62. var state = _Children[i];
  63. if (state == null)
  64. continue;
  65. state.Destroy();
  66. }
  67. _Children = new AnimancerState[childCount];
  68. if (_Playable.IsValid())
  69. {
  70. _Playable.SetInputCount(childCount);
  71. }
  72. else if (Root != null)
  73. {
  74. CreatePlayable();
  75. }
  76. }
  77. /************************************************************************************************************************/
  78. /// <summary>Initializes this mixer with one state per clip.</summary>
  79. public void Initialize(params AnimationClip[] clips)
  80. {
  81. #if UNITY_ASSERTIONS
  82. if (clips == null)
  83. throw new ArgumentNullException(nameof(clips));
  84. #endif
  85. var count = clips.Length;
  86. Initialize(count);
  87. for (int i = 0; i < count; i++)
  88. {
  89. var clip = clips[i];
  90. if (clip != null)
  91. CreateChild(i, clip);
  92. }
  93. }
  94. /************************************************************************************************************************/
  95. /// <summary>
  96. /// Initializes this mixer by calling <see cref="MixerState.CreateChild(int, Object)"/> for each of the
  97. /// `states`.
  98. /// </summary>
  99. public void Initialize(params Object[] animations)
  100. {
  101. #if UNITY_ASSERTIONS
  102. if (animations == null)
  103. throw new ArgumentNullException(nameof(animations));
  104. #endif
  105. var count = animations.Length;
  106. Initialize(count);
  107. for (int i = 0; i < count; i++)
  108. {
  109. var state = animations[i];
  110. if (state != null)
  111. CreateChild(i, state);
  112. }
  113. }
  114. /************************************************************************************************************************/
  115. #endregion
  116. /************************************************************************************************************************/
  117. }
  118. }