TransitionLibraryAssetEditor.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. #if UNITY_EDITOR
  3. using Animancer.TransitionLibraries;
  4. using System;
  5. using UnityEditor;
  6. using UnityEngine;
  7. using Object = UnityEngine.Object;
  8. namespace Animancer.Editor.TransitionLibraries
  9. {
  10. /// <summary>[Editor-Only]
  11. /// A custom Inspector for <see cref="TransitionLibraryAsset"/>.
  12. /// </summary>
  13. /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryAssetEditor
  14. [CustomEditor(typeof(TransitionLibraryAsset), true)]
  15. public class TransitionLibraryAssetEditor : UnityEditor.Editor
  16. {
  17. /************************************************************************************************************************/
  18. private static GUIStyle _HeaderStyle;
  19. /// <summary>Style for section headers.</summary>
  20. public static GUIStyle HeaderStyle
  21. => _HeaderStyle ??= new(EditorStyles.label)
  22. {
  23. fontSize = EditorStyles.label.fontSize * 2,
  24. };
  25. /************************************************************************************************************************/
  26. [NonSerialized]
  27. private SerializedProperty _AliasAllTransitions;
  28. /************************************************************************************************************************/
  29. /// <summary>Called when a <see cref="TransitionLibraryAsset"/> is selected.</summary>
  30. protected virtual void OnEnable()
  31. {
  32. _AliasAllTransitions = serializedObject.FindProperty(
  33. TransitionLibraryAsset.DefinitionField + "." + TransitionLibraryDefinition.AliasAllTransitionsField);
  34. }
  35. /************************************************************************************************************************/
  36. /// <summary>Called when a <see cref="TransitionLibraryAsset"/> is deselected.</summary>
  37. protected virtual void OnDestroy()
  38. {
  39. NestedEditor.Dispose();
  40. }
  41. /************************************************************************************************************************/
  42. /// <inheritdoc/>
  43. public override void OnInspectorGUI()
  44. {
  45. var library = target as TransitionLibraryAsset;
  46. if (library == null)
  47. return;
  48. DoMainButtonsGUI(library);
  49. DoSettingsGUI(library);
  50. DoEditorDataGUI(library);
  51. DoSubAssetWarningGUI(library);
  52. }
  53. /************************************************************************************************************************/
  54. /// <summary>Draws several buttons with utility functions.</summary>
  55. private void DoMainButtonsGUI(TransitionLibraryAsset library)
  56. {
  57. var editLabel = TransitionLibraryWindow.IsShowing(library)
  58. ? "Currently Editing"
  59. : "Edit";
  60. if (GUILayout.Button(editLabel))
  61. TransitionLibraryWindow.Open(library);
  62. using (var label = PooledGUIContent.Acquire("Documentation", Strings.DocsURLs.TransitionLibraries))
  63. if (GUILayout.Button(label))
  64. Application.OpenURL(Strings.DocsURLs.TransitionLibraries);
  65. }
  66. /************************************************************************************************************************/
  67. /// <summary>Draws the `library`'s main settings.</summary>
  68. private void DoSettingsGUI(TransitionLibraryAsset library)
  69. {
  70. GUILayout.Space(AnimancerGUI.LineHeight);
  71. GUILayout.Label("Settings", HeaderStyle);
  72. EditorGUILayout.PropertyField(_AliasAllTransitions);
  73. }
  74. /************************************************************************************************************************/
  75. [NonSerialized] private readonly CachedEditor NestedEditor = new();
  76. /// <summary>Draws the `library`'s <see cref="TransitionLibraryEditorData"/>.</summary>
  77. private void DoEditorDataGUI(TransitionLibraryAsset library)
  78. {
  79. GUILayout.Space(AnimancerGUI.LineHeight);
  80. GUILayout.Label("Editor-Only Settings", HeaderStyle);
  81. var data = library.GetOrCreateEditorData();
  82. var editor = NestedEditor.GetEditor(data);
  83. editor.OnInspectorGUI();
  84. }
  85. /************************************************************************************************************************/
  86. /// <summary>Draws warnings about any sub-assets which aren't actually referenced by the `library`.</summary>
  87. private void DoSubAssetWarningGUI(TransitionLibraryAsset library)
  88. {
  89. var assetPath = AssetDatabase.GetAssetPath(library);
  90. if (string.IsNullOrEmpty(assetPath))
  91. return;
  92. var subAssets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
  93. for (int i = 0; i < subAssets.Length; i++)
  94. DoSubAssetWarningGUI(library, assetPath, subAssets[i]);
  95. }
  96. /// <summary>Draws a warning about the `subAsset` if it isn't actually referenced by the `library`.</summary>
  97. private void DoSubAssetWarningGUI(
  98. TransitionLibraryAsset library,
  99. string assetPath,
  100. Object subAsset)
  101. {
  102. switch (subAsset)
  103. {
  104. case TransitionAssetBase transition:
  105. if (Array.IndexOf(library.Definition.Transitions, transition) < 0)
  106. break;
  107. return;
  108. case StringAsset alias:
  109. var aliases = library.Definition.Aliases;
  110. for (int i = 0; i < aliases.Length; i++)
  111. if (aliases[i].Name == alias)
  112. return;
  113. break;
  114. default:
  115. return;
  116. }
  117. EditorGUILayout.HelpBox(
  118. $"Sub-Asset '{subAsset.name}' isn't referenced by this Transition Library." +
  119. $" Click to ping. Shift + Click to delete.",
  120. MessageType.Warning);
  121. if (AnimancerGUI.TryUseClickEventInLastRect(0))
  122. {
  123. if (Event.current.shift)
  124. {
  125. if (EditorUtility.DisplayDialog("Delete Sub-Asset",
  126. $"Are you sure you want to delete '{subAsset.name}'" +
  127. $" inside {assetPath}?" +
  128. $"\n\nThis operation cannot be undone.",
  129. "Delete",
  130. "Cancel"))
  131. AnimancerEditorUtilities.DeleteSubAsset(subAsset);
  132. }
  133. else
  134. {
  135. EditorGUIUtility.PingObject(subAsset);
  136. }
  137. }
  138. }
  139. /************************************************************************************************************************/
  140. }
  141. }
  142. #endif