Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

TMP_FontAssetEditor.cs 81KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEditorInternal;
  4. using System.Collections.Generic;
  5. using UnityEngine.TextCore;
  6. using UnityEngine.TextCore.LowLevel;
  7. #if UNITY_2018_4_OR_NEWER && !UNITY_2018_4_0 && !UNITY_2018_4_1 && !UNITY_2018_4_2 && !UNITY_2018_4_3 && !UNITY_2018_4_4
  8. using UnityEditor.TextCore.LowLevel;
  9. #endif
  10. namespace TMPro.EditorUtilities
  11. {
  12. [CustomPropertyDrawer(typeof(TMP_FontWeightPair))]
  13. public class FontWeightDrawer : PropertyDrawer
  14. {
  15. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
  16. {
  17. SerializedProperty prop_regular = property.FindPropertyRelative("regularTypeface");
  18. SerializedProperty prop_italic = property.FindPropertyRelative("italicTypeface");
  19. float width = position.width;
  20. position.width = EditorGUIUtility.labelWidth;
  21. EditorGUI.LabelField(position, label);
  22. int oldIndent = EditorGUI.indentLevel;
  23. EditorGUI.indentLevel = 0;
  24. // NORMAL TYPEFACE
  25. if (label.text[0] == '4') GUI.enabled = false;
  26. position.x += position.width; position.width = (width - position.width) / 2;
  27. EditorGUI.PropertyField(position, prop_regular, GUIContent.none);
  28. // ITALIC TYPEFACE
  29. GUI.enabled = true;
  30. position.x += position.width;
  31. EditorGUI.PropertyField(position, prop_italic, GUIContent.none);
  32. EditorGUI.indentLevel = oldIndent;
  33. }
  34. }
  35. [CustomEditor(typeof(TMP_FontAsset))]
  36. public class TMP_FontAssetEditor : Editor
  37. {
  38. private struct UI_PanelState
  39. {
  40. public static bool faceInfoPanel = true;
  41. public static bool generationSettingsPanel = true;
  42. public static bool fontAtlasInfoPanel = true;
  43. public static bool fontWeightPanel = true;
  44. public static bool fallbackFontAssetPanel = true;
  45. public static bool glyphTablePanel = false;
  46. public static bool characterTablePanel = false;
  47. public static bool fontFeatureTablePanel = false;
  48. }
  49. private struct AtlasSettings
  50. {
  51. public GlyphRenderMode glyphRenderMode;
  52. public int pointSize;
  53. public int padding;
  54. public int atlasWidth;
  55. public int atlasHeight;
  56. }
  57. /// <summary>
  58. /// Material used to display SDF glyphs in the Character and Glyph tables.
  59. /// </summary>
  60. internal static Material internalSDFMaterial
  61. {
  62. get
  63. {
  64. if (s_InternalSDFMaterial == null)
  65. {
  66. Shader shader = Shader.Find("Hidden/TMP/Internal/Editor/Distance Field SSD");
  67. if (shader != null)
  68. s_InternalSDFMaterial = new Material(shader);
  69. }
  70. return s_InternalSDFMaterial;
  71. }
  72. }
  73. static Material s_InternalSDFMaterial;
  74. /// <summary>
  75. /// Material used to display Bitmap glyphs in the Character and Glyph tables.
  76. /// </summary>
  77. internal static Material internalBitmapMaterial
  78. {
  79. get
  80. {
  81. if (s_InternalBitmapMaterial == null)
  82. {
  83. Shader shader = Shader.Find("Hidden/Internal-GUITextureClipText");
  84. if (shader != null)
  85. s_InternalBitmapMaterial = new Material(shader);
  86. }
  87. return s_InternalBitmapMaterial;
  88. }
  89. }
  90. static Material s_InternalBitmapMaterial;
  91. private static string[] s_UiStateLabel = new string[] { "<i>(Click to collapse)</i> ", "<i>(Click to expand)</i> " };
  92. private GUIContent[] m_AtlasResolutionLabels = { new GUIContent("8"), new GUIContent("16"), new GUIContent("32"), new GUIContent("64"), new GUIContent("128"), new GUIContent("256"), new GUIContent("512"), new GUIContent("1024"), new GUIContent("2048"), new GUIContent("4096"), new GUIContent("8192") };
  93. private int[] m_AtlasResolutions = { 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
  94. private struct Warning
  95. {
  96. public bool isEnabled;
  97. public double expirationTime;
  98. }
  99. private int m_CurrentGlyphPage = 0;
  100. private int m_CurrentCharacterPage = 0;
  101. private int m_CurrentKerningPage = 0;
  102. private int m_SelectedGlyphRecord = -1;
  103. private int m_SelectedCharacterRecord = -1;
  104. private int m_SelectedAdjustmentRecord = -1;
  105. private string m_dstGlyphID;
  106. private string m_dstUnicode;
  107. private const string k_placeholderUnicodeHex = "<i>New Unicode (Hex)</i>";
  108. private string m_unicodeHexLabel = k_placeholderUnicodeHex;
  109. private const string k_placeholderGlyphID = "<i>New Glyph ID</i>";
  110. private string m_GlyphIDLabel = k_placeholderGlyphID;
  111. private Warning m_AddGlyphWarning;
  112. private Warning m_AddCharacterWarning;
  113. private bool m_DisplayDestructiveChangeWarning;
  114. private AtlasSettings m_AtlasSettings;
  115. private bool m_MaterialPresetsRequireUpdate;
  116. private string m_GlyphSearchPattern;
  117. private List<int> m_GlyphSearchList;
  118. private string m_CharacterSearchPattern;
  119. private List<int> m_CharacterSearchList;
  120. private string m_KerningTableSearchPattern;
  121. private List<int> m_KerningTableSearchList;
  122. private bool m_isSearchDirty;
  123. private const string k_UndoRedo = "UndoRedoPerformed";
  124. private SerializedProperty m_AtlasPopulationMode_prop;
  125. private SerializedProperty font_atlas_prop;
  126. private SerializedProperty font_material_prop;
  127. private SerializedProperty m_AtlasRenderMode_prop;
  128. private SerializedProperty m_SamplingPointSize_prop;
  129. private SerializedProperty m_AtlasPadding_prop;
  130. private SerializedProperty m_AtlasWidth_prop;
  131. private SerializedProperty m_AtlasHeight_prop;
  132. private SerializedProperty m_IsMultiAtlasTexturesEnabled_prop;
  133. private SerializedProperty m_ClearDynamicDataOnBuild_prop;
  134. private SerializedProperty fontWeights_prop;
  135. //private SerializedProperty fallbackFontAssets_prop;
  136. private ReorderableList m_list;
  137. private SerializedProperty font_normalStyle_prop;
  138. private SerializedProperty font_normalSpacing_prop;
  139. private SerializedProperty font_boldStyle_prop;
  140. private SerializedProperty font_boldSpacing_prop;
  141. private SerializedProperty font_italicStyle_prop;
  142. private SerializedProperty font_tabSize_prop;
  143. private SerializedProperty m_FaceInfo_prop;
  144. private SerializedProperty m_GlyphTable_prop;
  145. private SerializedProperty m_CharacterTable_prop;
  146. private TMP_FontFeatureTable m_FontFeatureTable;
  147. private SerializedProperty m_FontFeatureTable_prop;
  148. private SerializedProperty m_GlyphPairAdjustmentRecords_prop;
  149. private TMP_SerializedPropertyHolder m_SerializedPropertyHolder;
  150. private SerializedProperty m_EmptyGlyphPairAdjustmentRecord_prop;
  151. private TMP_FontAsset m_fontAsset;
  152. private Material[] m_materialPresets;
  153. private bool isAssetDirty = false;
  154. private int errorCode;
  155. private System.DateTime timeStamp;
  156. public void OnEnable()
  157. {
  158. m_FaceInfo_prop = serializedObject.FindProperty("m_FaceInfo");
  159. font_atlas_prop = serializedObject.FindProperty("m_AtlasTextures").GetArrayElementAtIndex(0);
  160. font_material_prop = serializedObject.FindProperty("material");
  161. m_AtlasPopulationMode_prop = serializedObject.FindProperty("m_AtlasPopulationMode");
  162. m_AtlasRenderMode_prop = serializedObject.FindProperty("m_AtlasRenderMode");
  163. m_SamplingPointSize_prop = m_FaceInfo_prop.FindPropertyRelative("m_PointSize");
  164. m_AtlasPadding_prop = serializedObject.FindProperty("m_AtlasPadding");
  165. m_AtlasWidth_prop = serializedObject.FindProperty("m_AtlasWidth");
  166. m_AtlasHeight_prop = serializedObject.FindProperty("m_AtlasHeight");
  167. m_IsMultiAtlasTexturesEnabled_prop = serializedObject.FindProperty("m_IsMultiAtlasTexturesEnabled");
  168. m_ClearDynamicDataOnBuild_prop = serializedObject.FindProperty("m_ClearDynamicDataOnBuild");
  169. fontWeights_prop = serializedObject.FindProperty("m_FontWeightTable");
  170. m_list = new ReorderableList(serializedObject, serializedObject.FindProperty("m_FallbackFontAssetTable"), true, true, true, true);
  171. m_list.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
  172. {
  173. var element = m_list.serializedProperty.GetArrayElementAtIndex(index);
  174. rect.y += 2;
  175. EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
  176. };
  177. m_list.drawHeaderCallback = rect =>
  178. {
  179. EditorGUI.LabelField(rect, "Fallback List");
  180. };
  181. // Clean up fallback list in the event if contains null elements.
  182. CleanFallbackFontAssetTable();
  183. font_normalStyle_prop = serializedObject.FindProperty("normalStyle");
  184. font_normalSpacing_prop = serializedObject.FindProperty("normalSpacingOffset");
  185. font_boldStyle_prop = serializedObject.FindProperty("boldStyle");
  186. font_boldSpacing_prop = serializedObject.FindProperty("boldSpacing");
  187. font_italicStyle_prop = serializedObject.FindProperty("italicStyle");
  188. font_tabSize_prop = serializedObject.FindProperty("tabSize");
  189. m_CharacterTable_prop = serializedObject.FindProperty("m_CharacterTable");
  190. m_GlyphTable_prop = serializedObject.FindProperty("m_GlyphTable");
  191. m_FontFeatureTable_prop = serializedObject.FindProperty("m_FontFeatureTable");
  192. m_GlyphPairAdjustmentRecords_prop = m_FontFeatureTable_prop.FindPropertyRelative("m_GlyphPairAdjustmentRecords");
  193. m_fontAsset = target as TMP_FontAsset;
  194. m_FontFeatureTable = m_fontAsset.fontFeatureTable;
  195. // Upgrade Font Feature Table if necessary
  196. if (m_fontAsset.m_KerningTable != null && m_fontAsset.m_KerningTable.kerningPairs != null && m_fontAsset.m_KerningTable.kerningPairs.Count > 0)
  197. m_fontAsset.ReadFontAssetDefinition();
  198. // Create serialized object to allow us to use a serialized property of an empty kerning pair.
  199. m_SerializedPropertyHolder = CreateInstance<TMP_SerializedPropertyHolder>();
  200. m_SerializedPropertyHolder.fontAsset = m_fontAsset;
  201. SerializedObject internalSerializedObject = new SerializedObject(m_SerializedPropertyHolder);
  202. m_EmptyGlyphPairAdjustmentRecord_prop = internalSerializedObject.FindProperty("glyphPairAdjustmentRecord");
  203. m_materialPresets = TMP_EditorUtility.FindMaterialReferences(m_fontAsset);
  204. m_GlyphSearchList = new List<int>();
  205. m_KerningTableSearchList = new List<int>();
  206. // Sort Font Asset Tables
  207. m_fontAsset.SortAllTables();
  208. }
  209. public void OnDisable()
  210. {
  211. // Revert changes if user closes or changes selection without having made a choice.
  212. if (m_DisplayDestructiveChangeWarning)
  213. {
  214. m_DisplayDestructiveChangeWarning = false;
  215. RestoreAtlasGenerationSettings();
  216. GUIUtility.keyboardControl = 0;
  217. serializedObject.ApplyModifiedProperties();
  218. }
  219. }
  220. public override void OnInspectorGUI()
  221. {
  222. //Debug.Log("OnInspectorGUI Called.");
  223. Event currentEvent = Event.current;
  224. serializedObject.Update();
  225. Rect rect = EditorGUILayout.GetControlRect(false, 24);
  226. float labelWidth = EditorGUIUtility.labelWidth;
  227. float fieldWidth = EditorGUIUtility.fieldWidth;
  228. // FACE INFO PANEL
  229. #region Face info
  230. GUI.Label(rect, new GUIContent("<b>Face Info</b> - v" + m_fontAsset.version), TMP_UIStyleManager.sectionHeader);
  231. rect.x += rect.width - 132f;
  232. rect.y += 2;
  233. rect.width = 130f;
  234. rect.height = 18f;
  235. if (GUI.Button(rect, new GUIContent("Update Atlas Texture")))
  236. {
  237. TMPro_FontAssetCreatorWindow.ShowFontAtlasCreatorWindow(target as TMP_FontAsset);
  238. }
  239. EditorGUI.indentLevel = 1;
  240. GUI.enabled = false; // Lock UI
  241. // TODO : Consider creating a property drawer for these.
  242. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_FamilyName"));
  243. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_StyleName"));
  244. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_PointSize"));
  245. GUI.enabled = true;
  246. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_Scale"));
  247. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_LineHeight"));
  248. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_AscentLine"));
  249. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_CapLine"));
  250. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_MeanLine"));
  251. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_Baseline"));
  252. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_DescentLine"));
  253. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_UnderlineOffset"));
  254. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_UnderlineThickness"));
  255. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_StrikethroughOffset"));
  256. //EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("strikethroughThickness"));
  257. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_SuperscriptOffset"));
  258. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_SuperscriptSize"));
  259. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_SubscriptOffset"));
  260. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_SubscriptSize"));
  261. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_TabWidth"));
  262. // TODO : Add clamping for some of these values.
  263. //subSize_prop.floatValue = Mathf.Clamp(subSize_prop.floatValue, 0.25f, 1f);
  264. EditorGUILayout.Space();
  265. #endregion
  266. // GENERATION SETTINGS
  267. #region Generation Settings
  268. rect = EditorGUILayout.GetControlRect(false, 24);
  269. if (GUI.Button(rect, new GUIContent("<b>Generation Settings</b>"), TMP_UIStyleManager.sectionHeader))
  270. UI_PanelState.generationSettingsPanel = !UI_PanelState.generationSettingsPanel;
  271. GUI.Label(rect, (UI_PanelState.generationSettingsPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  272. if (UI_PanelState.generationSettingsPanel)
  273. {
  274. EditorGUI.indentLevel = 1;
  275. EditorGUI.BeginChangeCheck();
  276. Font sourceFont = (Font)EditorGUILayout.ObjectField("Source Font File", m_fontAsset.m_SourceFontFile_EditorRef, typeof(Font), false);
  277. if (EditorGUI.EndChangeCheck())
  278. {
  279. string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(sourceFont));
  280. m_fontAsset.m_SourceFontFileGUID = guid;
  281. m_fontAsset.m_SourceFontFile_EditorRef = sourceFont;
  282. }
  283. EditorGUI.BeginDisabledGroup(sourceFont == null);
  284. {
  285. EditorGUI.BeginChangeCheck();
  286. EditorGUILayout.PropertyField(m_AtlasPopulationMode_prop, new GUIContent("Atlas Population Mode"));
  287. if (EditorGUI.EndChangeCheck())
  288. {
  289. serializedObject.ApplyModifiedProperties();
  290. bool isDatabaseRefreshRequired = false;
  291. if (m_AtlasPopulationMode_prop.intValue == 0)
  292. {
  293. m_fontAsset.sourceFontFile = null;
  294. //Set atlas textures to non readable.
  295. for (int i = 0; i < m_fontAsset.atlasTextures.Length; i++)
  296. {
  297. Texture2D tex = m_fontAsset.atlasTextures[i];
  298. if (tex != null && tex.isReadable)
  299. {
  300. #if UNITY_2018_4_OR_NEWER && !UNITY_2018_4_0 && !UNITY_2018_4_1 && !UNITY_2018_4_2 && !UNITY_2018_4_3 && !UNITY_2018_4_4
  301. FontEngineEditorUtilities.SetAtlasTextureIsReadable(tex, false);
  302. #endif
  303. }
  304. }
  305. Debug.Log("Atlas Population mode set to [Static].");
  306. }
  307. else if (m_AtlasPopulationMode_prop.intValue == 1)
  308. {
  309. if (m_fontAsset.m_SourceFontFile_EditorRef.dynamic == false)
  310. {
  311. Debug.LogWarning("Please set the [" + m_fontAsset.name + "] font to dynamic mode as this is required for Dynamic SDF support.", m_fontAsset.m_SourceFontFile_EditorRef);
  312. m_AtlasPopulationMode_prop.intValue = 0;
  313. serializedObject.ApplyModifiedProperties();
  314. }
  315. else
  316. {
  317. m_fontAsset.sourceFontFile = m_fontAsset.m_SourceFontFile_EditorRef;
  318. // Set atlas textures to non readable.
  319. for (int i = 0; i < m_fontAsset.atlasTextures.Length; i++)
  320. {
  321. Texture2D tex = m_fontAsset.atlasTextures[i];
  322. if (tex != null && tex.isReadable == false)
  323. {
  324. #if UNITY_2018_4_OR_NEWER && !UNITY_2018_4_0 && !UNITY_2018_4_1 && !UNITY_2018_4_2 && !UNITY_2018_4_3 && !UNITY_2018_4_4
  325. FontEngineEditorUtilities.SetAtlasTextureIsReadable(tex, true);
  326. #endif
  327. }
  328. }
  329. Debug.Log("Atlas Population mode set to [Dynamic].");
  330. }
  331. }
  332. if (isDatabaseRefreshRequired)
  333. AssetDatabase.Refresh();
  334. serializedObject.Update();
  335. isAssetDirty = true;
  336. }
  337. // Save state of atlas settings
  338. if (m_DisplayDestructiveChangeWarning == false)
  339. {
  340. SavedAtlasGenerationSettings();
  341. //Undo.RegisterCompleteObjectUndo(m_fontAsset, "Font Asset Changes");
  342. }
  343. EditorGUI.BeginDisabledGroup(m_AtlasPopulationMode_prop.intValue == (int)AtlasPopulationMode.Static);
  344. {
  345. EditorGUI.BeginChangeCheck();
  346. // TODO: Switch shaders depending on GlyphRenderMode.
  347. EditorGUILayout.PropertyField(m_AtlasRenderMode_prop);
  348. EditorGUILayout.PropertyField(m_SamplingPointSize_prop, new GUIContent("Sampling Point Size"));
  349. if (EditorGUI.EndChangeCheck())
  350. {
  351. m_DisplayDestructiveChangeWarning = true;
  352. }
  353. // Changes to these properties require updating Material Presets for this font asset.
  354. EditorGUI.BeginChangeCheck();
  355. EditorGUILayout.PropertyField(m_AtlasPadding_prop, new GUIContent("Padding"));
  356. EditorGUILayout.IntPopup(m_AtlasWidth_prop, m_AtlasResolutionLabels, m_AtlasResolutions, new GUIContent("Atlas Width"));
  357. EditorGUILayout.IntPopup(m_AtlasHeight_prop, m_AtlasResolutionLabels, m_AtlasResolutions, new GUIContent("Atlas Height"));
  358. EditorGUILayout.PropertyField(m_IsMultiAtlasTexturesEnabled_prop, new GUIContent("Multi Atlas Textures", "Determines if the font asset will store glyphs in multiple atlas textures."));
  359. EditorGUILayout.PropertyField(m_ClearDynamicDataOnBuild_prop, new GUIContent("Clear Dynamic Data On Build", "Clears all dynamic data restoring the font asset back to its default creation and empty state."));
  360. if (EditorGUI.EndChangeCheck())
  361. {
  362. m_MaterialPresetsRequireUpdate = true;
  363. m_DisplayDestructiveChangeWarning = true;
  364. }
  365. EditorGUILayout.Space();
  366. if (m_DisplayDestructiveChangeWarning)
  367. {
  368. // These changes are destructive on the font asset
  369. rect = EditorGUILayout.GetControlRect(false, 60);
  370. rect.x += 15;
  371. rect.width -= 15;
  372. EditorGUI.HelpBox(rect, "Changing these settings will clear the font asset's character, glyph and texture data.", MessageType.Warning);
  373. if (GUI.Button(new Rect(rect.width - 140, rect.y + 36, 80, 18), new GUIContent("Apply")))
  374. {
  375. m_DisplayDestructiveChangeWarning = false;
  376. // Update face info is sampling point size was changed.
  377. if (m_AtlasSettings.pointSize != m_SamplingPointSize_prop.intValue)
  378. {
  379. FontEngine.LoadFontFace(m_fontAsset.sourceFontFile, m_SamplingPointSize_prop.intValue);
  380. m_fontAsset.faceInfo = FontEngine.GetFaceInfo();
  381. }
  382. Material mat = m_fontAsset.material;
  383. // Update material
  384. mat.SetFloat(ShaderUtilities.ID_TextureWidth, m_AtlasWidth_prop.intValue);
  385. mat.SetFloat(ShaderUtilities.ID_TextureHeight, m_AtlasHeight_prop.intValue);
  386. if (mat.HasProperty(ShaderUtilities.ID_GradientScale))
  387. mat.SetFloat(ShaderUtilities.ID_GradientScale, m_AtlasPadding_prop.intValue + 1);
  388. // Update material presets if any of the relevant properties have been changed.
  389. if (m_MaterialPresetsRequireUpdate)
  390. {
  391. m_MaterialPresetsRequireUpdate = false;
  392. Material[] materialPresets = TMP_EditorUtility.FindMaterialReferences(m_fontAsset);
  393. for (int i = 0; i < materialPresets.Length; i++)
  394. {
  395. mat = materialPresets[i];
  396. mat.SetFloat(ShaderUtilities.ID_TextureWidth, m_AtlasWidth_prop.intValue);
  397. mat.SetFloat(ShaderUtilities.ID_TextureHeight, m_AtlasHeight_prop.intValue);
  398. if (mat.HasProperty(ShaderUtilities.ID_GradientScale))
  399. mat.SetFloat(ShaderUtilities.ID_GradientScale, m_AtlasPadding_prop.intValue + 1);
  400. }
  401. }
  402. m_fontAsset.UpdateFontAssetData();
  403. GUIUtility.keyboardControl = 0;
  404. isAssetDirty = true;
  405. // Update Font Asset Creation Settings to reflect new changes.
  406. UpdateFontAssetCreationSettings();
  407. // TODO: Clear undo buffers.
  408. //Undo.ClearUndo(m_fontAsset);
  409. }
  410. if (GUI.Button(new Rect(rect.width - 56, rect.y + 36, 80, 18), new GUIContent("Revert")))
  411. {
  412. m_DisplayDestructiveChangeWarning = false;
  413. RestoreAtlasGenerationSettings();
  414. GUIUtility.keyboardControl = 0;
  415. // TODO: Clear undo buffers.
  416. //Undo.ClearUndo(m_fontAsset);
  417. }
  418. }
  419. }
  420. EditorGUI.EndDisabledGroup();
  421. }
  422. EditorGUI.EndDisabledGroup();
  423. EditorGUILayout.Space();
  424. }
  425. #endregion
  426. // ATLAS & MATERIAL PANEL
  427. #region Atlas & Material
  428. rect = EditorGUILayout.GetControlRect(false, 24);
  429. if (GUI.Button(rect, new GUIContent("<b>Atlas & Material</b>"), TMP_UIStyleManager.sectionHeader))
  430. UI_PanelState.fontAtlasInfoPanel = !UI_PanelState.fontAtlasInfoPanel;
  431. GUI.Label(rect, (UI_PanelState.fontAtlasInfoPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  432. if (UI_PanelState.fontAtlasInfoPanel)
  433. {
  434. EditorGUI.indentLevel = 1;
  435. GUI.enabled = false;
  436. EditorGUILayout.PropertyField(font_atlas_prop, new GUIContent("Font Atlas"));
  437. EditorGUILayout.PropertyField(font_material_prop, new GUIContent("Font Material"));
  438. GUI.enabled = true;
  439. EditorGUILayout.Space();
  440. }
  441. #endregion
  442. string evt_cmd = Event.current.commandName; // Get Current Event CommandName to check for Undo Events
  443. // FONT WEIGHT PANEL
  444. #region Font Weights
  445. rect = EditorGUILayout.GetControlRect(false, 24);
  446. if (GUI.Button(rect, new GUIContent("<b>Font Weights</b>", "The Font Assets that will be used for different font weights and the settings used to simulate a typeface when no asset is available."), TMP_UIStyleManager.sectionHeader))
  447. UI_PanelState.fontWeightPanel = !UI_PanelState.fontWeightPanel;
  448. GUI.Label(rect, (UI_PanelState.fontWeightPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  449. if (UI_PanelState.fontWeightPanel)
  450. {
  451. EditorGUIUtility.labelWidth *= 0.75f;
  452. EditorGUIUtility.fieldWidth *= 0.25f;
  453. EditorGUILayout.BeginVertical();
  454. EditorGUI.indentLevel = 1;
  455. rect = EditorGUILayout.GetControlRect(true);
  456. rect.x += EditorGUIUtility.labelWidth;
  457. rect.width = (rect.width - EditorGUIUtility.labelWidth) / 2f;
  458. GUI.Label(rect, "Regular Typeface", EditorStyles.label);
  459. rect.x += rect.width;
  460. GUI.Label(rect, "Italic Typeface", EditorStyles.label);
  461. EditorGUI.indentLevel = 1;
  462. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(1), new GUIContent("100 - Thin"));
  463. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(2), new GUIContent("200 - Extra-Light"));
  464. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(3), new GUIContent("300 - Light"));
  465. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(4), new GUIContent("400 - Regular"));
  466. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(5), new GUIContent("500 - Medium"));
  467. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(6), new GUIContent("600 - Semi-Bold"));
  468. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(7), new GUIContent("700 - Bold"));
  469. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(8), new GUIContent("800 - Heavy"));
  470. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(9), new GUIContent("900 - Black"));
  471. EditorGUILayout.EndVertical();
  472. EditorGUILayout.Space();
  473. EditorGUILayout.BeginVertical();
  474. EditorGUILayout.BeginHorizontal();
  475. EditorGUILayout.PropertyField(font_normalStyle_prop, new GUIContent("Normal Weight"));
  476. font_normalStyle_prop.floatValue = Mathf.Clamp(font_normalStyle_prop.floatValue, -3.0f, 3.0f);
  477. if (GUI.changed || evt_cmd == k_UndoRedo)
  478. {
  479. GUI.changed = false;
  480. // Modify the material property on matching material presets.
  481. for (int i = 0; i < m_materialPresets.Length; i++)
  482. m_materialPresets[i].SetFloat("_WeightNormal", font_normalStyle_prop.floatValue);
  483. }
  484. EditorGUILayout.PropertyField(font_boldStyle_prop, new GUIContent("Bold Weight"));
  485. font_boldStyle_prop.floatValue = Mathf.Clamp(font_boldStyle_prop.floatValue, -3.0f, 3.0f);
  486. if (GUI.changed || evt_cmd == k_UndoRedo)
  487. {
  488. GUI.changed = false;
  489. // Modify the material property on matching material presets.
  490. for (int i = 0; i < m_materialPresets.Length; i++)
  491. m_materialPresets[i].SetFloat("_WeightBold", font_boldStyle_prop.floatValue);
  492. }
  493. EditorGUILayout.EndHorizontal();
  494. EditorGUILayout.BeginHorizontal();
  495. EditorGUILayout.PropertyField(font_normalSpacing_prop, new GUIContent("Spacing Offset"));
  496. font_normalSpacing_prop.floatValue = Mathf.Clamp(font_normalSpacing_prop.floatValue, -100, 100);
  497. if (GUI.changed || evt_cmd == k_UndoRedo)
  498. {
  499. GUI.changed = false;
  500. }
  501. EditorGUILayout.PropertyField(font_boldSpacing_prop, new GUIContent("Bold Spacing"));
  502. font_boldSpacing_prop.floatValue = Mathf.Clamp(font_boldSpacing_prop.floatValue, 0, 100);
  503. if (GUI.changed || evt_cmd == k_UndoRedo)
  504. {
  505. GUI.changed = false;
  506. }
  507. EditorGUILayout.EndHorizontal();
  508. EditorGUILayout.BeginHorizontal();
  509. EditorGUILayout.PropertyField(font_italicStyle_prop, new GUIContent("Italic Style"));
  510. font_italicStyle_prop.intValue = Mathf.Clamp(font_italicStyle_prop.intValue, 15, 60);
  511. EditorGUILayout.PropertyField(font_tabSize_prop, new GUIContent("Tab Multiple"));
  512. EditorGUILayout.EndHorizontal();
  513. EditorGUILayout.EndVertical();
  514. EditorGUILayout.Space();
  515. }
  516. EditorGUIUtility.labelWidth = 0;
  517. EditorGUIUtility.fieldWidth = 0;
  518. #endregion
  519. // FALLBACK FONT ASSETS
  520. #region Fallback Font Asset
  521. rect = EditorGUILayout.GetControlRect(false, 24);
  522. EditorGUI.indentLevel = 0;
  523. if (GUI.Button(rect, new GUIContent("<b>Fallback Font Assets</b>", "Select the Font Assets that will be searched and used as fallback when characters are missing from this font asset."), TMP_UIStyleManager.sectionHeader))
  524. UI_PanelState.fallbackFontAssetPanel = !UI_PanelState.fallbackFontAssetPanel;
  525. GUI.Label(rect, (UI_PanelState.fallbackFontAssetPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  526. if (UI_PanelState.fallbackFontAssetPanel)
  527. {
  528. EditorGUIUtility.labelWidth = 120;
  529. EditorGUI.indentLevel = 0;
  530. m_list.DoLayoutList();
  531. EditorGUILayout.Space();
  532. }
  533. #endregion
  534. // CHARACTER TABLE TABLE
  535. #region Character Table
  536. EditorGUIUtility.labelWidth = labelWidth;
  537. EditorGUIUtility.fieldWidth = fieldWidth;
  538. EditorGUI.indentLevel = 0;
  539. rect = EditorGUILayout.GetControlRect(false, 24);
  540. int characterCount = m_fontAsset.characterTable.Count;
  541. if (GUI.Button(rect, new GUIContent("<b>Character Table</b> [" + characterCount + "]" + (rect.width > 320 ? " Characters" : ""), "List of characters contained in this font asset."), TMP_UIStyleManager.sectionHeader))
  542. UI_PanelState.characterTablePanel = !UI_PanelState.characterTablePanel;
  543. GUI.Label(rect, (UI_PanelState.characterTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  544. if (UI_PanelState.characterTablePanel)
  545. {
  546. int arraySize = m_CharacterTable_prop.arraySize;
  547. int itemsPerPage = 15;
  548. // Display Glyph Management Tools
  549. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  550. {
  551. // Search Bar implementation
  552. #region DISPLAY SEARCH BAR
  553. EditorGUILayout.BeginHorizontal();
  554. {
  555. EditorGUIUtility.labelWidth = 130f;
  556. EditorGUI.BeginChangeCheck();
  557. string searchPattern = EditorGUILayout.TextField("Character Search", m_CharacterSearchPattern, "SearchTextField");
  558. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  559. {
  560. if (string.IsNullOrEmpty(searchPattern) == false)
  561. {
  562. m_CharacterSearchPattern = searchPattern;
  563. // Search Character Table for potential matches
  564. SearchCharacterTable (m_CharacterSearchPattern, ref m_CharacterSearchList);
  565. }
  566. else
  567. m_CharacterSearchPattern = null;
  568. m_isSearchDirty = false;
  569. }
  570. string styleName = string.IsNullOrEmpty(m_CharacterSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  571. if (GUILayout.Button(GUIContent.none, styleName))
  572. {
  573. GUIUtility.keyboardControl = 0;
  574. m_CharacterSearchPattern = string.Empty;
  575. }
  576. }
  577. EditorGUILayout.EndHorizontal();
  578. #endregion
  579. // Display Page Navigation
  580. if (!string.IsNullOrEmpty(m_CharacterSearchPattern))
  581. arraySize = m_CharacterSearchList.Count;
  582. DisplayPageNavigation(ref m_CurrentCharacterPage, arraySize, itemsPerPage);
  583. }
  584. EditorGUILayout.EndVertical();
  585. // Display Character Table Elements
  586. if (arraySize > 0)
  587. {
  588. // Display each character entry using the CharacterPropertyDrawer.
  589. for (int i = itemsPerPage * m_CurrentCharacterPage; i < arraySize && i < itemsPerPage * (m_CurrentCharacterPage + 1); i++)
  590. {
  591. // Define the start of the selection region of the element.
  592. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  593. int elementIndex = i;
  594. if (!string.IsNullOrEmpty(m_CharacterSearchPattern))
  595. elementIndex = m_CharacterSearchList[i];
  596. SerializedProperty characterProperty = m_CharacterTable_prop.GetArrayElementAtIndex(elementIndex);
  597. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  598. EditorGUI.BeginDisabledGroup(i != m_SelectedCharacterRecord);
  599. {
  600. EditorGUILayout.PropertyField(characterProperty);
  601. }
  602. EditorGUI.EndDisabledGroup();
  603. EditorGUILayout.EndVertical();
  604. // Define the end of the selection region of the element.
  605. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  606. // Check for Item selection
  607. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  608. if (DoSelectionCheck(selectionArea))
  609. {
  610. if (m_SelectedCharacterRecord == i)
  611. m_SelectedCharacterRecord = -1;
  612. else
  613. {
  614. m_SelectedCharacterRecord = i;
  615. m_AddCharacterWarning.isEnabled = false;
  616. m_unicodeHexLabel = k_placeholderUnicodeHex;
  617. GUIUtility.keyboardControl = 0;
  618. }
  619. }
  620. // Draw Selection Highlight and Glyph Options
  621. if (m_SelectedCharacterRecord == i)
  622. {
  623. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  624. // Draw Glyph management options
  625. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  626. float optionAreaWidth = controlRect.width * 0.6f;
  627. float btnWidth = optionAreaWidth / 3;
  628. Rect position = new Rect(controlRect.x + controlRect.width * .4f, controlRect.y, btnWidth, controlRect.height);
  629. // Copy Selected Glyph to Target Glyph ID
  630. GUI.enabled = !string.IsNullOrEmpty(m_dstUnicode);
  631. if (GUI.Button(position, new GUIContent("Copy to")))
  632. {
  633. GUIUtility.keyboardControl = 0;
  634. // Convert Hex Value to Decimal
  635. int dstGlyphID = TMP_TextUtilities.StringHexToInt(m_dstUnicode);
  636. //Add new glyph at target Unicode hex id.
  637. if (!AddNewCharacter(elementIndex, dstGlyphID))
  638. {
  639. m_AddCharacterWarning.isEnabled = true;
  640. m_AddCharacterWarning.expirationTime = EditorApplication.timeSinceStartup + 1;
  641. }
  642. m_dstUnicode = string.Empty;
  643. m_isSearchDirty = true;
  644. TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, m_fontAsset);
  645. }
  646. // Target Glyph ID
  647. GUI.enabled = true;
  648. position.x += btnWidth;
  649. GUI.SetNextControlName("CharacterID_Input");
  650. m_dstUnicode = EditorGUI.TextField(position, m_dstUnicode);
  651. // Placeholder text
  652. EditorGUI.LabelField(position, new GUIContent(m_unicodeHexLabel, "The Unicode (Hex) ID of the duplicated Character"), TMP_UIStyleManager.label);
  653. // Only filter the input when the destination glyph ID text field has focus.
  654. if (GUI.GetNameOfFocusedControl() == "CharacterID_Input")
  655. {
  656. m_unicodeHexLabel = string.Empty;
  657. //Filter out unwanted characters.
  658. char chr = Event.current.character;
  659. if ((chr < '0' || chr > '9') && (chr < 'a' || chr > 'f') && (chr < 'A' || chr > 'F'))
  660. {
  661. Event.current.character = '\0';
  662. }
  663. }
  664. else
  665. {
  666. m_unicodeHexLabel = k_placeholderUnicodeHex;
  667. //m_dstUnicode = string.Empty;
  668. }
  669. // Remove Glyph
  670. position.x += btnWidth;
  671. if (GUI.Button(position, "Remove"))
  672. {
  673. GUIUtility.keyboardControl = 0;
  674. RemoveCharacterFromList(elementIndex);
  675. isAssetDirty = true;
  676. m_SelectedCharacterRecord = -1;
  677. m_isSearchDirty = true;
  678. break;
  679. }
  680. if (m_AddCharacterWarning.isEnabled && EditorApplication.timeSinceStartup < m_AddCharacterWarning.expirationTime)
  681. {
  682. EditorGUILayout.HelpBox("The Destination Character ID already exists", MessageType.Warning);
  683. }
  684. }
  685. }
  686. }
  687. DisplayPageNavigation(ref m_CurrentCharacterPage, arraySize, itemsPerPage);
  688. EditorGUILayout.Space();
  689. }
  690. #endregion
  691. // GLYPH TABLE
  692. #region Glyph Table
  693. EditorGUIUtility.labelWidth = labelWidth;
  694. EditorGUIUtility.fieldWidth = fieldWidth;
  695. EditorGUI.indentLevel = 0;
  696. rect = EditorGUILayout.GetControlRect(false, 24);
  697. GUIStyle glyphPanelStyle = new GUIStyle(EditorStyles.helpBox);
  698. int glyphCount = m_fontAsset.glyphTable.Count;
  699. if (GUI.Button(rect, new GUIContent("<b>Glyph Table</b> [" + glyphCount + "]" + (rect.width > 275 ? " Glyphs" : ""), "List of glyphs contained in this font asset."), TMP_UIStyleManager.sectionHeader))
  700. UI_PanelState.glyphTablePanel = !UI_PanelState.glyphTablePanel;
  701. GUI.Label(rect, (UI_PanelState.glyphTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  702. if (UI_PanelState.glyphTablePanel)
  703. {
  704. int arraySize = m_GlyphTable_prop.arraySize;
  705. int itemsPerPage = 15;
  706. // Display Glyph Management Tools
  707. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  708. {
  709. // Search Bar implementation
  710. #region DISPLAY SEARCH BAR
  711. EditorGUILayout.BeginHorizontal();
  712. {
  713. EditorGUIUtility.labelWidth = 130f;
  714. EditorGUI.BeginChangeCheck();
  715. string searchPattern = EditorGUILayout.TextField("Glyph Search", m_GlyphSearchPattern, "SearchTextField");
  716. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  717. {
  718. if (string.IsNullOrEmpty(searchPattern) == false)
  719. {
  720. m_GlyphSearchPattern = searchPattern;
  721. // Search Glyph Table for potential matches
  722. SearchGlyphTable(m_GlyphSearchPattern, ref m_GlyphSearchList);
  723. }
  724. else
  725. m_GlyphSearchPattern = null;
  726. m_isSearchDirty = false;
  727. }
  728. string styleName = string.IsNullOrEmpty(m_GlyphSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  729. if (GUILayout.Button(GUIContent.none, styleName))
  730. {
  731. GUIUtility.keyboardControl = 0;
  732. m_GlyphSearchPattern = string.Empty;
  733. }
  734. }
  735. EditorGUILayout.EndHorizontal();
  736. #endregion
  737. // Display Page Navigation
  738. if (!string.IsNullOrEmpty(m_GlyphSearchPattern))
  739. arraySize = m_GlyphSearchList.Count;
  740. DisplayPageNavigation(ref m_CurrentGlyphPage, arraySize, itemsPerPage);
  741. }
  742. EditorGUILayout.EndVertical();
  743. // Display Glyph Table Elements
  744. if (arraySize > 0)
  745. {
  746. // Display each GlyphInfo entry using the GlyphInfo property drawer.
  747. for (int i = itemsPerPage * m_CurrentGlyphPage; i < arraySize && i < itemsPerPage * (m_CurrentGlyphPage + 1); i++)
  748. {
  749. // Define the start of the selection region of the element.
  750. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  751. int elementIndex = i;
  752. if (!string.IsNullOrEmpty(m_GlyphSearchPattern))
  753. elementIndex = m_GlyphSearchList[i];
  754. SerializedProperty glyphProperty = m_GlyphTable_prop.GetArrayElementAtIndex(elementIndex);
  755. EditorGUILayout.BeginVertical(glyphPanelStyle);
  756. using (new EditorGUI.DisabledScope(i != m_SelectedGlyphRecord))
  757. {
  758. EditorGUILayout.PropertyField(glyphProperty);
  759. }
  760. EditorGUILayout.EndVertical();
  761. // Define the end of the selection region of the element.
  762. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  763. // Check for Item selection
  764. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  765. if (DoSelectionCheck(selectionArea))
  766. {
  767. if (m_SelectedGlyphRecord == i)
  768. m_SelectedGlyphRecord = -1;
  769. else
  770. {
  771. m_SelectedGlyphRecord = i;
  772. m_AddGlyphWarning.isEnabled = false;
  773. m_unicodeHexLabel = k_placeholderUnicodeHex;
  774. GUIUtility.keyboardControl = 0;
  775. }
  776. }
  777. // Draw Selection Highlight and Glyph Options
  778. if (m_SelectedGlyphRecord == i)
  779. {
  780. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  781. // Draw Glyph management options
  782. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  783. float optionAreaWidth = controlRect.width * 0.6f;
  784. float btnWidth = optionAreaWidth / 3;
  785. Rect position = new Rect(controlRect.x + controlRect.width * .4f, controlRect.y, btnWidth, controlRect.height);
  786. // Copy Selected Glyph to Target Glyph ID
  787. GUI.enabled = !string.IsNullOrEmpty(m_dstGlyphID);
  788. if (GUI.Button(position, new GUIContent("Copy to")))
  789. {
  790. GUIUtility.keyboardControl = 0;
  791. int dstGlyphID;
  792. // Convert Hex Value to Decimal
  793. int.TryParse(m_dstGlyphID, out dstGlyphID);
  794. //Add new glyph at target Unicode hex id.
  795. if (!AddNewGlyph(elementIndex, dstGlyphID))
  796. {
  797. m_AddGlyphWarning.isEnabled = true;
  798. m_AddGlyphWarning.expirationTime = EditorApplication.timeSinceStartup + 1;
  799. }
  800. m_dstGlyphID = string.Empty;
  801. m_isSearchDirty = true;
  802. TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, m_fontAsset);
  803. }
  804. // Target Glyph ID
  805. GUI.enabled = true;
  806. position.x += btnWidth;
  807. GUI.SetNextControlName("GlyphID_Input");
  808. m_dstGlyphID = EditorGUI.TextField(position, m_dstGlyphID);
  809. // Placeholder text
  810. EditorGUI.LabelField(position, new GUIContent(m_GlyphIDLabel, "The Glyph ID of the duplicated Glyph"), TMP_UIStyleManager.label);
  811. // Only filter the input when the destination glyph ID text field has focus.
  812. if (GUI.GetNameOfFocusedControl() == "GlyphID_Input")
  813. {
  814. m_GlyphIDLabel = string.Empty;
  815. //Filter out unwanted characters.
  816. char chr = Event.current.character;
  817. if ((chr < '0' || chr > '9'))
  818. {
  819. Event.current.character = '\0';
  820. }
  821. }
  822. else
  823. {
  824. m_GlyphIDLabel = k_placeholderGlyphID;
  825. //m_dstGlyphID = string.Empty;
  826. }
  827. // Remove Glyph
  828. position.x += btnWidth;
  829. if (GUI.Button(position, "Remove"))
  830. {
  831. GUIUtility.keyboardControl = 0;
  832. RemoveGlyphFromList(elementIndex);
  833. isAssetDirty = true;
  834. m_SelectedGlyphRecord = -1;
  835. m_isSearchDirty = true;
  836. break;
  837. }
  838. if (m_AddGlyphWarning.isEnabled && EditorApplication.timeSinceStartup < m_AddGlyphWarning.expirationTime)
  839. {
  840. EditorGUILayout.HelpBox("The Destination Glyph ID already exists", MessageType.Warning);
  841. }
  842. }
  843. }
  844. }
  845. DisplayPageNavigation(ref m_CurrentGlyphPage, arraySize, itemsPerPage);
  846. EditorGUILayout.Space();
  847. }
  848. #endregion
  849. // FONT FEATURE TABLE
  850. #region Font Feature Table
  851. EditorGUIUtility.labelWidth = labelWidth;
  852. EditorGUIUtility.fieldWidth = fieldWidth;
  853. EditorGUI.indentLevel = 0;
  854. rect = EditorGUILayout.GetControlRect(false, 24);
  855. int adjustmentPairCount = m_fontAsset.fontFeatureTable.glyphPairAdjustmentRecords.Count;
  856. if (GUI.Button(rect, new GUIContent("<b>Glyph Adjustment Table</b> [" + adjustmentPairCount + "]" + (rect.width > 340 ? " Records" : ""), "List of glyph adjustment / advanced kerning pairs."), TMP_UIStyleManager.sectionHeader))
  857. UI_PanelState.fontFeatureTablePanel = !UI_PanelState.fontFeatureTablePanel;
  858. GUI.Label(rect, (UI_PanelState.fontFeatureTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  859. if (UI_PanelState.fontFeatureTablePanel)
  860. {
  861. int arraySize = m_GlyphPairAdjustmentRecords_prop.arraySize;
  862. int itemsPerPage = 20;
  863. // Display Kerning Pair Management Tools
  864. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  865. {
  866. // Search Bar implementation
  867. #region DISPLAY SEARCH BAR
  868. EditorGUILayout.BeginHorizontal();
  869. {
  870. EditorGUIUtility.labelWidth = 150f;
  871. EditorGUI.BeginChangeCheck();
  872. string searchPattern = EditorGUILayout.TextField("Adjustment Pair Search", m_KerningTableSearchPattern, "SearchTextField");
  873. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  874. {
  875. if (string.IsNullOrEmpty(searchPattern) == false)
  876. {
  877. m_KerningTableSearchPattern = searchPattern;
  878. // Search Glyph Table for potential matches
  879. SearchKerningTable(m_KerningTableSearchPattern, ref m_KerningTableSearchList);
  880. }
  881. else
  882. m_KerningTableSearchPattern = null;
  883. m_isSearchDirty = false;
  884. }
  885. string styleName = string.IsNullOrEmpty(m_KerningTableSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  886. if (GUILayout.Button(GUIContent.none, styleName))
  887. {
  888. GUIUtility.keyboardControl = 0;
  889. m_KerningTableSearchPattern = string.Empty;
  890. }
  891. }
  892. EditorGUILayout.EndHorizontal();
  893. #endregion
  894. // Display Page Navigation
  895. if (!string.IsNullOrEmpty(m_KerningTableSearchPattern))
  896. arraySize = m_KerningTableSearchList.Count;
  897. DisplayPageNavigation(ref m_CurrentKerningPage, arraySize, itemsPerPage);
  898. }
  899. EditorGUILayout.EndVertical();
  900. if (arraySize > 0)
  901. {
  902. // Display each GlyphInfo entry using the GlyphInfo property drawer.
  903. for (int i = itemsPerPage * m_CurrentKerningPage; i < arraySize && i < itemsPerPage * (m_CurrentKerningPage + 1); i++)
  904. {
  905. // Define the start of the selection region of the element.
  906. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  907. int elementIndex = i;
  908. if (!string.IsNullOrEmpty(m_KerningTableSearchPattern))
  909. elementIndex = m_KerningTableSearchList[i];
  910. SerializedProperty pairAdjustmentRecordProperty = m_GlyphPairAdjustmentRecords_prop.GetArrayElementAtIndex(elementIndex);
  911. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  912. using (new EditorGUI.DisabledScope(i != m_SelectedAdjustmentRecord))
  913. {
  914. EditorGUILayout.PropertyField(pairAdjustmentRecordProperty, new GUIContent("Selectable"));
  915. }
  916. EditorGUILayout.EndVertical();
  917. // Define the end of the selection region of the element.
  918. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  919. // Check for Item selection
  920. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  921. if (DoSelectionCheck(selectionArea))
  922. {
  923. if (m_SelectedAdjustmentRecord == i)
  924. {
  925. m_SelectedAdjustmentRecord = -1;
  926. }
  927. else
  928. {
  929. m_SelectedAdjustmentRecord = i;
  930. GUIUtility.keyboardControl = 0;
  931. }
  932. }
  933. // Draw Selection Highlight and Kerning Pair Options
  934. if (m_SelectedAdjustmentRecord == i)
  935. {
  936. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  937. // Draw Glyph management options
  938. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  939. float optionAreaWidth = controlRect.width;
  940. float btnWidth = optionAreaWidth / 4;
  941. Rect position = new Rect(controlRect.x + controlRect.width - btnWidth, controlRect.y, btnWidth, controlRect.height);
  942. // Remove Kerning pair
  943. GUI.enabled = true;
  944. if (GUI.Button(position, "Remove"))
  945. {
  946. GUIUtility.keyboardControl = 0;
  947. RemoveAdjustmentPairFromList(i);
  948. isAssetDirty = true;
  949. m_SelectedAdjustmentRecord = -1;
  950. m_isSearchDirty = true;
  951. break;
  952. }
  953. }
  954. }
  955. }
  956. DisplayPageNavigation(ref m_CurrentKerningPage, arraySize, itemsPerPage);
  957. GUILayout.Space(5);
  958. // Add new kerning pair
  959. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  960. {
  961. EditorGUILayout.PropertyField(m_EmptyGlyphPairAdjustmentRecord_prop);
  962. }
  963. EditorGUILayout.EndVertical();
  964. if (GUILayout.Button("Add New Glyph Adjustment Record"))
  965. {
  966. SerializedProperty firstAdjustmentRecordProperty = m_EmptyGlyphPairAdjustmentRecord_prop.FindPropertyRelative("m_FirstAdjustmentRecord");
  967. SerializedProperty secondAdjustmentRecordProperty = m_EmptyGlyphPairAdjustmentRecord_prop.FindPropertyRelative("m_SecondAdjustmentRecord");
  968. uint firstGlyphIndex = (uint)firstAdjustmentRecordProperty.FindPropertyRelative("m_GlyphIndex").intValue;
  969. uint secondGlyphIndex = (uint)secondAdjustmentRecordProperty.FindPropertyRelative("m_GlyphIndex").intValue;
  970. TMP_GlyphValueRecord firstValueRecord = GetValueRecord(firstAdjustmentRecordProperty.FindPropertyRelative("m_GlyphValueRecord"));
  971. TMP_GlyphValueRecord secondValueRecord = GetValueRecord(secondAdjustmentRecordProperty.FindPropertyRelative("m_GlyphValueRecord"));
  972. errorCode = -1;
  973. uint pairKey = secondGlyphIndex << 16 | firstGlyphIndex;
  974. if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.ContainsKey(pairKey) == false)
  975. {
  976. TMP_GlyphPairAdjustmentRecord adjustmentRecord = new TMP_GlyphPairAdjustmentRecord(new TMP_GlyphAdjustmentRecord(firstGlyphIndex, firstValueRecord), new TMP_GlyphAdjustmentRecord(secondGlyphIndex, secondValueRecord));
  977. m_FontFeatureTable.m_GlyphPairAdjustmentRecords.Add(adjustmentRecord);
  978. m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.Add(pairKey, adjustmentRecord);
  979. errorCode = 0;
  980. }
  981. // Add glyphs and characters
  982. TMP_Character character;
  983. uint firstCharacter = m_SerializedPropertyHolder.firstCharacter;
  984. if (!m_fontAsset.characterLookupTable.ContainsKey(firstCharacter))
  985. m_fontAsset.TryAddCharacterInternal(firstCharacter, out character);
  986. uint secondCharacter = m_SerializedPropertyHolder.secondCharacter;
  987. if (!m_fontAsset.characterLookupTable.ContainsKey(secondCharacter))
  988. m_fontAsset.TryAddCharacterInternal(secondCharacter, out character);
  989. // Sort Kerning Pairs & Reload Font Asset if new kerning pair was added.
  990. if (errorCode != -1)
  991. {
  992. m_FontFeatureTable.SortGlyphPairAdjustmentRecords();
  993. serializedObject.ApplyModifiedProperties();
  994. isAssetDirty = true;
  995. m_isSearchDirty = true;
  996. }
  997. else
  998. {
  999. timeStamp = System.DateTime.Now.AddSeconds(5);
  1000. }
  1001. // Clear Add Kerning Pair Panel
  1002. // TODO
  1003. }
  1004. if (errorCode == -1)
  1005. {
  1006. GUILayout.BeginHorizontal();
  1007. GUILayout.FlexibleSpace();
  1008. GUILayout.Label("Kerning Pair already <color=#ffff00>exists!</color>", TMP_UIStyleManager.label);
  1009. GUILayout.FlexibleSpace();
  1010. GUILayout.EndHorizontal();
  1011. if (System.DateTime.Now > timeStamp)
  1012. errorCode = 0;
  1013. }
  1014. }
  1015. #endregion
  1016. if (serializedObject.ApplyModifiedProperties() || evt_cmd == k_UndoRedo || isAssetDirty)
  1017. {
  1018. // Delay callback until user has decided to Apply or Revert the changes.
  1019. if (m_DisplayDestructiveChangeWarning == false)
  1020. TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, m_fontAsset);
  1021. if (m_fontAsset.IsFontAssetLookupTablesDirty || evt_cmd == k_UndoRedo)
  1022. m_fontAsset.ReadFontAssetDefinition();
  1023. isAssetDirty = false;
  1024. EditorUtility.SetDirty(target);
  1025. }
  1026. // Clear selection if mouse event was not consumed.
  1027. GUI.enabled = true;
  1028. if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0)
  1029. m_SelectedAdjustmentRecord = -1;
  1030. }
  1031. void CleanFallbackFontAssetTable()
  1032. {
  1033. SerializedProperty m_FallbackFontAsseTable = serializedObject.FindProperty("m_FallbackFontAssetTable");
  1034. bool isListDirty = false;
  1035. int elementCount = m_FallbackFontAsseTable.arraySize;
  1036. for (int i = 0; i < elementCount; i++)
  1037. {
  1038. SerializedProperty element = m_FallbackFontAsseTable.GetArrayElementAtIndex(i);
  1039. if (element.objectReferenceValue == null)
  1040. {
  1041. m_FallbackFontAsseTable.DeleteArrayElementAtIndex(i);
  1042. elementCount -= 1;
  1043. i -= 1;
  1044. isListDirty = true;
  1045. }
  1046. }
  1047. if (isListDirty)
  1048. {
  1049. serializedObject.ApplyModifiedProperties();
  1050. serializedObject.Update();
  1051. }
  1052. }
  1053. void SavedAtlasGenerationSettings()
  1054. {
  1055. m_AtlasSettings.glyphRenderMode = (GlyphRenderMode)m_AtlasRenderMode_prop.intValue;
  1056. m_AtlasSettings.pointSize = m_SamplingPointSize_prop.intValue;
  1057. m_AtlasSettings.padding = m_AtlasPadding_prop.intValue;
  1058. m_AtlasSettings.atlasWidth = m_AtlasWidth_prop.intValue;
  1059. m_AtlasSettings.atlasHeight = m_AtlasHeight_prop.intValue;
  1060. }
  1061. void RestoreAtlasGenerationSettings()
  1062. {
  1063. m_AtlasRenderMode_prop.intValue = (int)m_AtlasSettings.glyphRenderMode;
  1064. m_SamplingPointSize_prop.intValue = m_AtlasSettings.pointSize;
  1065. m_AtlasPadding_prop.intValue = m_AtlasSettings.padding;
  1066. m_AtlasWidth_prop.intValue = m_AtlasSettings.atlasWidth;
  1067. m_AtlasHeight_prop.intValue = m_AtlasSettings.atlasHeight;
  1068. }
  1069. void UpdateFontAssetCreationSettings()
  1070. {
  1071. m_fontAsset.m_CreationSettings.pointSize = m_SamplingPointSize_prop.intValue;
  1072. m_fontAsset.m_CreationSettings.renderMode = m_AtlasRenderMode_prop.intValue;
  1073. m_fontAsset.m_CreationSettings.padding = m_AtlasPadding_prop.intValue;
  1074. m_fontAsset.m_CreationSettings.atlasWidth = m_AtlasWidth_prop.intValue;
  1075. m_fontAsset.m_CreationSettings.atlasHeight = m_AtlasHeight_prop.intValue;
  1076. }
  1077. void UpdateCharacterData(SerializedProperty property, int index)
  1078. {
  1079. TMP_Character character = m_fontAsset.characterTable[index];
  1080. character.unicode = (uint)property.FindPropertyRelative("m_Unicode").intValue;
  1081. character.scale = property.FindPropertyRelative("m_Scale").floatValue;
  1082. SerializedProperty glyphProperty = property.FindPropertyRelative("m_Glyph");
  1083. character.glyph.index = (uint)glyphProperty.FindPropertyRelative("m_Index").intValue;
  1084. SerializedProperty glyphRectProperty = glyphProperty.FindPropertyRelative("m_GlyphRect");
  1085. character.glyph.glyphRect = new GlyphRect(glyphRectProperty.FindPropertyRelative("m_X").intValue, glyphRectProperty.FindPropertyRelative("m_Y").intValue, glyphRectProperty.FindPropertyRelative("m_Width").intValue, glyphRectProperty.FindPropertyRelative("m_Height").intValue);
  1086. SerializedProperty glyphMetricsProperty = glyphProperty.FindPropertyRelative("m_Metrics");
  1087. character.glyph.metrics = new GlyphMetrics(glyphMetricsProperty.FindPropertyRelative("m_Width").floatValue, glyphMetricsProperty.FindPropertyRelative("m_Height").floatValue, glyphMetricsProperty.FindPropertyRelative("m_HorizontalBearingX").floatValue, glyphMetricsProperty.FindPropertyRelative("m_HorizontalBearingY").floatValue, glyphMetricsProperty.FindPropertyRelative("m_HorizontalAdvance").floatValue);
  1088. character.glyph.scale = glyphProperty.FindPropertyRelative("m_Scale").floatValue;
  1089. character.glyph.atlasIndex = glyphProperty.FindPropertyRelative("m_AtlasIndex").intValue;
  1090. }
  1091. void UpdateGlyphData(SerializedProperty property, int index)
  1092. {
  1093. Glyph glyph = m_fontAsset.glyphTable[index];
  1094. glyph.index = (uint)property.FindPropertyRelative("m_Index").intValue;
  1095. SerializedProperty glyphRect = property.FindPropertyRelative("m_GlyphRect");
  1096. glyph.glyphRect = new GlyphRect(glyphRect.FindPropertyRelative("m_X").intValue, glyphRect.FindPropertyRelative("m_Y").intValue, glyphRect.FindPropertyRelative("m_Width").intValue, glyphRect.FindPropertyRelative("m_Height").intValue);
  1097. SerializedProperty glyphMetrics = property.FindPropertyRelative("m_Metrics");
  1098. glyph.metrics = new GlyphMetrics(glyphMetrics.FindPropertyRelative("m_Width").floatValue, glyphMetrics.FindPropertyRelative("m_Height").floatValue, glyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue, glyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue, glyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue);
  1099. glyph.scale = property.FindPropertyRelative("m_Scale").floatValue;
  1100. }
  1101. void DisplayPageNavigation(ref int currentPage, int arraySize, int itemsPerPage)
  1102. {
  1103. Rect pagePos = EditorGUILayout.GetControlRect(false, 20);
  1104. pagePos.width /= 3;
  1105. int shiftMultiplier = Event.current.shift ? 10 : 1; // Page + Shift goes 10 page forward
  1106. // Previous Page
  1107. GUI.enabled = currentPage > 0;
  1108. if (GUI.Button(pagePos, "Previous Page"))
  1109. currentPage -= 1 * shiftMultiplier;
  1110. // Page Counter
  1111. GUI.enabled = true;
  1112. pagePos.x += pagePos.width;
  1113. int totalPages = (int)(arraySize / (float)itemsPerPage + 0.999f);
  1114. GUI.Label(pagePos, "Page " + (currentPage + 1) + " / " + totalPages, TMP_UIStyleManager.centeredLabel);
  1115. // Next Page
  1116. pagePos.x += pagePos.width;
  1117. GUI.enabled = itemsPerPage * (currentPage + 1) < arraySize;
  1118. if (GUI.Button(pagePos, "Next Page"))
  1119. currentPage += 1 * shiftMultiplier;
  1120. // Clamp page range
  1121. currentPage = Mathf.Clamp(currentPage, 0, arraySize / itemsPerPage);
  1122. GUI.enabled = true;
  1123. }
  1124. /// <summary>
  1125. ///
  1126. /// </summary>
  1127. /// <param name="srcGlyphID"></param>
  1128. /// <param name="dstGlyphID"></param>
  1129. bool AddNewGlyph(int srcIndex, int dstGlyphID)
  1130. {
  1131. // Make sure Destination Glyph ID doesn't already contain a Glyph
  1132. if (m_fontAsset.glyphLookupTable.ContainsKey((uint)dstGlyphID))
  1133. return false;
  1134. // Add new element to glyph list.
  1135. m_GlyphTable_prop.arraySize += 1;
  1136. // Get a reference to the source glyph.
  1137. SerializedProperty sourceGlyph = m_GlyphTable_prop.GetArrayElementAtIndex(srcIndex);
  1138. int dstIndex = m_GlyphTable_prop.arraySize - 1;
  1139. // Get a reference to the target / destination glyph.
  1140. SerializedProperty targetGlyph = m_GlyphTable_prop.GetArrayElementAtIndex(dstIndex);
  1141. CopyGlyphSerializedProperty(sourceGlyph, ref targetGlyph);
  1142. // Update the ID of the glyph
  1143. targetGlyph.FindPropertyRelative("m_Index").intValue = dstGlyphID;
  1144. serializedObject.ApplyModifiedProperties();
  1145. m_fontAsset.SortGlyphTable();
  1146. m_fontAsset.ReadFontAssetDefinition();
  1147. return true;
  1148. }
  1149. /// <summary>
  1150. ///
  1151. /// </summary>
  1152. /// <param name="glyphID"></param>
  1153. void RemoveGlyphFromList(int index)
  1154. {
  1155. if (index > m_GlyphTable_prop.arraySize)
  1156. return;
  1157. int targetGlyphIndex = m_GlyphTable_prop.GetArrayElementAtIndex(index).FindPropertyRelative("m_Index").intValue;
  1158. m_GlyphTable_prop.DeleteArrayElementAtIndex(index);
  1159. // Remove all characters referencing this glyph.
  1160. for (int i = 0; i < m_CharacterTable_prop.arraySize; i++)
  1161. {
  1162. int glyphIndex = m_CharacterTable_prop.GetArrayElementAtIndex(i).FindPropertyRelative("m_GlyphIndex").intValue;
  1163. if (glyphIndex == targetGlyphIndex)
  1164. {
  1165. // Remove character
  1166. m_CharacterTable_prop.DeleteArrayElementAtIndex(i);
  1167. }
  1168. }
  1169. serializedObject.ApplyModifiedProperties();
  1170. m_fontAsset.ReadFontAssetDefinition();
  1171. }
  1172. bool AddNewCharacter(int srcIndex, int dstGlyphID)
  1173. {
  1174. // Make sure Destination Glyph ID doesn't already contain a Glyph
  1175. if (m_fontAsset.characterLookupTable.ContainsKey((uint)dstGlyphID))
  1176. return false;
  1177. // Add new element to glyph list.
  1178. m_CharacterTable_prop.arraySize += 1;
  1179. // Get a reference to the source glyph.
  1180. SerializedProperty sourceCharacter = m_CharacterTable_prop.GetArrayElementAtIndex(srcIndex);
  1181. int dstIndex = m_CharacterTable_prop.arraySize - 1;
  1182. // Get a reference to the target / destination glyph.
  1183. SerializedProperty targetCharacter = m_CharacterTable_prop.GetArrayElementAtIndex(dstIndex);
  1184. CopyCharacterSerializedProperty(sourceCharacter, ref targetCharacter);
  1185. // Update the ID of the glyph
  1186. targetCharacter.FindPropertyRelative("m_Unicode").intValue = dstGlyphID;
  1187. serializedObject.ApplyModifiedProperties();
  1188. m_fontAsset.SortCharacterTable();
  1189. m_fontAsset.ReadFontAssetDefinition();
  1190. return true;
  1191. }
  1192. void RemoveCharacterFromList(int index)
  1193. {
  1194. if (index > m_CharacterTable_prop.arraySize)
  1195. return;
  1196. m_CharacterTable_prop.DeleteArrayElementAtIndex(index);
  1197. serializedObject.ApplyModifiedProperties();
  1198. m_fontAsset.ReadFontAssetDefinition();
  1199. }
  1200. // Check if any of the Style elements were clicked on.
  1201. private bool DoSelectionCheck(Rect selectionArea)
  1202. {
  1203. Event currentEvent = Event.current;
  1204. switch (currentEvent.type)
  1205. {
  1206. case EventType.MouseDown:
  1207. if (selectionArea.Contains(currentEvent.mousePosition) && currentEvent.button == 0)
  1208. {
  1209. currentEvent.Use();
  1210. return true;
  1211. }
  1212. break;
  1213. }
  1214. return false;
  1215. }
  1216. TMP_GlyphValueRecord GetValueRecord(SerializedProperty property)
  1217. {
  1218. TMP_GlyphValueRecord record = new TMP_GlyphValueRecord();
  1219. record.xPlacement = property.FindPropertyRelative("m_XPlacement").floatValue;
  1220. record.yPlacement = property.FindPropertyRelative("m_YPlacement").floatValue;
  1221. record.xAdvance = property.FindPropertyRelative("m_XAdvance").floatValue;
  1222. record.yAdvance = property.FindPropertyRelative("m_YAdvance").floatValue;
  1223. return record;
  1224. }
  1225. void RemoveAdjustmentPairFromList(int index)
  1226. {
  1227. if (index > m_GlyphPairAdjustmentRecords_prop.arraySize)
  1228. return;
  1229. m_GlyphPairAdjustmentRecords_prop.DeleteArrayElementAtIndex(index);
  1230. serializedObject.ApplyModifiedProperties();
  1231. m_fontAsset.ReadFontAssetDefinition();
  1232. }
  1233. /// <summary>
  1234. ///
  1235. /// </summary>
  1236. /// <param name="srcGlyph"></param>
  1237. /// <param name="dstGlyph"></param>
  1238. void CopyGlyphSerializedProperty(SerializedProperty srcGlyph, ref SerializedProperty dstGlyph)
  1239. {
  1240. // TODO : Should make a generic function which copies each of the properties.
  1241. dstGlyph.FindPropertyRelative("m_Index").intValue = srcGlyph.FindPropertyRelative("m_Index").intValue;
  1242. // Glyph -> GlyphMetrics
  1243. SerializedProperty srcGlyphMetrics = srcGlyph.FindPropertyRelative("m_Metrics");
  1244. SerializedProperty dstGlyphMetrics = dstGlyph.FindPropertyRelative("m_Metrics");
  1245. dstGlyphMetrics.FindPropertyRelative("m_Width").floatValue = srcGlyphMetrics.FindPropertyRelative("m_Width").floatValue;
  1246. dstGlyphMetrics.FindPropertyRelative("m_Height").floatValue = srcGlyphMetrics.FindPropertyRelative("m_Height").floatValue;
  1247. dstGlyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue;
  1248. dstGlyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue;
  1249. dstGlyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue;
  1250. // Glyph -> GlyphRect
  1251. SerializedProperty srcGlyphRect = srcGlyph.FindPropertyRelative("m_GlyphRect");
  1252. SerializedProperty dstGlyphRect = dstGlyph.FindPropertyRelative("m_GlyphRect");
  1253. dstGlyphRect.FindPropertyRelative("m_X").intValue = srcGlyphRect.FindPropertyRelative("m_X").intValue;
  1254. dstGlyphRect.FindPropertyRelative("m_Y").intValue = srcGlyphRect.FindPropertyRelative("m_Y").intValue;
  1255. dstGlyphRect.FindPropertyRelative("m_Width").intValue = srcGlyphRect.FindPropertyRelative("m_Width").intValue;
  1256. dstGlyphRect.FindPropertyRelative("m_Height").intValue = srcGlyphRect.FindPropertyRelative("m_Height").intValue;
  1257. dstGlyph.FindPropertyRelative("m_Scale").floatValue = srcGlyph.FindPropertyRelative("m_Scale").floatValue;
  1258. dstGlyph.FindPropertyRelative("m_AtlasIndex").intValue = srcGlyph.FindPropertyRelative("m_AtlasIndex").intValue;
  1259. }
  1260. void CopyCharacterSerializedProperty(SerializedProperty source, ref SerializedProperty target)
  1261. {
  1262. // TODO : Should make a generic function which copies each of the properties.
  1263. int unicode = source.FindPropertyRelative("m_Unicode").intValue;
  1264. target.FindPropertyRelative("m_Unicode").intValue = unicode;
  1265. int srcGlyphIndex = source.FindPropertyRelative("m_GlyphIndex").intValue;
  1266. target.FindPropertyRelative("m_GlyphIndex").intValue = srcGlyphIndex;
  1267. target.FindPropertyRelative("m_Scale").floatValue = source.FindPropertyRelative("m_Scale").floatValue;
  1268. }
  1269. /// <summary>
  1270. ///
  1271. /// </summary>
  1272. /// <param name="searchPattern"></param>
  1273. /// <returns></returns>
  1274. void SearchGlyphTable (string searchPattern, ref List<int> searchResults)
  1275. {
  1276. if (searchResults == null) searchResults = new List<int>();
  1277. searchResults.Clear();
  1278. int arraySize = m_GlyphTable_prop.arraySize;
  1279. for (int i = 0; i < arraySize; i++)
  1280. {
  1281. SerializedProperty sourceGlyph = m_GlyphTable_prop.GetArrayElementAtIndex(i);
  1282. int id = sourceGlyph.FindPropertyRelative("m_Index").intValue;
  1283. // Check for potential match against a character.
  1284. //if (searchPattern.Length == 1 && id == searchPattern[0])
  1285. // searchResults.Add(i);
  1286. // Check for potential match against decimal id
  1287. if (id.ToString().Contains(searchPattern))
  1288. searchResults.Add(i);
  1289. //if (id.ToString("x").Contains(searchPattern))
  1290. // searchResults.Add(i);
  1291. //if (id.ToString("X").Contains(searchPattern))
  1292. // searchResults.Add(i);
  1293. }
  1294. }
  1295. void SearchCharacterTable(string searchPattern, ref List<int> searchResults)
  1296. {
  1297. if (searchResults == null) searchResults = new List<int>();
  1298. searchResults.Clear();
  1299. int arraySize = m_CharacterTable_prop.arraySize;
  1300. for (int i = 0; i < arraySize; i++)
  1301. {
  1302. SerializedProperty sourceCharacter = m_CharacterTable_prop.GetArrayElementAtIndex(i);
  1303. int id = sourceCharacter.FindPropertyRelative("m_Unicode").intValue;
  1304. // Check for potential match against a character.
  1305. if (searchPattern.Length == 1 && id == searchPattern[0])
  1306. searchResults.Add(i);
  1307. else if (id.ToString("x").Contains(searchPattern))
  1308. searchResults.Add(i);
  1309. else if (id.ToString("X").Contains(searchPattern))
  1310. searchResults.Add(i);
  1311. // Check for potential match against decimal id
  1312. //if (id.ToString().Contains(searchPattern))
  1313. // searchResults.Add(i);
  1314. }
  1315. }
  1316. void SearchKerningTable(string searchPattern, ref List<int> searchResults)
  1317. {
  1318. if (searchResults == null) searchResults = new List<int>();
  1319. searchResults.Clear();
  1320. // Lookup glyph index of potential characters contained in the search pattern.
  1321. uint firstGlyphIndex = 0;
  1322. TMP_Character firstCharacterSearch;
  1323. if (searchPattern.Length > 0 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[0], out firstCharacterSearch))
  1324. firstGlyphIndex = firstCharacterSearch.glyphIndex;
  1325. uint secondGlyphIndex = 0;
  1326. TMP_Character secondCharacterSearch;
  1327. if (searchPattern.Length > 1 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[1], out secondCharacterSearch))
  1328. secondGlyphIndex = secondCharacterSearch.glyphIndex;
  1329. int arraySize = m_GlyphPairAdjustmentRecords_prop.arraySize;
  1330. for (int i = 0; i < arraySize; i++)
  1331. {
  1332. SerializedProperty record = m_GlyphPairAdjustmentRecords_prop.GetArrayElementAtIndex(i);
  1333. SerializedProperty firstAdjustmentRecord = record.FindPropertyRelative("m_FirstAdjustmentRecord");
  1334. SerializedProperty secondAdjustmentRecord = record.FindPropertyRelative("m_SecondAdjustmentRecord");
  1335. int firstGlyph = firstAdjustmentRecord.FindPropertyRelative("m_GlyphIndex").intValue;
  1336. int secondGlyph = secondAdjustmentRecord.FindPropertyRelative("m_GlyphIndex").intValue;
  1337. if (firstGlyphIndex == firstGlyph && secondGlyphIndex == secondGlyph)
  1338. searchResults.Add(i);
  1339. else if (searchPattern.Length == 1 && (firstGlyphIndex == firstGlyph || firstGlyphIndex == secondGlyph))
  1340. searchResults.Add(i);
  1341. else if (firstGlyph.ToString().Contains(searchPattern))
  1342. searchResults.Add(i);
  1343. else if (secondGlyph.ToString().Contains(searchPattern))
  1344. searchResults.Add(i);
  1345. }
  1346. }
  1347. }
  1348. }