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.

SpriteLibraryDataInspector.cs 34KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using UnityEditorInternal;
  5. using UnityEngine;
  6. using UnityEngine.U2D.Animation;
  7. namespace UnityEditor.U2D.Animation
  8. {
  9. internal class SpriteLibraryDataInspector
  10. {
  11. class Style
  12. {
  13. public GUIContent duplicateWarningText = EditorGUIUtility.TrTextContent("Duplicate name found or name hash clashes. Please use a different name");
  14. public GUIContent duplicateWarning;
  15. public int lineSpacing = 3;
  16. public int spriteGridSize = 64;
  17. public float gridPadding = EditorGUIUtility.standardVerticalSpacing * 2;
  18. public int gridHeaderSize = 20;
  19. public int gridFooterSize = 20;
  20. public float gridHeight;
  21. public Vector2 gridSize;
  22. public GUIStyle footerBackground;
  23. public GUIStyle boxBackground;
  24. public GUIStyle preButton;
  25. public GUIStyle headerBackground;
  26. public GUIStyle gridList;
  27. public GUIContent iconToolbarPlus = EditorGUIUtility.TrIconContent("Toolbar Plus", "Add to list");
  28. public GUIContent iconToolbarMinus = EditorGUIUtility.TrIconContent("Toolbar Minus", "Remove selection or last element from list");
  29. public GUIContent overrideIcon = EditorGUIUtility.TrIconContent("PrefabOverlayAdded Icon");
  30. public string newCategoryText = L10n.Tr("New Category");
  31. public string categoryLabel = L10n.Tr("Category");
  32. public float categoryElementHeight;
  33. public float categoryTextFieldHeight;
  34. public string newEntryText = L10n.Tr("Entry");
  35. public float categoryLabelWidth = 100;
  36. public Style()
  37. {
  38. gridSize = new Vector2(spriteGridSize + gridPadding * 2,
  39. spriteGridSize + lineSpacing + EditorGUIUtility.singleLineHeight + gridPadding * 2);
  40. duplicateWarning = EditorGUIUtility.TrIconContent("console.warnicon.sml", duplicateWarningText.text);
  41. gridHeight = gridSize.y +gridPadding + gridFooterSize;
  42. categoryTextFieldHeight = EditorGUIUtility.singleLineHeight + lineSpacing;
  43. categoryElementHeight = gridHeight + categoryTextFieldHeight + gridHeaderSize;
  44. }
  45. public void InitStyle(Event currentEvent)
  46. {
  47. if (footerBackground == null && currentEvent.type == EventType.Repaint)
  48. {
  49. footerBackground = "RL Footer";
  50. boxBackground = "RL Background";
  51. preButton = "RL FooterButton";
  52. headerBackground = "RL Header";
  53. gridList = "GridList";
  54. }
  55. }
  56. }
  57. class SpriteCategoryGridState
  58. {
  59. public Vector2 scrollPos;
  60. public int selectedIndex;
  61. public static SpriteCategoryGridState Default =>
  62. new SpriteCategoryGridState()
  63. {
  64. scrollPos = Vector2.zero,
  65. selectedIndex = 0
  66. };
  67. }
  68. private Style m_Style;
  69. private SerializedProperty m_Library;
  70. private List<SpriteCategoryGridState> m_GridStates = new List<SpriteCategoryGridState>();
  71. private ReorderableList m_LabelReorderableList;
  72. public SpriteLibraryDataInspector(SerializedObject so,
  73. SerializedProperty library)
  74. {
  75. m_Style = new Style();
  76. m_Library = library;
  77. m_LabelReorderableList = new ReorderableList(so, library, true, false,
  78. true, true);
  79. m_LabelReorderableList.drawElementCallback = DrawElement;
  80. m_LabelReorderableList.elementHeight = m_Style.categoryTextFieldHeight;
  81. m_LabelReorderableList.elementHeightCallback = delegate(int index) { return m_Style.categoryElementHeight; };
  82. m_LabelReorderableList.onAddCallback = OnAddCallback;
  83. m_LabelReorderableList.onCanRemoveCallback = OnCanRemoveCallback;
  84. }
  85. public static void UpdateLibraryWithNewMainLibrary(SpriteLibraryAsset spriteLib, SerializedProperty library)
  86. {
  87. var emptyStringArray = new string[0];
  88. var categories = spriteLib != null ? spriteLib.GetCategoryNames() : emptyStringArray;
  89. // populate new primary
  90. int newCatgoryIndex = 0;
  91. foreach (var newCategory in categories)
  92. {
  93. SerializedProperty existingCategory = null;
  94. if (library.arraySize > 0)
  95. {
  96. var cat = library.GetArrayElementAtIndex(0);
  97. for (int i = 0; i < library.arraySize; ++i)
  98. {
  99. if (cat.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue == newCategory)
  100. {
  101. existingCategory = cat;
  102. if(i != newCatgoryIndex)
  103. library.MoveArrayElement(i, newCatgoryIndex);
  104. break;
  105. }
  106. cat.Next(false);
  107. }
  108. }
  109. if (existingCategory != null)
  110. {
  111. if(!existingCategory.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue)
  112. existingCategory.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue = true;
  113. }
  114. else
  115. {
  116. library.InsertArrayElementAtIndex(newCatgoryIndex);
  117. existingCategory = library.GetArrayElementAtIndex(newCatgoryIndex);
  118. SetPropertyName(existingCategory, newCategory);
  119. existingCategory.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue = true;
  120. existingCategory.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntryCount).intValue = 0;
  121. existingCategory.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntries).arraySize = 0;
  122. }
  123. newCatgoryIndex++;
  124. var newEntries = spriteLib.GetCategoryLabelNames(newCategory);
  125. var entries = existingCategory.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntries);
  126. int newEntryIndex = 0;
  127. foreach (var newEntry in newEntries)
  128. {
  129. SerializedProperty cacheEntry = null;
  130. if (entries.arraySize > 0)
  131. {
  132. var ent = entries.GetArrayElementAtIndex(0);
  133. for (int j = 0; j < entries.arraySize; ++j)
  134. {
  135. if (ent.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue == newEntry)
  136. {
  137. cacheEntry = ent;
  138. if(j != newEntryIndex)
  139. entries.MoveArrayElement(j, newEntryIndex);
  140. break;
  141. }
  142. ent.Next(false);
  143. }
  144. }
  145. var mainSprite = spriteLib.GetSprite(newCategory, newEntry);
  146. if (cacheEntry == null)
  147. {
  148. entries.InsertArrayElementAtIndex(newEntryIndex);
  149. cacheEntry = entries.GetArrayElementAtIndex(newEntryIndex);
  150. SetPropertyName(cacheEntry, newEntry);
  151. cacheEntry.FindPropertyRelative(SpriteLibraryPropertyString.spriteOverride)
  152. .objectReferenceValue = mainSprite;
  153. }
  154. ++newEntryIndex;
  155. if(!cacheEntry.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue)
  156. cacheEntry.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue = true;
  157. if(cacheEntry.FindPropertyRelative(SpriteLibraryPropertyString.sprite).objectReferenceValue != mainSprite)
  158. cacheEntry.FindPropertyRelative(SpriteLibraryPropertyString.sprite).objectReferenceValue = mainSprite;
  159. }
  160. }
  161. // Remove any library or entry that is not in primary and not overridden
  162. for (int i = 0; i < library.arraySize; ++i)
  163. {
  164. var categoryProperty = library.GetArrayElementAtIndex(i);
  165. var categoryEntriesProperty = categoryProperty.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntries);
  166. var categoryFromMainProperty = categoryProperty.FindPropertyRelative(SpriteLibraryPropertyString.fromMain);
  167. var categoryName = categoryProperty.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue;
  168. var categoryInPrimary = categories.Contains(categoryName);
  169. var entriesInPrimary = categoryInPrimary ? spriteLib.GetCategoryLabelNames(categoryName) : emptyStringArray;
  170. var categoryOverride = 0;
  171. for (int j = 0; j < categoryEntriesProperty.arraySize; ++j)
  172. {
  173. var entry = categoryEntriesProperty.GetArrayElementAtIndex(j);
  174. var entryName = entry.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue;
  175. var entryInPrimary = entriesInPrimary.Contains(entryName);
  176. var entryFromMainProperty = entry.FindPropertyRelative(SpriteLibraryPropertyString.fromMain);
  177. var overrideSpriteProperty = entry.FindPropertyRelative(SpriteLibraryPropertyString.spriteOverride);
  178. var spriteProperty = entry.FindPropertyRelative(SpriteLibraryPropertyString.sprite);
  179. if (!entryInPrimary)
  180. {
  181. // Entry no longer in new primary.
  182. // Check for override and set it to us
  183. if (entryFromMainProperty.boolValue)
  184. {
  185. if (overrideSpriteProperty.objectReferenceValue == spriteProperty.objectReferenceValue)
  186. {
  187. categoryEntriesProperty.DeleteArrayElementAtIndex(j);
  188. --j;
  189. continue;
  190. }
  191. }
  192. if(entryFromMainProperty.boolValue)
  193. entryFromMainProperty.boolValue = false;
  194. if(spriteProperty.objectReferenceValue != overrideSpriteProperty.objectReferenceValue)
  195. spriteProperty.objectReferenceValue = overrideSpriteProperty.objectReferenceValue;
  196. ++categoryOverride;
  197. }
  198. else
  199. {
  200. // Check if sprite has been override
  201. if(spriteProperty.objectReferenceValue != overrideSpriteProperty.objectReferenceValue)
  202. ++categoryOverride;
  203. }
  204. }
  205. if (!categoryInPrimary && categoryEntriesProperty.arraySize == 0 && categoryFromMainProperty.boolValue)
  206. {
  207. library.DeleteArrayElementAtIndex(i);
  208. --i;
  209. continue;
  210. }
  211. // since there is override, and we removed the main. This category now
  212. // belows to the library
  213. if (!categoryInPrimary)
  214. {
  215. if(categoryFromMainProperty.boolValue)
  216. categoryFromMainProperty.boolValue = false;
  217. }
  218. else
  219. {
  220. if(categoryProperty.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntryCount).intValue != categoryOverride)
  221. categoryProperty.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntryCount).intValue = categoryOverride;
  222. }
  223. }
  224. }
  225. public void OnGUI()
  226. {
  227. m_Style.InitStyle(Event.current);
  228. m_LabelReorderableList.DoLayoutList();
  229. HandleCategoryCreateSpriteDragAndDrop();
  230. }
  231. void HandleCategoryCreateSpriteDragAndDrop()
  232. {
  233. bool dragAccepted = false;
  234. switch (Event.current.type)
  235. {
  236. case EventType.DragPerform:
  237. foreach (var obj in DragAndDrop.objectReferences)
  238. {
  239. if (obj is Sprite || obj is Texture2D)
  240. {
  241. dragAccepted = true;
  242. }
  243. }
  244. if (dragAccepted)
  245. {
  246. DragAndDrop.AcceptDrag();
  247. foreach (var obj in DragAndDrop.objectReferences)
  248. {
  249. if (obj is Sprite)
  250. {
  251. var category = AddCategory(obj.name, false);
  252. AddSpriteToCategory(category, (Sprite)obj);
  253. }
  254. else if (obj is Texture2D)
  255. {
  256. var sprites = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(obj))
  257. .Where(x => x is Sprite);
  258. foreach (var s in sprites)
  259. {
  260. var category = AddCategory(s.name, false);
  261. AddSpriteToCategory(category, (Sprite)s);
  262. }
  263. }
  264. }
  265. }
  266. Event.current.Use();
  267. break;
  268. case EventType.DragUpdated:
  269. if (DragAndDrop.objectReferences.Count(x => x is Sprite || x is Texture2D) > 0)
  270. DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
  271. else
  272. DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
  273. Event.current.Use();
  274. break;
  275. }
  276. }
  277. SerializedProperty IsCategoryNameInUsed(string name)
  278. {
  279. if (m_Library.arraySize == 0)
  280. return null;
  281. var nameHash = SpriteLibraryUtility.GetStringHash(name);
  282. var sp = m_Library.GetArrayElementAtIndex(0);
  283. for (int i = 0; i < m_Library.arraySize; ++i)
  284. {
  285. var nameProperty = sp.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue;
  286. var hash = SpriteLibraryUtility.GetStringHash(nameProperty);
  287. if (nameProperty == name || nameHash == hash)
  288. return sp;
  289. sp.Next(false);
  290. }
  291. return null;
  292. }
  293. void DrawElement(Rect rect, int index, bool selected, bool focused)
  294. {
  295. DrawCategory(rect, index);
  296. }
  297. void DrawCategory(Rect rect, int index)
  298. {
  299. var categorySerializedProperty = m_Library.GetArrayElementAtIndex(index);
  300. var catRect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
  301. var vaRect = new Rect(rect.x, rect.y + m_Style.categoryTextFieldHeight, rect.width, EditorGUIUtility.singleLineHeight);
  302. var categoryName = categorySerializedProperty.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue;
  303. var fromMain = categorySerializedProperty.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue;
  304. using (new EditorGUI.DisabledScope(fromMain))
  305. {
  306. EditorGUI.BeginChangeCheck();
  307. var oldLabelWidth = EditorGUIUtility.labelWidth;
  308. EditorGUIUtility.labelWidth = m_Style.categoryLabelWidth;
  309. var newCatName = EditorGUI.TextField(catRect, m_Style.categoryLabel, categoryName);
  310. EditorGUIUtility.labelWidth = oldLabelWidth;
  311. if (EditorGUI.EndChangeCheck())
  312. {
  313. newCatName = newCatName.Trim();
  314. if (categoryName != newCatName)
  315. {
  316. // Check if this nameLabel is already taken
  317. if (IsCategoryNameInUsed(newCatName) == null)
  318. SetPropertyName(categorySerializedProperty, newCatName);
  319. else
  320. Debug.LogWarning(m_Style.duplicateWarningText.text);
  321. }
  322. }
  323. }
  324. while(m_GridStates.Count <= index)
  325. m_GridStates.Add(new SpriteCategoryGridState());
  326. DrawCategorySpriteListHeader(vaRect, m_Style.newEntryText);
  327. vaRect.y += vaRect.height;
  328. vaRect.height = m_Style.gridHeight;
  329. DrawCategorySpriteList(vaRect, index, categorySerializedProperty);
  330. HandleSpriteDragAndDropToCategory(vaRect, categorySerializedProperty);
  331. }
  332. void OnAddCallback(ReorderableList list)
  333. {
  334. AddCategory(m_Style.newCategoryText, true);
  335. }
  336. SerializedProperty AddCategory(string categoryName, bool createNew)
  337. {
  338. var intendedCategoryName = categoryName;
  339. int catNameIncrement = 1;
  340. while (true)
  341. {
  342. var catOverride = IsCategoryNameInUsed(categoryName);
  343. if (catOverride != null)
  344. {
  345. if (!createNew)
  346. return catOverride;
  347. categoryName = string.Format("{0} {1}", intendedCategoryName, catNameIncrement++);
  348. }
  349. else
  350. break;
  351. }
  352. var oldSize = m_Library.arraySize;
  353. m_Library.arraySize += 1;
  354. var sp = m_Library.GetArrayElementAtIndex(oldSize);
  355. SetPropertyName(sp, categoryName);
  356. sp.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue = false;
  357. sp.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntries).arraySize = 0;
  358. return sp;
  359. }
  360. bool HandleSpriteDragAndDropToCategory(Rect rect, SerializedProperty category)
  361. {
  362. bool dragAccepted = false;
  363. if (rect.Contains(Event.current.mousePosition))
  364. {
  365. switch (Event.current.type)
  366. {
  367. case EventType.DragPerform:
  368. foreach (var obj in DragAndDrop.objectReferences)
  369. {
  370. if (obj is Sprite)
  371. {
  372. AddSpriteToCategory(category, (Sprite)obj);
  373. dragAccepted = true;
  374. }
  375. }
  376. if (dragAccepted)
  377. {
  378. DragAndDrop.AcceptDrag();
  379. }
  380. Event.current.Use();
  381. break;
  382. case EventType.DragUpdated:
  383. if (DragAndDrop.objectReferences.Count(x => x is Sprite) > 0)
  384. DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
  385. else
  386. DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
  387. Event.current.Use();
  388. break;
  389. }
  390. }
  391. return dragAccepted;
  392. }
  393. static void GetRowColumnCount(float drawWidth, float size, int contentCount, out int column, out int row, out float columnf)
  394. {
  395. columnf = (drawWidth) / size;
  396. column = (int)Mathf.Floor(columnf);
  397. if (column == 0)
  398. row = 0;
  399. else
  400. row = (int)Mathf.Ceil((contentCount + column-1) / column);
  401. }
  402. void DrawCategorySpriteList(Rect rect, int index, SerializedProperty category)
  403. {
  404. var spriteListProp = category.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntries);
  405. var footerRect = rect;
  406. var gridState = m_GridStates[index];
  407. gridState.selectedIndex = (gridState.selectedIndex > spriteListProp.arraySize) ? 0 : gridState.selectedIndex;
  408. rect.height -= m_Style.gridFooterSize;
  409. if(Event.current.type == EventType.Repaint)
  410. m_Style.boxBackground.Draw(rect, "", false, false, false, false);
  411. rect.x += m_Style.gridPadding;
  412. rect.y += m_Style.gridPadding;
  413. rect.width -= m_Style.gridPadding * 2;
  414. rect.height -= m_Style.gridPadding * 2;
  415. float columnF;
  416. int columnCount, rowCount;
  417. GetRowColumnCount(rect.width, m_Style.gridSize.x, spriteListProp.arraySize, out columnCount, out rowCount, out columnF);
  418. bool canRemoveSelectedEntry = true;
  419. bool selectedEntryIsOverwrite = false;
  420. var overrideCountProperty = category.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntryCount);
  421. if (spriteListProp.arraySize <= 0 && overrideCountProperty.intValue != 0)
  422. overrideCountProperty.intValue = 0;
  423. if (columnCount > 0 && rowCount > 0)
  424. {
  425. var spriteOverwrite = 0;
  426. var scrollViewRect = new Rect(rect.x, rect.y, columnCount * m_Style.gridSize.x,
  427. rowCount * m_Style.gridSize.y);
  428. if (rowCount >= 2)
  429. gridState.scrollPos = GUI.BeginScrollView(new Rect(rect.x, rect.y, rect.width, rect.height),gridState.scrollPos, scrollViewRect, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar);
  430. var viewPortMinY = rect.y + gridState.scrollPos.y;
  431. var viewPortMaxY = rect.y + rect.height + gridState.scrollPos.y;
  432. var spriteObjectFieldRect = new Rect(rect.x, rect.y, m_Style.spriteGridSize, m_Style.spriteGridSize);
  433. var labelTextfieldRect = new Rect(rect.x, rect.y + m_Style.spriteGridSize + m_Style.lineSpacing, m_Style.spriteGridSize, EditorGUIUtility.singleLineHeight);
  434. var backgroundSelectedRect = new Rect(rect.x, rect.y, m_Style.gridSize.x, m_Style.gridSize.y);
  435. for (int i = 0, row = 0, column = 0; i < spriteListProp.arraySize; ++i, ++column)
  436. {
  437. if (column >= columnCount)
  438. {
  439. column = 0;
  440. ++row;
  441. }
  442. backgroundSelectedRect.x = column * m_Style.gridSize.x + rect.x;
  443. backgroundSelectedRect.y = row * m_Style.gridSize.y + rect.y;
  444. spriteObjectFieldRect.x = column * m_Style.gridSize.x + rect.x + m_Style.gridPadding;
  445. spriteObjectFieldRect.y = row * m_Style.gridSize.y + rect.y + m_Style.gridPadding;
  446. labelTextfieldRect.x = column * m_Style.gridSize.x +rect.x + m_Style.gridPadding;
  447. labelTextfieldRect.y = row * m_Style.gridSize.y + m_Style.spriteGridSize +rect.y + m_Style.gridPadding;
  448. var element = spriteListProp.GetArrayElementAtIndex(i);
  449. var spriteProperty = element.FindPropertyRelative(SpriteLibraryPropertyString.sprite);
  450. var spriteOverrideProperty = element.FindPropertyRelative(SpriteLibraryPropertyString.spriteOverride);
  451. var spriteOverride = spriteProperty.objectReferenceValue != spriteOverrideProperty.objectReferenceValue;
  452. var entryFromMain = element.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue;
  453. if (!entryFromMain || spriteOverride)
  454. ++spriteOverwrite;
  455. if(!IsLabelVisible(viewPortMinY, viewPortMaxY, backgroundSelectedRect))
  456. continue;
  457. DrawLabel(i,
  458. spriteListProp,
  459. spriteOverrideProperty,
  460. gridState,
  461. spriteOverride,
  462. entryFromMain,
  463. backgroundSelectedRect,
  464. spriteObjectFieldRect,
  465. labelTextfieldRect,
  466. ref canRemoveSelectedEntry,
  467. ref selectedEntryIsOverwrite);
  468. }
  469. if (overrideCountProperty.intValue != spriteOverwrite)
  470. {
  471. overrideCountProperty.intValue = spriteOverwrite;
  472. GUI.changed = true;
  473. }
  474. if (rowCount >= 2)
  475. GUI.EndScrollView();
  476. }
  477. footerRect = new Rect(footerRect.x, footerRect.y + footerRect.height - m_Style.gridFooterSize, footerRect.width, m_Style.gridFooterSize);
  478. Action<SerializedProperty , SpriteCategoryGridState> removeCallback = DeleteSpriteEntry;
  479. if (selectedEntryIsOverwrite)
  480. removeCallback = DeleteSpriteEntryOverride;
  481. DrawCategorySpriteListFooter(footerRect, category, gridState,canRemoveSelectedEntry, removeCallback);
  482. }
  483. static bool IsLabelVisible(float viewPortMinY, float viewPortMaxY, Rect labelRect)
  484. {
  485. return (labelRect.y + labelRect.height) >= viewPortMinY && labelRect.y <= viewPortMaxY;
  486. }
  487. void DrawLabel(int index,
  488. SerializedProperty spriteListProp,
  489. SerializedProperty spriteOverrideProperty,
  490. SpriteCategoryGridState gridState,
  491. bool spriteOverride,
  492. bool entryFromMain,
  493. Rect backgroundSelectedRect,
  494. Rect spriteObjectFieldRect,
  495. Rect labelTextfieldRect,
  496. ref bool canRemoveSelectedEntry,
  497. ref bool selectedEntryIsOverwrite)
  498. {
  499. var element = spriteListProp.GetArrayElementAtIndex(index);
  500. if (gridState.selectedIndex == index)
  501. {
  502. canRemoveSelectedEntry = entryFromMain && spriteOverride || !entryFromMain;
  503. selectedEntryIsOverwrite = entryFromMain && spriteOverride;
  504. if(Event.current.type == EventType.Repaint)
  505. m_Style.gridList.Draw(backgroundSelectedRect, true, true, true, false);
  506. }
  507. spriteOverrideProperty.objectReferenceValue = EditorGUI.ObjectField(spriteObjectFieldRect, spriteOverrideProperty.objectReferenceValue, typeof(Sprite), false) as Sprite;
  508. if (Event.current.type == EventType.MouseUp &&
  509. backgroundSelectedRect.Contains(Event.current.mousePosition))
  510. {
  511. gridState.selectedIndex = index;
  512. }
  513. if (!entryFromMain || spriteOverride)
  514. {
  515. var overrideIconRect = spriteObjectFieldRect;
  516. overrideIconRect.x -= 12;
  517. overrideIconRect.y -= 12;
  518. overrideIconRect.width = 20;
  519. overrideIconRect.height = 20;
  520. GUI.Label(overrideIconRect, m_Style.overrideIcon);
  521. }
  522. //disable m_Name editing if the entry is from main
  523. using (new EditorGUI.DisabledScope(entryFromMain))
  524. {
  525. EditorGUI.BeginChangeCheck();
  526. var oldName = element.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue;
  527. if (string.IsNullOrEmpty(oldName) && spriteOverrideProperty.objectReferenceValue != null && entryFromMain)
  528. {
  529. oldName = spriteOverrideProperty.name;
  530. SetPropertyName(element, oldName);
  531. }
  532. var nameRect = labelTextfieldRect;
  533. bool nameDuplicate = IsEntryNameUsed(oldName, spriteListProp, 1);
  534. if (nameDuplicate)
  535. {
  536. nameRect.width -= 20;
  537. }
  538. var newName = EditorGUI.TextField(
  539. nameRect,
  540. GUIContent.none,
  541. oldName);
  542. if (nameDuplicate)
  543. {
  544. nameRect.x += nameRect.width;
  545. nameRect.width = 20;
  546. GUI.Label(nameRect, m_Style.duplicateWarning);
  547. }
  548. if (EditorGUI.EndChangeCheck() && !string.IsNullOrEmpty(newName))
  549. {
  550. newName = newName.Trim();
  551. SetPropertyName(element, newName);
  552. }
  553. }
  554. }
  555. bool IsEntryNameUsed(string name, SerializedProperty spriteList, int duplicateAllow)
  556. {
  557. if (spriteList.arraySize == 0)
  558. return false;
  559. var sp = spriteList.GetArrayElementAtIndex(0);
  560. var nameHash = SpriteLibraryUtility.GetStringHash(name);
  561. int count = 0;
  562. for (int i = 0; i < spriteList.arraySize; ++i, sp.Next(false))
  563. {
  564. var stringValue = sp.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue;
  565. var hash = SpriteLibraryUtility.GetStringHash(stringValue);
  566. if (stringValue == name || hash == nameHash)
  567. {
  568. ++count;
  569. if(count > duplicateAllow)
  570. return true;
  571. }
  572. }
  573. return false;
  574. }
  575. static void DeleteSpriteEntryOverride(SerializedProperty spriteList, SpriteCategoryGridState gridState)
  576. {
  577. var sp = spriteList.GetArrayElementAtIndex(gridState.selectedIndex);
  578. sp.FindPropertyRelative(SpriteLibraryPropertyString.spriteOverride).objectReferenceValue = sp.FindPropertyRelative(SpriteLibraryPropertyString.sprite).objectReferenceValue;
  579. }
  580. static void DeleteSpriteEntry(SerializedProperty spriteList, SpriteCategoryGridState gridState)
  581. {
  582. spriteList.DeleteArrayElementAtIndex(gridState.selectedIndex);
  583. var count = spriteList.arraySize;
  584. gridState.selectedIndex = (gridState.selectedIndex >= count) ? count - 1 : gridState.selectedIndex;
  585. }
  586. void DrawCategorySpriteListHeader(Rect rect, string text)
  587. {
  588. if (Event.current.type == UnityEngine.EventType.Repaint)
  589. m_Style.headerBackground.Draw(rect, false, false, false, false);
  590. rect.x += 10;
  591. EditorGUI.LabelField(rect, text);
  592. }
  593. void DrawCategorySpriteListFooter(Rect rect, SerializedProperty category, SpriteCategoryGridState gridState, bool canRemove, Action<SerializedProperty, SpriteCategoryGridState> onRemove)
  594. {
  595. float num = rect.xMax - 10f;
  596. float x = num - 8f;
  597. x -= 25f;
  598. x -= 25f;
  599. rect = new Rect(x, rect.y, num - x, rect.height);
  600. Rect rect1 = new Rect(x + 4f, rect.y, 25f, 16f);
  601. Rect position = new Rect(num - 29f, rect.y, 25f, 16f);
  602. if (Event.current.type == UnityEngine.EventType.Repaint)
  603. m_Style.footerBackground.Draw(rect, false, false, false, false);
  604. if (GUI.Button(rect1, m_Style.iconToolbarPlus, m_Style.preButton))
  605. AddSpriteToCategory(category, null);
  606. var spriteList = category.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntries);
  607. using (new EditorGUI.DisabledScope(!canRemove || gridState.selectedIndex < 0 || spriteList.arraySize <= gridState.selectedIndex))
  608. {
  609. if (GUI.Button(position, m_Style.iconToolbarMinus, m_Style.preButton))
  610. onRemove(spriteList, gridState);
  611. }
  612. }
  613. string GetUniqueEntryName(SerializedProperty list, string name)
  614. {
  615. var newName = name;
  616. var count = 0;
  617. while (IsEntryNameUsed(newName, list, 0))
  618. {
  619. newName = string.Format("{0}_{1}", name, count);
  620. ++count;
  621. }
  622. return newName;
  623. }
  624. void AddSpriteToCategory(SerializedProperty category, Sprite sprite)
  625. {
  626. var name = sprite == null ? m_Style.newEntryText : sprite.name;
  627. var spriteList = category.FindPropertyRelative(SpriteLibraryPropertyString.overrideEntries);
  628. name = GetUniqueEntryName(spriteList, name);
  629. spriteList.arraySize += 1;
  630. var sp = spriteList.GetArrayElementAtIndex(spriteList.arraySize - 1);
  631. SetPropertyName(sp, name);
  632. sp.FindPropertyRelative(SpriteLibraryPropertyString.sprite).objectReferenceValue = sprite;
  633. sp.FindPropertyRelative(SpriteLibraryPropertyString.spriteOverride).objectReferenceValue = sprite;
  634. sp.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue = false;
  635. }
  636. static void SetPropertyName(SerializedProperty sp, string newName)
  637. {
  638. sp.FindPropertyRelative(SpriteLibraryPropertyString.name).stringValue = newName;
  639. sp.FindPropertyRelative(SpriteLibraryPropertyString.hash).intValue = SpriteLibraryUtility.GetStringHash(newName);
  640. }
  641. bool OnCanRemoveCallback(ReorderableList list)
  642. {
  643. bool canDelete = true;
  644. if (list.index >= 0 && list.index < list.count)
  645. {
  646. var item = list.serializedProperty.GetArrayElementAtIndex(list.index);
  647. canDelete = !item.FindPropertyRelative(SpriteLibraryPropertyString.fromMain).boolValue;
  648. }
  649. return canDelete;
  650. }
  651. }
  652. }