AnimatedProperty.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using System;
  3. using UnityEngine;
  4. using UnityEngine.Animations;
  5. using Unity.Collections;
  6. namespace Animancer
  7. {
  8. /// <summary>[Pro-Only]
  9. /// A base wrapper which allows access to the value of properties that are controlled by animations.
  10. /// </summary>
  11. ///
  12. /// <remarks>
  13. /// <strong>Documentation:</strong>
  14. /// <see href="https://kybernetik.com.au/animancer/docs/manual/ik#animated-properties">
  15. /// Animated Properties</see>
  16. /// </remarks>
  17. ///
  18. /// https://kybernetik.com.au/animancer/api/Animancer/AnimatedProperty_2
  19. ///
  20. public abstract class AnimatedProperty<TJob, TValue> : AnimancerJob<TJob>, IDisposable
  21. where TJob : struct, IAnimationJob
  22. where TValue : struct
  23. {
  24. /************************************************************************************************************************/
  25. /// <summary>The properties wrapped by this object.</summary>
  26. protected NativeArray<PropertyStreamHandle> _Properties;
  27. /// <summary>The value of each of the <see cref="_Properties"/> from the most recent update.</summary>
  28. protected NativeArray<TValue> _Values;
  29. /************************************************************************************************************************/
  30. #region Initialization
  31. /************************************************************************************************************************/
  32. /// <summary>
  33. /// Allocates room for a specified number of properties to be filled by
  34. /// <see cref="InitializeProperty(int, Transform, Type, string)"/>.
  35. /// </summary>
  36. public AnimatedProperty(IAnimancerComponent animancer, int propertyCount,
  37. NativeArrayOptions options = NativeArrayOptions.ClearMemory)
  38. {
  39. _Properties = new(propertyCount, Allocator.Persistent, options);
  40. _Values = new(propertyCount, Allocator.Persistent);
  41. CreateJob();
  42. var playable = animancer.Graph;
  43. CreatePlayable(playable);
  44. playable.Disposables.Add(this);
  45. }
  46. /// <summary>Initializes a single property.</summary>
  47. public AnimatedProperty(IAnimancerComponent animancer, string propertyName)
  48. : this(animancer, 1, NativeArrayOptions.UninitializedMemory)
  49. {
  50. var animator = animancer.Animator;
  51. _Properties[0] = animator.BindStreamProperty(animator.transform, typeof(Animator), propertyName);
  52. }
  53. /// <summary>Initializes a group of properties.</summary>
  54. public AnimatedProperty(IAnimancerComponent animancer, params string[] propertyNames)
  55. : this(animancer, propertyNames.Length, NativeArrayOptions.UninitializedMemory)
  56. {
  57. var count = propertyNames.Length;
  58. var animator = animancer.Animator;
  59. var transform = animator.transform;
  60. for (int i = 0; i < count; i++)
  61. InitializeProperty(animator, i, transform, typeof(Animator), propertyNames[i]);
  62. }
  63. /************************************************************************************************************************/
  64. /// <summary>Initializes a property on the target <see cref="Animator"/>.</summary>
  65. public void InitializeProperty(Animator animator, int index, string name)
  66. => InitializeProperty(animator, index, animator.transform, typeof(Animator), name);
  67. /// <summary>Initializes the specified `index` to read a property with the specified `name`.</summary>
  68. public void InitializeProperty(Animator animator, int index, Transform transform, Type type, string name)
  69. => _Properties[index] = animator.BindStreamProperty(transform, type, name);
  70. /************************************************************************************************************************/
  71. /// <summary>Creates and assigns the <see cref="AnimancerJob._Job"/>.</summary>
  72. protected abstract void CreateJob();
  73. /************************************************************************************************************************/
  74. #endregion
  75. /************************************************************************************************************************/
  76. #region Accessors
  77. /************************************************************************************************************************/
  78. /// <summary>Returns the value of the first property.</summary>
  79. public TValue Value => this[0];
  80. /// <summary>Returns the value of the first property.</summary>
  81. public static implicit operator TValue(AnimatedProperty<TJob, TValue> properties) => properties[0];
  82. /************************************************************************************************************************/
  83. /// <summary>Returns the value of the property at the specified `index`.</summary>
  84. /// <remarks>This method is identical to <see cref="this[int]"/>.</remarks>
  85. public TValue GetValue(int index) => _Values[index];
  86. /// <summary>Returns the value of the property at the specified `index`.</summary>
  87. /// <remarks>This indexer is identical to <see cref="GetValue(int)"/>.</remarks>
  88. public TValue this[int index] => _Values[index];
  89. /************************************************************************************************************************/
  90. /// <summary>Resizes the `values` if necessary and copies the value of each property into it.</summary>
  91. public void GetValues(ref TValue[] values)
  92. {
  93. AnimancerUtilities.SetLength(ref values, _Values.Length);
  94. _Values.CopyTo(values);
  95. }
  96. /// <summary>Returns a new array containing the values of all properties.</summary>
  97. /// <remarks>Use <see cref="GetValues(ref TValue[])"/> to avoid allocating a new array every call.</remarks>
  98. public TValue[] GetValues()
  99. {
  100. var values = new TValue[_Values.Length];
  101. _Values.CopyTo(values);
  102. return values;
  103. }
  104. /************************************************************************************************************************/
  105. #endregion
  106. /************************************************************************************************************************/
  107. void IDisposable.Dispose() => Dispose();
  108. /// <summary>Cleans up the <see cref="NativeArray{T}"/>s.</summary>
  109. /// <remarks>Called by <see cref="AnimancerGraph.OnPlayableDestroy"/>.</remarks>
  110. protected virtual void Dispose()
  111. {
  112. if (_Properties.IsCreated)
  113. {
  114. _Properties.Dispose();
  115. _Values.Dispose();
  116. }
  117. }
  118. /// <summary>Destroys the <see cref="_Playable"/> and restores the graph connection it was intercepting.</summary>
  119. public override void Destroy()
  120. {
  121. Dispose();
  122. base.Destroy();
  123. }
  124. /************************************************************************************************************************/
  125. }
  126. }