// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik // #if UNITY_EDITOR using Animancer.TransitionLibraries; using System; using UnityEditor; using UnityEngine; namespace Animancer.Editor.TransitionLibraries { /// [Editor-Only] /// A dummy object for tracking the selection within the /// and showing its details in the Inspector. /// /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibrarySelection [AnimancerHelpUrl(typeof(TransitionLibrarySelection))] public class TransitionLibrarySelection : ScriptableObject { /************************************************************************************************************************/ /// [Editor-Only] Types of objects can be selected. public enum SelectionType { /// Nothing selected. None, /// The main library. Library, /// A from-transition. FromTransition, /// A to-transition. ToTransition, /// A fade duration modifier. Modifier, } /************************************************************************************************************************/ [SerializeField] private TransitionLibraryWindow _Window; [SerializeField] private SelectionType _Type; [SerializeField] private int _FromIndex = -1; [SerializeField] private int _ToIndex = -1; [SerializeField] private int _Version; /// The window this selection is associated with. public TransitionLibraryWindow Window => _Window; /// The type of selected object. public SelectionType Type => _Type; /// The index of the . public int FromIndex => _FromIndex; /// The index of the . public int ToIndex => _ToIndex; /// The number of times this selection has been changed. public int Version => _Version; /************************************************************************************************************************/ /// The transition the current selection is coming from. public TransitionAssetBase FromTransition { get; private set; } /// The transition the current selection is going to. public TransitionAssetBase ToTransition { get; private set; } /// The of the current selection. public float FadeDuration { get; private set; } /// Does the current selection have a modified ? public bool HasModifier { get; private set; } /************************************************************************************************************************/ [NonSerialized] private object _Selected; /// The currently selected object. public object Selected { get { Validate(); return _Selected; } } /************************************************************************************************************************/ /// Deselects the current object if it isn't valid. public bool Validate() { if (IsValid()) return true; Deselect(); return false; } /// Is the current selection valid? public bool IsValid() { if (this == null || _Window == null || Selection.activeObject != this) return false; var library = _Window.SourceObject; if (library == null) return false; FromTransition = null; ToTransition = null; FadeDuration = float.NaN; HasModifier = false; switch (_Type) { case SelectionType.Library: name = "Transition Library"; _Selected = library; return library != null; case SelectionType.FromTransition: name = "From Transition"; if (!_Window.Data.Transitions.TryGet(_FromIndex, out var transition)) return false; FromTransition = transition; FadeDuration = transition.TryGetFadeDuration(); _Selected = transition; return true; case SelectionType.ToTransition: name = "To Transition"; if (!_Window.Data.Transitions.TryGet(_ToIndex, out transition)) return false; ToTransition = transition; FadeDuration = transition.TryGetFadeDuration(); _Selected = transition; return true; case SelectionType.Modifier: name = "Transition Modifier"; var hasTransitions = _Window.Data.TryGetTransition(_FromIndex, out transition); FromTransition = transition; hasTransitions |= _Window.Data.TryGetTransition(_ToIndex, out transition); ToTransition = transition; if (_Window.Data.TryGetModifier(_FromIndex, _ToIndex, out var modifier)) { HasModifier = true; } else if (hasTransitions) { modifier = modifier.WithFadeDuration(transition.TryGetFadeDuration()); } else { return false; } FadeDuration = modifier.FadeDuration; _Selected = modifier; return true; default: return false; }; } /************************************************************************************************************************/ /// Sets the object. /// /// We can't simply set the /// because it might not be a /// and if it is then we don't want the Project window to move to it. /// /// So instead, we select this dummy object and /// draws a custom Inspector for the target object. /// public void Select( TransitionLibraryWindow window, object select, int index, SelectionType type) { switch (type) { case SelectionType.Library: _FromIndex = -1; _ToIndex = -1; break; case SelectionType.FromTransition: _FromIndex = index; _ToIndex = -1; break; case SelectionType.ToTransition: _FromIndex = -1; _ToIndex = index; break; case SelectionType.Modifier: if (select is TransitionModifierDefinition modifier) { _FromIndex = modifier.FromIndex; _ToIndex = modifier.ToIndex; break; } else { Deselect(); return; } default: Deselect(); throw new ArgumentException($"Unhandled {nameof(SelectionType)}", nameof(type)); } _Window = window; _Type = type; _Selected = select; _Version++; Selection.activeObject = this; Validate(); } /************************************************************************************************************************/ /// Clears the object. public void Deselect() { _Window = null; _Type = default; _FromIndex = -1; _ToIndex = -1; _Selected = null; _Version++; if (Selection.activeObject == this) Selection.activeObject = null; } /************************************************************************************************************************/ /// Handles selection changes. public void OnSelectionChange() { if (Selection.activeObject == this) return; Deselect(); if (_Window != null) _Window.Repaint(); } /************************************************************************************************************************/ /// Selects this object if it contains a valid selection. protected virtual void OnEnable() { if (Selected != null) Selection.activeObject = this; } /************************************************************************************************************************/ } } #endif