TMP_FontAssetEditor.cs 80 KB

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