// Animancer // Copyright 2020 Kybernetik //
using System;
using UnityEngine;
namespace Animancer
{
///
/// A which extracts a particular from an
/// in the Unity Editor so that it can be accessed at runtime.
///
[CreateAssetMenu(menuName = Strings.MenuPrefix + "Exposed Curve", order = Strings.AssetMenuOrder + 9)]
public class ExposedCurve : ScriptableObject
{
/************************************************************************************************************************/
[SerializeField, Tooltip("The animation to extract the curve from")]
private AnimationClip _Clip;
/// [] The animation to extract the curve from.
public AnimationClip Clip
{
get { return _Clip; }
set
{
if (value != null)
Validate.NotLegacy(value);
_Clip = value;
}
}
/// Returns the .
/// Thrown if the `curve` is null.
public static implicit operator AnimationClip(ExposedCurve curve)
{
return curve.Clip;
}
/************************************************************************************************************************/
#if UNITY_EDITOR
[SerializeField, Tooltip("[Editor-Only] The name of the curve to extract")]
private string _PropertyName;
/// [Editor-Only] [] The name of the curve to extract.
public string PropertyName
{
get { return _PropertyName; }
set
{
_PropertyName = value;
}
}
#endif
/************************************************************************************************************************/
[SerializeField]
private AnimationCurve _Curve;
/// []
/// The that has been extracted from the .
///
public AnimationCurve Curve
{
get { return _Curve; }
set
{
if (value == null)
throw new ArgumentNullException("value");
_Curve = value;
}
}
///
/// Returns the .
///
/// Thrown if the `curve` is null.
public static implicit operator AnimationCurve(ExposedCurve curve)
{
return curve.Curve;
}
/************************************************************************************************************************/
///
/// Returns the value of the at the current of the state
/// registered with the as its key.
///
public float Evaluate(AnimancerComponent animancer)
{
return Evaluate(animancer.States[_Clip]);
}
///
/// Returns the value of the at the current .
///
public float Evaluate(AnimancerState state)
{
if (state == null)
return 0;
return Evaluate(state.Time % state.Length);
}
///
/// Returns the value of the at the specified `time`.
///
public float Evaluate(float time)
{
return _Curve.Evaluate(time);
}
/************************************************************************************************************************/
#if UNITY_EDITOR
/************************************************************************************************************************/
private void OnEnable()
{
UnityEditor.EditorCurveBinding binding;
if (TryGetCurveBinding(out binding))
{
_Curve = UnityEditor.AnimationUtility.GetEditorCurve(_Clip, binding);
}
else
{
_Curve = null;
}
}
/************************************************************************************************************************/
private void OnValidate()
{
OnEnable();
}
/************************************************************************************************************************/
private bool TryGetCurveBinding(out UnityEditor.EditorCurveBinding binding)
{
if (_Clip != null &&
!string.IsNullOrEmpty(_PropertyName))
{
var bindings = UnityEditor.AnimationUtility.GetCurveBindings(_Clip);
for (int i = 0; i < bindings.Length; i++)
{
binding = bindings[i];
if (binding.propertyName == _PropertyName)
return true;
}
}
binding = new UnityEditor.EditorCurveBinding();
return false;
}
/************************************************************************************************************************/
[UnityEditor.CustomEditor(typeof(ExposedCurve), true)]
private class Editor : Animancer.Editor.ScriptableObjectEditor { }
/************************************************************************************************************************/
#endif
/************************************************************************************************************************/
}
}