暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

TMP_SpriteAssetEditor.cs 42KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. using UnityEngine;
  2. using UnityEngine.TextCore;
  3. using UnityEditor;
  4. using UnityEditorInternal;
  5. using System.Collections.Generic;
  6. namespace TMPro.EditorUtilities
  7. {
  8. [CustomEditor(typeof(TMP_SpriteAsset))]
  9. public class TMP_SpriteAssetEditor : Editor
  10. {
  11. struct UI_PanelState
  12. {
  13. public static bool spriteAssetFaceInfoPanel = true;
  14. public static bool spriteAtlasInfoPanel = true;
  15. public static bool fallbackSpriteAssetPanel = true;
  16. public static bool spriteCharacterTablePanel;
  17. public static bool spriteGlyphTablePanel;
  18. }
  19. private static string[] s_UiStateLabel = new string[] { "<i>(Click to collapse)</i> ", "<i>(Click to expand)</i> " };
  20. int m_moveToIndex;
  21. int m_selectedElement = -1;
  22. bool m_isCharacterSelected = false;
  23. bool m_isSpriteSelected = false;
  24. int m_CurrentCharacterPage;
  25. int m_CurrentGlyphPage;
  26. const string k_UndoRedo = "UndoRedoPerformed";
  27. string m_CharacterSearchPattern;
  28. List<int> m_CharacterSearchList;
  29. bool m_IsCharacterSearchDirty;
  30. string m_GlyphSearchPattern;
  31. List<int> m_GlyphSearchList;
  32. bool m_IsGlyphSearchDirty;
  33. SerializedProperty m_FaceInfoProperty;
  34. SerializedProperty m_PointSizeProperty;
  35. SerializedProperty m_ScaleProperty;
  36. SerializedProperty m_LineHeightProperty;
  37. SerializedProperty m_AscentLineProperty;
  38. SerializedProperty m_BaselineProperty;
  39. SerializedProperty m_DescentLineProperty;
  40. SerializedProperty m_spriteAtlas_prop;
  41. SerializedProperty m_material_prop;
  42. SerializedProperty m_SpriteCharacterTableProperty;
  43. SerializedProperty m_SpriteGlyphTableProperty;
  44. ReorderableList m_fallbackSpriteAssetList;
  45. TMP_SpriteAsset m_SpriteAsset;
  46. bool isAssetDirty;
  47. float m_xOffset;
  48. float m_yOffset;
  49. float m_xAdvance;
  50. float m_scale;
  51. public void OnEnable()
  52. {
  53. m_SpriteAsset = target as TMP_SpriteAsset;
  54. m_FaceInfoProperty = serializedObject.FindProperty("m_FaceInfo");
  55. m_PointSizeProperty = m_FaceInfoProperty.FindPropertyRelative("m_PointSize");
  56. m_ScaleProperty = m_FaceInfoProperty.FindPropertyRelative("m_Scale");
  57. m_LineHeightProperty = m_FaceInfoProperty.FindPropertyRelative("m_LineHeight");
  58. m_AscentLineProperty = m_FaceInfoProperty.FindPropertyRelative("m_AscentLine");
  59. m_BaselineProperty = m_FaceInfoProperty.FindPropertyRelative("m_Baseline");
  60. m_DescentLineProperty = m_FaceInfoProperty.FindPropertyRelative("m_DescentLine");
  61. m_spriteAtlas_prop = serializedObject.FindProperty("spriteSheet");
  62. m_material_prop = serializedObject.FindProperty("m_Material");
  63. m_SpriteCharacterTableProperty = serializedObject.FindProperty("m_SpriteCharacterTable");
  64. m_SpriteGlyphTableProperty = serializedObject.FindProperty("m_GlyphTable");
  65. // Fallback TMP Sprite Asset list
  66. m_fallbackSpriteAssetList = new ReorderableList(serializedObject, serializedObject.FindProperty("fallbackSpriteAssets"), true, true, true, true);
  67. m_fallbackSpriteAssetList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
  68. {
  69. var element = m_fallbackSpriteAssetList.serializedProperty.GetArrayElementAtIndex(index);
  70. rect.y += 2;
  71. EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
  72. };
  73. m_fallbackSpriteAssetList.drawHeaderCallback = rect =>
  74. {
  75. EditorGUI.LabelField(rect, new GUIContent("Fallback Sprite Asset List", "Select the Sprite Assets that will be searched and used as fallback when a given sprite is missing from this sprite asset."));
  76. };
  77. // Clear glyph proxy lookups
  78. TMP_PropertyDrawerUtilities.ClearGlyphProxyLookups();
  79. }
  80. public override void OnInspectorGUI()
  81. {
  82. //Debug.Log("OnInspectorGUI Called.");
  83. Event currentEvent = Event.current;
  84. string evt_cmd = currentEvent.commandName; // Get Current Event CommandName to check for Undo Events
  85. serializedObject.Update();
  86. // TEXTMESHPRO SPRITE INFO PANEL
  87. #region Display Sprite Asset Face Info
  88. Rect rect = EditorGUILayout.GetControlRect(false, 24);
  89. GUI.Label(rect, new GUIContent("<b>Face Info</b> - v" + m_SpriteAsset.version), TMP_UIStyleManager.sectionHeader);
  90. rect.x += rect.width - 132f;
  91. rect.y += 2;
  92. rect.width = 130f;
  93. rect.height = 18f;
  94. if (GUI.Button(rect, new GUIContent("Update Sprite Asset")))
  95. {
  96. TMP_SpriteAssetMenu.UpdateSpriteAsset(m_SpriteAsset);
  97. }
  98. EditorGUI.indentLevel = 1;
  99. EditorGUILayout.PropertyField(m_PointSizeProperty);
  100. EditorGUILayout.PropertyField(m_ScaleProperty);
  101. //EditorGUILayout.PropertyField(m_LineHeightProperty);
  102. EditorGUILayout.PropertyField(m_AscentLineProperty);
  103. EditorGUILayout.PropertyField(m_BaselineProperty);
  104. EditorGUILayout.PropertyField(m_DescentLineProperty);
  105. EditorGUILayout.Space();
  106. #endregion
  107. // ATLAS TEXTURE & MATERIAL
  108. #region Display Atlas Texture and Material
  109. rect = EditorGUILayout.GetControlRect(false, 24);
  110. if (GUI.Button(rect, new GUIContent("<b>Atlas & Material</b>"), TMP_UIStyleManager.sectionHeader))
  111. UI_PanelState.spriteAtlasInfoPanel = !UI_PanelState.spriteAtlasInfoPanel;
  112. GUI.Label(rect, (UI_PanelState.spriteAtlasInfoPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  113. if (UI_PanelState.spriteAtlasInfoPanel)
  114. {
  115. EditorGUI.BeginChangeCheck();
  116. EditorGUILayout.PropertyField(m_spriteAtlas_prop, new GUIContent("Sprite Atlas"));
  117. if (EditorGUI.EndChangeCheck())
  118. {
  119. // Assign the new sprite atlas texture to the current material
  120. Texture2D tex = m_spriteAtlas_prop.objectReferenceValue as Texture2D;
  121. if (tex != null)
  122. {
  123. Material mat = m_material_prop.objectReferenceValue as Material;
  124. if (mat != null)
  125. mat.mainTexture = tex;
  126. }
  127. }
  128. EditorGUILayout.PropertyField(m_material_prop, new GUIContent("Default Material"));
  129. EditorGUILayout.Space();
  130. }
  131. #endregion
  132. // FALLBACK SPRITE ASSETS
  133. #region Display Sprite Fallbacks
  134. rect = EditorGUILayout.GetControlRect(false, 24);
  135. EditorGUI.indentLevel = 0;
  136. if (GUI.Button(rect, new GUIContent("<b>Fallback Sprite Assets</b>", "Select the Sprite Assets that will be searched and used as fallback when a given sprite is missing from this sprite asset."), TMP_UIStyleManager.sectionHeader))
  137. UI_PanelState.fallbackSpriteAssetPanel = !UI_PanelState.fallbackSpriteAssetPanel;
  138. GUI.Label(rect, (UI_PanelState.fallbackSpriteAssetPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  139. if (UI_PanelState.fallbackSpriteAssetPanel)
  140. {
  141. m_fallbackSpriteAssetList.DoLayoutList();
  142. EditorGUILayout.Space();
  143. }
  144. #endregion
  145. // SPRITE CHARACTER TABLE
  146. #region Display Sprite Character Table
  147. EditorGUI.indentLevel = 0;
  148. rect = EditorGUILayout.GetControlRect(false, 24);
  149. if (GUI.Button(rect, new GUIContent("<b>Sprite Character Table</b>", "List of sprite characters contained in this sprite asset."), TMP_UIStyleManager.sectionHeader))
  150. UI_PanelState.spriteCharacterTablePanel = !UI_PanelState.spriteCharacterTablePanel;
  151. GUI.Label(rect, (UI_PanelState.spriteCharacterTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  152. if (UI_PanelState.spriteCharacterTablePanel)
  153. {
  154. int arraySize = m_SpriteCharacterTableProperty.arraySize;
  155. int itemsPerPage = 10;
  156. // Display Glyph Management Tools
  157. EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.ExpandWidth(true));
  158. {
  159. // Search Bar implementation
  160. #region DISPLAY SEARCH BAR
  161. EditorGUILayout.BeginHorizontal();
  162. {
  163. EditorGUIUtility.labelWidth = 110f;
  164. EditorGUI.BeginChangeCheck();
  165. string searchPattern = EditorGUILayout.TextField("Sprite Search", m_CharacterSearchPattern, "SearchTextField");
  166. if (EditorGUI.EndChangeCheck() || m_IsCharacterSearchDirty)
  167. {
  168. if (string.IsNullOrEmpty(searchPattern) == false)
  169. {
  170. //GUIUtility.keyboardControl = 0;
  171. m_CharacterSearchPattern = searchPattern.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim();
  172. // Search Glyph Table for potential matches
  173. SearchCharacterTable(m_CharacterSearchPattern, ref m_CharacterSearchList);
  174. }
  175. else
  176. m_CharacterSearchPattern = null;
  177. m_IsCharacterSearchDirty = false;
  178. }
  179. string styleName = string.IsNullOrEmpty(m_CharacterSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  180. if (GUILayout.Button(GUIContent.none, styleName))
  181. {
  182. GUIUtility.keyboardControl = 0;
  183. m_CharacterSearchPattern = string.Empty;
  184. }
  185. }
  186. EditorGUILayout.EndHorizontal();
  187. #endregion
  188. // Display Page Navigation
  189. if (!string.IsNullOrEmpty(m_CharacterSearchPattern))
  190. arraySize = m_CharacterSearchList.Count;
  191. // Display Page Navigation
  192. DisplayPageNavigation(ref m_CurrentCharacterPage, arraySize, itemsPerPage);
  193. }
  194. EditorGUILayout.EndVertical();
  195. if (arraySize > 0)
  196. {
  197. // Display each SpriteInfo entry using the SpriteInfo property drawer.
  198. for (int i = itemsPerPage * m_CurrentCharacterPage; i < arraySize && i < itemsPerPage * (m_CurrentCharacterPage + 1); i++)
  199. {
  200. // Define the start of the selection region of the element.
  201. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  202. int elementIndex = i;
  203. if (!string.IsNullOrEmpty(m_CharacterSearchPattern))
  204. elementIndex = m_CharacterSearchList[i];
  205. SerializedProperty spriteCharacterProperty = m_SpriteCharacterTableProperty.GetArrayElementAtIndex(elementIndex);
  206. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  207. {
  208. EditorGUI.BeginDisabledGroup(i != m_selectedElement || !m_isCharacterSelected);
  209. {
  210. EditorGUILayout.PropertyField(spriteCharacterProperty);
  211. }
  212. EditorGUI.EndDisabledGroup();
  213. }
  214. EditorGUILayout.EndVertical();
  215. // Define the end of the selection region of the element.
  216. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  217. // Check for Item selection
  218. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  219. if (DoSelectionCheck(selectionArea))
  220. {
  221. if (m_selectedElement == i)
  222. {
  223. m_selectedElement = -1;
  224. m_isCharacterSelected = false;
  225. }
  226. else
  227. {
  228. m_selectedElement = i;
  229. m_isCharacterSelected = true;
  230. m_isSpriteSelected = false;
  231. GUIUtility.keyboardControl = 0;
  232. }
  233. }
  234. // Draw & Handle Section Area
  235. if (m_selectedElement == i && m_isCharacterSelected)
  236. {
  237. // Draw selection highlight
  238. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  239. // Draw options to MoveUp, MoveDown, Add or Remove Sprites
  240. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  241. controlRect.width /= 8;
  242. // Move sprite up.
  243. bool guiEnabled = GUI.enabled;
  244. if (i == 0) { GUI.enabled = false; }
  245. if (GUI.Button(controlRect, "Up"))
  246. {
  247. SwapCharacterElements(i, i - 1);
  248. }
  249. GUI.enabled = guiEnabled;
  250. // Move sprite down.
  251. controlRect.x += controlRect.width;
  252. if (i == arraySize - 1) { GUI.enabled = false; }
  253. if (GUI.Button(controlRect, "Down"))
  254. {
  255. SwapCharacterElements(i, i + 1);
  256. }
  257. GUI.enabled = guiEnabled;
  258. // Move sprite to new index
  259. controlRect.x += controlRect.width * 2;
  260. //if (i == arraySize - 1) { GUI.enabled = false; }
  261. m_moveToIndex = EditorGUI.IntField(controlRect, m_moveToIndex);
  262. controlRect.x -= controlRect.width;
  263. if (GUI.Button(controlRect, "Goto"))
  264. {
  265. MoveCharacterToIndex(i, m_moveToIndex);
  266. }
  267. //controlRect.x += controlRect.width;
  268. GUI.enabled = guiEnabled;
  269. // Add new Sprite
  270. controlRect.x += controlRect.width * 4;
  271. if (GUI.Button(controlRect, "+"))
  272. {
  273. m_SpriteCharacterTableProperty.arraySize += 1;
  274. int index = m_SpriteCharacterTableProperty.arraySize - 1;
  275. SerializedProperty spriteInfo_prop = m_SpriteCharacterTableProperty.GetArrayElementAtIndex(index);
  276. // Copy properties of the selected element
  277. CopyCharacterSerializedProperty(m_SpriteCharacterTableProperty.GetArrayElementAtIndex(elementIndex), ref spriteInfo_prop);
  278. //spriteInfo_prop.FindPropertyRelative("m_Index").intValue = index;
  279. serializedObject.ApplyModifiedProperties();
  280. m_IsCharacterSearchDirty = true;
  281. }
  282. // Delete selected Sprite
  283. controlRect.x += controlRect.width;
  284. if (m_selectedElement == -1) GUI.enabled = false;
  285. if (GUI.Button(controlRect, "-"))
  286. {
  287. m_SpriteCharacterTableProperty.DeleteArrayElementAtIndex(elementIndex);
  288. m_selectedElement = -1;
  289. serializedObject.ApplyModifiedProperties();
  290. m_IsCharacterSearchDirty = true;
  291. return;
  292. }
  293. }
  294. }
  295. }
  296. DisplayPageNavigation(ref m_CurrentCharacterPage, arraySize, itemsPerPage);
  297. EditorGUIUtility.labelWidth = 40f;
  298. EditorGUIUtility.fieldWidth = 20f;
  299. GUILayout.Space(5f);
  300. // GLOBAL TOOLS
  301. #region Global Tools
  302. /*
  303. GUI.enabled = true;
  304. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  305. rect = EditorGUILayout.GetControlRect(false, 40);
  306. float width = (rect.width - 75f) / 4;
  307. EditorGUI.LabelField(rect, "Global Offsets & Scale", EditorStyles.boldLabel);
  308. rect.x += 70;
  309. bool old_ChangedState = GUI.changed;
  310. GUI.changed = false;
  311. m_xOffset = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 0, rect.y + 20, width - 5f, 18), new GUIContent("OX:"), m_xOffset);
  312. if (GUI.changed) UpdateGlobalProperty("m_HorizontalBearingX", m_xOffset);
  313. m_yOffset = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 1, rect.y + 20, width - 5f, 18), new GUIContent("OY:"), m_yOffset);
  314. if (GUI.changed) UpdateGlobalProperty("m_HorizontalBearingY", m_yOffset);
  315. m_xAdvance = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 2, rect.y + 20, width - 5f, 18), new GUIContent("ADV."), m_xAdvance);
  316. if (GUI.changed) UpdateGlobalProperty("m_HorizontalAdvance", m_xAdvance);
  317. m_scale = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 3, rect.y + 20, width - 5f, 18), new GUIContent("SF."), m_scale);
  318. if (GUI.changed) UpdateGlobalProperty("m_Scale", m_scale);
  319. EditorGUILayout.EndVertical();
  320. GUI.changed = old_ChangedState;
  321. */
  322. #endregion
  323. }
  324. #endregion
  325. // SPRITE GLYPH TABLE
  326. #region Display Sprite Glyph Table
  327. EditorGUI.indentLevel = 0;
  328. rect = EditorGUILayout.GetControlRect(false, 24);
  329. if (GUI.Button(rect, new GUIContent("<b>Sprite Glyph Table</b>", "A list of the SpriteGlyphs contained in this sprite asset."), TMP_UIStyleManager.sectionHeader))
  330. UI_PanelState.spriteGlyphTablePanel = !UI_PanelState.spriteGlyphTablePanel;
  331. GUI.Label(rect, (UI_PanelState.spriteGlyphTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  332. if (UI_PanelState.spriteGlyphTablePanel)
  333. {
  334. int arraySize = m_SpriteGlyphTableProperty.arraySize;
  335. int itemsPerPage = 10;
  336. // Display Glyph Management Tools
  337. EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.ExpandWidth(true));
  338. {
  339. // Search Bar implementation
  340. #region DISPLAY SEARCH BAR
  341. EditorGUILayout.BeginHorizontal();
  342. {
  343. EditorGUIUtility.labelWidth = 110f;
  344. EditorGUI.BeginChangeCheck();
  345. string searchPattern = EditorGUILayout.TextField("Sprite Search", m_GlyphSearchPattern, "SearchTextField");
  346. if (EditorGUI.EndChangeCheck() || m_IsGlyphSearchDirty)
  347. {
  348. if (string.IsNullOrEmpty(searchPattern) == false)
  349. {
  350. //GUIUtility.keyboardControl = 0;
  351. m_GlyphSearchPattern = searchPattern.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim();
  352. // Search Glyph Table for potential matches
  353. SearchCharacterTable(m_GlyphSearchPattern, ref m_GlyphSearchList);
  354. }
  355. else
  356. m_GlyphSearchPattern = null;
  357. m_IsGlyphSearchDirty = false;
  358. }
  359. string styleName = string.IsNullOrEmpty(m_GlyphSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  360. if (GUILayout.Button(GUIContent.none, styleName))
  361. {
  362. GUIUtility.keyboardControl = 0;
  363. m_GlyphSearchPattern = string.Empty;
  364. }
  365. }
  366. EditorGUILayout.EndHorizontal();
  367. #endregion
  368. // Display Page Navigation
  369. if (!string.IsNullOrEmpty(m_GlyphSearchPattern))
  370. arraySize = m_GlyphSearchList.Count;
  371. // Display Page Navigation
  372. DisplayPageNavigation(ref m_CurrentGlyphPage, arraySize, itemsPerPage);
  373. }
  374. EditorGUILayout.EndVertical();
  375. if (arraySize > 0)
  376. {
  377. // Display each SpriteInfo entry using the SpriteInfo property drawer.
  378. for (int i = itemsPerPage * m_CurrentGlyphPage; i < arraySize && i < itemsPerPage * (m_CurrentGlyphPage + 1); i++)
  379. {
  380. // Define the start of the selection region of the element.
  381. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  382. int elementIndex = i;
  383. if (!string.IsNullOrEmpty(m_GlyphSearchPattern))
  384. elementIndex = m_GlyphSearchList[i];
  385. SerializedProperty spriteGlyphProperty = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(elementIndex);
  386. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  387. {
  388. EditorGUI.BeginDisabledGroup(i != m_selectedElement || !m_isSpriteSelected);
  389. {
  390. EditorGUILayout.PropertyField(spriteGlyphProperty);
  391. }
  392. EditorGUI.EndDisabledGroup();
  393. }
  394. EditorGUILayout.EndVertical();
  395. // Define the end of the selection region of the element.
  396. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  397. // Check for Item selection
  398. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  399. if (DoSelectionCheck(selectionArea))
  400. {
  401. if (m_selectedElement == i)
  402. {
  403. m_selectedElement = -1;
  404. m_isSpriteSelected = false;
  405. }
  406. else
  407. {
  408. m_selectedElement = i;
  409. m_isCharacterSelected = false;
  410. m_isSpriteSelected = true;
  411. GUIUtility.keyboardControl = 0;
  412. }
  413. }
  414. // Draw & Handle Section Area
  415. if (m_selectedElement == i && m_isSpriteSelected)
  416. {
  417. // Draw selection highlight
  418. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  419. // Draw options to MoveUp, MoveDown, Add or Remove Sprites
  420. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  421. controlRect.width /= 8;
  422. // Move sprite up.
  423. bool guiEnabled = GUI.enabled;
  424. if (i == 0) { GUI.enabled = false; }
  425. if (GUI.Button(controlRect, "Up"))
  426. {
  427. SwapGlyphElements(i, i - 1);
  428. }
  429. GUI.enabled = guiEnabled;
  430. // Move sprite down.
  431. controlRect.x += controlRect.width;
  432. if (i == arraySize - 1) { GUI.enabled = false; }
  433. if (GUI.Button(controlRect, "Down"))
  434. {
  435. SwapGlyphElements(i, i + 1);
  436. }
  437. GUI.enabled = guiEnabled;
  438. // Move sprite to new index
  439. controlRect.x += controlRect.width * 2;
  440. //if (i == arraySize - 1) { GUI.enabled = false; }
  441. m_moveToIndex = EditorGUI.IntField(controlRect, m_moveToIndex);
  442. controlRect.x -= controlRect.width;
  443. if (GUI.Button(controlRect, "Goto"))
  444. {
  445. MoveGlyphToIndex(i, m_moveToIndex);
  446. }
  447. //controlRect.x += controlRect.width;
  448. GUI.enabled = guiEnabled;
  449. // Add new Sprite
  450. controlRect.x += controlRect.width * 4;
  451. if (GUI.Button(controlRect, "+"))
  452. {
  453. m_SpriteGlyphTableProperty.arraySize += 1;
  454. int index = m_SpriteGlyphTableProperty.arraySize - 1;
  455. SerializedProperty newSpriteGlyphProperty = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(index);
  456. // Copy properties of the selected element
  457. CopyGlyphSerializedProperty(m_SpriteGlyphTableProperty.GetArrayElementAtIndex(elementIndex), ref newSpriteGlyphProperty);
  458. newSpriteGlyphProperty.FindPropertyRelative("m_Index").intValue = index;
  459. serializedObject.ApplyModifiedProperties();
  460. m_IsGlyphSearchDirty = true;
  461. //m_SpriteAsset.UpdateLookupTables();
  462. }
  463. // Delete selected Sprite
  464. controlRect.x += controlRect.width;
  465. if (m_selectedElement == -1) GUI.enabled = false;
  466. if (GUI.Button(controlRect, "-"))
  467. {
  468. SerializedProperty selectedSpriteGlyphProperty = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(elementIndex);
  469. int selectedGlyphIndex = selectedSpriteGlyphProperty.FindPropertyRelative("m_Index").intValue;
  470. m_SpriteGlyphTableProperty.DeleteArrayElementAtIndex(elementIndex);
  471. // Remove all Sprite Characters referencing this glyph.
  472. for (int j = 0; j < m_SpriteCharacterTableProperty.arraySize; j++)
  473. {
  474. int glyphIndex = m_SpriteCharacterTableProperty.GetArrayElementAtIndex(j).FindPropertyRelative("m_GlyphIndex").intValue;
  475. if (glyphIndex == selectedGlyphIndex)
  476. {
  477. // Remove character
  478. m_SpriteCharacterTableProperty.DeleteArrayElementAtIndex(j);
  479. }
  480. }
  481. m_selectedElement = -1;
  482. serializedObject.ApplyModifiedProperties();
  483. m_IsGlyphSearchDirty = true;
  484. //m_SpriteAsset.UpdateLookupTables();
  485. return;
  486. }
  487. }
  488. }
  489. }
  490. DisplayPageNavigation(ref m_CurrentGlyphPage, arraySize, itemsPerPage);
  491. EditorGUIUtility.labelWidth = 40f;
  492. EditorGUIUtility.fieldWidth = 20f;
  493. GUILayout.Space(5f);
  494. // GLOBAL TOOLS
  495. #region Global Tools
  496. GUI.enabled = true;
  497. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  498. EditorGUILayout.LabelField("Global Offsets & Scale", EditorStyles.boldLabel);
  499. bool old_ChangedState = GUI.changed;
  500. GUI.changed = false;
  501. EditorGUILayout.BeginHorizontal();
  502. GUILayout.Space(25f);
  503. m_xOffset = EditorGUILayout.FloatField(new GUIContent("OX:"), m_xOffset);
  504. if (GUI.changed) UpdateGlobalProperty("m_HorizontalBearingX", m_xOffset);
  505. m_yOffset = EditorGUILayout.FloatField(new GUIContent("OY:"), m_yOffset);
  506. if (GUI.changed) UpdateGlobalProperty("m_HorizontalBearingY", m_yOffset);
  507. m_xAdvance = EditorGUILayout.FloatField(new GUIContent("ADV."), m_xAdvance);
  508. if (GUI.changed) UpdateGlobalProperty("m_HorizontalAdvance", m_xAdvance);
  509. m_scale = EditorGUILayout.FloatField(new GUIContent("SF."), m_scale);
  510. if (GUI.changed) UpdateGlobalProperty("m_Scale", m_scale);
  511. EditorGUILayout.EndHorizontal();
  512. EditorGUILayout.EndVertical();
  513. #endregion
  514. GUI.changed = old_ChangedState;
  515. }
  516. #endregion
  517. if (serializedObject.ApplyModifiedProperties() || evt_cmd == k_UndoRedo || isAssetDirty)
  518. {
  519. if (m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty || evt_cmd == k_UndoRedo)
  520. {
  521. m_SpriteAsset.UpdateLookupTables();
  522. TMP_ResourceManager.RebuildFontAssetCache();
  523. }
  524. TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, m_SpriteAsset);
  525. isAssetDirty = false;
  526. EditorUtility.SetDirty(target);
  527. }
  528. // Clear selection if mouse event was not consumed.
  529. GUI.enabled = true;
  530. if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0)
  531. m_selectedElement = -1;
  532. }
  533. /// <summary>
  534. ///
  535. /// </summary>
  536. /// <param name="arraySize"></param>
  537. /// <param name="itemsPerPage"></param>
  538. void DisplayPageNavigation(ref int currentPage, int arraySize, int itemsPerPage)
  539. {
  540. Rect pagePos = EditorGUILayout.GetControlRect(false, 20);
  541. pagePos.width /= 3;
  542. int shiftMultiplier = Event.current.shift ? 10 : 1; // Page + Shift goes 10 page forward
  543. // Previous Page
  544. GUI.enabled = currentPage > 0;
  545. if (GUI.Button(pagePos, "Previous Page"))
  546. {
  547. currentPage -= 1 * shiftMultiplier;
  548. //m_isNewPage = true;
  549. }
  550. // Page Counter
  551. GUI.enabled = true;
  552. pagePos.x += pagePos.width;
  553. int totalPages = (int)(arraySize / (float)itemsPerPage + 0.999f);
  554. GUI.Label(pagePos, "Page " + (currentPage + 1) + " / " + totalPages, TMP_UIStyleManager.centeredLabel);
  555. // Next Page
  556. pagePos.x += pagePos.width;
  557. GUI.enabled = itemsPerPage * (currentPage + 1) < arraySize;
  558. if (GUI.Button(pagePos, "Next Page"))
  559. {
  560. currentPage += 1 * shiftMultiplier;
  561. //m_isNewPage = true;
  562. }
  563. // Clamp page range
  564. currentPage = Mathf.Clamp(currentPage, 0, arraySize / itemsPerPage);
  565. GUI.enabled = true;
  566. }
  567. /// <summary>
  568. /// Method to update the properties of all sprites
  569. /// </summary>
  570. /// <param name="property"></param>
  571. /// <param name="value"></param>
  572. void UpdateGlobalProperty(string property, float value)
  573. {
  574. int arraySize = m_SpriteGlyphTableProperty.arraySize;
  575. for (int i = 0; i < arraySize; i++)
  576. {
  577. // Get a reference to the sprite glyph.
  578. SerializedProperty spriteGlyphProperty = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(i);
  579. if (property == "m_Scale")
  580. {
  581. spriteGlyphProperty.FindPropertyRelative(property).floatValue = value;
  582. }
  583. else
  584. {
  585. SerializedProperty glyphMetricsProperty = spriteGlyphProperty.FindPropertyRelative("m_Metrics");
  586. glyphMetricsProperty.FindPropertyRelative(property).floatValue = value;
  587. }
  588. }
  589. GUI.changed = false;
  590. }
  591. // Check if any of the Style elements were clicked on.
  592. private bool DoSelectionCheck(Rect selectionArea)
  593. {
  594. Event currentEvent = Event.current;
  595. switch (currentEvent.type)
  596. {
  597. case EventType.MouseDown:
  598. if (selectionArea.Contains(currentEvent.mousePosition) && currentEvent.button == 0)
  599. {
  600. currentEvent.Use();
  601. return true;
  602. }
  603. break;
  604. }
  605. return false;
  606. }
  607. /// <summary>
  608. /// Swap the sprite item at the currently selected array index to another index.
  609. /// </summary>
  610. /// <param name="selectedIndex">Selected index.</param>
  611. /// <param name="newIndex">New index.</param>
  612. void SwapCharacterElements(int selectedIndex, int newIndex)
  613. {
  614. m_SpriteCharacterTableProperty.MoveArrayElement(selectedIndex, newIndex);
  615. m_selectedElement = newIndex;
  616. m_IsCharacterSearchDirty = true;
  617. m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
  618. }
  619. /// <summary>
  620. /// Move Sprite Element at selected index to another index and reorder sprite list.
  621. /// </summary>
  622. /// <param name="selectedIndex"></param>
  623. /// <param name="newIndex"></param>
  624. void MoveCharacterToIndex(int selectedIndex, int newIndex)
  625. {
  626. int arraySize = m_SpriteCharacterTableProperty.arraySize;
  627. if (newIndex >= arraySize)
  628. newIndex = arraySize - 1;
  629. m_SpriteCharacterTableProperty.MoveArrayElement(selectedIndex, newIndex);
  630. m_selectedElement = newIndex;
  631. m_IsCharacterSearchDirty = true;
  632. m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
  633. // TODO: Need to handle switching pages if the character or glyph is moved to a different page.
  634. }
  635. /// <summary>
  636. ///
  637. /// </summary>
  638. /// <param name="selectedIndex"></param>
  639. /// <param name="newIndex"></param>
  640. void SwapGlyphElements(int selectedIndex, int newIndex)
  641. {
  642. m_SpriteGlyphTableProperty.MoveArrayElement(selectedIndex, newIndex);
  643. m_selectedElement = newIndex;
  644. m_IsGlyphSearchDirty = true;
  645. m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
  646. }
  647. /// <summary>
  648. /// Move Sprite Element at selected index to another index and reorder sprite list.
  649. /// </summary>
  650. /// <param name="selectedIndex"></param>
  651. /// <param name="newIndex"></param>
  652. void MoveGlyphToIndex(int selectedIndex, int newIndex)
  653. {
  654. int arraySize = m_SpriteGlyphTableProperty.arraySize;
  655. if (newIndex >= arraySize)
  656. newIndex = arraySize - 1;
  657. m_SpriteGlyphTableProperty.MoveArrayElement(selectedIndex, newIndex);
  658. m_selectedElement = newIndex;
  659. m_IsGlyphSearchDirty = true;
  660. m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
  661. // TODO: Need to handle switching pages if the character or glyph is moved to a different page.
  662. }
  663. /// <summary>
  664. ///
  665. /// </summary>
  666. /// <param name="source"></param>
  667. /// <param name="target"></param>
  668. void CopyCharacterSerializedProperty(SerializedProperty source, ref SerializedProperty target)
  669. {
  670. target.FindPropertyRelative("m_Name").stringValue = source.FindPropertyRelative("m_Name").stringValue;
  671. target.FindPropertyRelative("m_Unicode").intValue = source.FindPropertyRelative("m_Unicode").intValue;
  672. target.FindPropertyRelative("m_GlyphIndex").intValue = source.FindPropertyRelative("m_GlyphIndex").intValue;
  673. target.FindPropertyRelative("m_Scale").floatValue = source.FindPropertyRelative("m_Scale").floatValue;
  674. }
  675. void CopyGlyphSerializedProperty(SerializedProperty srcGlyph, ref SerializedProperty dstGlyph)
  676. {
  677. // TODO : Should make a generic function which copies each of the properties.
  678. // Index
  679. dstGlyph.FindPropertyRelative("m_Index").intValue = srcGlyph.FindPropertyRelative("m_Index").intValue;
  680. // GlyphMetrics
  681. SerializedProperty srcGlyphMetrics = srcGlyph.FindPropertyRelative("m_Metrics");
  682. SerializedProperty dstGlyphMetrics = dstGlyph.FindPropertyRelative("m_Metrics");
  683. dstGlyphMetrics.FindPropertyRelative("m_Width").floatValue = srcGlyphMetrics.FindPropertyRelative("m_Width").floatValue;
  684. dstGlyphMetrics.FindPropertyRelative("m_Height").floatValue = srcGlyphMetrics.FindPropertyRelative("m_Height").floatValue;
  685. dstGlyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue;
  686. dstGlyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue;
  687. dstGlyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue;
  688. // GlyphRect
  689. SerializedProperty srcGlyphRect = srcGlyph.FindPropertyRelative("m_GlyphRect");
  690. SerializedProperty dstGlyphRect = dstGlyph.FindPropertyRelative("m_GlyphRect");
  691. dstGlyphRect.FindPropertyRelative("m_X").intValue = srcGlyphRect.FindPropertyRelative("m_X").intValue;
  692. dstGlyphRect.FindPropertyRelative("m_Y").intValue = srcGlyphRect.FindPropertyRelative("m_Y").intValue;
  693. dstGlyphRect.FindPropertyRelative("m_Width").intValue = srcGlyphRect.FindPropertyRelative("m_Width").intValue;
  694. dstGlyphRect.FindPropertyRelative("m_Height").intValue = srcGlyphRect.FindPropertyRelative("m_Height").intValue;
  695. dstGlyph.FindPropertyRelative("m_Scale").floatValue = srcGlyph.FindPropertyRelative("m_Scale").floatValue;
  696. dstGlyph.FindPropertyRelative("m_AtlasIndex").intValue = srcGlyph.FindPropertyRelative("m_AtlasIndex").intValue;
  697. }
  698. /// <summary>
  699. ///
  700. /// </summary>
  701. /// <param name="searchPattern"></param>
  702. /// <returns></returns>
  703. void SearchCharacterTable(string searchPattern, ref List<int> searchResults)
  704. {
  705. if (searchResults == null) searchResults = new List<int>();
  706. searchResults.Clear();
  707. int arraySize = m_SpriteCharacterTableProperty.arraySize;
  708. for (int i = 0; i < arraySize; i++)
  709. {
  710. SerializedProperty sourceSprite = m_SpriteCharacterTableProperty.GetArrayElementAtIndex(i);
  711. // Check for potential match against array index
  712. if (i.ToString().Contains(searchPattern))
  713. {
  714. searchResults.Add(i);
  715. continue;
  716. }
  717. // Check for potential match against decimal id
  718. int id = sourceSprite.FindPropertyRelative("m_GlyphIndex").intValue;
  719. if (id.ToString().Contains(searchPattern))
  720. {
  721. searchResults.Add(i);
  722. continue;
  723. }
  724. // Check for potential match against name
  725. string name = sourceSprite.FindPropertyRelative("m_Name").stringValue.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim();
  726. if (name.Contains(searchPattern))
  727. {
  728. searchResults.Add(i);
  729. continue;
  730. }
  731. }
  732. }
  733. void SearchGlyphTable(string searchPattern, ref List<int> searchResults)
  734. {
  735. if (searchResults == null) searchResults = new List<int>();
  736. searchResults.Clear();
  737. int arraySize = m_SpriteGlyphTableProperty.arraySize;
  738. for (int i = 0; i < arraySize; i++)
  739. {
  740. SerializedProperty sourceSprite = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(i);
  741. // Check for potential match against array index
  742. if (i.ToString().Contains(searchPattern))
  743. {
  744. searchResults.Add(i);
  745. continue;
  746. }
  747. // Check for potential match against decimal id
  748. int id = sourceSprite.FindPropertyRelative("m_GlyphIndex").intValue;
  749. if (id.ToString().Contains(searchPattern))
  750. {
  751. searchResults.Add(i);
  752. continue;
  753. }
  754. // Check for potential match against name
  755. string name = sourceSprite.FindPropertyRelative("m_Name").stringValue.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim();
  756. if (name.Contains(searchPattern))
  757. {
  758. searchResults.Add(i);
  759. continue;
  760. }
  761. }
  762. }
  763. }
  764. }