| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 | // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //#if UNITY_EDITORusing Animancer.TransitionLibraries;using System;using System.Collections.Generic;using System.IO;using UnityEditor;using UnityEditor.Callbacks;using UnityEngine;using static Animancer.Editor.AnimancerGUI;using Object = UnityEngine.Object;namespace Animancer.Editor.TransitionLibraries{    /// <summary>[Editor-Only]    /// An <see cref="EditorWindow"/> for configuring <see cref="TransitionLibraryAsset"/>.    /// </summary>    /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryWindow    public class TransitionLibraryWindow :        SerializedDataEditorWindow<TransitionLibraryAsset, TransitionLibraryDefinition>    {        /************************************************************************************************************************/        /// <summary>Opens a window for the `library`.</summary>        public static TransitionLibraryWindow Open(TransitionLibraryAsset library)            => Open<TransitionLibraryWindow>(library, true, typeof(SceneView));        /************************************************************************************************************************/        /// <summary>        /// Double clicking a <see cref="TransitionLibraryAsset"/>        /// opens it in the <see cref="TransitionLibraryWindow"/>.        /// </summary>        [OnOpenAsset]        private static bool OnOpenAsset(int instanceID, int line)        {            var library = EditorUtility.InstanceIDToObject(instanceID) as TransitionLibraryAsset;            if (library == null)                return false;            Open(library);            return true;        }        /************************************************************************************************************************/        /// <summary>The current window instance.</summary>        public static TransitionLibraryWindow Instance { get; private set; }        /// <summary>Is a window currently showing the `library`.</summary>        public static bool IsShowing(Object library)            => Instance != null            && Instance.SourceObject == library;        /************************************************************************************************************************/        /// <inheritdoc/>        public override TransitionLibraryDefinition SourceData        {            get => SourceObject.Definition;            set => SourceObject.Definition = value;        }        /************************************************************************************************************************/        [SerializeField]        private TransitionLibrarySelection _Selection;        /// <summary>Manages the objects which can be selected within a library.</summary>        public TransitionLibrarySelection Selection            => AnimancerEditorUtilities.FindOrCreate(ref _Selection);        /************************************************************************************************************************/        [SerializeReference]        private List<TransitionLibraryWindowPage> _Pages;        [SerializeField]        private int _CurrentPage;        /// <summary>The currently selected page.</summary>        public TransitionLibraryWindowPage CurrentPage        {            get            {                _CurrentPage = Mathf.Clamp(_CurrentPage, 0, _Pages.Count - 1);                return _Pages[_CurrentPage];            }        }        /************************************************************************************************************************/        /// <summary>Object highlight manager.</summary>        public readonly TransitionLibraryWindowHighlighter            Highlighter = new();        /************************************************************************************************************************/        /// <summary>Called when an object is selected.</summary>        private void OnSelectionChange()        {            if (_Selection != null)                _Selection.OnSelectionChange();            var library = UnityEditor.Selection.activeObject as TransitionLibraryAsset;            if (library != null && library != SourceObject)                SetAndCaptureSource(library);        }        /************************************************************************************************************************/        /// <inheritdoc/>        protected override void OnEnable()        {            base.OnEnable();            Instance = this;            wantsMouseMove = true;            // MainStageView, CanvasGroup Icon, GridLayoutGroup Icon.            titleContent = EditorGUIUtility.IconContent("CanvasGroup Icon");            titleContent.text = "Transition Library";            AnimancerEditorUtilities.InstantiateDerivedTypes(ref _Pages);            for (int i = 0; i < _Pages.Count; i++)                _Pages[i].Window = this;            OnSelectionChange();        }        /************************************************************************************************************************/        /// <inheritdoc/>        protected override void OnDisable()        {            base.OnDisable();            if (Instance == this)                Instance = null;        }        /************************************************************************************************************************/        /// <inheritdoc/>        protected override void OnDestroy()        {            base.OnDestroy();            DestroyImmediate(_Selection);        }        /************************************************************************************************************************/        /// <summary>Draws the GUI of this window.</summary>        protected virtual void OnGUI()        {            if (SourceObject == null)            {                GUILayout.Label("No Transition Library has been selected");                return;            }            DoHeaderGUI();            DoBodyGUI();        }        /************************************************************************************************************************/        /// <inheritdoc/>        protected override void CaptureData()        {            base.CaptureData();            Data.SortAliases();        }        /************************************************************************************************************************/        /// <inheritdoc/>        public override void Apply()        {            base.Apply();            for (int i = 0; i < Data.Transitions.Length; i++)            {                var transition = Data.Transitions[i];                if (EditorUtility.IsPersistent(transition))                    continue;                AssetDatabase.AddObjectToAsset(transition, SourceObject);            }        }        /************************************************************************************************************************/        private static ButtonGroupStyles _ApplyRevertStyles;        /// <summary>Draws the header GUI.</summary>        private void DoHeaderGUI()        {            if (_ApplyRevertStyles.left == null)                _ApplyRevertStyles = new(                    EditorStyles.toolbarButton,                    EditorStyles.toolbarButton,                    EditorStyles.toolbarButton);            GUILayout.BeginHorizontal();            var style = EditorStyles.toolbar;            var applyRevertWidth = CalculateApplyRevertWidth(_ApplyRevertStyles) - StandardSpacing - 1;            var area = GUILayoutUtility.GetRect(position.width, style.fixedHeight);            var currentEvent = Event.current;            if (currentEvent.type == EventType.Repaint)                style.Draw(area, false, false, false, false);            var pageArea = StealFromLeft(ref area, PageSelectionWidth);            var applyRevertArea = StealFromRight(ref area, applyRevertWidth);            var pathArea = area;            DoPageSelectionDropdown(pageArea);            DoAssetPathButton(pathArea, currentEvent);            DoApplyRevertGUI(applyRevertArea, _ApplyRevertStyles);            GUILayout.EndHorizontal();        }        /************************************************************************************************************************/        [NonSerialized]        private float _PageSelectionWidth;        private float PageSelectionWidth        {            get            {                if (_PageSelectionWidth == 0)                {                    for (int i = 0; i < _Pages.Count; i++)                    {                        _PageSelectionWidth = Math.Max(                            _PageSelectionWidth,                            EditorStyles.toolbarDropDown.CalculateWidth(_Pages[i].DisplayName));                    }                }                return _PageSelectionWidth;            }        }        /************************************************************************************************************************/        /// <summary>Draws a dropdown button for selecting the <see cref="CurrentPage"/>.</summary>        private void DoPageSelectionDropdown(Rect area)        {            using (var label = PooledGUIContent.Acquire(CurrentPage.DisplayName, CurrentPage.HelpTooltip))                if (!EditorGUI.DropdownButton(area, label, FocusType.Passive, EditorStyles.toolbarDropDown))                    return;            var menu = new GenericMenu();            for (int i = 0; i < _Pages.Count; i++)            {                var index = i;                var page = _Pages[index];                menu.AddItem(                    new(page.DisplayName),                    _CurrentPage == index,                    () => _CurrentPage = index);            }            menu.AddSeparator("");            menu.AddItem(                new("Documentation"),                false,                () => Application.OpenURL(Strings.DocsURLs.TransitionLibraries));            menu.ShowAsContext();        }        /************************************************************************************************************************/        private static GUIStyle _AssetPathStyle;        private readonly GUIContent AssetPath = new();        /// <summary>Draws the asset path of the target library and selects it if clicked.</summary>        private void DoAssetPathButton(Rect area, Event currentEvent)        {            _AssetPathStyle ??= new(EditorStyles.toolbarButton)            {                richText = true,                alignment = TextAnchor.MiddleRight,                fontStyle = FontStyle.Italic,                fontSize = (int)(EditorStyles.toolbarButton.fontSize * 0.8f),            };            if (currentEvent.type == EventType.Repaint)            {                var assetPath = AssetDatabase.GetAssetPath(SourceObject);                if (string.IsNullOrEmpty(assetPath))                {                    AssetPath.text = "The target Transition Library isn't saved as an asset.";                    AssetPath.tooltip = null;                }                else if (AssetPath.tooltip != assetPath)                {                    AssetPath.tooltip = assetPath;                    var directory = Path.GetDirectoryName(assetPath).Replace('\\', '/');                    var file = Path.GetFileNameWithoutExtension(assetPath);                    assetPath = $"{directory}/<b>{file}</b>";                    AssetPath.text = assetPath;                }            }            if (GUI.Button(area, AssetPath, _AssetPathStyle))            {                if (Selection.Selected != (object)SourceObject)                    Selection.Select(this, SourceObject, -1, TransitionLibrarySelection.SelectionType.Library);                else                    EditorGUIUtility.PingObject(SourceObject);            }        }        /************************************************************************************************************************/        /// <summary>Draws the <see cref="CurrentPage"/>.</summary>        private void DoBodyGUI()        {            GUILayout.FlexibleSpace();            var area = GUILayoutUtility.GetLastRect();            area.width = position.width;            EditorGUI.DrawRect(area, Grey(0.2f, 0.5f));            if (_Pages.Count > 0)            {                Highlighter.BeginGUI(area);                CurrentPage?.OnGUI(area);                Highlighter.EndGUI(this);            }        }        /************************************************************************************************************************/    }}#endif
 |