SpriteVisibilityTool.cs 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEditor.IMGUI.Controls;
  4. using System;
  5. using System.Linq;
  6. using UnityEngine.Experimental.U2D.Animation;
  7. using UnityEngine.UIElements;
  8. namespace UnityEditor.U2D.Animation
  9. {
  10. internal interface ISpriteVisibilityToolModel
  11. {
  12. ISpriteVisibilityToolView view { get; }
  13. CharacterCache character { get; }
  14. bool previousVisibility { get; set; }
  15. bool allVisibility { get; set; }
  16. SkinningMode mode { get; }
  17. bool hasCharacter { get; }
  18. UndoScope UndoScope(string description);
  19. SpriteCache selectedSprite { get; }
  20. SpriteCategoryListCacheObject spriteCategoryList { get; }
  21. }
  22. internal interface ISpriteVisibilityToolView
  23. {
  24. void Setup();
  25. void SetSelection(SpriteCache sprite);
  26. void SetSelectionIds(IList<int> selectedIds);
  27. }
  28. internal class SpriteVisibilityToolData : CacheObject
  29. {
  30. [SerializeField]
  31. bool m_AllVisibility = true;
  32. bool m_PreviousVisibility = true;
  33. public bool allVisibility
  34. {
  35. get { return m_AllVisibility; }
  36. set { m_PreviousVisibility = m_AllVisibility = value; }
  37. }
  38. public bool previousVisibility
  39. {
  40. get { return m_PreviousVisibility; }
  41. set { m_PreviousVisibility = value; }
  42. }
  43. }
  44. internal class SpriteVisibilityToolController
  45. {
  46. bool m_UpdateViewOnSelection = true;
  47. internal interface ISpriteVisibilityItem
  48. {
  49. bool visibility { get; set; }
  50. ICharacterOrder characterOrder { get;}
  51. }
  52. internal class SpriteVisibilityGroupItem : ISpriteVisibilityItem
  53. {
  54. public CharacterGroupCache group;
  55. public ISpriteVisibilityItem[] childItems;
  56. bool ISpriteVisibilityItem.visibility
  57. {
  58. get { return group.isVisible; }
  59. set
  60. {
  61. if (childItems != null)
  62. {
  63. foreach (var item in childItems)
  64. item.visibility = value;
  65. }
  66. group.isVisible = value;
  67. }
  68. }
  69. public ICharacterOrder characterOrder { get { return group; } }
  70. }
  71. internal class SpriteVisibilitySpriteItem : ISpriteVisibilityItem
  72. {
  73. public CharacterPartCache sprite;
  74. bool ISpriteVisibilityItem.visibility
  75. {
  76. get { return sprite.isVisible; }
  77. set { sprite.isVisible = value; }
  78. }
  79. public ICharacterOrder characterOrder { get { return sprite; } }
  80. }
  81. ISpriteVisibilityToolModel m_Model;
  82. SkinningEvents m_Events;
  83. public event Action OnAvailabilityChangeListeners = () => {};
  84. public SpriteVisibilityToolController(ISpriteVisibilityToolModel model, SkinningEvents events)
  85. {
  86. m_Model = model;
  87. m_Events = events;
  88. m_Events.skinningModeChanged.AddListener(OnViewModeChanged);
  89. }
  90. public void Activate()
  91. {
  92. m_Events.selectedSpriteChanged.AddListener(OnSpriteSelectedChanged);
  93. m_Model.view.Setup();
  94. m_Model.view.SetSelection(m_Model.selectedSprite);
  95. if (m_Model.previousVisibility != m_Model.allVisibility)
  96. {
  97. SetAllCharacterSpriteVisibility();
  98. m_Model.previousVisibility = m_Model.allVisibility;
  99. }
  100. }
  101. public void Deactivate()
  102. {
  103. m_Events.selectedSpriteChanged.RemoveListener(OnSpriteSelectedChanged);
  104. }
  105. public void Dispose()
  106. {
  107. m_Events.skinningModeChanged.RemoveListener(OnViewModeChanged);
  108. }
  109. void OnViewModeChanged(SkinningMode mode)
  110. {
  111. OnAvailabilityChangeListeners();
  112. if (isAvailable && m_Model.previousVisibility != m_Model.allVisibility)
  113. SetAllCharacterSpriteVisibility();
  114. }
  115. private void OnSpriteSelectedChanged(SpriteCache sprite)
  116. {
  117. if (m_UpdateViewOnSelection)
  118. m_Model.view.SetSelection(sprite);
  119. m_UpdateViewOnSelection = true;
  120. }
  121. public bool isAvailable
  122. {
  123. get { return m_Model.mode == SkinningMode.Character; }
  124. }
  125. void SetAllCharacterSpriteVisibility()
  126. {
  127. if (m_Model.hasCharacter)
  128. {
  129. using (m_Model.UndoScope(TextContent.spriteVisibility))
  130. {
  131. var parts = m_Model.character.parts;
  132. foreach (var part in parts)
  133. part.isVisible = m_Model.allVisibility;
  134. var groups = m_Model.character.groups;
  135. foreach (var group in groups)
  136. group.isVisible = m_Model.allVisibility;
  137. }
  138. }
  139. }
  140. public void SetAllVisibility(bool visibility)
  141. {
  142. using (m_Model.UndoScope(TextContent.spriteVisibility))
  143. {
  144. m_Model.allVisibility = visibility;
  145. SetAllCharacterSpriteVisibility();
  146. }
  147. }
  148. public bool GetAllVisibility()
  149. {
  150. return m_Model.allVisibility;
  151. }
  152. public List<TreeViewItem> BuildTreeView()
  153. {
  154. var rows = new List<TreeViewItem>();
  155. var character = m_Model.character;
  156. if (character != null)
  157. {
  158. var parts = character.parts;
  159. var groups = character.groups;
  160. var items = CreateTreeGroup(-1, groups, parts, 0);
  161. foreach (var item in items)
  162. rows.Add(item);
  163. var groupParts = parts.Where(x => x.parentGroup < 0);
  164. foreach (var part in groupParts)
  165. {
  166. var ii = CreateTreeViewItem(part, groups, 0);
  167. rows.Add(ii);
  168. }
  169. }
  170. rows.Sort((x, y) =>
  171. {
  172. var x1 = (TreeViewItemBase<ISpriteVisibilityItem>)x;
  173. var y1 = (TreeViewItemBase<ISpriteVisibilityItem>)y;
  174. return SpriteVisibilityItemOrderSort(x1.customData, y1.customData);
  175. });
  176. return rows;
  177. }
  178. int SpriteVisibilityItemOrderSort(ISpriteVisibilityItem x, ISpriteVisibilityItem y)
  179. {
  180. return x.characterOrder.order.CompareTo(y.characterOrder.order);
  181. }
  182. private List<TreeViewItem> CreateTreeGroup(int level, CharacterGroupCache[] groups, CharacterPartCache[] parts, int depth)
  183. {
  184. var items = new List<TreeViewItem>();
  185. for (int j = 0; j < groups.Length; ++j)
  186. {
  187. if (groups[j].parentGroup == level)
  188. {
  189. var item = new TreeViewItemBase<ISpriteVisibilityItem>(groups[j].GetInstanceID(), depth, groups[j].name, new SpriteVisibilityGroupItem()
  190. {
  191. group = groups[j],
  192. });
  193. items.Add(item);
  194. var children = new List<ISpriteVisibilityItem>();
  195. // find all sprite that has this group
  196. var groupParts = parts.Where(x => x.parentGroup == j);
  197. foreach (var part in groupParts)
  198. {
  199. var ii = CreateTreeViewItem(part, groups, depth + 1);
  200. items.Add(ii);
  201. var visibilityItem = ii as TreeViewItemBase<ISpriteVisibilityItem>;
  202. if (visibilityItem != null)
  203. children.Add(visibilityItem.customData);
  204. }
  205. var childItemes = CreateTreeGroup(j, groups, parts, depth + 1);
  206. foreach (var iii in childItemes)
  207. {
  208. items.Add(iii);
  209. var visibilityItem = iii as TreeViewItemBase<ISpriteVisibilityItem>;
  210. if (visibilityItem != null)
  211. children.Add(visibilityItem.customData);
  212. }
  213. (item.customData as SpriteVisibilityGroupItem).childItems = children.ToArray();
  214. }
  215. }
  216. return items;
  217. }
  218. private TreeViewItem CreateTreeViewItem(CharacterPartCache part, CharacterGroupCache[] groups, int depth)
  219. {
  220. var name = part.sprite.name;
  221. return new TreeViewItemBase<ISpriteVisibilityItem>(part.sprite.GetInstanceID(), depth, name,
  222. new SpriteVisibilitySpriteItem()
  223. {
  224. sprite = part,
  225. });
  226. }
  227. public bool GetCharacterPartVisibility(TreeViewItem item)
  228. {
  229. var i = item as TreeViewItemBase<ISpriteVisibilityItem>;
  230. if (i != null)
  231. return i.customData.visibility;
  232. return false;
  233. }
  234. public void SetCharacterPartVisibility(TreeViewItem item, bool visible, bool isolate)
  235. {
  236. var i = item as TreeViewItemBase<ISpriteVisibilityItem>;
  237. if (i != null)
  238. {
  239. var characterPart = i.customData;
  240. var character = m_Model.character;
  241. using (m_Model.UndoScope(TextContent.spriteVisibility))
  242. {
  243. if (isolate)
  244. {
  245. foreach (var cpart in character.parts)
  246. {
  247. cpart.isVisible = visible;
  248. }
  249. characterPart.visibility = !visible;
  250. }
  251. else
  252. {
  253. characterPart.visibility = visible;
  254. }
  255. }
  256. }
  257. }
  258. public void SetSelectedSprite(IList<TreeViewItem> rows, IList<int> selectedIds)
  259. {
  260. SpriteCache newSelected = null;
  261. if (selectedIds.Count > 0)
  262. {
  263. var selected = rows.FirstOrDefault(x =>
  264. {
  265. var item = ((TreeViewItemBase<ISpriteVisibilityItem>)x).customData as SpriteVisibilitySpriteItem;
  266. if (item != null && item.sprite.sprite.GetInstanceID() == selectedIds[0])
  267. return true;
  268. return false;
  269. }) as TreeViewItemBase<ISpriteVisibilityItem>;
  270. if (selected != null)
  271. newSelected = ((SpriteVisibilitySpriteItem)selected.customData).sprite.sprite;
  272. }
  273. using (m_Model.UndoScope(TextContent.selectionChange))
  274. {
  275. m_UpdateViewOnSelection = false;
  276. m_Events.selectedSpriteChanged.Invoke(newSelected);
  277. if (newSelected == null)
  278. m_Model.view.SetSelectionIds(selectedIds);
  279. }
  280. }
  281. public int GetTreeViewSelectionID(SpriteCache sprite)
  282. {
  283. if (sprite != null)
  284. return sprite.GetInstanceID();
  285. return 0;
  286. }
  287. public SpriteCategory GetCategoryForSprite(TreeViewItem treeViewItem)
  288. {
  289. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  290. var customData = spriteTreeViewItem.customData as SpriteVisibilitySpriteItem;
  291. var characterPart = customData != null ? customData.sprite : null;
  292. if (characterPart != null)
  293. {
  294. var spriteLib = m_Model.spriteCategoryList;
  295. foreach (var category in spriteLib.categories)
  296. {
  297. if (category.labels.FindIndex(x => x.spriteId == characterPart.sprite.id) != -1)
  298. return category;
  299. }
  300. }
  301. return new SpriteCategory()
  302. {
  303. name = "",
  304. labels = new List<SpriteCategoryLabel>()
  305. };
  306. }
  307. public string[] GetCategoryStrings()
  308. {
  309. return m_Model.spriteCategoryList.categories.Select(x => x.name).ToArray();
  310. }
  311. public string GetSpriteLabelName(SpriteCategory category, TreeViewItem treeViewItem)
  312. {
  313. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  314. var customData = spriteTreeViewItem.customData as SpriteVisibilitySpriteItem;
  315. var characterPart = customData != null ? customData.sprite : null;
  316. var index = -1;
  317. if (characterPart != null)
  318. {
  319. index = category.labels.FindIndex(x => x.spriteId == characterPart.sprite.id);
  320. }
  321. if (index >= 0)
  322. return category.labels[index].name;
  323. return "";
  324. }
  325. int GetCategoryIndexForSprite(SpriteCategory category, TreeViewItem treeViewItem)
  326. {
  327. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  328. var customData = spriteTreeViewItem.customData as SpriteVisibilitySpriteItem;
  329. var characterPart = customData != null ? customData.sprite : null;
  330. var index = -1;
  331. if (characterPart != null)
  332. {
  333. index = category.labels.FindIndex(x => x.spriteId == characterPart.sprite.id);
  334. }
  335. return index;
  336. }
  337. public void RemoveSpriteFromCategory(TreeViewItem treeViewItem)
  338. {
  339. var spriteLibCategory = GetCategoryForSprite(treeViewItem);
  340. var index = GetCategoryIndexForSprite(spriteLibCategory, treeViewItem);
  341. if (index >= 0)
  342. {
  343. var labels = spriteLibCategory.labels.ToList();
  344. labels.RemoveAt(index);
  345. spriteLibCategory.labels = labels;
  346. m_Events.spriteLibraryChanged.Invoke();
  347. }
  348. }
  349. public void SetCategoryForSprite(string categoryName, TreeViewItem treeViewItem)
  350. {
  351. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  352. var spriteData = spriteTreeViewItem.customData as SpriteVisibilitySpriteItem;
  353. if (spriteData != null)
  354. {
  355. var category = GetCategoryForSprite(treeViewItem);
  356. var labelName = GetSpriteLabelName(category, treeViewItem);
  357. if (string.IsNullOrEmpty(labelName))
  358. labelName = spriteData.sprite.sprite.name;
  359. SetCategoryForSprite(categoryName, labelName, spriteTreeViewItem.customData);
  360. }
  361. }
  362. public void SetCategoryForSprite(string categoryName, string labelName, TreeViewItem treeViewItem)
  363. {
  364. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  365. SetCategoryForSprite(categoryName, labelName, spriteTreeViewItem.customData);
  366. }
  367. void SetCategoryForSprite(string categoryName, string labelName, ISpriteVisibilityItem spriteVisibilityItem)
  368. {
  369. categoryName = categoryName.Trim();
  370. labelName = labelName.Trim();
  371. var customData = spriteVisibilityItem as SpriteVisibilitySpriteItem;
  372. var characterPart = customData != null ? customData.sprite : null;
  373. if (characterPart != null && characterPart.sprite != null)
  374. {
  375. var spriteLib = m_Model.spriteCategoryList;
  376. using (m_Model.UndoScope(TextContent.spriteCategoryChanged))
  377. {
  378. spriteLib.AddSpriteToCategory(categoryName, new SpriteCategoryLabel()
  379. {
  380. name = labelName,
  381. spriteId = characterPart.sprite.id
  382. }
  383. );
  384. m_Events.spriteLibraryChanged.Invoke();
  385. }
  386. }
  387. }
  388. public bool IsLabelDuplicate(SpriteCategory category, string labelName)
  389. {
  390. var hash = SpriteLibraryAsset.GetStringHash(labelName);
  391. return category.labels.Count(x => x.name == labelName || hash == SpriteLibraryAsset.GetStringHash(x.name)) > 1;
  392. }
  393. public void SetCategoryLabelName(string labelname, TreeViewItem treeViewItem)
  394. {
  395. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  396. var customData = spriteTreeViewItem.customData as SpriteVisibilitySpriteItem;
  397. var characterPart = customData != null ? customData.sprite : null;
  398. if (characterPart != null && characterPart.sprite != null)
  399. {
  400. var spriteLib = m_Model.spriteCategoryList;
  401. using (m_Model.UndoScope(TextContent.spriteCategoryIndexChanged))
  402. {
  403. spriteLib.ChangeSpriteLabelName(labelname, characterPart.sprite.id);
  404. m_Events.spriteLibraryChanged.Invoke();
  405. }
  406. }
  407. }
  408. public bool SupportCateogry(TreeViewItem treeViewItem)
  409. {
  410. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  411. var customData = spriteTreeViewItem.customData as SpriteVisibilitySpriteItem;
  412. return customData != null;
  413. }
  414. public bool SupportConvertToCatgory(TreeViewItem treeViewItem)
  415. {
  416. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  417. var customData = spriteTreeViewItem.customData as SpriteVisibilityGroupItem;
  418. return customData != null;
  419. }
  420. private bool SupportConvertToCatgory(ISpriteVisibilityItem treeViewItem)
  421. {
  422. return treeViewItem is SpriteVisibilityGroupItem;
  423. }
  424. private void ConvertLayerToCategory(ISpriteVisibilityItem treeViewItem)
  425. {
  426. if (SupportConvertToCatgory(treeViewItem))
  427. {
  428. var groupItem = treeViewItem as SpriteVisibilityGroupItem;
  429. foreach (var item in groupItem.childItems)
  430. ConvertLayerToCategory(item);
  431. }
  432. else
  433. {
  434. var groupItem = treeViewItem as SpriteVisibilitySpriteItem;
  435. var name = groupItem.sprite.sprite.name;
  436. SetCategoryForSprite(name, name, groupItem);
  437. }
  438. }
  439. public void ClearCategory(TreeViewItem treeViewItem)
  440. {
  441. if (SupportConvertToCatgory(treeViewItem))
  442. {
  443. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  444. var customData = spriteTreeViewItem.customData as SpriteVisibilityGroupItem;
  445. AddGroupToCategory("", customData);
  446. }
  447. else
  448. {
  449. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  450. var item = spriteTreeViewItem.customData as SpriteVisibilitySpriteItem;
  451. SetCategoryForSprite("", "", item);
  452. }
  453. }
  454. public void ConvertLayerToCategory(TreeViewItem treeViewItem)
  455. {
  456. if (SupportConvertToCatgory(treeViewItem))
  457. {
  458. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  459. ConvertLayerToCategory(spriteTreeViewItem.customData);
  460. }
  461. else
  462. {
  463. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  464. var groupItem = spriteTreeViewItem.customData as SpriteVisibilitySpriteItem;
  465. var name = groupItem.sprite.sprite.name;
  466. SetCategoryForSprite(name, name, groupItem);
  467. }
  468. }
  469. public void ConvertToCategory(TreeViewItem treeViewItem)
  470. {
  471. if (SupportConvertToCatgory(treeViewItem))
  472. {
  473. var spriteTreeViewItem = treeViewItem as TreeViewItemBase<ISpriteVisibilityItem>;
  474. var groupItem = spriteTreeViewItem.customData as SpriteVisibilityGroupItem;
  475. AddGroupToCategory(groupItem.group.name, groupItem);
  476. }
  477. }
  478. void AddGroupToCategory(string categoryName, SpriteVisibilityGroupItem groupItem)
  479. {
  480. foreach (var item in groupItem.childItems)
  481. {
  482. if (item is SpriteVisibilityGroupItem)
  483. AddGroupToCategory(categoryName, item as SpriteVisibilityGroupItem);
  484. else if (item is SpriteVisibilitySpriteItem)
  485. {
  486. var spriteItem = (SpriteVisibilitySpriteItem)item;
  487. SetCategoryForSprite(categoryName, spriteItem.sprite.sprite.name, item);
  488. }
  489. }
  490. }
  491. public void RemoveUnusedCategory()
  492. {
  493. var spriteLib = m_Model.spriteCategoryList;
  494. var changed = false;
  495. var spriteIds = m_Model.character.parts.Select(partCache => partCache.sprite.id);
  496. for (var i = 0; i < spriteLib.categories.Count; ++i)
  497. {
  498. if (spriteLib.categories[i].labels.Count == 0 ||
  499. !spriteLib.categories[i].labels.Any(label => spriteIds.Contains(label.spriteId)))
  500. {
  501. spriteLib.categories.RemoveAt(i);
  502. --i;
  503. changed = true;
  504. }
  505. }
  506. if (changed)
  507. m_Events.spriteLibraryChanged.Invoke();
  508. }
  509. }
  510. internal class SpriteVisibilityTool : IVisibilityTool, ISpriteVisibilityToolModel
  511. {
  512. SpriteVisibilityToolView m_View;
  513. SpriteVisibilityToolController m_Controller;
  514. private SpriteVisibilityToolData m_Data;
  515. private SkinningCache m_SkinningCache;
  516. public SkinningCache skinningCache { get { return m_SkinningCache; } }
  517. public SpriteVisibilityTool(SkinningCache s)
  518. {
  519. m_SkinningCache = s;
  520. m_Data = skinningCache.CreateCache<SpriteVisibilityToolData>();
  521. m_Controller = new SpriteVisibilityToolController(this, skinningCache.events);
  522. m_View = new SpriteVisibilityToolView()
  523. {
  524. GetController = () => m_Controller
  525. };
  526. }
  527. public void Setup()
  528. {}
  529. public void Dispose()
  530. {
  531. m_Controller.Dispose();
  532. }
  533. public VisualElement view { get { return m_View; } }
  534. public string name { get { return L10n.Tr(TextContent.sprite); } }
  535. public void Activate()
  536. {
  537. m_Controller.Activate();
  538. }
  539. public void Deactivate()
  540. {
  541. m_Controller.Deactivate();
  542. }
  543. public bool isAvailable
  544. {
  545. get { return m_Controller.isAvailable; }
  546. }
  547. public void SetAvailabilityChangeCallback(Action callback)
  548. {
  549. m_Controller.OnAvailabilityChangeListeners += callback;
  550. }
  551. ISpriteVisibilityToolView ISpriteVisibilityToolModel.view { get {return m_View;} }
  552. bool ISpriteVisibilityToolModel.hasCharacter { get { return skinningCache.hasCharacter; } }
  553. SpriteCache ISpriteVisibilityToolModel.selectedSprite { get { return skinningCache.selectedSprite; } }
  554. CharacterCache ISpriteVisibilityToolModel.character { get { return skinningCache.character; } }
  555. bool ISpriteVisibilityToolModel.previousVisibility { get { return m_Data.previousVisibility; } set { m_Data.previousVisibility = value; } }
  556. bool ISpriteVisibilityToolModel.allVisibility { get { return m_Data.allVisibility; } set { m_Data.allVisibility = value; } }
  557. SkinningMode ISpriteVisibilityToolModel.mode { get { return skinningCache.mode; } }
  558. SpriteCategoryListCacheObject ISpriteVisibilityToolModel.spriteCategoryList { get { return skinningCache.spriteCategoryList; }}
  559. UndoScope ISpriteVisibilityToolModel.UndoScope(string description)
  560. {
  561. return skinningCache.UndoScope(description);
  562. }
  563. }
  564. internal class SpriteVisibilityToolView : VisibilityToolViewBase, ISpriteVisibilityToolView
  565. {
  566. public Func<SpriteVisibilityToolController> GetController = () => null;
  567. public SpriteVisibilityToolView()
  568. {
  569. var columns = new MultiColumnHeaderState.Column[4];
  570. columns[0] = new MultiColumnHeaderState.Column
  571. {
  572. headerContent = VisibilityTreeViewBase.VisibilityIconStyle.visibilityOnIcon,
  573. headerTextAlignment = TextAlignment.Center,
  574. width = 32,
  575. minWidth = 32,
  576. maxWidth = 32,
  577. autoResize = false,
  578. allowToggleVisibility = true
  579. };
  580. columns[1] = new MultiColumnHeaderState.Column
  581. {
  582. headerContent = EditorGUIUtility.TrTextContent(TextContent.name),
  583. headerTextAlignment = TextAlignment.Center,
  584. width = 130,
  585. minWidth = 100,
  586. autoResize = true,
  587. allowToggleVisibility = false
  588. };
  589. columns[2] = new MultiColumnHeaderState.Column
  590. {
  591. headerContent = EditorGUIUtility.TrTextContent(TextContent.category),
  592. headerTextAlignment = TextAlignment.Center,
  593. width = 70,
  594. minWidth = 50,
  595. autoResize = true,
  596. allowToggleVisibility = false
  597. };
  598. columns[3] = new MultiColumnHeaderState.Column
  599. {
  600. headerContent = EditorGUIUtility.TrTextContent(TextContent.label),
  601. headerTextAlignment = TextAlignment.Center,
  602. width = 50,
  603. minWidth = 30,
  604. autoResize = true,
  605. allowToggleVisibility = false
  606. };
  607. var multiColumnHeaderState = new MultiColumnHeaderState(columns);
  608. var multiColumnHeader = new VisibilityToolColumnHeader(multiColumnHeaderState)
  609. {
  610. GetAllVisibility = InternalGetAllVisibility,
  611. SetAllVisibility = InternalSetAllVisibility,
  612. canSort = false,
  613. height = 20,
  614. visibilityColumn = 0
  615. };
  616. m_TreeView = new SpriteTreeView(m_TreeViewState, multiColumnHeader)
  617. {
  618. GetController = InternalGetController
  619. };
  620. SetupSearchField();
  621. }
  622. SpriteVisibilityToolController InternalGetController()
  623. {
  624. return GetController();
  625. }
  626. bool InternalGetAllVisibility()
  627. {
  628. return GetController().GetAllVisibility();
  629. }
  630. void InternalSetAllVisibility(bool visibility)
  631. {
  632. GetController().SetAllVisibility(visibility);
  633. }
  634. public void Setup()
  635. {
  636. ((SpriteTreeView)m_TreeView).Setup();
  637. }
  638. public void SetSelection(SpriteCache sprite)
  639. {
  640. ((SpriteTreeView)m_TreeView).SetSelection(sprite);
  641. }
  642. public void SetSelectionIds(IList<int> selectedIds)
  643. {
  644. ((SpriteTreeView)m_TreeView).SetSelectionIds(selectedIds);
  645. }
  646. }
  647. class SpriteTreeView : VisibilityTreeViewBase
  648. {
  649. public Func<SpriteVisibilityToolController> GetController = () => null;
  650. private static int k_CategorySeletionOffset = 4;
  651. public GUIStyle m_Style;
  652. public GUIContent m_WarningIcon;
  653. int m_SpriteCategoryRenameID;
  654. static string[] k_DefaultCategoryList = new string[]
  655. {
  656. TextContent.none,
  657. TextContent.newTrailingDots,
  658. TextContent.removeEmptyCategory,
  659. ""
  660. };
  661. private TreeViewItem m_CurrentEdittingItem;
  662. public SpriteTreeView(TreeViewState treeViewState, MultiColumnHeader multiColumnHeader)
  663. : base(treeViewState, multiColumnHeader)
  664. {
  665. columnIndexForTreeFoldouts = 1;
  666. }
  667. void SkinInit()
  668. {
  669. if (m_Style == null)
  670. {
  671. GUIStyle foldOut = "IN Foldout";
  672. m_Style = new GUIStyle(foldOut);
  673. m_Style.stretchWidth = false;
  674. m_Style.richText = false;
  675. m_Style.border = new RectOffset(-800, -10, 0, -10);
  676. m_Style.padding = new RectOffset(11, 16, 2, 2);
  677. m_Style.fixedWidth = 0;
  678. m_Style.alignment = TextAnchor.MiddleCenter;
  679. m_Style.clipping = TextClipping.Clip;
  680. m_Style.normal.background = foldOut.onFocused.background;
  681. m_Style.normal.scaledBackgrounds = foldOut.onFocused.scaledBackgrounds;
  682. m_Style.normal.textColor = foldOut.normal.textColor;
  683. m_Style.onNormal.background = m_Style.normal.background;
  684. m_Style.onNormal.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  685. m_Style.onNormal.textColor = m_Style.normal.textColor;
  686. m_Style.onActive.background = m_Style.normal.background;
  687. m_Style.onActive.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  688. m_Style.onActive.textColor = m_Style.normal.textColor;
  689. m_Style.active.background = m_Style.normal.background;
  690. m_Style.active.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  691. m_Style.active.textColor = m_Style.normal.textColor;
  692. m_Style.onFocused.background = m_Style.normal.background;
  693. m_Style.onFocused.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  694. m_Style.onFocused.textColor = m_Style.normal.textColor;
  695. m_Style.focused.background = m_Style.normal.background;
  696. m_Style.focused.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
  697. m_Style.focused.textColor = m_Style.normal.textColor;
  698. m_WarningIcon = EditorGUIUtility.TrIconContent("console.warnicon.sml", "Duplicate label name found or label hash value clash. Please use a different name");
  699. m_SpriteCategoryRenameID = EditorGUIUtility.GetControlID("SpriteCategoryRenameControlId".GetHashCode(), FocusType.Passive);
  700. }
  701. }
  702. public void Setup()
  703. {
  704. Reload();
  705. }
  706. public override void OnGUI(Rect rect)
  707. {
  708. if (Event.current.type == EventType.Repaint)
  709. SkinInit();
  710. if (Event.current.type == EventType.MouseUp && Event.current.button == 1)
  711. {
  712. var canCovert = false;
  713. foreach (var item in GetRows())
  714. {
  715. if (IsSelected(item.id) && GetController().SupportConvertToCatgory(item))
  716. {
  717. canCovert = true;
  718. break;
  719. }
  720. }
  721. var genericMenu = new GenericMenu();
  722. if (canCovert)
  723. {
  724. genericMenu.AddItem(new GUIContent(TextContent.convertGroupToCategory), false, ConvertGroupToCategory);
  725. }
  726. genericMenu.AddItem(new GUIContent(TextContent.convertLayerToCategory), false, ConvertLayerToCategory);
  727. genericMenu.AddItem(new GUIContent(TextContent.clearAllCategory), false, ClearAllCategory);
  728. genericMenu.ShowAsContext();
  729. }
  730. base.OnGUI(rect);
  731. }
  732. void ConvertGroupToCategory()
  733. {
  734. foreach (var item in GetRows())
  735. {
  736. if (IsSelected(item.id) && GetController().SupportConvertToCatgory(item))
  737. {
  738. GetController().ConvertToCategory(item);
  739. }
  740. }
  741. }
  742. void ClearAllCategory()
  743. {
  744. foreach (var item in GetRows())
  745. {
  746. GetController().ClearCategory(item);
  747. }
  748. }
  749. void ConvertLayerToCategory()
  750. {
  751. foreach (var item in GetRows())
  752. {
  753. if (IsSelected(item.id))
  754. {
  755. GetController().ConvertLayerToCategory(item);
  756. }
  757. }
  758. }
  759. void CellGUI(Rect cellRect, TreeViewItem item, int column, ref RowGUIArgs args)
  760. {
  761. CenterRectUsingSingleLineHeight(ref cellRect);
  762. switch (column)
  763. {
  764. case 0:
  765. DrawVisibilityCell(cellRect, item);
  766. break;
  767. case 1:
  768. DrawNameCell(cellRect, item, ref args);
  769. break;
  770. case 2:
  771. DrawCategoryCell(cellRect, item, ref args);
  772. break;
  773. case 3:
  774. DrawIndexCell(cellRect, item, ref args);
  775. break;
  776. }
  777. }
  778. void DrawVisibilityCell(Rect cellRect, TreeViewItem item)
  779. {
  780. var style = MultiColumnHeader.DefaultStyles.columnHeaderCenterAligned;
  781. var characterPartVisibility = GetController().GetCharacterPartVisibility(item);
  782. EditorGUI.BeginChangeCheck();
  783. var visible = GUI.Toggle(cellRect, characterPartVisibility, characterPartVisibility ? VisibilityIconStyle.visibilityOnIcon : VisibilityIconStyle.visibilityOffIcon, style);
  784. if (EditorGUI.EndChangeCheck())
  785. {
  786. GetController().SetCharacterPartVisibility(item, visible, Event.current.alt);
  787. }
  788. }
  789. void DrawNameCell(Rect cellRect, TreeViewItem item, ref RowGUIArgs args)
  790. {
  791. args.rowRect = cellRect;
  792. base.RowGUI(args);
  793. }
  794. void DrawCategoryCell(Rect cellRect, TreeViewItem item, ref RowGUIArgs args)
  795. {
  796. if (!GetController().SupportCateogry(item))
  797. return;
  798. if (m_CurrentEdittingItem != item)
  799. {
  800. List<string> displayedOptions = new List<string>(k_DefaultCategoryList);
  801. var allCategoryStrings = GetController().GetCategoryStrings();
  802. foreach (var s in allCategoryStrings)
  803. displayedOptions.Add(s);
  804. var category = GetController().GetCategoryForSprite(item);
  805. var currentSelection = Array.FindIndex(allCategoryStrings, x => x == category.name);
  806. currentSelection = currentSelection < 0 ? 0 : currentSelection + k_CategorySeletionOffset;
  807. EditorGUI.BeginChangeCheck();
  808. currentSelection = EditorGUI.Popup(cellRect, currentSelection, displayedOptions.ToArray(), m_Style);
  809. if (EditorGUI.EndChangeCheck())
  810. {
  811. if (currentSelection == 1)
  812. {
  813. m_CurrentEdittingItem = item;
  814. DrawCategoryNameControl(cellRect, item);
  815. }
  816. else if (currentSelection == 2)
  817. {
  818. GetController().RemoveUnusedCategory();
  819. }
  820. else
  821. {
  822. var realSelectionIndex = currentSelection - k_CategorySeletionOffset;
  823. var categoryName = realSelectionIndex >= 0 ? displayedOptions[currentSelection] : "";
  824. GetController().SetCategoryForSprite(categoryName, item);
  825. }
  826. }
  827. }
  828. else
  829. {
  830. if (GUIUtility.keyboardControl != m_SpriteCategoryRenameID)
  831. m_CurrentEdittingItem = null;
  832. else
  833. DrawCategoryNameControl(cellRect, item);
  834. }
  835. }
  836. void DrawCategoryNameControl(Rect cellRect, TreeViewItem item)
  837. {
  838. EditorGUI.BeginChangeCheck();
  839. if (Event.current.type == EventType.Layout)
  840. {
  841. GUI.SetNextControlName("SpriteCategoryRename");
  842. GUI.FocusControl("SpriteCategoryRename");
  843. }
  844. GUIUtility.keyboardControl = m_SpriteCategoryRenameID;
  845. string categoryName = EditorGUI.DelayedTextField(cellRect, GUIContent.none, m_SpriteCategoryRenameID, "");
  846. if (EditorGUI.EndChangeCheck())
  847. {
  848. if (Array.FindIndex(k_DefaultCategoryList, x => x == categoryName) == -1)
  849. GetController().SetCategoryForSprite(categoryName, item);
  850. m_CurrentEdittingItem = null;
  851. }
  852. }
  853. void DrawIndexCell(Rect cellRect, TreeViewItem item, ref RowGUIArgs args)
  854. {
  855. if (!GetController().SupportCateogry(item))
  856. return;
  857. var category = GetController().GetCategoryForSprite(item);
  858. if (!string.IsNullOrEmpty(category.name))
  859. {
  860. var labelName = GetController().GetSpriteLabelName(category, item);
  861. var isDuplicate = GetController().IsLabelDuplicate(category, labelName);
  862. if (isDuplicate)
  863. {
  864. GUI.Label(new Rect(cellRect.x, cellRect.y, 20, cellRect.height), m_WarningIcon);
  865. cellRect.x += 20;
  866. cellRect.width -= 20;
  867. }
  868. EditorGUI.BeginChangeCheck();
  869. string newlabelname = EditorGUI.DelayedTextField(cellRect, labelName);
  870. if (EditorGUI.EndChangeCheck())
  871. {
  872. GetController().SetCategoryLabelName(newlabelname, item);
  873. }
  874. }
  875. }
  876. protected override void RowGUI(RowGUIArgs args)
  877. {
  878. var item = args.item;
  879. for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
  880. {
  881. CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);
  882. }
  883. }
  884. protected override Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item)
  885. {
  886. Rect cellRect = GetCellRectForTreeFoldouts(rowRect);
  887. CenterRectUsingSingleLineHeight(ref cellRect);
  888. return base.GetRenameRect(cellRect, row, item);
  889. }
  890. protected override TreeViewItem BuildRoot()
  891. {
  892. var root = new TreeViewItem {id = 0, depth = -1, displayName = "Root"};
  893. var rows = GetController() != null ? GetController().BuildTreeView() : new List<TreeViewItem>();
  894. SetupParentsAndChildrenFromDepths(root, rows);
  895. return root;
  896. }
  897. protected override void SelectionChanged(IList<int> selectedIds)
  898. {
  899. GetController().SetSelectedSprite(GetRows(), selectedIds);
  900. }
  901. public void SetSelectionIds(IList<int> selectedIds)
  902. {
  903. SetSelection(selectedIds, TreeViewSelectionOptions.RevealAndFrame);
  904. }
  905. public void SetSelection(SpriteCache sprite)
  906. {
  907. var id = GetController().GetTreeViewSelectionID(sprite);
  908. SetSelection(new[] { id }, TreeViewSelectionOptions.RevealAndFrame);
  909. }
  910. }
  911. }