Ei kuvausta
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SpriteResolverSelector.cs 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor.U2D.Common;
  4. using UnityEditor.UIElements;
  5. using UnityEngine;
  6. using UnityEngine.U2D.Animation;
  7. using UnityEngine.UIElements;
  8. namespace UnityEditor.U2D.Animation.SceneOverlays
  9. {
  10. class SpriteResolverSelector : VisualElement
  11. {
  12. static class Styles
  13. {
  14. public const string spriteResolverNameLabel = SpriteSwapOverlay.rootStyle + "__resolver-name-label";
  15. public const string categoryAndLabelNameContainer = SpriteSwapOverlay.rootStyle + "__category-and-label-name-container";
  16. public const string selector = SpriteSwapOverlay.rootStyle + "__selector";
  17. public const string descriptionLabel = SpriteSwapOverlay.rootStyle + "__label-description";
  18. }
  19. Label m_SpriteResolverLabel;
  20. INavigableElement m_CategoryContainer;
  21. INavigableElement m_LabelContainer;
  22. INavigableElement m_CurrentSelection;
  23. Label m_LabelNameLabel;
  24. string m_Category = string.Empty;
  25. string m_Label = string.Empty;
  26. List<string> m_AvailableCategories;
  27. List<Tuple<string, Sprite>> m_AvailableLabels;
  28. SerializedObject m_SerializedResolver;
  29. SerializedProperty m_SpriteHashProperty;
  30. SpriteResolver spriteResolver => (SpriteResolver)m_SerializedResolver?.targetObject;
  31. public SpriteResolverSelector(INavigableElement categoryContainer, INavigableElement labelContainer)
  32. {
  33. focusable = true;
  34. AddToClassList(Styles.selector);
  35. m_SpriteResolverLabel = new Label();
  36. m_SpriteResolverLabel.AddToClassList(Styles.spriteResolverNameLabel);
  37. Add(m_SpriteResolverLabel);
  38. var categoryAndLabelNameHolder = new VisualElement();
  39. categoryAndLabelNameHolder.AddToClassList(Styles.categoryAndLabelNameContainer);
  40. Add(categoryAndLabelNameHolder);
  41. m_CategoryContainer = categoryContainer;
  42. m_CategoryContainer.onSelectionChange += OnCategorySelected;
  43. var categoryContainerVisual = m_CategoryContainer.visualElement;
  44. categoryContainerVisual.RegisterCallback<FocusInEvent>(OnFocusIn);
  45. categoryContainerVisual.RegisterCallback<FocusOutEvent>(OnFocusOut);
  46. categoryAndLabelNameHolder.Add(categoryContainerVisual);
  47. m_LabelNameLabel = new Label();
  48. m_LabelNameLabel.AddToClassList(Styles.descriptionLabel);
  49. categoryAndLabelNameHolder.Add(m_LabelNameLabel);
  50. m_LabelContainer = labelContainer;
  51. m_LabelContainer.onSelectionChange += OnLabelSelected;
  52. var labelContainerVisual = m_LabelContainer.visualElement;
  53. labelContainerVisual.RegisterCallback<FocusInEvent>(OnFocusIn);
  54. labelContainerVisual.RegisterCallback<FocusOutEvent>(OnFocusOut);
  55. Add(labelContainerVisual);
  56. RegisterCallback<KeyDownEvent>(OnKeyDown);
  57. RegisterCallback<DetachFromPanelEvent>(OnDetachFromPanel);
  58. }
  59. public void Select()
  60. {
  61. m_LabelContainer.visualElement.Focus();
  62. }
  63. public void SceneUpdate()
  64. {
  65. UpdateAnimationColor();
  66. }
  67. void OnDetachFromPanel(DetachFromPanelEvent evt)
  68. {
  69. SetSpriteResolver(null);
  70. }
  71. public void SetSpriteResolver(SpriteResolver newSpriteResolver)
  72. {
  73. this.Unbind();
  74. if (newSpriteResolver == null)
  75. return;
  76. m_SerializedResolver = new SerializedObject(newSpriteResolver);
  77. m_SpriteHashProperty = m_SerializedResolver.FindProperty(SpriteResolver.spriteHashPropertyName);
  78. this.TrackPropertyValue(m_SpriteHashProperty, OnResolvedSprite);
  79. ReadCategoryAndLabelFromSelection();
  80. }
  81. void OnResolvedSprite(SerializedProperty serializedProperty)
  82. {
  83. ReadCategoryAndLabelFromSelection();
  84. }
  85. void ReadCategoryAndLabelFromSelection()
  86. {
  87. var resolver = spriteResolver;
  88. if (resolver == null)
  89. return;
  90. m_Category = resolver.GetCategory() ?? string.Empty;
  91. m_Label = resolver.GetLabel() ?? string.Empty;
  92. UpdateVisuals();
  93. }
  94. void UpdateVisuals()
  95. {
  96. var resolver = spriteResolver;
  97. if (resolver == null)
  98. return;
  99. m_SpriteResolverLabel.text = m_SpriteResolverLabel.tooltip = resolver.name;
  100. m_AvailableCategories = GetAvailableCategories(resolver) ?? new List<string>();
  101. m_AvailableLabels = new List<Tuple<string, Sprite>>();
  102. if (resolver.spriteLibrary != null)
  103. {
  104. foreach (var labelName in GetAvailableLabels(resolver, m_Category))
  105. m_AvailableLabels.Add(new Tuple<string, Sprite>(labelName, resolver.spriteLibrary.GetSprite(m_Category, labelName)));
  106. }
  107. m_CategoryContainer.SetItems(m_AvailableCategories);
  108. m_CategoryContainer.Select(m_AvailableCategories.IndexOf(m_Category));
  109. m_LabelContainer.SetItems(m_AvailableLabels);
  110. m_LabelContainer.Select(m_AvailableLabels.FindIndex(label => label.Item1 == m_Label));
  111. m_Label = !string.IsNullOrWhiteSpace(m_Label) ? m_Label : TextContent.emptyCategory;
  112. m_LabelNameLabel.text = m_LabelNameLabel.tooltip = m_Label;
  113. m_LabelNameLabel.SetEnabled(m_AvailableLabels.Count > 0);
  114. if (m_LabelContainer.itemCount == 0)
  115. m_CurrentSelection = m_CategoryContainer;
  116. UpdateAnimationColor();
  117. }
  118. void OnCategorySelected(int newSelection)
  119. {
  120. var resolver = spriteResolver;
  121. if (resolver == null)
  122. return;
  123. var categoryName = (string)m_CategoryContainer.GetItem(newSelection);
  124. if (categoryName == null || categoryName == m_Category)
  125. return;
  126. var availableLabels = resolver.spriteLibrary != null ? resolver.spriteLibrary.GetEntryNames(categoryName) : null;
  127. var labelList = availableLabels != null ? new List<string>(availableLabels) : new List<string>();
  128. var labelName = string.Empty;
  129. if (labelList.Count > 0)
  130. labelName = labelList.Contains(m_Label) ? m_Label : labelList[0];
  131. m_SpriteHashProperty.intValue = SpriteLibrary.GetHashForCategoryAndEntry(categoryName, labelName);
  132. m_SerializedResolver.ApplyModifiedProperties();
  133. }
  134. void OnLabelSelected(int newSelection)
  135. {
  136. var resolver = spriteResolver;
  137. if (resolver == null)
  138. return;
  139. var (labelName, _) = (Tuple<string, Sprite>)m_LabelContainer.GetItem(newSelection);
  140. if (string.IsNullOrWhiteSpace(labelName) || labelName == m_Label)
  141. return;
  142. m_SpriteHashProperty.intValue = SpriteLibrary.GetHashForCategoryAndEntry(m_Category, labelName);
  143. m_SerializedResolver.ApplyModifiedProperties();
  144. m_LabelNameLabel.text = m_LabelNameLabel.tooltip = labelName;
  145. }
  146. void OnKeyDown(KeyDownEvent evt)
  147. {
  148. if (m_CurrentSelection == null)
  149. return;
  150. switch (evt.keyCode)
  151. {
  152. case KeyCode.LeftArrow:
  153. var previousIndex = m_CurrentSelection.selectedIndex - 1;
  154. if (previousIndex < 0)
  155. previousIndex += m_CurrentSelection.itemCount;
  156. m_CurrentSelection.Select(previousIndex);
  157. evt.StopPropagation();
  158. break;
  159. case KeyCode.RightArrow:
  160. var nextIndex = m_CurrentSelection.selectedIndex + 1;
  161. if (nextIndex >= m_CurrentSelection.itemCount)
  162. nextIndex = 0;
  163. m_CurrentSelection?.Select(nextIndex);
  164. evt.StopPropagation();
  165. break;
  166. case KeyCode.DownArrow:
  167. case KeyCode.UpArrow:
  168. evt.StopPropagation();
  169. break;
  170. }
  171. }
  172. void OnFocusIn(FocusInEvent evt)
  173. {
  174. var navigable = (INavigableElement)evt.currentTarget;
  175. if (navigable != null)
  176. m_CurrentSelection = navigable;
  177. }
  178. void OnFocusOut(FocusOutEvent evt)
  179. {
  180. var navigable = (INavigableElement)evt.currentTarget;
  181. if (navigable != null && m_CurrentSelection == navigable)
  182. m_CurrentSelection = null;
  183. }
  184. static List<string> GetAvailableCategories(SpriteResolver spriteResolver)
  185. {
  186. if (spriteResolver == null || spriteResolver.spriteLibrary == null)
  187. return new List<string>();
  188. var availableCategories = spriteResolver.spriteLibrary.categoryNames;
  189. return availableCategories != null ? new List<string>(availableCategories) : new List<string>();
  190. }
  191. static List<string> GetAvailableLabels(SpriteResolver spriteResolver, string categoryName)
  192. {
  193. if (spriteResolver == null || spriteResolver.spriteLibrary == null || string.IsNullOrEmpty(categoryName))
  194. return new List<string>();
  195. var availableLabels = spriteResolver.spriteLibrary.GetEntryNames(categoryName);
  196. return availableLabels != null ? new List<string>(availableLabels) : new List<string>();
  197. }
  198. void UpdateAnimationColor()
  199. {
  200. var spriteResolverObject = spriteResolver;
  201. var animationState = PropertyAnimationState.NotAnimated;
  202. if (spriteResolverObject != null && m_SpriteHashProperty != null)
  203. {
  204. if (InternalEditorBridge.IsAnimated(spriteResolverObject, m_SpriteHashProperty))
  205. {
  206. if (InternalEditorBridge.InAnimationRecording())
  207. animationState = PropertyAnimationState.Recording;
  208. else if (InternalEditorBridge.IsCandidate(spriteResolverObject, m_SpriteHashProperty))
  209. animationState = PropertyAnimationState.Candidate;
  210. else
  211. animationState = PropertyAnimationState.Animated;
  212. }
  213. }
  214. (m_LabelContainer as LabelContainer)?.SetAnimationState(animationState);
  215. }
  216. }
  217. }