// Animancer // https://kybernetik.com.au/animancer // Copyright 2021 Kybernetik // using UnityEngine; using System; #if UNITY_EDITOR using Animancer.Editor; using UnityEditor; #endif namespace Animancer { /// /// https://kybernetik.com.au/animancer/api/Animancer/AnimancerTransitionAsset [CreateAssetMenu(menuName = Strings.MenuPrefix + "Animancer Transition", order = Strings.AssetMenuOrder + 0)] [HelpURL(Strings.DocsURLs.APIDocumentation + "/" + nameof(AnimancerTransitionAsset))] public class AnimancerTransitionAsset : AnimancerTransitionAsset { /************************************************************************************************************************/ #if UNITY_EDITOR /// protected override void Reset() { Transition = new ClipTransition(); } #endif /************************************************************************************************************************/ /// /// An wrapper which stores its own and /// to allow multiple objects to reference the same transition asset without interfering /// with each other. /// /// /// Documentation: /// Transition Assets - UnShared /// /// https://kybernetik.com.au/animancer/api/Animancer/UnShared_3 /// [Serializable] public class UnShared : ITransition, ITransitionWithEvents, IWrapper where TAsset : AnimancerTransitionAsset where TTransition : ITransition, IHasEvents where TState : AnimancerState { /************************************************************************************************************************/ [SerializeField] private TAsset _Asset; /// The wrapped by this object. public ref TAsset Asset => ref _Asset; /// object IWrapper.WrappedObject => _Asset; /// The wrapped by this object. public ref TTransition Transition => ref _Asset.Transition; /************************************************************************************************************************/ /// Can this transition create a valid ? public virtual bool IsValid => _Asset.IsValid(); /************************************************************************************************************************/ private AnimancerState _BaseState; /// /// The state that was created by this object. Specifically, this is the state that was most recently /// passed into (usually by ). /// /// You can use or /// to get or create the state for a /// specific object. /// /// is simply a shorthand for casting this to . /// public AnimancerState BaseState { get => _BaseState; private set { _BaseState = value; if (_State != value) _State = null; } } /************************************************************************************************************************/ private TState _State; /// /// The state that was created by this object. Specifically, this is the state that was most recently /// passed into (usually by ). /// /// /// /// You can use or /// to get or create the state for a /// specific object. /// /// This property is shorthand for casting the to . /// /// /// /// The is not actually a . This should only /// happen if a different type of state was created by something else and registered using the /// , causing this to pass that /// state into instead of calling to make the correct type of /// state. /// public TState State { get { if (_State == null) _State = (TState)BaseState; return _State; } protected set { BaseState = _State = value; } } /************************************************************************************************************************/ private AnimancerEvent.Sequence _Events; /// /// This property stores a copy of the events from the public virtual AnimancerEvent.Sequence Events { get { if (_Events == null) _Events = new AnimancerEvent.Sequence(SerializedEvents.GetEventsOptional()); return _Events; } } /// public virtual ref AnimancerEvent.Sequence.Serializable SerializedEvents => ref _Asset.Transition.SerializedEvents; /************************************************************************************************************************/ /// Wraps and assigns the local . public virtual void Apply(AnimancerState state) { BaseState = state; _Asset.Apply(state); if (_Events == null) { _Events = SerializedEvents.GetEventsOptional(); if (_Events == null) return; _Events = new AnimancerEvent.Sequence(_Events); } state.Events = _Events; } /************************************************************************************************************************/ /// public virtual object Key => _Asset.Key; /// public virtual float FadeDuration => _Asset.FadeDuration; /// public virtual FadeMode FadeMode => _Asset.FadeMode; /// public virtual TState CreateState() => State = (TState)_Asset.CreateState(); /// AnimancerState ITransition.CreateState() => BaseState = _Asset.CreateState(); /************************************************************************************************************************/ } /************************************************************************************************************************/ #if UNITY_EDITOR /// [Editor-Only] /// A for . /// /// /// This class doesn't inherit from (which would let it draw the button to open the /// ) because it would only show the Transition Asset reference field without /// any of the actual values (fade duration, speed, etc.) and trying to redirect everything necessary to preview /// the asset's transition would require significant additional complexity. /// /// This issue can be avoided using the /// /// Nested Inspectors in Inspector Gadgets by opening the asset's Inspector and previewing it directly. /// [CustomPropertyDrawer(typeof(UnShared<,,>), true)] public class UnSharedTransitionDrawer : PropertyDrawer { /************************************************************************************************************************/ /// public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { var height = AnimancerGUI.LineHeight; if (property.propertyType == SerializedPropertyType.ManagedReference && property.isExpanded) height += AnimancerGUI.LineHeight + AnimancerGUI.StandardSpacing; return height; } /************************************************************************************************************************/ /// public override void OnGUI(Rect area, SerializedProperty property, GUIContent label) { if (property.propertyType == SerializedPropertyType.ManagedReference) { using (new TypeSelectionButton(area, property, true)) EditorGUI.PropertyField(area, property, label, true); } else { var transitionProperty = property.FindPropertyRelative("_Asset"); EditorGUI.PropertyField(area, transitionProperty, label, false); } } /************************************************************************************************************************/ } #endif } }