// 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 /************************************************************************************************************************/ } }