설명 없음
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.

SpriteSwapOverlay.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEditor.Overlays;
  6. using UnityEngine;
  7. using UnityEngine.U2D.Animation;
  8. using UnityEngine.UIElements;
  9. namespace UnityEditor.U2D.Animation.SceneOverlays
  10. {
  11. internal interface INavigableElement
  12. {
  13. public event Action<int> onSelectionChange;
  14. int itemCount { get; }
  15. int selectedIndex { get; }
  16. public void Select(int index);
  17. void SetItems(IList items);
  18. object GetItem(int index);
  19. VisualElement visualElement { get; }
  20. }
  21. internal enum PropertyAnimationState
  22. {
  23. NotAnimated,
  24. Animated,
  25. Candidate,
  26. Recording
  27. }
  28. [Overlay(typeof(SceneView), overlayId, k_DefaultName,
  29. defaultDisplay = k_DefaultVisibility,
  30. defaultDockZone = DockZone.RightColumn,
  31. defaultDockPosition = DockPosition.Bottom,
  32. defaultLayout = Overlays.Layout.Panel,
  33. defaultWidth = k_DefaultWidth + k_WidthPadding,
  34. defaultHeight = k_DefaultHeight + k_HeightPadding)]
  35. [Icon("Packages/com.unity.2d.animation/Editor/Assets/ComponentIcons/Animation.SpriteResolver.png")]
  36. internal class SpriteSwapOverlay : Overlay
  37. {
  38. public static class Settings
  39. {
  40. public const float minThumbnailSize = 20.0f + k_ThumbnailPadding;
  41. public const float maxThumbnailSize = 110.0f + k_ThumbnailPadding;
  42. public const float defaultThumbnailSize = 50.0f + k_ThumbnailPadding;
  43. const float k_ThumbnailPadding = 8.0f;
  44. const string k_FilterKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.filter";
  45. const string k_LockKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.lock";
  46. const string k_ThumbnailSizeKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.thumbnailSize";
  47. const string k_PreferredWidthKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.preferredWidth";
  48. const string k_PreferredHeightKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.preferredHeight";
  49. public static bool filter
  50. {
  51. get => EditorPrefs.GetBool(k_FilterKey, false);
  52. set => EditorPrefs.SetBool(k_FilterKey, value);
  53. }
  54. public static bool locked
  55. {
  56. get => EditorPrefs.GetBool(k_LockKey, false);
  57. set => EditorPrefs.SetBool(k_LockKey, value);
  58. }
  59. public static float thumbnailSize
  60. {
  61. get => EditorPrefs.GetFloat(k_ThumbnailSizeKey, defaultThumbnailSize);
  62. set => EditorPrefs.SetFloat(k_ThumbnailSizeKey, Mathf.Clamp(value, minThumbnailSize, maxThumbnailSize));
  63. }
  64. public static float preferredWidth
  65. {
  66. get => EditorPrefs.GetFloat(k_PreferredWidthKey, k_DefaultWidth);
  67. set => EditorPrefs.SetFloat(k_PreferredWidthKey, value);
  68. }
  69. public static float preferredHeight
  70. {
  71. get => EditorPrefs.GetFloat(k_PreferredHeightKey, k_DefaultHeight);
  72. set => EditorPrefs.SetFloat(k_PreferredHeightKey, value);
  73. }
  74. }
  75. public const string overlayId = "Scene View/Sprite Swap";
  76. public const string rootStyle = "sprite-swap-overlay";
  77. const float k_DefaultWidth = 230.0f;
  78. const float k_DefaultHeight = 133.0f;
  79. const float k_WidthPadding = 6.0f;
  80. const float k_HeightPadding = 19.0f;
  81. const bool k_DefaultVisibility = false;
  82. const string k_DefaultName = "Sprite Swap";
  83. public SpriteSwapVisualElement mainVisualElement => m_MainVisualElement;
  84. bool isViewInitialized => m_MainVisualElement != null;
  85. GameObject[] m_GameObjectSelection;
  86. SpriteResolver[] m_Selection;
  87. internal SpriteResolver[] selection => m_Selection;
  88. SpriteSwapVisualElement m_MainVisualElement;
  89. public SpriteSwapOverlay()
  90. {
  91. minSize = new Vector2(k_DefaultWidth + k_WidthPadding, k_DefaultHeight + k_HeightPadding);
  92. maxSize = new Vector2(k_DefaultWidth * 10.0f + k_WidthPadding, k_DefaultHeight * 10.0f + k_HeightPadding);
  93. }
  94. public override VisualElement CreatePanelContent()
  95. {
  96. var overlayElement = new SpriteSwapVisualElement { style = { width = Settings.preferredWidth, height = Settings.preferredHeight } };
  97. var toolbar = overlayElement.Q<OverlayToolbar>();
  98. toolbar.onFilterToggled += OnFilterToggled;
  99. toolbar.onLockToggled += OnLockToggled;
  100. toolbar.onResetSliderValue += OnResetThumbnailSize;
  101. toolbar.onSliderValueChanged += OnChangeThumbnailSize;
  102. overlayElement.RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);
  103. overlayElement.RegisterCallback<DetachFromPanelEvent>(OnDetachFromPanel);
  104. overlayElement.styleSheets.Add(ResourceLoader.Load<StyleSheet>("SpriteSwap/SpriteSwapOverlay.uss"));
  105. return overlayElement;
  106. }
  107. public override void OnCreated()
  108. {
  109. base.OnCreated();
  110. EditorApplication.hierarchyChanged += OnHierarchyChanged;
  111. EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
  112. Selection.selectionChanged += OnSelectionChanged;
  113. SceneView.duringSceneGui += OnSceneGUI;
  114. }
  115. public override void OnWillBeDestroyed()
  116. {
  117. EditorApplication.hierarchyChanged -= OnHierarchyChanged;
  118. EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
  119. Selection.selectionChanged -= OnSelectionChanged;
  120. SceneView.duringSceneGui -= OnSceneGUI;
  121. base.OnWillBeDestroyed();
  122. }
  123. void OnSceneGUI(SceneView sceneView)
  124. {
  125. if (containerWindow != sceneView || m_MainVisualElement == null)
  126. return;
  127. m_MainVisualElement.OnSceneGUI();
  128. }
  129. internal void OnSelectionChanged()
  130. {
  131. if (Settings.locked)
  132. return;
  133. UpdateSelection();
  134. }
  135. void OnHierarchyChanged()
  136. {
  137. UpdateSelection();
  138. }
  139. void OnPlayModeStateChanged(PlayModeStateChange newState)
  140. {
  141. if (newState is PlayModeStateChange.EnteredEditMode or PlayModeStateChange.EnteredPlayMode)
  142. UpdateSelection();
  143. }
  144. void OnAttachToPanel(AttachToPanelEvent evt)
  145. {
  146. var element = (SpriteSwapVisualElement)evt.target;
  147. if (element != null)
  148. {
  149. m_MainVisualElement = element;
  150. m_MainVisualElement.parent.RegisterCallback<GeometryChangedEvent>(OnParentGeometryChanged);
  151. if (collapsed || isInToolbar)
  152. {
  153. m_MainVisualElement.style.width = m_MainVisualElement.style.maxWidth = Settings.preferredWidth;
  154. m_MainVisualElement.style.height = m_MainVisualElement.style.maxHeight = Settings.preferredHeight;
  155. }
  156. SetSelection(GetSelectedSpriteResolvers());
  157. }
  158. }
  159. void OnDetachFromPanel(DetachFromPanelEvent evt)
  160. {
  161. var element = (SpriteSwapVisualElement)evt.currentTarget;
  162. if (element == m_MainVisualElement)
  163. m_MainVisualElement = null;
  164. }
  165. void OnParentGeometryChanged(GeometryChangedEvent evt)
  166. {
  167. if (m_MainVisualElement == null)
  168. return;
  169. if (!isInToolbar && !collapsed)
  170. {
  171. Settings.preferredWidth = evt.newRect.width;
  172. Settings.preferredHeight = evt.newRect.height;
  173. }
  174. m_MainVisualElement.style.width = evt.newRect.width;
  175. }
  176. void OnFilterToggled(bool filter)
  177. {
  178. if (Settings.filter == filter)
  179. return;
  180. Settings.filter = filter;
  181. UpdateVisuals();
  182. }
  183. void OnLockToggled(bool locked)
  184. {
  185. if (Settings.locked == locked)
  186. return;
  187. Settings.locked = locked;
  188. if (!locked)
  189. UpdateSelection();
  190. }
  191. void OnChangeThumbnailSize(float newSize)
  192. {
  193. if (Math.Abs(Settings.thumbnailSize - newSize) < 0.01f)
  194. return;
  195. Settings.thumbnailSize = newSize;
  196. UpdateVisuals();
  197. }
  198. void OnResetThumbnailSize()
  199. {
  200. if (Math.Abs(Settings.thumbnailSize - Settings.defaultThumbnailSize) < 0.01f)
  201. return;
  202. Settings.thumbnailSize = Settings.defaultThumbnailSize;
  203. UpdateVisuals();
  204. }
  205. void UpdateSelection()
  206. {
  207. m_GameObjectSelection = Selection.gameObjects.Where(go => go.activeInHierarchy).ToArray();
  208. SetSelection(GetSelectedSpriteResolvers());
  209. }
  210. void SetSelection(SpriteResolver[] newSelection)
  211. {
  212. m_Selection = newSelection;
  213. if (isViewInitialized)
  214. UpdateVisuals();
  215. }
  216. void UpdateVisuals()
  217. {
  218. var filtered = false;
  219. var filteredSelection = Settings.filter ? FilterSelection(out filtered) : selection;
  220. m_MainVisualElement.SetSpriteResolvers(filteredSelection);
  221. m_MainVisualElement.SetFiltered(filtered);
  222. }
  223. SpriteResolver[] FilterSelection(out bool filtered)
  224. {
  225. filtered = false;
  226. var filteredSelection = new List<SpriteResolver>();
  227. if (selection != null)
  228. {
  229. for (var i = 0; i < selection.Length; i++)
  230. {
  231. var spriteResolver = selection[i];
  232. var spriteLibrary = spriteResolver.spriteLibrary;
  233. if (spriteLibrary == null)
  234. {
  235. filtered = true;
  236. continue;
  237. }
  238. var selectedCategory = spriteResolver.GetCategory();
  239. if (string.IsNullOrEmpty(selectedCategory))
  240. {
  241. filtered = true;
  242. continue;
  243. }
  244. var labelNames = spriteLibrary.GetEntryNames(selectedCategory);
  245. if (labelNames != null && labelNames.Count() > 1)
  246. filteredSelection.Add(spriteResolver);
  247. else
  248. filtered = true;
  249. }
  250. }
  251. return filteredSelection.ToArray();
  252. }
  253. SpriteResolver[] GetSelectedSpriteResolvers()
  254. {
  255. var spriteResolvers = new HashSet<SpriteResolver>();
  256. if (m_GameObjectSelection != null)
  257. {
  258. for (var o = 0; o < m_GameObjectSelection.Length; o++)
  259. {
  260. var gameObject = m_GameObjectSelection[o];
  261. if (gameObject == null || !gameObject.activeSelf)
  262. continue;
  263. var children = gameObject.GetComponentsInChildren<SpriteResolver>();
  264. for (var c = 0; c < children.Length; c++)
  265. {
  266. var spriteResolver = children[c];
  267. spriteResolvers.Add(spriteResolver);
  268. }
  269. }
  270. }
  271. return spriteResolvers.ToArray();
  272. }
  273. }
  274. }