No Description
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.

SpriteVisibilityTool.cs 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEditor.IMGUI.Controls;
  4. using System;
  5. using System.Linq;
  6. using UnityEngine.UIElements;
  7. namespace UnityEditor.U2D.Animation
  8. {
  9. internal interface ISpriteVisibilityToolModel
  10. {
  11. ISpriteVisibilityToolView view { get; }
  12. CharacterCache character { get; }
  13. bool previousVisibility { get; set; }
  14. bool allVisibility { get; set; }
  15. SkinningMode mode { get; }
  16. bool hasCharacter { get; }
  17. UndoScope UndoScope(string description);
  18. SpriteCache selectedSprite { get; }
  19. }
  20. internal interface ISpriteVisibilityToolView
  21. {
  22. void Setup();
  23. void SetSelection(SpriteCache sprite);
  24. void SetSelectionIds(IList<int> selectedIds);
  25. }
  26. internal class SpriteVisibilityToolData : CacheObject
  27. {
  28. [SerializeField]
  29. bool m_AllVisibility = true;
  30. bool m_PreviousVisibility = true;
  31. public bool allVisibility
  32. {
  33. get { return m_AllVisibility; }
  34. set { m_PreviousVisibility = m_AllVisibility = value; }
  35. }
  36. public bool previousVisibility
  37. {
  38. get { return m_PreviousVisibility; }
  39. set { m_PreviousVisibility = value; }
  40. }
  41. }
  42. internal class SpriteVisibilityToolController
  43. {
  44. bool m_UpdateViewOnSelection = true;
  45. internal interface ISpriteVisibilityItem
  46. {
  47. bool visibility { get; set; }
  48. ICharacterOrder characterOrder { get;}
  49. }
  50. internal class SpriteVisibilityGroupItem : ISpriteVisibilityItem
  51. {
  52. public CharacterGroupCache group;
  53. public ISpriteVisibilityItem[] childItems;
  54. bool ISpriteVisibilityItem.visibility
  55. {
  56. get { return group.isVisible; }
  57. set
  58. {
  59. if (childItems != null)
  60. {
  61. foreach (var item in childItems)
  62. item.visibility = value;
  63. }
  64. group.isVisible = value;
  65. }
  66. }
  67. public ICharacterOrder characterOrder { get { return group; } }
  68. }
  69. internal class SpriteVisibilitySpriteItem : ISpriteVisibilityItem
  70. {
  71. public CharacterPartCache sprite;
  72. bool ISpriteVisibilityItem.visibility
  73. {
  74. get { return sprite.isVisible; }
  75. set { sprite.isVisible = value; }
  76. }
  77. public ICharacterOrder characterOrder { get { return sprite; } }
  78. }
  79. ISpriteVisibilityToolModel m_Model;
  80. SkinningEvents m_Events;
  81. public event Action OnAvailabilityChangeListeners = () => {};
  82. public SpriteVisibilityToolController(ISpriteVisibilityToolModel model, SkinningEvents events)
  83. {
  84. m_Model = model;
  85. m_Events = events;
  86. m_Events.skinningModeChanged.AddListener(OnViewModeChanged);
  87. }
  88. public void Activate()
  89. {
  90. m_Events.selectedSpriteChanged.AddListener(OnSpriteSelectedChanged);
  91. m_Model.view.Setup();
  92. m_Model.view.SetSelection(m_Model.selectedSprite);
  93. if (m_Model.previousVisibility != m_Model.allVisibility)
  94. {
  95. SetAllCharacterSpriteVisibility();
  96. m_Model.previousVisibility = m_Model.allVisibility;
  97. }
  98. }
  99. public void Deactivate()
  100. {
  101. m_Events.selectedSpriteChanged.RemoveListener(OnSpriteSelectedChanged);
  102. }
  103. public void Dispose()
  104. {
  105. m_Events.skinningModeChanged.RemoveListener(OnViewModeChanged);
  106. }
  107. void OnViewModeChanged(SkinningMode mode)
  108. {
  109. OnAvailabilityChangeListeners();
  110. if (isAvailable && m_Model.previousVisibility != m_Model.allVisibility)
  111. SetAllCharacterSpriteVisibility();
  112. }
  113. private void OnSpriteSelectedChanged(SpriteCache sprite)
  114. {
  115. if (m_UpdateViewOnSelection)
  116. m_Model.view.SetSelection(sprite);
  117. m_UpdateViewOnSelection = true;
  118. }
  119. public bool isAvailable
  120. {
  121. get { return m_Model.mode == SkinningMode.Character; }
  122. }
  123. void SetAllCharacterSpriteVisibility()
  124. {
  125. if (m_Model.hasCharacter)
  126. {
  127. using (m_Model.UndoScope(TextContent.spriteVisibility))
  128. {
  129. var parts = m_Model.character.parts;
  130. foreach (var part in parts)
  131. part.isVisible = m_Model.allVisibility;
  132. var groups = m_Model.character.groups;
  133. foreach (var group in groups)
  134. group.isVisible = m_Model.allVisibility;
  135. }
  136. }
  137. }
  138. public void SetAllVisibility(bool visibility)
  139. {
  140. using (m_Model.UndoScope(TextContent.spriteVisibility))
  141. {
  142. m_Model.allVisibility = visibility;
  143. SetAllCharacterSpriteVisibility();
  144. }
  145. }
  146. public bool GetAllVisibility()
  147. {
  148. return m_Model.allVisibility;
  149. }
  150. public List<TreeViewItem> BuildTreeView()
  151. {
  152. var rows = new List<TreeViewItem>();
  153. var character = m_Model.character;
  154. if (character != null)
  155. {
  156. var parts = character.parts;
  157. var groups = character.groups;
  158. var items = CreateTreeGroup(-1, groups, parts, 0);
  159. foreach (var item in items)
  160. rows.Add(item);
  161. var groupParts = parts.Where(x => x.parentGroup < 0);
  162. foreach (var part in groupParts)
  163. {
  164. var ii = CreateTreeViewItem(part, groups, 0);
  165. rows.Add(ii);
  166. }
  167. }
  168. rows.Sort((x, y) =>
  169. {
  170. var x1 = (TreeViewItemBase<ISpriteVisibilityItem>)x;
  171. var y1 = (TreeViewItemBase<ISpriteVisibilityItem>)y;
  172. return SpriteVisibilityItemOrderSort(x1.customData, y1.customData);
  173. });
  174. return rows;
  175. }
  176. int SpriteVisibilityItemOrderSort(ISpriteVisibilityItem x, ISpriteVisibilityItem y)
  177. {
  178. return x.characterOrder.order.CompareTo(y.characterOrder.order);
  179. }
  180. private List<TreeViewItem> CreateTreeGroup(int level, CharacterGroupCache[] groups, CharacterPartCache[] parts, int depth)
  181. {
  182. var items = new List<TreeViewItem>();
  183. for (int j = 0; j < groups.Length; ++j)
  184. {
  185. if (groups[j].parentGroup == level)
  186. {
  187. var item = new TreeViewItemBase<ISpriteVisibilityItem>(groups[j].GetInstanceID(), depth, groups[j].name, new SpriteVisibilityGroupItem()
  188. {
  189. group = groups[j],
  190. });
  191. items.Add(item);
  192. var children = new List<ISpriteVisibilityItem>();
  193. // find all sprite that has this group
  194. var groupParts = parts.Where(x => x.parentGroup == j);
  195. foreach (var part in groupParts)
  196. {
  197. var ii = CreateTreeViewItem(part, groups, depth + 1);
  198. items.Add(ii);
  199. var visibilityItem = ii as TreeViewItemBase<ISpriteVisibilityItem>;
  200. if (visibilityItem != null)
  201. children.Add(visibilityItem.customData);
  202. }
  203. var childItemes = CreateTreeGroup(j, groups, parts, depth + 1);
  204. foreach (var iii in childItemes)
  205. {
  206. items.Add(iii);
  207. var visibilityItem = iii as TreeViewItemBase<ISpriteVisibilityItem>;
  208. if (visibilityItem != null)
  209. children.Add(visibilityItem.customData);
  210. }
  211. (item.customData as SpriteVisibilityGroupItem).childItems = children.ToArray();
  212. }
  213. }
  214. return items;
  215. }
  216. private TreeViewItem CreateTreeViewItem(CharacterPartCache part, CharacterGroupCache[] groups, int depth)
  217. {
  218. var name = part.sprite.name;
  219. return new TreeViewItemBase<ISpriteVisibilityItem>(part.sprite.GetInstanceID(), depth, name,
  220. new SpriteVisibilitySpriteItem()
  221. {
  222. sprite = part,
  223. });
  224. }
  225. public bool GetCharacterPartVisibility(TreeViewItem item)
  226. {
  227. var i = item as TreeViewItemBase<ISpriteVisibilityItem>;
  228. if (i != null)
  229. return i.customData.visibility;
  230. return false;
  231. }
  232. public void SetCharacterPartVisibility(TreeViewItem item, bool visible, bool isolate)
  233. {
  234. var i = item as TreeViewItemBase<ISpriteVisibilityItem>;
  235. if (i != null)
  236. {
  237. var characterPart = i.customData;
  238. var character = m_Model.character;
  239. using (m_Model.UndoScope(TextContent.spriteVisibility))
  240. {
  241. if (isolate)
  242. {
  243. foreach (var characterPartCache in character.parts)
  244. characterPartCache.isVisible = !visible;
  245. foreach (var group in character.groups)
  246. group.isVisible = !visible;
  247. }
  248. characterPart.visibility = visible;
  249. }
  250. }
  251. }
  252. public void SetSelectedSprite(IList<TreeViewItem> rows, IList<int> selectedIds)
  253. {
  254. SpriteCache newSelected = null;
  255. if (selectedIds.Count > 0)
  256. {
  257. var selected = rows.FirstOrDefault(x =>
  258. {
  259. var item = ((TreeViewItemBase<ISpriteVisibilityItem>)x).customData as SpriteVisibilitySpriteItem;
  260. if (item != null && item.sprite.sprite.GetInstanceID() == selectedIds[0])
  261. return true;
  262. return false;
  263. }) as TreeViewItemBase<ISpriteVisibilityItem>;
  264. if (selected != null)
  265. newSelected = ((SpriteVisibilitySpriteItem)selected.customData).sprite.sprite;
  266. }
  267. using (m_Model.UndoScope(TextContent.selectionChange))
  268. {
  269. m_UpdateViewOnSelection = false;
  270. m_Events.selectedSpriteChanged.Invoke(newSelected);
  271. if (newSelected == null)
  272. m_Model.view.SetSelectionIds(selectedIds);
  273. }
  274. }
  275. public int GetTreeViewSelectionID(SpriteCache sprite)
  276. {
  277. if (sprite != null)
  278. return sprite.GetInstanceID();
  279. return 0;
  280. }
  281. }
  282. internal class SpriteVisibilityTool : IVisibilityTool, ISpriteVisibilityToolModel
  283. {
  284. SpriteVisibilityToolView m_View;
  285. SpriteVisibilityToolController m_Controller;
  286. private SpriteVisibilityToolData m_Data;
  287. private SkinningCache m_SkinningCache;
  288. public SkinningCache skinningCache { get { return m_SkinningCache; } }
  289. public SpriteVisibilityTool(SkinningCache s)
  290. {
  291. m_SkinningCache = s;
  292. m_Data = skinningCache.CreateCache<SpriteVisibilityToolData>();
  293. m_Controller = new SpriteVisibilityToolController(this, skinningCache.events);
  294. m_View = new SpriteVisibilityToolView()
  295. {
  296. GetController = () => m_Controller
  297. };
  298. }
  299. public void Setup()
  300. {}
  301. public void Dispose()
  302. {
  303. m_Controller.Dispose();
  304. }
  305. public VisualElement view => m_View;
  306. public string name => TextContent.sprite;
  307. public void Activate()
  308. {
  309. m_Controller.Activate();
  310. }
  311. public void Deactivate()
  312. {
  313. m_Controller.Deactivate();
  314. }
  315. public bool isAvailable
  316. {
  317. get { return m_Controller.isAvailable; }
  318. }
  319. public void SetAvailabilityChangeCallback(Action callback)
  320. {
  321. m_Controller.OnAvailabilityChangeListeners += callback;
  322. }
  323. ISpriteVisibilityToolView ISpriteVisibilityToolModel.view { get {return m_View;} }
  324. bool ISpriteVisibilityToolModel.hasCharacter { get { return skinningCache.hasCharacter; } }
  325. SpriteCache ISpriteVisibilityToolModel.selectedSprite { get { return skinningCache.selectedSprite; } }
  326. CharacterCache ISpriteVisibilityToolModel.character { get { return skinningCache.character; } }
  327. bool ISpriteVisibilityToolModel.previousVisibility { get { return m_Data.previousVisibility; } set { m_Data.previousVisibility = value; } }
  328. bool ISpriteVisibilityToolModel.allVisibility { get { return m_Data.allVisibility; } set { m_Data.allVisibility = value; } }
  329. SkinningMode ISpriteVisibilityToolModel.mode { get { return skinningCache.mode; } }
  330. UndoScope ISpriteVisibilityToolModel.UndoScope(string description)
  331. {
  332. return skinningCache.UndoScope(description);
  333. }
  334. }
  335. internal class SpriteVisibilityToolView : VisibilityToolViewBase, ISpriteVisibilityToolView
  336. {
  337. public Func<SpriteVisibilityToolController> GetController = () => null;
  338. public SpriteVisibilityToolView()
  339. {
  340. var columns = new MultiColumnHeaderState.Column[2];
  341. columns[0] = new MultiColumnHeaderState.Column
  342. {
  343. headerContent = VisibilityTreeViewBase.VisibilityIconStyle.visibilityOnIcon,
  344. headerTextAlignment = TextAlignment.Center,
  345. width = 32,
  346. minWidth = 32,
  347. maxWidth = 32,
  348. autoResize = false,
  349. allowToggleVisibility = true
  350. };
  351. columns[1] = new MultiColumnHeaderState.Column
  352. {
  353. headerContent = new GUIContent(TextContent.name),
  354. headerTextAlignment = TextAlignment.Center,
  355. width = 230,
  356. minWidth = 100,
  357. autoResize = true,
  358. allowToggleVisibility = false
  359. };
  360. var multiColumnHeaderState = new MultiColumnHeaderState(columns);
  361. var multiColumnHeader = new VisibilityToolColumnHeader(multiColumnHeaderState)
  362. {
  363. GetAllVisibility = InternalGetAllVisibility,
  364. SetAllVisibility = InternalSetAllVisibility,
  365. canSort = false,
  366. height = 20,
  367. visibilityColumn = 0
  368. };
  369. m_TreeView = new SpriteTreeView(m_TreeViewState, multiColumnHeader)
  370. {
  371. GetController = InternalGetController
  372. };
  373. SetupSearchField();
  374. }
  375. SpriteVisibilityToolController InternalGetController()
  376. {
  377. return GetController();
  378. }
  379. bool InternalGetAllVisibility()
  380. {
  381. return GetController().GetAllVisibility();
  382. }
  383. void InternalSetAllVisibility(bool visibility)
  384. {
  385. GetController().SetAllVisibility(visibility);
  386. }
  387. public void Setup()
  388. {
  389. ((SpriteTreeView)m_TreeView).Setup();
  390. }
  391. public void SetSelection(SpriteCache sprite)
  392. {
  393. ((SpriteTreeView)m_TreeView).SetSelection(sprite);
  394. }
  395. public void SetSelectionIds(IList<int> selectedIds)
  396. {
  397. ((SpriteTreeView)m_TreeView).SetSelectionIds(selectedIds);
  398. }
  399. }
  400. class SpriteTreeView : VisibilityTreeViewBase
  401. {
  402. public Func<SpriteVisibilityToolController> GetController = () => null;
  403. public GUIStyle m_Style;
  404. private TreeViewItem m_CurrentEdittingItem;
  405. public SpriteTreeView(TreeViewState treeViewState, MultiColumnHeader multiColumnHeader)
  406. : base(treeViewState, multiColumnHeader)
  407. {
  408. columnIndexForTreeFoldouts = 1;
  409. }
  410. void SkinInit()
  411. {
  412. if (m_Style == null)
  413. {
  414. GUIStyle foldOut = "IN Foldout";
  415. m_Style = new GUIStyle(foldOut);
  416. m_Style.stretchWidth = false;
  417. m_Style.richText = false;
  418. m_Style.border = new RectOffset(-800, -10, 0, -10);
  419. m_Style.padding = new RectOffset(11, 16, 2, 2);
  420. m_Style.fixedWidth = 0;
  421. m_Style.alignment = TextAnchor.MiddleCenter;
  422. m_Style.clipping = TextClipping.Clip;
  423. m_Style.normal.background = foldOut.onFocused.background;
  424. m_Style.normal.scaledBackgrounds = foldOut.onFocused.scaledBackgrounds;
  425. m_Style.normal.textColor = foldOut.normal.textColor;
  426. m_Style.onNormal.background = m_Style.normal.background;
  427. m_Style.onNormal.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  428. m_Style.onNormal.textColor = m_Style.normal.textColor;
  429. m_Style.onActive.background = m_Style.normal.background;
  430. m_Style.onActive.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  431. m_Style.onActive.textColor = m_Style.normal.textColor;
  432. m_Style.active.background = m_Style.normal.background;
  433. m_Style.active.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  434. m_Style.active.textColor = m_Style.normal.textColor;
  435. m_Style.onFocused.background = m_Style.normal.background;
  436. m_Style.onFocused.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  437. m_Style.onFocused.textColor = m_Style.normal.textColor;
  438. m_Style.focused.background = m_Style.normal.background;
  439. m_Style.focused.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  440. m_Style.focused.textColor = m_Style.normal.textColor;
  441. }
  442. }
  443. public void Setup()
  444. {
  445. Reload();
  446. }
  447. public override void OnGUI(Rect rect)
  448. {
  449. if (Event.current.type == EventType.Repaint)
  450. SkinInit();
  451. base.OnGUI(rect);
  452. }
  453. void CellGUI(Rect cellRect, TreeViewItem item, int column, ref RowGUIArgs args)
  454. {
  455. CenterRectUsingSingleLineHeight(ref cellRect);
  456. switch (column)
  457. {
  458. case 0:
  459. DrawVisibilityCell(cellRect, item);
  460. break;
  461. case 1:
  462. DrawNameCell(cellRect, item, ref args);
  463. break;
  464. }
  465. }
  466. void DrawVisibilityCell(Rect cellRect, TreeViewItem item)
  467. {
  468. var style = MultiColumnHeader.DefaultStyles.columnHeaderCenterAligned;
  469. var characterPartVisibility = GetController().GetCharacterPartVisibility(item);
  470. EditorGUI.BeginChangeCheck();
  471. var visible = GUI.Toggle(cellRect, characterPartVisibility, characterPartVisibility ? VisibilityIconStyle.visibilityOnIcon : VisibilityIconStyle.visibilityOffIcon, style);
  472. if (EditorGUI.EndChangeCheck())
  473. {
  474. GetController().SetCharacterPartVisibility(item, visible, Event.current.alt);
  475. }
  476. }
  477. void DrawNameCell(Rect cellRect, TreeViewItem item, ref RowGUIArgs args)
  478. {
  479. args.rowRect = cellRect;
  480. base.RowGUI(args);
  481. }
  482. protected override void RowGUI(RowGUIArgs args)
  483. {
  484. var item = args.item;
  485. for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
  486. {
  487. CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);
  488. }
  489. }
  490. protected override Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item)
  491. {
  492. Rect cellRect = GetCellRectForTreeFoldouts(rowRect);
  493. CenterRectUsingSingleLineHeight(ref cellRect);
  494. return base.GetRenameRect(cellRect, row, item);
  495. }
  496. protected override TreeViewItem BuildRoot()
  497. {
  498. var root = new TreeViewItem {id = 0, depth = -1, displayName = "Root"};
  499. var rows = GetController() != null ? GetController().BuildTreeView() : new List<TreeViewItem>();
  500. SetupParentsAndChildrenFromDepths(root, rows);
  501. return root;
  502. }
  503. protected override void SelectionChanged(IList<int> selectedIds)
  504. {
  505. GetController().SetSelectedSprite(GetRows(), selectedIds);
  506. }
  507. public void SetSelectionIds(IList<int> selectedIds)
  508. {
  509. SetSelection(selectedIds, TreeViewSelectionOptions.RevealAndFrame);
  510. }
  511. public void SetSelection(SpriteCache sprite)
  512. {
  513. var id = GetController().GetTreeViewSelectionID(sprite);
  514. SetSelection(new[] { id }, TreeViewSelectionOptions.RevealAndFrame);
  515. }
  516. }
  517. }