TransitionLibraryOperations.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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 static Animancer.Editor.AnimancerGUI;
  8. using static Animancer.Editor.TransitionLibraries.TransitionLibrarySelection;
  9. namespace Animancer.Editor.TransitionLibraries
  10. {
  11. /// <summary>[Editor-Only]
  12. /// Operations for modifying a <see cref="TransitionLibraryAsset"/>.
  13. /// </summary>
  14. /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryOperations
  15. public static class TransitionLibraryOperations
  16. {
  17. /************************************************************************************************************************/
  18. /// <summary>Handles input events for the background of the `window`.</summary>
  19. public static void HandleBackgroundInput(
  20. Rect area,
  21. TransitionLibraryWindow window)
  22. {
  23. // Click to select the library.
  24. if (TryUseClickEvent(area, 0))
  25. window.Selection.Select(window, window.SourceObject, -1, SelectionType.Library);
  26. var currentEvent = Event.current;
  27. switch (currentEvent.type)
  28. {
  29. // Drag and drop to add transition.
  30. case EventType.DragUpdated:
  31. case EventType.DragPerform:
  32. HandleDragAndDrop(currentEvent, window);
  33. break;
  34. case EventType.ValidateCommand:
  35. case EventType.ExecuteCommand:
  36. switch (currentEvent.commandName)
  37. {
  38. // Delete to remove the selection.
  39. case Commands.Delete:
  40. case Commands.SoftDelete:
  41. HandleDelete(currentEvent, window);
  42. break;
  43. }
  44. break;
  45. }
  46. }
  47. /************************************************************************************************************************/
  48. /// <summary>Handles drag and drop events to add transitions to the `window`.</summary>
  49. private static void HandleDragAndDrop(
  50. Event currentEvent,
  51. TransitionLibraryWindow window)
  52. {
  53. var dragging = DragAndDrop.objectReferences;
  54. TransitionAssetBase dropped = null;
  55. int index = -1;
  56. for (int i = dragging.Length - 1; i >= 0; i--)
  57. {
  58. var transition = TryCreateTransitionAttribute.TryCreateTransitionAsset(dragging[i]);
  59. if (transition != null &&
  60. Array.IndexOf(window.Data.Transitions, transition) >= 0)
  61. continue;
  62. switch (currentEvent.type)
  63. {
  64. case EventType.DragUpdated:
  65. DragAndDrop.visualMode = DragAndDropVisualMode.Link;
  66. currentEvent.Use();
  67. return;
  68. case EventType.DragPerform:
  69. dropped = transition;
  70. index = window.Data.Transitions.Length;
  71. window.RecordUndo().AddTransition(transition);
  72. break;
  73. }
  74. }
  75. if (dropped != null)
  76. {
  77. window.Selection.Select(
  78. window,
  79. dropped,
  80. index,
  81. SelectionType.ToTransition);
  82. DragAndDrop.AcceptDrag();
  83. currentEvent.Use();
  84. }
  85. }
  86. /************************************************************************************************************************/
  87. /// <summary>Creates a new transition as a sub-asset of the `window`'s library.</summary>
  88. public static TransitionAssetBase CreateTransition(
  89. TransitionLibraryWindow window)
  90. {
  91. var createInstance = TransitionAssetBase.CreateInstance;
  92. if (createInstance == null)
  93. {
  94. Debug.LogError(
  95. $"{nameof(CreateTransition)} failed because " +
  96. $"{nameof(TransitionAssetBase)}.{nameof(TransitionAssetBase.CreateInstance)}" +
  97. $" hasn't been assigned." +
  98. $" It should be automatically initialized by TransitionAsset.");
  99. return null;
  100. }
  101. var definition = window.RecordUndo();
  102. var transition = createInstance(null);
  103. transition.name = "Transition " + (definition.Transitions.Length + 1);
  104. AnimancerReflection.TryInvoke(transition, "Reset");
  105. definition.AddTransition(transition);
  106. var index = definition.Transitions.Length;
  107. window.Selection.Select(window, transition, index, SelectionType.ToTransition);
  108. return transition;
  109. }
  110. /************************************************************************************************************************/
  111. /// <summary>Handles a delete event.</summary>
  112. private static void HandleDelete(
  113. Event currentEvent,
  114. TransitionLibraryWindow window)
  115. {
  116. if (!window.Selection.Validate())
  117. return;
  118. switch (window.Selection.Type)
  119. {
  120. case SelectionType.FromTransition:
  121. if (currentEvent.type == EventType.ExecuteCommand &&
  122. window.Selection.Selected is TransitionAssetBase fromTransition)
  123. AskHowToDeleteTransition(
  124. fromTransition,
  125. window.Selection.FromIndex,
  126. window);
  127. break;
  128. case SelectionType.ToTransition:
  129. if (currentEvent.type == EventType.ExecuteCommand &&
  130. window.Selection.Selected is TransitionAssetBase toTransition)
  131. AskHowToDeleteTransition(
  132. toTransition,
  133. window.Selection.ToIndex,
  134. window);
  135. break;
  136. case SelectionType.Modifier:
  137. if (currentEvent.type == EventType.ExecuteCommand &&
  138. window.Selection.Selected is TransitionModifierDefinition modifier)
  139. window.RecordUndo().RemoveModifier(modifier);
  140. break;
  141. default:
  142. return;
  143. }
  144. currentEvent.Use();
  145. }
  146. /************************************************************************************************************************/
  147. /// <summary>Asks if the user wants to delete a transition asset or just remove it from the library.</summary>
  148. public static void AskHowToDeleteTransition(
  149. TransitionAssetBase transition,
  150. int index,
  151. TransitionLibraryWindow window)
  152. {
  153. var assetPath = AssetDatabase.GetAssetPath(transition);
  154. if (string.IsNullOrEmpty(assetPath))
  155. {
  156. if (transition != null)
  157. Undo.DestroyObjectImmediate(transition);
  158. window.RecordUndo().RemoveTransition(index);
  159. return;
  160. }
  161. var isMainAsset = AssetDatabase.IsMainAsset(transition);
  162. var assetType = isMainAsset ? "Asset" : "Sub-Asset";
  163. var isSubAssetOfLibrary =
  164. !isMainAsset &&
  165. assetPath == AssetDatabase.GetAssetPath(window.SourceObject);
  166. var message = assetPath;
  167. if (!isSubAssetOfLibrary)
  168. message += "\n\nRemove Transition: removes it from this Transition Library.";
  169. message += $"\n\nDelete {assetType}: deletes the Transition {assetType} from your project (cannot be undone).";
  170. int choice;
  171. if (isSubAssetOfLibrary)
  172. {
  173. if (EditorUtility.DisplayDialog(
  174. "Delete transition?",
  175. message,
  176. "Delete " + assetType,
  177. "Cancel"))
  178. choice = 2;
  179. else
  180. return;
  181. }
  182. else
  183. {
  184. choice = EditorUtility.DisplayDialogComplex(
  185. "Remove or Delete transition?",
  186. message,
  187. "Remove Transition",
  188. "Cancel",
  189. "Delete " + assetType);
  190. }
  191. switch (choice)
  192. {
  193. case 0:// Remove.
  194. window.RecordUndo().RemoveTransition(index);
  195. break;
  196. case 2:// Delete.
  197. if (isMainAsset)
  198. {
  199. AssetDatabase.DeleteAsset(assetPath);
  200. }
  201. else
  202. {
  203. AnimancerEditorUtilities.DeleteSubAsset(transition);
  204. }
  205. window.Data.RemoveTransition(index);
  206. Undo.ClearUndo(window);
  207. break;
  208. default:
  209. return;
  210. }
  211. }
  212. /************************************************************************************************************************/
  213. }
  214. }
  215. #endif