123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
- using System;
- using UnityEngine;
- using UnityEngine.Animations;
- using Unity.Collections;
- namespace Animancer
- {
- /// <summary>[Pro-Only]
- /// A base wrapper which allows access to the value of properties that are controlled by animations.
- /// </summary>
- /// <remarks>
- /// Documentation: <see href="https://kybernetik.com.au/animancer/docs/manual/ik#animated-properties">Animated Properties</see>
- /// </remarks>
- /// <example><see href="https://kybernetik.com.au/animancer/docs/examples/jobs">Animation Jobs</see></example>
- /// https://kybernetik.com.au/animancer/api/Animancer/AnimatedProperty_2
- ///
- public abstract class AnimatedProperty<TJob, TValue> : AnimancerJob<TJob>, IDisposable
- where TJob : struct, IAnimationJob
- where TValue : struct
- {
- /************************************************************************************************************************/
- /// <summary>The properties wrapped by this object.</summary>
- protected NativeArray<PropertyStreamHandle> _Properties;
- /// <summary>The value of each of the <see cref="_Properties"/> from the most recent update.</summary>
- protected NativeArray<TValue> _Values;
- /************************************************************************************************************************/
- #region Initialisation
- /************************************************************************************************************************/
- /// <summary>
- /// Allocates room for a specified number of properties to be filled by
- /// <see cref="InitializeProperty(int, Transform, Type, string)"/>.
- /// </summary>
- public AnimatedProperty(IAnimancerComponent animancer, int propertyCount,
- NativeArrayOptions options = NativeArrayOptions.ClearMemory)
- {
- _Properties = new NativeArray<PropertyStreamHandle>(propertyCount, Allocator.Persistent, options);
- _Values = new NativeArray<TValue>(propertyCount, Allocator.Persistent);
- CreateJob();
- var playable = animancer.Playable;
- CreatePlayable(playable);
- playable.Disposables.Add(this);
- }
- /// <summary>Initializes a single property.</summary>
- public AnimatedProperty(IAnimancerComponent animancer, string propertyName)
- : this(animancer, 1, NativeArrayOptions.UninitializedMemory)
- {
- var animator = animancer.Animator;
- _Properties[0] = animator.BindStreamProperty(animator.transform, typeof(Animator), propertyName);
- }
- /// <summary>Initializes a group of properties.</summary>
- public AnimatedProperty(IAnimancerComponent animancer, params string[] propertyNames)
- : this(animancer, propertyNames.Length, NativeArrayOptions.UninitializedMemory)
- {
- var count = propertyNames.Length;
- var animator = animancer.Animator;
- var transform = animator.transform;
- for (int i = 0; i < count; i++)
- InitializeProperty(animator, i, transform, typeof(Animator), propertyNames[i]);
- }
- /************************************************************************************************************************/
- /// <summary>Initializes a property on the target <see cref="Animator"/>.</summary>
- public void InitializeProperty(Animator animator, int index, string name)
- => InitializeProperty(animator, index, animator.transform, typeof(Animator), name);
- /// <summary>Initializes the specified `index` to read a property with the specified `name`.</summary>
- public void InitializeProperty(Animator animator, int index, Transform transform, Type type, string name)
- => _Properties[index] = animator.BindStreamProperty(transform, type, name);
- /************************************************************************************************************************/
- /// <summary>Creates and assigns the <see cref="AnimancerJob._Job"/>.</summary>
- protected abstract void CreateJob();
- /************************************************************************************************************************/
- #endregion
- /************************************************************************************************************************/
- #region Accessors
- /************************************************************************************************************************/
- /// <summary>Returns the value of the first property.</summary>
- public TValue Value => this[0];
- /// <summary>Returns the value of the first property.</summary>
- public static implicit operator TValue(AnimatedProperty<TJob, TValue> properties) => properties[0];
- /************************************************************************************************************************/
- /// <summary>Returns the value of the property at the specified `index`.</summary>
- /// <remarks>This method is identical to <see cref="this[int]"/>.</remarks>
- public TValue GetValue(int index) => _Values[index];
- /// <summary>Returns the value of the property at the specified `index`.</summary>
- /// <remarks>This indexer is identical to <see cref="GetValue(int)"/>.</remarks>
- public TValue this[int index] => _Values[index];
- /************************************************************************************************************************/
- /// <summary>Resizes the `values` if necessary and copies the value of each property into it.</summary>
- public void GetValues(ref TValue[] values)
- {
- AnimancerUtilities.SetLength(ref values, _Values.Length);
- _Values.CopyTo(values);
- }
- /// <summary>Returns a new array containing the values of all properties.</summary>
- /// <remarks>Use <see cref="GetValues(ref TValue[])"/> to avoid allocating a new array every call.</remarks>
- public TValue[] GetValues()
- {
- var values = new TValue[_Values.Length];
- _Values.CopyTo(values);
- return values;
- }
- /************************************************************************************************************************/
- #endregion
- /************************************************************************************************************************/
- void IDisposable.Dispose() => Dispose();
- /// <summary>Cleans up the <see cref="NativeArray{T}"/>s.</summary>
- /// <remarks>Called by <see cref="AnimancerPlayable.OnPlayableDestroy"/>.</remarks>
- protected virtual void Dispose()
- {
- if (_Properties.IsCreated)
- {
- _Properties.Dispose();
- _Values.Dispose();
- }
- }
- /// <summary>Destroys the <see cref="_Playable"/> and restores the graph connection it was intercepting.</summary>
- public override void Destroy()
- {
- Dispose();
- base.Destroy();
- }
- /************************************************************************************************************************/
- }
- }
|