// 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