123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- #if UNITY_EDITOR
- using 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
|