// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik // #if UNITY_EDITOR using Animancer.TransitionLibraries; using System; using UnityEditor; using UnityEngine; using Object = UnityEngine.Object; namespace Animancer.Editor.TransitionLibraries { /// [Editor-Only] /// A custom Inspector for . /// /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryAssetEditor [CustomEditor(typeof(TransitionLibraryAsset), true)] public class TransitionLibraryAssetEditor : UnityEditor.Editor { /************************************************************************************************************************/ private static GUIStyle _HeaderStyle; /// Style for section headers. public static GUIStyle HeaderStyle => _HeaderStyle ??= new(EditorStyles.label) { fontSize = EditorStyles.label.fontSize * 2, }; /************************************************************************************************************************/ [NonSerialized] private SerializedProperty _AliasAllTransitions; /************************************************************************************************************************/ /// Called when a is selected. protected virtual void OnEnable() { _AliasAllTransitions = serializedObject.FindProperty( TransitionLibraryAsset.DefinitionField + "." + TransitionLibraryDefinition.AliasAllTransitionsField); } /************************************************************************************************************************/ /// Called when a is deselected. protected virtual void OnDestroy() { NestedEditor.Dispose(); } /************************************************************************************************************************/ /// public override void OnInspectorGUI() { var library = target as TransitionLibraryAsset; if (library == null) return; DoMainButtonsGUI(library); DoSettingsGUI(library); DoEditorDataGUI(library); DoSubAssetWarningGUI(library); } /************************************************************************************************************************/ /// Draws several buttons with utility functions. private void DoMainButtonsGUI(TransitionLibraryAsset library) { var editLabel = TransitionLibraryWindow.IsShowing(library) ? "Currently Editing" : "Edit"; if (GUILayout.Button(editLabel)) TransitionLibraryWindow.Open(library); using (var label = PooledGUIContent.Acquire("Documentation", Strings.DocsURLs.TransitionLibraries)) if (GUILayout.Button(label)) Application.OpenURL(Strings.DocsURLs.TransitionLibraries); } /************************************************************************************************************************/ /// Draws the `library`'s main settings. private void DoSettingsGUI(TransitionLibraryAsset library) { GUILayout.Space(AnimancerGUI.LineHeight); GUILayout.Label("Settings", HeaderStyle); EditorGUILayout.PropertyField(_AliasAllTransitions); } /************************************************************************************************************************/ [NonSerialized] private readonly CachedEditor NestedEditor = new(); /// Draws the `library`'s . private void DoEditorDataGUI(TransitionLibraryAsset library) { GUILayout.Space(AnimancerGUI.LineHeight); GUILayout.Label("Editor-Only Settings", HeaderStyle); var data = library.GetOrCreateEditorData(); var editor = NestedEditor.GetEditor(data); editor.OnInspectorGUI(); } /************************************************************************************************************************/ /// Draws warnings about any sub-assets which aren't actually referenced by the `library`. private void DoSubAssetWarningGUI(TransitionLibraryAsset library) { var assetPath = AssetDatabase.GetAssetPath(library); if (string.IsNullOrEmpty(assetPath)) return; var subAssets = AssetDatabase.LoadAllAssetsAtPath(assetPath); for (int i = 0; i < subAssets.Length; i++) DoSubAssetWarningGUI(library, assetPath, subAssets[i]); } /// Draws a warning about the `subAsset` if it isn't actually referenced by the `library`. private void DoSubAssetWarningGUI( TransitionLibraryAsset library, string assetPath, Object subAsset) { switch (subAsset) { case TransitionAssetBase transition: if (Array.IndexOf(library.Definition.Transitions, transition) < 0) break; return; case StringAsset alias: var aliases = library.Definition.Aliases; for (int i = 0; i < aliases.Length; i++) if (aliases[i].Name == alias) return; break; default: return; } EditorGUILayout.HelpBox( $"Sub-Asset '{subAsset.name}' isn't referenced by this Transition Library." + $" Click to ping. Shift + Click to delete.", MessageType.Warning); if (AnimancerGUI.TryUseClickEventInLastRect(0)) { if (Event.current.shift) { if (EditorUtility.DisplayDialog("Delete Sub-Asset", $"Are you sure you want to delete '{subAsset.name}'" + $" inside {assetPath}?" + $"\n\nThis operation cannot be undone.", "Delete", "Cancel")) AnimancerEditorUtilities.DeleteSubAsset(subAsset); } else { EditorGUIUtility.PingObject(subAsset); } } } /************************************************************************************************************************/ } } #endif