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