TransitionLibrarySelection.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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. namespace Animancer.Editor.TransitionLibraries
  8. {
  9. /// <summary>[Editor-Only]
  10. /// A dummy object for tracking the selection within the <see cref="TransitionLibraryWindow"/>
  11. /// and showing its details in the Inspector.
  12. /// </summary>
  13. /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibrarySelection
  14. [AnimancerHelpUrl(typeof(TransitionLibrarySelection))]
  15. public class TransitionLibrarySelection : ScriptableObject
  16. {
  17. /************************************************************************************************************************/
  18. /// <summary>[Editor-Only] Types of objects can be selected.</summary>
  19. public enum SelectionType
  20. {
  21. /// <summary>Nothing selected.</summary>
  22. None,
  23. /// <summary>The main library.</summary>
  24. Library,
  25. /// <summary>A from-transition.</summary>
  26. FromTransition,
  27. /// <summary>A to-transition.</summary>
  28. ToTransition,
  29. /// <summary>A fade duration modifier.</summary>
  30. Modifier,
  31. }
  32. /************************************************************************************************************************/
  33. [SerializeField] private TransitionLibraryWindow _Window;
  34. [SerializeField] private SelectionType _Type;
  35. [SerializeField] private int _FromIndex = -1;
  36. [SerializeField] private int _ToIndex = -1;
  37. [SerializeField] private int _Version;
  38. /// <summary>The window this selection is associated with.</summary>
  39. public TransitionLibraryWindow Window
  40. => _Window;
  41. /// <summary>The type of selected object.</summary>
  42. public SelectionType Type
  43. => _Type;
  44. /// <summary>The index of the <see cref="FromTransition"/>.</summary>
  45. public int FromIndex
  46. => _FromIndex;
  47. /// <summary>The index of the <see cref="ToTransition"/>.</summary>
  48. public int ToIndex
  49. => _ToIndex;
  50. /// <summary>The number of times this selection has been changed.</summary>
  51. public int Version
  52. => _Version;
  53. /************************************************************************************************************************/
  54. /// <summary>The transition the current selection is coming from.</summary>
  55. public TransitionAssetBase FromTransition { get; private set; }
  56. /// <summary>The transition the current selection is going to.</summary>
  57. public TransitionAssetBase ToTransition { get; private set; }
  58. /// <summary>The <see cref="ITransition.FadeDuration"/> of the current selection.</summary>
  59. public float FadeDuration { get; private set; }
  60. /// <summary>Does the current selection have a modified <see cref="FadeDuration"/>?</summary>
  61. public bool HasModifier { get; private set; }
  62. /************************************************************************************************************************/
  63. [NonSerialized] private object _Selected;
  64. /// <summary>The currently selected object.</summary>
  65. public object Selected
  66. {
  67. get
  68. {
  69. Validate();
  70. return _Selected;
  71. }
  72. }
  73. /************************************************************************************************************************/
  74. /// <summary>Deselects the current object if it isn't valid.</summary>
  75. public bool Validate()
  76. {
  77. if (IsValid())
  78. return true;
  79. Deselect();
  80. return false;
  81. }
  82. /// <summary>Is the current selection valid?</summary>
  83. public bool IsValid()
  84. {
  85. if (this == null ||
  86. _Window == null ||
  87. Selection.activeObject != this)
  88. return false;
  89. var library = _Window.SourceObject;
  90. if (library == null)
  91. return false;
  92. FromTransition = null;
  93. ToTransition = null;
  94. FadeDuration = float.NaN;
  95. HasModifier = false;
  96. switch (_Type)
  97. {
  98. case SelectionType.Library:
  99. name = "Transition Library";
  100. _Selected = library;
  101. return library != null;
  102. case SelectionType.FromTransition:
  103. name = "From Transition";
  104. if (!_Window.Data.Transitions.TryGet(_FromIndex, out var transition))
  105. return false;
  106. FromTransition = transition;
  107. FadeDuration = transition.TryGetFadeDuration();
  108. _Selected = transition;
  109. return true;
  110. case SelectionType.ToTransition:
  111. name = "To Transition";
  112. if (!_Window.Data.Transitions.TryGet(_ToIndex, out transition))
  113. return false;
  114. ToTransition = transition;
  115. FadeDuration = transition.TryGetFadeDuration();
  116. _Selected = transition;
  117. return true;
  118. case SelectionType.Modifier:
  119. name = "Transition Modifier";
  120. var hasTransitions = _Window.Data.TryGetTransition(_FromIndex, out transition);
  121. FromTransition = transition;
  122. hasTransitions |= _Window.Data.TryGetTransition(_ToIndex, out transition);
  123. ToTransition = transition;
  124. if (_Window.Data.TryGetModifier(_FromIndex, _ToIndex, out var modifier))
  125. {
  126. HasModifier = true;
  127. }
  128. else if (hasTransitions)
  129. {
  130. modifier = modifier.WithFadeDuration(transition.TryGetFadeDuration());
  131. }
  132. else
  133. {
  134. return false;
  135. }
  136. FadeDuration = modifier.FadeDuration;
  137. _Selected = modifier;
  138. return true;
  139. default:
  140. return false;
  141. };
  142. }
  143. /************************************************************************************************************************/
  144. /// <summary>Sets the <see cref="Selected"/> object.</summary>
  145. /// <remarks>
  146. /// We can't simply set the <see cref="Selection.activeObject"/>
  147. /// because it might not be a <see cref="UnityEngine.Object"/>
  148. /// and if it is then we don't want the Project window to move to it.
  149. /// <para></para>
  150. /// So instead, we select this dummy object and <see cref="TransitionLibrarySelectionEditor"/>
  151. /// draws a custom Inspector for the target object.
  152. /// </remarks>
  153. public void Select(
  154. TransitionLibraryWindow window,
  155. object select,
  156. int index,
  157. SelectionType type)
  158. {
  159. switch (type)
  160. {
  161. case SelectionType.Library:
  162. _FromIndex = -1;
  163. _ToIndex = -1;
  164. break;
  165. case SelectionType.FromTransition:
  166. _FromIndex = index;
  167. _ToIndex = -1;
  168. break;
  169. case SelectionType.ToTransition:
  170. _FromIndex = -1;
  171. _ToIndex = index;
  172. break;
  173. case SelectionType.Modifier:
  174. if (select is TransitionModifierDefinition modifier)
  175. {
  176. _FromIndex = modifier.FromIndex;
  177. _ToIndex = modifier.ToIndex;
  178. break;
  179. }
  180. else
  181. {
  182. Deselect();
  183. return;
  184. }
  185. default:
  186. Deselect();
  187. throw new ArgumentException($"Unhandled {nameof(SelectionType)}", nameof(type));
  188. }
  189. _Window = window;
  190. _Type = type;
  191. _Selected = select;
  192. _Version++;
  193. Selection.activeObject = this;
  194. Validate();
  195. }
  196. /************************************************************************************************************************/
  197. /// <summary>Clears the <see cref="Selected"/> object.</summary>
  198. public void Deselect()
  199. {
  200. _Window = null;
  201. _Type = default;
  202. _FromIndex = -1;
  203. _ToIndex = -1;
  204. _Selected = null;
  205. _Version++;
  206. if (Selection.activeObject == this)
  207. Selection.activeObject = null;
  208. }
  209. /************************************************************************************************************************/
  210. /// <summary>Handles selection changes.</summary>
  211. public void OnSelectionChange()
  212. {
  213. if (Selection.activeObject == this)
  214. return;
  215. Deselect();
  216. if (_Window != null)
  217. _Window.Repaint();
  218. }
  219. /************************************************************************************************************************/
  220. /// <summary>Selects this object if it contains a valid selection.</summary>
  221. protected virtual void OnEnable()
  222. {
  223. if (Selected != null)
  224. Selection.activeObject = this;
  225. }
  226. /************************************************************************************************************************/
  227. }
  228. }
  229. #endif