暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TMP_FontAssetEditor.cs 140KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEditorInternal;
  4. using System.Collections.Generic;
  5. using JetBrains.Annotations;
  6. using UnityEngine.TextCore;
  7. using UnityEngine.TextCore.LowLevel;
  8. using UnityEditor.TextCore.LowLevel;
  9. namespace TMPro.EditorUtilities
  10. {
  11. [CustomPropertyDrawer(typeof(TMP_FontWeightPair))]
  12. public class FontWeightDrawer : PropertyDrawer
  13. {
  14. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
  15. {
  16. SerializedProperty prop_regular = property.FindPropertyRelative("regularTypeface");
  17. SerializedProperty prop_italic = property.FindPropertyRelative("italicTypeface");
  18. float width = position.width;
  19. position.width = EditorGUIUtility.labelWidth;
  20. EditorGUI.LabelField(position, label);
  21. int oldIndent = EditorGUI.indentLevel;
  22. EditorGUI.indentLevel = 0;
  23. // NORMAL TYPEFACE
  24. if (label.text[0] == '4') GUI.enabled = false;
  25. position.x += position.width; position.width = (width - position.width) / 2;
  26. EditorGUI.PropertyField(position, prop_regular, GUIContent.none);
  27. // ITALIC TYPEFACE
  28. GUI.enabled = true;
  29. position.x += position.width;
  30. EditorGUI.PropertyField(position, prop_italic, GUIContent.none);
  31. EditorGUI.indentLevel = oldIndent;
  32. }
  33. }
  34. [CustomEditor(typeof(TMP_FontAsset))]
  35. public class TMP_FontAssetEditor : Editor
  36. {
  37. private struct UI_PanelState
  38. {
  39. public static bool faceInfoPanel = true;
  40. public static bool generationSettingsPanel = true;
  41. public static bool fontAtlasInfoPanel = true;
  42. public static bool fontWeightPanel = true;
  43. public static bool fallbackFontAssetPanel = true;
  44. public static bool glyphTablePanel = false;
  45. public static bool characterTablePanel = false;
  46. public static bool LigatureSubstitutionTablePanel;
  47. public static bool PairAdjustmentTablePanel = false;
  48. public static bool MarkToBaseTablePanel = false;
  49. public static bool MarkToMarkTablePanel = false;
  50. }
  51. private struct GenerationSettings
  52. {
  53. public Font sourceFont;
  54. public int faceIndex;
  55. public GlyphRenderMode glyphRenderMode;
  56. public int pointSize;
  57. public int padding;
  58. public int atlasWidth;
  59. public int atlasHeight;
  60. }
  61. /// <summary>
  62. /// Material used to display SDF glyphs in the Character and Glyph tables.
  63. /// </summary>
  64. internal static Material internalSDFMaterial
  65. {
  66. get
  67. {
  68. if (s_InternalSDFMaterial == null)
  69. {
  70. Shader shader = Shader.Find("Hidden/TMP/Internal/Editor/Distance Field SSD");
  71. if (shader != null)
  72. s_InternalSDFMaterial = new Material(shader);
  73. }
  74. return s_InternalSDFMaterial;
  75. }
  76. }
  77. static Material s_InternalSDFMaterial;
  78. /// <summary>
  79. /// Material used to display Bitmap glyphs in the Character and Glyph tables.
  80. /// </summary>
  81. internal static Material internalBitmapMaterial
  82. {
  83. get
  84. {
  85. if (s_InternalBitmapMaterial == null)
  86. {
  87. Shader shader = Shader.Find("Hidden/Internal-GUITextureClipText");
  88. if (shader != null)
  89. s_InternalBitmapMaterial = new Material(shader);
  90. }
  91. return s_InternalBitmapMaterial;
  92. }
  93. }
  94. static Material s_InternalBitmapMaterial;
  95. /// <summary>
  96. /// Material used to display color glyphs in the Character and Glyph tables.
  97. /// </summary>
  98. internal static Material internalRGBABitmapMaterial
  99. {
  100. get
  101. {
  102. if (s_Internal_Bitmap_RGBA_Material == null)
  103. {
  104. Shader shader = Shader.Find("Hidden/Internal-GUITextureClip");
  105. if (shader != null)
  106. s_Internal_Bitmap_RGBA_Material = new Material(shader);
  107. }
  108. return s_Internal_Bitmap_RGBA_Material;
  109. }
  110. }
  111. static Material s_Internal_Bitmap_RGBA_Material;
  112. private static string[] s_UiStateLabel = new string[] { "<i>(Click to collapse)</i> ", "<i>(Click to expand)</i> " };
  113. public static readonly GUIContent getFontFeaturesLabel = new GUIContent("Get Font Features", "Determines if OpenType font features should be retrieved from the source font file as new characters and glyphs are added to the font asset.");
  114. 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") };
  115. private int[] m_AtlasResolutions = { 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
  116. private struct Warning
  117. {
  118. public bool isEnabled;
  119. public double expirationTime;
  120. }
  121. private int m_CurrentGlyphPage = 0;
  122. private int m_CurrentCharacterPage = 0;
  123. private int m_CurrentLigaturePage = 0;
  124. private int m_CurrentAdjustmentPairPage = 0;
  125. private int m_CurrentMarkToBasePage = 0;
  126. private int m_CurrentMarkToMarkPage = 0;
  127. private int m_SelectedGlyphRecord = -1;
  128. private int m_SelectedCharacterRecord = -1;
  129. private int m_SelectedLigatureRecord = -1;
  130. private int m_SelectedAdjustmentRecord = -1;
  131. private int m_SelectedMarkToBaseRecord = -1;
  132. private int m_SelectedMarkToMarkRecord = -1;
  133. enum RecordSelectionType { CharacterRecord, GlyphRecord, LigatureSubstitutionRecord, AdjustmentPairRecord, MarkToBaseRecord, MarkToMarkRecord }
  134. private string m_dstGlyphID;
  135. private string m_dstUnicode;
  136. private const string k_placeholderUnicodeHex = "<i>New Unicode (Hex)</i>";
  137. private string m_unicodeHexLabel = k_placeholderUnicodeHex;
  138. private const string k_placeholderGlyphID = "<i>New Glyph ID</i>";
  139. private string m_GlyphIDLabel = k_placeholderGlyphID;
  140. private Warning m_AddGlyphWarning;
  141. private Warning m_AddCharacterWarning;
  142. private bool m_DisplayDestructiveChangeWarning;
  143. private GenerationSettings m_GenerationSettings;
  144. private bool m_MaterialPresetsRequireUpdate;
  145. private static readonly string[] k_InvalidFontFaces = { string.Empty };
  146. private string[] m_FontFaces;
  147. private bool m_FaceInfoDirty;
  148. private string m_GlyphSearchPattern;
  149. private List<int> m_GlyphSearchList;
  150. private string m_CharacterSearchPattern;
  151. private List<int> m_CharacterSearchList;
  152. private string m_LigatureTableSearchPattern;
  153. private List<int> m_LigatureTableSearchList;
  154. private string m_KerningTableSearchPattern;
  155. private List<int> m_KerningTableSearchList;
  156. private string m_MarkToBaseTableSearchPattern;
  157. private List<int> m_MarkToBaseTableSearchList;
  158. private string m_MarkToMarkTableSearchPattern;
  159. private List<int> m_MarkToMarkTableSearchList;
  160. private HashSet<uint> m_GlyphsToAdd;
  161. private bool m_isSearchDirty;
  162. private const string k_UndoRedo = "UndoRedoPerformed";
  163. private SerializedProperty m_AtlasPopulationMode_prop;
  164. private SerializedProperty font_atlas_prop;
  165. private SerializedProperty font_material_prop;
  166. private SerializedProperty m_FontFaceIndex_prop;
  167. private SerializedProperty m_AtlasRenderMode_prop;
  168. private SerializedProperty m_SamplingPointSize_prop;
  169. private SerializedProperty m_AtlasPadding_prop;
  170. private SerializedProperty m_AtlasWidth_prop;
  171. private SerializedProperty m_AtlasHeight_prop;
  172. private SerializedProperty m_IsMultiAtlasTexturesEnabled_prop;
  173. private SerializedProperty m_ClearDynamicDataOnBuild_prop;
  174. private SerializedProperty m_GetFontFeatures_prop;
  175. private SerializedProperty fontWeights_prop;
  176. //private SerializedProperty fallbackFontAssets_prop;
  177. private ReorderableList m_FallbackFontAssetList;
  178. private SerializedProperty font_normalStyle_prop;
  179. private SerializedProperty font_normalSpacing_prop;
  180. private SerializedProperty font_boldStyle_prop;
  181. private SerializedProperty font_boldSpacing_prop;
  182. private SerializedProperty font_italicStyle_prop;
  183. private SerializedProperty font_tabSize_prop;
  184. private SerializedProperty m_FaceInfo_prop;
  185. private SerializedProperty m_GlyphTable_prop;
  186. private SerializedProperty m_CharacterTable_prop;
  187. private TMP_FontFeatureTable m_FontFeatureTable;
  188. private SerializedProperty m_FontFeatureTable_prop;
  189. private SerializedProperty m_LigatureSubstitutionRecords_prop;
  190. private SerializedProperty m_GlyphPairAdjustmentRecords_prop;
  191. private SerializedProperty m_MarkToBaseAdjustmentRecords_prop;
  192. private SerializedProperty m_MarkToMarkAdjustmentRecords_prop;
  193. private TMP_SerializedPropertyHolder m_SerializedPropertyHolder;
  194. private SerializedProperty m_EmptyGlyphPairAdjustmentRecord_prop;
  195. private SerializedProperty m_FirstCharacterUnicode_prop;
  196. private SerializedProperty m_SecondCharacterUnicode_prop;
  197. private TMP_FontAsset m_fontAsset;
  198. private Material[] m_materialPresets;
  199. private bool isAssetDirty = false;
  200. private bool m_IsFallbackGlyphCacheDirty;
  201. private int errorCode;
  202. private System.DateTime timeStamp;
  203. public void OnEnable()
  204. {
  205. m_FaceInfo_prop = serializedObject.FindProperty("m_FaceInfo");
  206. font_atlas_prop = serializedObject.FindProperty("m_AtlasTextures").GetArrayElementAtIndex(0);
  207. font_material_prop = serializedObject.FindProperty("m_Material");
  208. m_FontFaceIndex_prop = m_FaceInfo_prop.FindPropertyRelative("m_FaceIndex");
  209. m_AtlasPopulationMode_prop = serializedObject.FindProperty("m_AtlasPopulationMode");
  210. m_AtlasRenderMode_prop = serializedObject.FindProperty("m_AtlasRenderMode");
  211. m_SamplingPointSize_prop = m_FaceInfo_prop.FindPropertyRelative("m_PointSize");
  212. m_AtlasPadding_prop = serializedObject.FindProperty("m_AtlasPadding");
  213. m_AtlasWidth_prop = serializedObject.FindProperty("m_AtlasWidth");
  214. m_AtlasHeight_prop = serializedObject.FindProperty("m_AtlasHeight");
  215. m_IsMultiAtlasTexturesEnabled_prop = serializedObject.FindProperty("m_IsMultiAtlasTexturesEnabled");
  216. m_ClearDynamicDataOnBuild_prop = serializedObject.FindProperty("m_ClearDynamicDataOnBuild");
  217. m_GetFontFeatures_prop = serializedObject.FindProperty("m_GetFontFeatures");
  218. fontWeights_prop = serializedObject.FindProperty("m_FontWeightTable");
  219. m_FallbackFontAssetList = PrepareReorderableList(serializedObject.FindProperty("m_FallbackFontAssetTable"), "Fallback Font Assets");
  220. // Clean up fallback list in the event if contains null elements.
  221. CleanFallbackFontAssetTable();
  222. font_normalStyle_prop = serializedObject.FindProperty("normalStyle");
  223. font_normalSpacing_prop = serializedObject.FindProperty("normalSpacingOffset");
  224. font_boldStyle_prop = serializedObject.FindProperty("boldStyle");
  225. font_boldSpacing_prop = serializedObject.FindProperty("boldSpacing");
  226. font_italicStyle_prop = serializedObject.FindProperty("italicStyle");
  227. font_tabSize_prop = serializedObject.FindProperty("tabSize");
  228. m_CharacterTable_prop = serializedObject.FindProperty("m_CharacterTable");
  229. m_GlyphTable_prop = serializedObject.FindProperty("m_GlyphTable");
  230. m_FontFeatureTable_prop = serializedObject.FindProperty("m_FontFeatureTable");
  231. m_LigatureSubstitutionRecords_prop = m_FontFeatureTable_prop.FindPropertyRelative("m_LigatureSubstitutionRecords");
  232. m_GlyphPairAdjustmentRecords_prop = m_FontFeatureTable_prop.FindPropertyRelative("m_GlyphPairAdjustmentRecords");
  233. m_MarkToBaseAdjustmentRecords_prop = m_FontFeatureTable_prop.FindPropertyRelative("m_MarkToBaseAdjustmentRecords");
  234. m_MarkToMarkAdjustmentRecords_prop = m_FontFeatureTable_prop.FindPropertyRelative("m_MarkToMarkAdjustmentRecords");
  235. m_fontAsset = target as TMP_FontAsset;
  236. m_FontFeatureTable = m_fontAsset.fontFeatureTable;
  237. // Get Font Faces and Styles
  238. m_FontFaces = GetFontFaces();
  239. // Upgrade Font Feature Table if necessary
  240. if (m_fontAsset.m_KerningTable != null && m_fontAsset.m_KerningTable.kerningPairs != null && m_fontAsset.m_KerningTable.kerningPairs.Count > 0)
  241. m_fontAsset.ReadFontAssetDefinition();
  242. // Create serialized object to allow us to use a serialized property of an empty kerning pair.
  243. m_SerializedPropertyHolder = CreateInstance<TMP_SerializedPropertyHolder>();
  244. m_SerializedPropertyHolder.fontAsset = m_fontAsset;
  245. SerializedObject internalSerializedObject = new SerializedObject(m_SerializedPropertyHolder);
  246. m_FirstCharacterUnicode_prop = internalSerializedObject.FindProperty("firstCharacter");
  247. m_SecondCharacterUnicode_prop = internalSerializedObject.FindProperty("secondCharacter");
  248. m_EmptyGlyphPairAdjustmentRecord_prop = internalSerializedObject.FindProperty("glyphPairAdjustmentRecord");
  249. m_materialPresets = TMP_EditorUtility.FindMaterialReferences(m_fontAsset);
  250. m_GlyphSearchList = new List<int>();
  251. m_KerningTableSearchList = new List<int>();
  252. // Sort Font Asset Tables
  253. m_fontAsset.SortAllTables();
  254. // Clear glyph proxy lookups
  255. TMP_PropertyDrawerUtilities.ClearGlyphProxyLookups();
  256. }
  257. private ReorderableList PrepareReorderableList(SerializedProperty property, string label)
  258. {
  259. SerializedObject so = property.serializedObject;
  260. ReorderableList list = new ReorderableList(so, property, true, true, true, true);
  261. list.drawHeaderCallback = rect =>
  262. {
  263. EditorGUI.LabelField(rect, label);
  264. };
  265. list.drawElementCallback = (rect, index, isActive, isFocused) =>
  266. {
  267. var element = list.serializedProperty.GetArrayElementAtIndex(index);
  268. rect.y += 2;
  269. EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
  270. };
  271. list.onChangedCallback = itemList => { };
  272. return list;
  273. }
  274. public void OnDisable()
  275. {
  276. // Revert changes if user closes or changes selection without having made a choice.
  277. if (m_DisplayDestructiveChangeWarning)
  278. {
  279. m_DisplayDestructiveChangeWarning = false;
  280. RestoreGenerationSettings();
  281. GUIUtility.keyboardControl = 0;
  282. serializedObject.ApplyModifiedProperties();
  283. }
  284. }
  285. public override void OnInspectorGUI()
  286. {
  287. //Debug.Log("OnInspectorGUI Called.");
  288. Event currentEvent = Event.current;
  289. serializedObject.Update();
  290. Rect rect = EditorGUILayout.GetControlRect(false, 24);
  291. float labelWidth = EditorGUIUtility.labelWidth;
  292. float fieldWidth = EditorGUIUtility.fieldWidth;
  293. // FACE INFO PANEL
  294. #region Face info
  295. GUI.Label(rect, new GUIContent("<b>Face Info</b> - v" + m_fontAsset.version), TMP_UIStyleManager.sectionHeader);
  296. rect.x += rect.width - 132f;
  297. rect.y += 2;
  298. rect.width = 130f;
  299. rect.height = 18f;
  300. if (GUI.Button(rect, new GUIContent("Update Atlas Texture")))
  301. {
  302. TMPro_FontAssetCreatorWindow.ShowFontAtlasCreatorWindow(target as TMP_FontAsset);
  303. }
  304. EditorGUI.indentLevel = 1;
  305. GUI.enabled = false; // Lock UI
  306. // TODO : Consider creating a property drawer for these.
  307. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_FamilyName"));
  308. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_StyleName"));
  309. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_PointSize"));
  310. GUI.enabled = true;
  311. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_Scale"));
  312. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_LineHeight"));
  313. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_AscentLine"));
  314. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_CapLine"));
  315. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_MeanLine"));
  316. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_Baseline"));
  317. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_DescentLine"));
  318. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_UnderlineOffset"));
  319. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_UnderlineThickness"));
  320. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_StrikethroughOffset"));
  321. //EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("strikethroughThickness"));
  322. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_SuperscriptOffset"));
  323. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_SuperscriptSize"));
  324. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_SubscriptOffset"));
  325. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_SubscriptSize"));
  326. EditorGUILayout.PropertyField(m_FaceInfo_prop.FindPropertyRelative("m_TabWidth"));
  327. // TODO : Add clamping for some of these values.
  328. //subSize_prop.floatValue = Mathf.Clamp(subSize_prop.floatValue, 0.25f, 1f);
  329. EditorGUILayout.Space();
  330. #endregion
  331. // GENERATION SETTINGS
  332. #region Generation Settings
  333. rect = EditorGUILayout.GetControlRect(false, 24);
  334. if (GUI.Button(rect, new GUIContent("<b>Generation Settings</b>"), TMP_UIStyleManager.sectionHeader))
  335. UI_PanelState.generationSettingsPanel = !UI_PanelState.generationSettingsPanel;
  336. GUI.Label(rect, (UI_PanelState.generationSettingsPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  337. if (UI_PanelState.generationSettingsPanel)
  338. {
  339. EditorGUI.indentLevel = 1;
  340. EditorGUI.BeginChangeCheck();
  341. Font sourceFont = (Font)EditorGUILayout.ObjectField("Source Font File", m_fontAsset.SourceFont_EditorRef, typeof(Font), false);
  342. if (EditorGUI.EndChangeCheck())
  343. {
  344. m_GenerationSettings.sourceFont = m_fontAsset.SourceFont_EditorRef;
  345. m_fontAsset.SourceFont_EditorRef = sourceFont;
  346. m_FontFaces = GetFontFaces(0);
  347. m_FaceInfoDirty = true;
  348. m_DisplayDestructiveChangeWarning = true;
  349. //m_MaterialPresetsRequireUpdate = true;
  350. }
  351. EditorGUI.BeginDisabledGroup(sourceFont == null);
  352. {
  353. EditorGUI.BeginChangeCheck();
  354. m_FontFaceIndex_prop.intValue = EditorGUILayout.Popup(new GUIContent("Font Face"), m_FontFaceIndex_prop.intValue, m_FontFaces);
  355. if (EditorGUI.EndChangeCheck())
  356. {
  357. m_MaterialPresetsRequireUpdate = true;
  358. m_DisplayDestructiveChangeWarning = true;
  359. m_FaceInfoDirty = true;
  360. }
  361. EditorGUI.BeginChangeCheck();
  362. EditorGUILayout.PropertyField(m_AtlasPopulationMode_prop, new GUIContent("Atlas Population Mode"));
  363. if (EditorGUI.EndChangeCheck())
  364. {
  365. serializedObject.ApplyModifiedProperties();
  366. bool isDatabaseRefreshRequired = false;
  367. // Static font asset
  368. if (m_AtlasPopulationMode_prop.intValue == 0)
  369. {
  370. m_fontAsset.sourceFontFile = null;
  371. //Set atlas textures to non readable.
  372. for (int i = 0; i < m_fontAsset.atlasTextures.Length; i++)
  373. {
  374. Texture2D tex = m_fontAsset.atlasTextures[i];
  375. if (tex != null && tex.isReadable)
  376. FontEngineEditorUtilities.SetAtlasTextureIsReadable(tex, false);
  377. }
  378. //Debug.Log("Atlas Population mode set to [Static].");
  379. }
  380. else // Dynamic font asset
  381. {
  382. if (m_fontAsset.m_SourceFontFile_EditorRef.dynamic == false)
  383. {
  384. 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);
  385. m_AtlasPopulationMode_prop.intValue = 0;
  386. serializedObject.ApplyModifiedProperties();
  387. }
  388. else
  389. {
  390. m_fontAsset.sourceFontFile = m_fontAsset.m_SourceFontFile_EditorRef;
  391. // Set atlas textures to non readable.
  392. for (int i = 0; i < m_fontAsset.atlasTextures.Length; i++)
  393. {
  394. Texture2D tex = m_fontAsset.atlasTextures[i];
  395. if (tex != null && tex.isReadable == false)
  396. FontEngineEditorUtilities.SetAtlasTextureIsReadable(tex, true);
  397. }
  398. //Debug.Log("Atlas Population mode set to [" + (m_AtlasPopulationMode_prop.intValue == 1 ? "Dynamic" : "Dynamic OS") + "].");
  399. }
  400. // Dynamic OS font asset
  401. if (m_AtlasPopulationMode_prop.intValue == 2)
  402. m_fontAsset.sourceFontFile = null;
  403. }
  404. if (isDatabaseRefreshRequired)
  405. AssetDatabase.Refresh();
  406. serializedObject.Update();
  407. isAssetDirty = true;
  408. }
  409. // Save state of atlas settings
  410. if (m_DisplayDestructiveChangeWarning == false)
  411. {
  412. SavedGenerationSettings();
  413. //Undo.RegisterCompleteObjectUndo(m_fontAsset, "Font Asset Changes");
  414. }
  415. EditorGUI.BeginDisabledGroup(m_AtlasPopulationMode_prop.intValue == (int)AtlasPopulationMode.Static);
  416. {
  417. EditorGUI.BeginChangeCheck();
  418. // TODO: Switch shaders depending on GlyphRenderMode.
  419. EditorGUILayout.PropertyField(m_AtlasRenderMode_prop);
  420. EditorGUILayout.PropertyField(m_SamplingPointSize_prop, new GUIContent("Sampling Point Size"));
  421. if (EditorGUI.EndChangeCheck())
  422. {
  423. m_DisplayDestructiveChangeWarning = true;
  424. }
  425. // Changes to these properties require updating Material Presets for this font asset.
  426. EditorGUI.BeginChangeCheck();
  427. EditorGUILayout.PropertyField(m_AtlasPadding_prop, new GUIContent("Padding"));
  428. EditorGUILayout.IntPopup(m_AtlasWidth_prop, m_AtlasResolutionLabels, m_AtlasResolutions, new GUIContent("Atlas Width"));
  429. EditorGUILayout.IntPopup(m_AtlasHeight_prop, m_AtlasResolutionLabels, m_AtlasResolutions, new GUIContent("Atlas Height"));
  430. EditorGUILayout.PropertyField(m_IsMultiAtlasTexturesEnabled_prop, new GUIContent("Multi Atlas Textures", "Determines if the font asset will store glyphs in multiple atlas textures."));
  431. if (EditorGUI.EndChangeCheck())
  432. {
  433. if (m_AtlasPadding_prop.intValue < 0)
  434. {
  435. m_AtlasPadding_prop.intValue = 0;
  436. serializedObject.ApplyModifiedProperties();
  437. }
  438. m_MaterialPresetsRequireUpdate = true;
  439. m_DisplayDestructiveChangeWarning = true;
  440. }
  441. 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."));
  442. EditorGUILayout.PropertyField(m_GetFontFeatures_prop, getFontFeaturesLabel);
  443. EditorGUILayout.Space();
  444. if (m_DisplayDestructiveChangeWarning)
  445. {
  446. bool guiEnabledState = GUI.enabled;
  447. GUI.enabled = true;
  448. // These changes are destructive on the font asset
  449. rect = EditorGUILayout.GetControlRect(false, 60);
  450. rect.x += 15;
  451. rect.width -= 15;
  452. EditorGUI.HelpBox(rect, "Changing these settings will clear the font asset's character, glyph and texture data.", MessageType.Warning);
  453. if (GUI.Button(new Rect(rect.width - 140, rect.y + 36, 80, 18), new GUIContent("Apply")))
  454. {
  455. m_DisplayDestructiveChangeWarning = false;
  456. // Update face info if sampling point size was changed.
  457. #if UNITY_2023_3_OR_NEWER
  458. if (m_GenerationSettings.pointSize != m_SamplingPointSize_prop.floatValue || m_FaceInfoDirty)
  459. {
  460. LoadFontFace((int)m_SamplingPointSize_prop.floatValue, m_FontFaceIndex_prop.intValue);
  461. #else
  462. if (m_GenerationSettings.pointSize != m_SamplingPointSize_prop.intValue || m_FaceInfoDirty)
  463. {
  464. LoadFontFace(m_SamplingPointSize_prop.intValue, m_FontFaceIndex_prop.intValue);
  465. #endif
  466. m_fontAsset.faceInfo = FontEngine.GetFaceInfo();
  467. m_FaceInfoDirty = false;
  468. }
  469. Material mat = m_fontAsset.material;
  470. // Update material
  471. mat.SetFloat(ShaderUtilities.ID_TextureWidth, m_AtlasWidth_prop.intValue);
  472. mat.SetFloat(ShaderUtilities.ID_TextureHeight, m_AtlasHeight_prop.intValue);
  473. if (mat.HasProperty(ShaderUtilities.ID_GradientScale))
  474. mat.SetFloat(ShaderUtilities.ID_GradientScale, m_AtlasPadding_prop.intValue + 1);
  475. // Update material presets if any of the relevant properties have been changed.
  476. if (m_MaterialPresetsRequireUpdate)
  477. {
  478. m_MaterialPresetsRequireUpdate = false;
  479. Material[] materialPresets = TMP_EditorUtility.FindMaterialReferences(m_fontAsset);
  480. for (int i = 0; i < materialPresets.Length; i++)
  481. {
  482. mat = materialPresets[i];
  483. mat.SetFloat(ShaderUtilities.ID_TextureWidth, m_AtlasWidth_prop.intValue);
  484. mat.SetFloat(ShaderUtilities.ID_TextureHeight, m_AtlasHeight_prop.intValue);
  485. if (mat.HasProperty(ShaderUtilities.ID_GradientScale))
  486. mat.SetFloat(ShaderUtilities.ID_GradientScale, m_AtlasPadding_prop.intValue + 1);
  487. }
  488. }
  489. m_fontAsset.UpdateFontAssetData();
  490. GUIUtility.keyboardControl = 0;
  491. isAssetDirty = true;
  492. // Update Font Asset Creation Settings to reflect new changes.
  493. UpdateFontAssetCreationSettings();
  494. // TODO: Clear undo buffers.
  495. //Undo.ClearUndo(m_fontAsset);
  496. }
  497. if (GUI.Button(new Rect(rect.width - 56, rect.y + 36, 80, 18), new GUIContent("Revert")))
  498. {
  499. m_DisplayDestructiveChangeWarning = false;
  500. RestoreGenerationSettings();
  501. GUIUtility.keyboardControl = 0;
  502. // TODO: Clear undo buffers.
  503. //Undo.ClearUndo(m_fontAsset);
  504. }
  505. GUI.enabled = guiEnabledState;
  506. }
  507. }
  508. EditorGUI.EndDisabledGroup();
  509. }
  510. EditorGUI.EndDisabledGroup();
  511. EditorGUILayout.Space();
  512. }
  513. #endregion
  514. // ATLAS & MATERIAL PANEL
  515. #region Atlas & Material
  516. rect = EditorGUILayout.GetControlRect(false, 24);
  517. if (GUI.Button(rect, new GUIContent("<b>Atlas & Material</b>"), TMP_UIStyleManager.sectionHeader))
  518. UI_PanelState.fontAtlasInfoPanel = !UI_PanelState.fontAtlasInfoPanel;
  519. GUI.Label(rect, (UI_PanelState.fontAtlasInfoPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  520. if (UI_PanelState.fontAtlasInfoPanel)
  521. {
  522. EditorGUI.indentLevel = 1;
  523. GUI.enabled = false;
  524. EditorGUILayout.PropertyField(font_atlas_prop, new GUIContent("Font Atlas"));
  525. EditorGUILayout.PropertyField(font_material_prop, new GUIContent("Font Material"));
  526. GUI.enabled = true;
  527. EditorGUILayout.Space();
  528. }
  529. #endregion
  530. string evt_cmd = Event.current.commandName; // Get Current Event CommandName to check for Undo Events
  531. // FONT WEIGHT PANEL
  532. #region Font Weights
  533. rect = EditorGUILayout.GetControlRect(false, 24);
  534. 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))
  535. UI_PanelState.fontWeightPanel = !UI_PanelState.fontWeightPanel;
  536. GUI.Label(rect, (UI_PanelState.fontWeightPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  537. if (UI_PanelState.fontWeightPanel)
  538. {
  539. EditorGUIUtility.labelWidth *= 0.75f;
  540. EditorGUIUtility.fieldWidth *= 0.25f;
  541. EditorGUILayout.BeginVertical();
  542. EditorGUI.indentLevel = 1;
  543. rect = EditorGUILayout.GetControlRect(true);
  544. rect.x += EditorGUIUtility.labelWidth;
  545. rect.width = (rect.width - EditorGUIUtility.labelWidth) / 2f;
  546. GUI.Label(rect, "Regular Typeface", EditorStyles.label);
  547. rect.x += rect.width;
  548. GUI.Label(rect, "Italic Typeface", EditorStyles.label);
  549. EditorGUI.indentLevel = 1;
  550. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(1), new GUIContent("100 - Thin"));
  551. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(2), new GUIContent("200 - Extra-Light"));
  552. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(3), new GUIContent("300 - Light"));
  553. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(4), new GUIContent("400 - Regular"));
  554. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(5), new GUIContent("500 - Medium"));
  555. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(6), new GUIContent("600 - Semi-Bold"));
  556. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(7), new GUIContent("700 - Bold"));
  557. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(8), new GUIContent("800 - Heavy"));
  558. EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(9), new GUIContent("900 - Black"));
  559. EditorGUILayout.EndVertical();
  560. EditorGUILayout.Space();
  561. EditorGUILayout.BeginVertical();
  562. EditorGUILayout.BeginHorizontal();
  563. EditorGUILayout.PropertyField(font_normalStyle_prop, new GUIContent("Normal Weight"));
  564. font_normalStyle_prop.floatValue = Mathf.Clamp(font_normalStyle_prop.floatValue, -3.0f, 3.0f);
  565. if (GUI.changed || evt_cmd == k_UndoRedo)
  566. {
  567. GUI.changed = false;
  568. // Modify the material property on matching material presets.
  569. for (int i = 0; i < m_materialPresets.Length; i++)
  570. m_materialPresets[i].SetFloat("_WeightNormal", font_normalStyle_prop.floatValue);
  571. }
  572. EditorGUILayout.PropertyField(font_boldStyle_prop, new GUIContent("Bold Weight"));
  573. font_boldStyle_prop.floatValue = Mathf.Clamp(font_boldStyle_prop.floatValue, -3.0f, 3.0f);
  574. if (GUI.changed || evt_cmd == k_UndoRedo)
  575. {
  576. GUI.changed = false;
  577. // Modify the material property on matching material presets.
  578. for (int i = 0; i < m_materialPresets.Length; i++)
  579. m_materialPresets[i].SetFloat("_WeightBold", font_boldStyle_prop.floatValue);
  580. }
  581. EditorGUILayout.EndHorizontal();
  582. EditorGUILayout.BeginHorizontal();
  583. EditorGUILayout.PropertyField(font_normalSpacing_prop, new GUIContent("Spacing Offset"));
  584. font_normalSpacing_prop.floatValue = Mathf.Clamp(font_normalSpacing_prop.floatValue, -100, 100);
  585. if (GUI.changed || evt_cmd == k_UndoRedo)
  586. {
  587. GUI.changed = false;
  588. }
  589. EditorGUILayout.PropertyField(font_boldSpacing_prop, new GUIContent("Bold Spacing"));
  590. font_boldSpacing_prop.floatValue = Mathf.Clamp(font_boldSpacing_prop.floatValue, 0, 100);
  591. if (GUI.changed || evt_cmd == k_UndoRedo)
  592. {
  593. GUI.changed = false;
  594. }
  595. EditorGUILayout.EndHorizontal();
  596. EditorGUILayout.BeginHorizontal();
  597. EditorGUILayout.PropertyField(font_italicStyle_prop, new GUIContent("Italic Style"));
  598. font_italicStyle_prop.intValue = Mathf.Clamp(font_italicStyle_prop.intValue, 15, 60);
  599. EditorGUILayout.PropertyField(font_tabSize_prop, new GUIContent("Tab Multiple"));
  600. EditorGUILayout.EndHorizontal();
  601. EditorGUILayout.EndVertical();
  602. EditorGUILayout.Space();
  603. }
  604. EditorGUIUtility.labelWidth = 0;
  605. EditorGUIUtility.fieldWidth = 0;
  606. #endregion
  607. // FALLBACK FONT ASSETS
  608. #region Fallback Font Asset
  609. rect = EditorGUILayout.GetControlRect(false, 24);
  610. EditorGUI.indentLevel = 0;
  611. 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))
  612. UI_PanelState.fallbackFontAssetPanel = !UI_PanelState.fallbackFontAssetPanel;
  613. GUI.Label(rect, (UI_PanelState.fallbackFontAssetPanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  614. if (UI_PanelState.fallbackFontAssetPanel)
  615. {
  616. EditorGUIUtility.labelWidth = 120;
  617. EditorGUI.indentLevel = 0;
  618. EditorGUI.BeginChangeCheck();
  619. m_FallbackFontAssetList.DoLayoutList();
  620. if (EditorGUI.EndChangeCheck())
  621. {
  622. m_IsFallbackGlyphCacheDirty = true;
  623. }
  624. EditorGUILayout.Space();
  625. }
  626. #endregion
  627. // CHARACTER TABLE TABLE
  628. #region Character Table
  629. EditorGUIUtility.labelWidth = labelWidth;
  630. EditorGUIUtility.fieldWidth = fieldWidth;
  631. EditorGUI.indentLevel = 0;
  632. rect = EditorGUILayout.GetControlRect(false, 24);
  633. int characterCount = m_fontAsset.characterTable.Count;
  634. 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))
  635. UI_PanelState.characterTablePanel = !UI_PanelState.characterTablePanel;
  636. GUI.Label(rect, (UI_PanelState.characterTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  637. if (UI_PanelState.characterTablePanel)
  638. {
  639. int arraySize = m_CharacterTable_prop.arraySize;
  640. int itemsPerPage = 15;
  641. // Display Glyph Management Tools
  642. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  643. {
  644. // Search Bar implementation
  645. #region DISPLAY SEARCH BAR
  646. EditorGUILayout.BeginHorizontal();
  647. {
  648. EditorGUIUtility.labelWidth = 130f;
  649. EditorGUI.BeginChangeCheck();
  650. string searchPattern = EditorGUILayout.TextField("Character Search", m_CharacterSearchPattern, "SearchTextField");
  651. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  652. {
  653. if (string.IsNullOrEmpty(searchPattern) == false)
  654. {
  655. m_CharacterSearchPattern = searchPattern;
  656. // Search Character Table for potential matches
  657. SearchCharacterTable(m_CharacterSearchPattern, ref m_CharacterSearchList);
  658. }
  659. else
  660. m_CharacterSearchPattern = null;
  661. m_isSearchDirty = false;
  662. }
  663. string styleName = string.IsNullOrEmpty(m_CharacterSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  664. if (GUILayout.Button(GUIContent.none, styleName))
  665. {
  666. GUIUtility.keyboardControl = 0;
  667. m_CharacterSearchPattern = string.Empty;
  668. }
  669. }
  670. EditorGUILayout.EndHorizontal();
  671. #endregion
  672. // Display Page Navigation
  673. if (!string.IsNullOrEmpty(m_CharacterSearchPattern))
  674. arraySize = m_CharacterSearchList.Count;
  675. DisplayPageNavigation(ref m_CurrentCharacterPage, arraySize, itemsPerPage);
  676. }
  677. EditorGUILayout.EndVertical();
  678. // Display Character Table Elements
  679. if (arraySize > 0)
  680. {
  681. // Display each character entry using the CharacterPropertyDrawer.
  682. for (int i = itemsPerPage * m_CurrentCharacterPage; i < arraySize && i < itemsPerPage * (m_CurrentCharacterPage + 1); i++)
  683. {
  684. // Define the start of the selection region of the element.
  685. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  686. int elementIndex = i;
  687. if (!string.IsNullOrEmpty(m_CharacterSearchPattern))
  688. elementIndex = m_CharacterSearchList[i];
  689. SerializedProperty characterProperty = m_CharacterTable_prop.GetArrayElementAtIndex(elementIndex);
  690. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  691. EditorGUI.BeginDisabledGroup(i != m_SelectedCharacterRecord);
  692. {
  693. EditorGUILayout.PropertyField(characterProperty);
  694. }
  695. EditorGUI.EndDisabledGroup();
  696. EditorGUILayout.EndVertical();
  697. // Define the end of the selection region of the element.
  698. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  699. // Check for Item selection
  700. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  701. if (DoSelectionCheck(selectionArea))
  702. {
  703. if (m_SelectedCharacterRecord == i)
  704. m_SelectedCharacterRecord = -1;
  705. else
  706. {
  707. m_SelectedCharacterRecord = i;
  708. m_AddCharacterWarning.isEnabled = false;
  709. m_unicodeHexLabel = k_placeholderUnicodeHex;
  710. GUIUtility.keyboardControl = 0;
  711. }
  712. }
  713. // Draw Selection Highlight and Glyph Options
  714. if (m_SelectedCharacterRecord == i)
  715. {
  716. // Reset other selections
  717. ResetSelections(RecordSelectionType.CharacterRecord);
  718. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  719. // Draw Glyph management options
  720. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  721. float optionAreaWidth = controlRect.width * 0.6f;
  722. float btnWidth = optionAreaWidth / 3;
  723. Rect position = new Rect(controlRect.x + controlRect.width * .4f, controlRect.y, btnWidth, controlRect.height);
  724. // Copy Selected Glyph to Target Glyph ID
  725. GUI.enabled = !string.IsNullOrEmpty(m_dstUnicode);
  726. if (GUI.Button(position, new GUIContent("Copy to")))
  727. {
  728. GUIUtility.keyboardControl = 0;
  729. // Convert Hex Value to Decimal
  730. int dstGlyphID = TMP_TextUtilities.StringHexToInt(m_dstUnicode);
  731. //Add new glyph at target Unicode hex id.
  732. if (!AddNewCharacter(elementIndex, dstGlyphID))
  733. {
  734. m_AddCharacterWarning.isEnabled = true;
  735. m_AddCharacterWarning.expirationTime = EditorApplication.timeSinceStartup + 1;
  736. }
  737. m_dstUnicode = string.Empty;
  738. m_isSearchDirty = true;
  739. TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, m_fontAsset);
  740. }
  741. // Target Glyph ID
  742. GUI.enabled = true;
  743. position.x += btnWidth;
  744. GUI.SetNextControlName("CharacterID_Input");
  745. m_dstUnicode = EditorGUI.TextField(position, m_dstUnicode);
  746. // Placeholder text
  747. EditorGUI.LabelField(position, new GUIContent(m_unicodeHexLabel, "The Unicode (Hex) ID of the duplicated Character"), TMP_UIStyleManager.label);
  748. // Only filter the input when the destination glyph ID text field has focus.
  749. if (GUI.GetNameOfFocusedControl() == "CharacterID_Input")
  750. {
  751. m_unicodeHexLabel = string.Empty;
  752. //Filter out unwanted characters.
  753. char chr = Event.current.character;
  754. if ((chr < '0' || chr > '9') && (chr < 'a' || chr > 'f') && (chr < 'A' || chr > 'F'))
  755. {
  756. Event.current.character = '\0';
  757. }
  758. }
  759. else
  760. {
  761. m_unicodeHexLabel = k_placeholderUnicodeHex;
  762. //m_dstUnicode = string.Empty;
  763. }
  764. // Remove Glyph
  765. position.x += btnWidth;
  766. if (GUI.Button(position, "Remove"))
  767. {
  768. GUIUtility.keyboardControl = 0;
  769. RemoveCharacterFromList(elementIndex);
  770. isAssetDirty = true;
  771. m_SelectedCharacterRecord = -1;
  772. m_isSearchDirty = true;
  773. break;
  774. }
  775. if (m_AddCharacterWarning.isEnabled && EditorApplication.timeSinceStartup < m_AddCharacterWarning.expirationTime)
  776. {
  777. EditorGUILayout.HelpBox("The Destination Character ID already exists", MessageType.Warning);
  778. }
  779. }
  780. }
  781. }
  782. DisplayPageNavigation(ref m_CurrentCharacterPage, arraySize, itemsPerPage);
  783. EditorGUILayout.Space();
  784. }
  785. #endregion
  786. // GLYPH TABLE
  787. #region Glyph Table
  788. EditorGUIUtility.labelWidth = labelWidth;
  789. EditorGUIUtility.fieldWidth = fieldWidth;
  790. EditorGUI.indentLevel = 0;
  791. rect = EditorGUILayout.GetControlRect(false, 24);
  792. GUIStyle glyphPanelStyle = new GUIStyle(EditorStyles.helpBox);
  793. int glyphRecordCount = m_fontAsset.glyphTable.Count;
  794. if (GUI.Button(rect, new GUIContent("<b>Glyph Table</b> [" + glyphRecordCount + "]" + (rect.width > 275 ? " Glyphs" : ""), "List of glyphs contained in this font asset."), TMP_UIStyleManager.sectionHeader))
  795. UI_PanelState.glyphTablePanel = !UI_PanelState.glyphTablePanel;
  796. GUI.Label(rect, (UI_PanelState.glyphTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  797. if (UI_PanelState.glyphTablePanel)
  798. {
  799. int arraySize = m_GlyphTable_prop.arraySize;
  800. int itemsPerPage = 15;
  801. // Display Glyph Management Tools
  802. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  803. {
  804. // Search Bar implementation
  805. #region DISPLAY SEARCH BAR
  806. EditorGUILayout.BeginHorizontal();
  807. {
  808. EditorGUIUtility.labelWidth = 130f;
  809. EditorGUI.BeginChangeCheck();
  810. string searchPattern = EditorGUILayout.TextField("Glyph Search", m_GlyphSearchPattern, "SearchTextField");
  811. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  812. {
  813. if (string.IsNullOrEmpty(searchPattern) == false)
  814. {
  815. m_GlyphSearchPattern = searchPattern;
  816. // Search Glyph Table for potential matches
  817. SearchGlyphTable(m_GlyphSearchPattern, ref m_GlyphSearchList);
  818. }
  819. else
  820. m_GlyphSearchPattern = null;
  821. m_isSearchDirty = false;
  822. }
  823. string styleName = string.IsNullOrEmpty(m_GlyphSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  824. if (GUILayout.Button(GUIContent.none, styleName))
  825. {
  826. GUIUtility.keyboardControl = 0;
  827. m_GlyphSearchPattern = string.Empty;
  828. }
  829. }
  830. EditorGUILayout.EndHorizontal();
  831. #endregion
  832. // Display Page Navigation
  833. if (!string.IsNullOrEmpty(m_GlyphSearchPattern))
  834. arraySize = m_GlyphSearchList.Count;
  835. DisplayPageNavigation(ref m_CurrentGlyphPage, arraySize, itemsPerPage);
  836. }
  837. EditorGUILayout.EndVertical();
  838. // Display Glyph Table Elements
  839. if (arraySize > 0)
  840. {
  841. // Display each GlyphInfo entry using the GlyphInfo property drawer.
  842. for (int i = itemsPerPage * m_CurrentGlyphPage; i < arraySize && i < itemsPerPage * (m_CurrentGlyphPage + 1); i++)
  843. {
  844. // Define the start of the selection region of the element.
  845. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  846. int elementIndex = i;
  847. if (!string.IsNullOrEmpty(m_GlyphSearchPattern))
  848. elementIndex = m_GlyphSearchList[i];
  849. SerializedProperty glyphProperty = m_GlyphTable_prop.GetArrayElementAtIndex(elementIndex);
  850. EditorGUILayout.BeginVertical(glyphPanelStyle);
  851. using (new EditorGUI.DisabledScope(i != m_SelectedGlyphRecord))
  852. {
  853. EditorGUILayout.PropertyField(glyphProperty);
  854. }
  855. EditorGUILayout.EndVertical();
  856. // Define the end of the selection region of the element.
  857. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  858. // Check for Item selection
  859. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  860. if (DoSelectionCheck(selectionArea))
  861. {
  862. if (m_SelectedGlyphRecord == i)
  863. m_SelectedGlyphRecord = -1;
  864. else
  865. {
  866. m_SelectedGlyphRecord = i;
  867. m_AddGlyphWarning.isEnabled = false;
  868. m_unicodeHexLabel = k_placeholderUnicodeHex;
  869. GUIUtility.keyboardControl = 0;
  870. }
  871. }
  872. // Draw Selection Highlight and Glyph Options
  873. if (m_SelectedGlyphRecord == i)
  874. {
  875. // Reset other selections
  876. ResetSelections(RecordSelectionType.GlyphRecord);
  877. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  878. // Draw Glyph management options
  879. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  880. float optionAreaWidth = controlRect.width * 0.6f;
  881. float btnWidth = optionAreaWidth / 3;
  882. Rect position = new Rect(controlRect.x + controlRect.width * .4f, controlRect.y, btnWidth, controlRect.height);
  883. // Copy Selected Glyph to Target Glyph ID
  884. GUI.enabled = !string.IsNullOrEmpty(m_dstGlyphID);
  885. if (GUI.Button(position, new GUIContent("Copy to")))
  886. {
  887. GUIUtility.keyboardControl = 0;
  888. int dstGlyphID;
  889. // Convert Hex Value to Decimal
  890. int.TryParse(m_dstGlyphID, out dstGlyphID);
  891. //Add new glyph at target Unicode hex id.
  892. if (!AddNewGlyph(elementIndex, dstGlyphID))
  893. {
  894. m_AddGlyphWarning.isEnabled = true;
  895. m_AddGlyphWarning.expirationTime = EditorApplication.timeSinceStartup + 1;
  896. }
  897. m_dstGlyphID = string.Empty;
  898. m_isSearchDirty = true;
  899. TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, m_fontAsset);
  900. }
  901. // Target Glyph ID
  902. GUI.enabled = true;
  903. position.x += btnWidth;
  904. GUI.SetNextControlName("GlyphID_Input");
  905. m_dstGlyphID = EditorGUI.TextField(position, m_dstGlyphID);
  906. // Placeholder text
  907. EditorGUI.LabelField(position, new GUIContent(m_GlyphIDLabel, "The Glyph ID of the duplicated Glyph"), TMP_UIStyleManager.label);
  908. // Only filter the input when the destination glyph ID text field has focus.
  909. if (GUI.GetNameOfFocusedControl() == "GlyphID_Input")
  910. {
  911. m_GlyphIDLabel = string.Empty;
  912. //Filter out unwanted characters.
  913. char chr = Event.current.character;
  914. if ((chr < '0' || chr > '9'))
  915. {
  916. Event.current.character = '\0';
  917. }
  918. }
  919. else
  920. {
  921. m_GlyphIDLabel = k_placeholderGlyphID;
  922. //m_dstGlyphID = string.Empty;
  923. }
  924. // Remove Glyph
  925. position.x += btnWidth;
  926. if (GUI.Button(position, "Remove"))
  927. {
  928. GUIUtility.keyboardControl = 0;
  929. RemoveGlyphFromList(elementIndex);
  930. isAssetDirty = true;
  931. m_SelectedGlyphRecord = -1;
  932. m_isSearchDirty = true;
  933. break;
  934. }
  935. if (m_AddGlyphWarning.isEnabled && EditorApplication.timeSinceStartup < m_AddGlyphWarning.expirationTime)
  936. {
  937. EditorGUILayout.HelpBox("The Destination Glyph ID already exists", MessageType.Warning);
  938. }
  939. }
  940. }
  941. }
  942. //DisplayAddRemoveButtons(m_GlyphTable_prop, m_SelectedGlyphRecord, glyphRecordCount);
  943. DisplayPageNavigation(ref m_CurrentGlyphPage, arraySize, itemsPerPage);
  944. EditorGUILayout.Space();
  945. }
  946. #endregion
  947. // FONT FEATURE TABLES
  948. // LIGATURE SUBSTITUTION TABLE
  949. #region LIGATURE
  950. EditorGUIUtility.labelWidth = labelWidth;
  951. EditorGUIUtility.fieldWidth = fieldWidth;
  952. EditorGUI.indentLevel = 0;
  953. rect = EditorGUILayout.GetControlRect(false, 24);
  954. int ligatureSubstitutionRecordCount = m_fontAsset.fontFeatureTable.ligatureRecords.Count;
  955. if (GUI.Button(rect, new GUIContent("<b>Ligature Table</b> [" + ligatureSubstitutionRecordCount + "]" + (rect.width > 340 ? " Records" : ""), "List of Ligature substitution records."), TMP_UIStyleManager.sectionHeader))
  956. UI_PanelState.LigatureSubstitutionTablePanel = !UI_PanelState.LigatureSubstitutionTablePanel;
  957. GUI.Label(rect, (UI_PanelState.LigatureSubstitutionTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  958. if (UI_PanelState.LigatureSubstitutionTablePanel)
  959. {
  960. int arraySize = m_LigatureSubstitutionRecords_prop.arraySize;
  961. int itemsPerPage = 20;
  962. // Display Mark Adjust Records Management Tools
  963. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  964. {
  965. // Search Bar implementation
  966. #region DISPLAY SEARCH BAR
  967. EditorGUILayout.BeginHorizontal();
  968. {
  969. EditorGUIUtility.labelWidth = 150f;
  970. EditorGUI.BeginChangeCheck();
  971. string searchPattern = EditorGUILayout.TextField("Ligature Search", m_LigatureTableSearchPattern, "SearchTextField");
  972. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  973. {
  974. if (string.IsNullOrEmpty(searchPattern) == false)
  975. {
  976. m_LigatureTableSearchPattern = searchPattern;
  977. // Search Glyph Table for potential matches
  978. SearchLigatureTable(m_LigatureTableSearchPattern, ref m_LigatureTableSearchList);
  979. }
  980. else
  981. m_LigatureTableSearchPattern = null;
  982. m_isSearchDirty = false;
  983. }
  984. string styleName = string.IsNullOrEmpty(m_LigatureTableSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  985. if (GUILayout.Button(GUIContent.none, styleName))
  986. {
  987. GUIUtility.keyboardControl = 0;
  988. m_LigatureTableSearchPattern = string.Empty;
  989. }
  990. }
  991. EditorGUILayout.EndHorizontal();
  992. #endregion
  993. // Display Page Navigation
  994. if (!string.IsNullOrEmpty(m_LigatureTableSearchPattern))
  995. arraySize = m_LigatureTableSearchList.Count;
  996. DisplayPageNavigation(ref m_CurrentLigaturePage, arraySize, itemsPerPage);
  997. }
  998. EditorGUILayout.EndVertical();
  999. if (arraySize > 0)
  1000. {
  1001. // Display each GlyphInfo entry using the GlyphInfo property drawer.
  1002. for (int i = itemsPerPage * m_CurrentLigaturePage; i < arraySize && i < itemsPerPage * (m_CurrentLigaturePage + 1); i++)
  1003. {
  1004. // Define the start of the selection region of the element.
  1005. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  1006. int elementIndex = i;
  1007. if (!string.IsNullOrEmpty(m_LigatureTableSearchPattern))
  1008. elementIndex = m_LigatureTableSearchList[i];
  1009. SerializedProperty ligaturePropertyRecord = m_LigatureSubstitutionRecords_prop.GetArrayElementAtIndex(elementIndex);
  1010. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  1011. using (new EditorGUI.DisabledScope(i != m_SelectedLigatureRecord))
  1012. {
  1013. EditorGUI.BeginChangeCheck();
  1014. EditorGUILayout.PropertyField(ligaturePropertyRecord);
  1015. if (EditorGUI.EndChangeCheck())
  1016. {
  1017. UpdateLigatureSubstitutionRecordLookup(ligaturePropertyRecord);
  1018. }
  1019. }
  1020. EditorGUILayout.EndVertical();
  1021. // Define the end of the selection region of the element.
  1022. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  1023. // Check for Item selection
  1024. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  1025. if (DoSelectionCheck(selectionArea))
  1026. {
  1027. if (m_SelectedLigatureRecord == i)
  1028. {
  1029. m_SelectedLigatureRecord = -1;
  1030. }
  1031. else
  1032. {
  1033. m_SelectedLigatureRecord = i;
  1034. GUIUtility.keyboardControl = 0;
  1035. }
  1036. }
  1037. // Draw Selection Highlight and Kerning Pair Options
  1038. if (m_SelectedLigatureRecord == i)
  1039. {
  1040. // Reset other selections
  1041. ResetSelections(RecordSelectionType.LigatureSubstitutionRecord);
  1042. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  1043. // Draw Glyph management options
  1044. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  1045. float optionAreaWidth = controlRect.width;
  1046. float btnWidth = optionAreaWidth / 4;
  1047. Rect position = new Rect(controlRect.x + controlRect.width - btnWidth, controlRect.y, btnWidth, controlRect.height);
  1048. // Move record up
  1049. bool guiEnabled = GUI.enabled;
  1050. if (m_SelectedLigatureRecord == 0) { GUI.enabled = false; }
  1051. if (GUI.Button(new Rect(controlRect.x, controlRect.y, btnWidth, controlRect.height), "Up"))
  1052. {
  1053. SwapCharacterElements(m_LigatureSubstitutionRecords_prop, m_SelectedLigatureRecord, m_SelectedLigatureRecord - 1);
  1054. serializedObject.ApplyModifiedProperties();
  1055. m_SelectedLigatureRecord -= 1;
  1056. isAssetDirty = true;
  1057. m_isSearchDirty = true;
  1058. m_fontAsset.InitializeLigatureSubstitutionLookupDictionary();
  1059. }
  1060. GUI.enabled = guiEnabled;
  1061. // Move record down
  1062. if (m_SelectedLigatureRecord == arraySize - 1) { GUI.enabled = false; }
  1063. if (GUI.Button(new Rect(controlRect.x + btnWidth, controlRect.y, btnWidth, controlRect.height), "Down"))
  1064. {
  1065. SwapCharacterElements(m_LigatureSubstitutionRecords_prop, m_SelectedLigatureRecord, m_SelectedLigatureRecord + 1);
  1066. serializedObject.ApplyModifiedProperties();
  1067. m_SelectedLigatureRecord += 1;
  1068. isAssetDirty = true;
  1069. m_isSearchDirty = true;
  1070. m_fontAsset.InitializeLigatureSubstitutionLookupDictionary();
  1071. }
  1072. GUI.enabled = guiEnabled;
  1073. // Remove record
  1074. GUI.enabled = true;
  1075. if (GUI.Button(position, "Remove"))
  1076. {
  1077. GUIUtility.keyboardControl = 0;
  1078. RemoveRecord(m_LigatureSubstitutionRecords_prop, m_SelectedLigatureRecord);
  1079. isAssetDirty = true;
  1080. m_SelectedLigatureRecord = -1;
  1081. m_isSearchDirty = true;
  1082. break;
  1083. }
  1084. }
  1085. }
  1086. }
  1087. DisplayAddRemoveButtons(m_LigatureSubstitutionRecords_prop, m_SelectedLigatureRecord, ligatureSubstitutionRecordCount);
  1088. DisplayPageNavigation(ref m_CurrentLigaturePage, arraySize, itemsPerPage);
  1089. GUILayout.Space(5);
  1090. }
  1091. #endregion
  1092. // PAIR ADJUSTMENT TABLE
  1093. #region Pair Adjustment Table
  1094. EditorGUIUtility.labelWidth = labelWidth;
  1095. EditorGUIUtility.fieldWidth = fieldWidth;
  1096. EditorGUI.indentLevel = 0;
  1097. rect = EditorGUILayout.GetControlRect(false, 24);
  1098. int adjustmentPairCount = m_fontAsset.fontFeatureTable.glyphPairAdjustmentRecords.Count;
  1099. 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))
  1100. UI_PanelState.PairAdjustmentTablePanel = !UI_PanelState.PairAdjustmentTablePanel;
  1101. GUI.Label(rect, (UI_PanelState.PairAdjustmentTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  1102. if (UI_PanelState.PairAdjustmentTablePanel)
  1103. {
  1104. int arraySize = m_GlyphPairAdjustmentRecords_prop.arraySize;
  1105. int itemsPerPage = 20;
  1106. // Display Kerning Pair Management Tools
  1107. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  1108. {
  1109. // Search Bar implementation
  1110. #region DISPLAY SEARCH BAR
  1111. EditorGUILayout.BeginHorizontal();
  1112. {
  1113. EditorGUIUtility.labelWidth = 150f;
  1114. EditorGUI.BeginChangeCheck();
  1115. string searchPattern = EditorGUILayout.TextField("Adjustment Pair Search", m_KerningTableSearchPattern, "SearchTextField");
  1116. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  1117. {
  1118. if (string.IsNullOrEmpty(searchPattern) == false)
  1119. {
  1120. m_KerningTableSearchPattern = searchPattern;
  1121. // Search Glyph Table for potential matches
  1122. SearchKerningTable(m_KerningTableSearchPattern, ref m_KerningTableSearchList);
  1123. }
  1124. else
  1125. m_KerningTableSearchPattern = null;
  1126. m_isSearchDirty = false;
  1127. }
  1128. string styleName = string.IsNullOrEmpty(m_KerningTableSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  1129. if (GUILayout.Button(GUIContent.none, styleName))
  1130. {
  1131. GUIUtility.keyboardControl = 0;
  1132. m_KerningTableSearchPattern = string.Empty;
  1133. }
  1134. }
  1135. EditorGUILayout.EndHorizontal();
  1136. #endregion
  1137. // Display Page Navigation
  1138. if (!string.IsNullOrEmpty(m_KerningTableSearchPattern))
  1139. arraySize = m_KerningTableSearchList.Count;
  1140. DisplayPageNavigation(ref m_CurrentAdjustmentPairPage, arraySize, itemsPerPage);
  1141. }
  1142. EditorGUILayout.EndVertical();
  1143. if (arraySize > 0)
  1144. {
  1145. // Display each GlyphInfo entry using the GlyphInfo property drawer.
  1146. for (int i = itemsPerPage * m_CurrentAdjustmentPairPage; i < arraySize && i < itemsPerPage * (m_CurrentAdjustmentPairPage + 1); i++)
  1147. {
  1148. // Define the start of the selection region of the element.
  1149. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  1150. int elementIndex = i;
  1151. if (!string.IsNullOrEmpty(m_KerningTableSearchPattern))
  1152. elementIndex = m_KerningTableSearchList[i];
  1153. SerializedProperty pairAdjustmentRecordProperty = m_GlyphPairAdjustmentRecords_prop.GetArrayElementAtIndex(elementIndex);
  1154. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  1155. using (new EditorGUI.DisabledScope(i != m_SelectedAdjustmentRecord))
  1156. {
  1157. EditorGUI.BeginChangeCheck();
  1158. EditorGUILayout.PropertyField(pairAdjustmentRecordProperty, new GUIContent("Selectable"));
  1159. if (EditorGUI.EndChangeCheck())
  1160. {
  1161. UpdatePairAdjustmentRecordLookup(pairAdjustmentRecordProperty);
  1162. }
  1163. }
  1164. EditorGUILayout.EndVertical();
  1165. // Define the end of the selection region of the element.
  1166. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  1167. // Check for Item selection
  1168. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  1169. if (DoSelectionCheck(selectionArea))
  1170. {
  1171. if (m_SelectedAdjustmentRecord == i)
  1172. {
  1173. m_SelectedAdjustmentRecord = -1;
  1174. }
  1175. else
  1176. {
  1177. m_SelectedAdjustmentRecord = i;
  1178. GUIUtility.keyboardControl = 0;
  1179. }
  1180. }
  1181. // Draw Selection Highlight and Kerning Pair Options
  1182. if (m_SelectedAdjustmentRecord == i)
  1183. {
  1184. // Reset other selections
  1185. ResetSelections(RecordSelectionType.AdjustmentPairRecord);
  1186. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  1187. // Draw Glyph management options
  1188. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  1189. float optionAreaWidth = controlRect.width;
  1190. float btnWidth = optionAreaWidth / 4;
  1191. Rect position = new Rect(controlRect.x + controlRect.width - btnWidth, controlRect.y, btnWidth, controlRect.height);
  1192. // Remove Kerning pair
  1193. GUI.enabled = true;
  1194. if (GUI.Button(position, "Remove"))
  1195. {
  1196. GUIUtility.keyboardControl = 0;
  1197. RemoveRecord(m_GlyphPairAdjustmentRecords_prop, i);
  1198. isAssetDirty = true;
  1199. m_SelectedAdjustmentRecord = -1;
  1200. m_isSearchDirty = true;
  1201. break;
  1202. }
  1203. }
  1204. }
  1205. }
  1206. DisplayPageNavigation(ref m_CurrentAdjustmentPairPage, arraySize, itemsPerPage);
  1207. GUILayout.Space(5);
  1208. // Add new kerning pair
  1209. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  1210. {
  1211. EditorGUI.BeginChangeCheck();
  1212. EditorGUILayout.PropertyField(m_EmptyGlyphPairAdjustmentRecord_prop);
  1213. if (EditorGUI.EndChangeCheck())
  1214. {
  1215. SetPropertyHolderGlyphIndexes();
  1216. }
  1217. }
  1218. EditorGUILayout.EndVertical();
  1219. if (GUILayout.Button("Add New Glyph Adjustment Record"))
  1220. {
  1221. SerializedProperty firstAdjustmentRecordProperty = m_EmptyGlyphPairAdjustmentRecord_prop.FindPropertyRelative("m_FirstAdjustmentRecord");
  1222. SerializedProperty secondAdjustmentRecordProperty = m_EmptyGlyphPairAdjustmentRecord_prop.FindPropertyRelative("m_SecondAdjustmentRecord");
  1223. uint firstGlyphIndex = (uint)firstAdjustmentRecordProperty.FindPropertyRelative("m_GlyphIndex").intValue;
  1224. uint secondGlyphIndex = (uint)secondAdjustmentRecordProperty.FindPropertyRelative("m_GlyphIndex").intValue;
  1225. GlyphValueRecord firstValueRecord = GetValueRecord(firstAdjustmentRecordProperty.FindPropertyRelative("m_GlyphValueRecord"));
  1226. GlyphValueRecord secondValueRecord = GetValueRecord(secondAdjustmentRecordProperty.FindPropertyRelative("m_GlyphValueRecord"));
  1227. errorCode = -1;
  1228. uint pairKey = secondGlyphIndex << 16 | firstGlyphIndex;
  1229. if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookup.ContainsKey(pairKey) == false)
  1230. {
  1231. GlyphPairAdjustmentRecord adjustmentRecord = new GlyphPairAdjustmentRecord(new GlyphAdjustmentRecord(firstGlyphIndex, firstValueRecord), new GlyphAdjustmentRecord(secondGlyphIndex, secondValueRecord));
  1232. m_FontFeatureTable.m_GlyphPairAdjustmentRecords.Add(adjustmentRecord);
  1233. m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookup.Add(pairKey, adjustmentRecord);
  1234. errorCode = 0;
  1235. }
  1236. // Add glyphs and characters
  1237. TMP_Character character;
  1238. uint firstCharacter = m_SerializedPropertyHolder.firstCharacter;
  1239. if (!m_fontAsset.characterLookupTable.ContainsKey(firstCharacter))
  1240. m_fontAsset.TryAddCharacterInternal(firstCharacter, out character);
  1241. uint secondCharacter = m_SerializedPropertyHolder.secondCharacter;
  1242. if (!m_fontAsset.characterLookupTable.ContainsKey(secondCharacter))
  1243. m_fontAsset.TryAddCharacterInternal(secondCharacter, out character);
  1244. // Sort Kerning Pairs & Reload Font Asset if new kerning pair was added.
  1245. if (errorCode != -1)
  1246. {
  1247. m_FontFeatureTable.SortGlyphPairAdjustmentRecords();
  1248. serializedObject.ApplyModifiedProperties();
  1249. isAssetDirty = true;
  1250. m_isSearchDirty = true;
  1251. }
  1252. else
  1253. {
  1254. timeStamp = System.DateTime.Now.AddSeconds(5);
  1255. }
  1256. // Clear Add Kerning Pair Panel
  1257. // TODO
  1258. }
  1259. if (errorCode == -1)
  1260. {
  1261. GUILayout.BeginHorizontal();
  1262. GUILayout.FlexibleSpace();
  1263. GUILayout.Label("Kerning Pair already <color=#ffff00>exists!</color>", TMP_UIStyleManager.label);
  1264. GUILayout.FlexibleSpace();
  1265. GUILayout.EndHorizontal();
  1266. if (System.DateTime.Now > timeStamp)
  1267. errorCode = 0;
  1268. }
  1269. }
  1270. #endregion
  1271. // MARK TO BASE Font Feature Table
  1272. #region MARK TO BASE
  1273. EditorGUIUtility.labelWidth = labelWidth;
  1274. EditorGUIUtility.fieldWidth = fieldWidth;
  1275. EditorGUI.indentLevel = 0;
  1276. rect = EditorGUILayout.GetControlRect(false, 24);
  1277. int markToBaseAdjustmentRecordCount = m_fontAsset.fontFeatureTable.MarkToBaseAdjustmentRecords.Count;
  1278. if (GUI.Button(rect, new GUIContent("<b>Mark To Base Adjustment Table</b> [" + markToBaseAdjustmentRecordCount + "]" + (rect.width > 340 ? " Records" : ""), "List of Mark to Base adjustment records."), TMP_UIStyleManager.sectionHeader))
  1279. UI_PanelState.MarkToBaseTablePanel = !UI_PanelState.MarkToBaseTablePanel;
  1280. GUI.Label(rect, (UI_PanelState.MarkToBaseTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  1281. if (UI_PanelState.MarkToBaseTablePanel)
  1282. {
  1283. int arraySize = m_MarkToBaseAdjustmentRecords_prop.arraySize;
  1284. int itemsPerPage = 20;
  1285. // Display Mark Adjust Records Management Tools
  1286. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  1287. {
  1288. // Search Bar implementation
  1289. #region DISPLAY SEARCH BAR
  1290. EditorGUILayout.BeginHorizontal();
  1291. {
  1292. EditorGUIUtility.labelWidth = 150f;
  1293. EditorGUI.BeginChangeCheck();
  1294. string searchPattern = EditorGUILayout.TextField("Mark to Base Search", m_MarkToBaseTableSearchPattern, "SearchTextField");
  1295. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  1296. {
  1297. if (string.IsNullOrEmpty(searchPattern) == false)
  1298. {
  1299. m_MarkToBaseTableSearchPattern = searchPattern;
  1300. // Search Glyph Table for potential matches
  1301. SearchMarkToBaseTable(m_MarkToBaseTableSearchPattern, ref m_MarkToBaseTableSearchList);
  1302. }
  1303. else
  1304. m_MarkToBaseTableSearchPattern = null;
  1305. m_isSearchDirty = false;
  1306. }
  1307. string styleName = string.IsNullOrEmpty(m_MarkToBaseTableSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  1308. if (GUILayout.Button(GUIContent.none, styleName))
  1309. {
  1310. GUIUtility.keyboardControl = 0;
  1311. m_MarkToBaseTableSearchPattern = string.Empty;
  1312. }
  1313. }
  1314. EditorGUILayout.EndHorizontal();
  1315. #endregion
  1316. // Display Page Navigation
  1317. if (!string.IsNullOrEmpty(m_MarkToBaseTableSearchPattern))
  1318. arraySize = m_MarkToBaseTableSearchList.Count;
  1319. DisplayPageNavigation(ref m_CurrentMarkToBasePage, arraySize, itemsPerPage);
  1320. }
  1321. EditorGUILayout.EndVertical();
  1322. if (arraySize > 0)
  1323. {
  1324. // Display each GlyphInfo entry using the GlyphInfo property drawer.
  1325. for (int i = itemsPerPage * m_CurrentMarkToBasePage; i < arraySize && i < itemsPerPage * (m_CurrentMarkToBasePage + 1); i++)
  1326. {
  1327. // Define the start of the selection region of the element.
  1328. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  1329. int elementIndex = i;
  1330. if (!string.IsNullOrEmpty(m_MarkToBaseTableSearchPattern))
  1331. elementIndex = m_MarkToBaseTableSearchList[i];
  1332. SerializedProperty markToBasePropertyRecord = m_MarkToBaseAdjustmentRecords_prop.GetArrayElementAtIndex(elementIndex);
  1333. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  1334. using (new EditorGUI.DisabledScope(i != m_SelectedMarkToBaseRecord))
  1335. {
  1336. EditorGUI.BeginChangeCheck();
  1337. EditorGUILayout.PropertyField(markToBasePropertyRecord, new GUIContent("Selectable"));
  1338. if (EditorGUI.EndChangeCheck())
  1339. {
  1340. UpdateMarkToBaseAdjustmentRecordLookup(markToBasePropertyRecord);
  1341. }
  1342. }
  1343. EditorGUILayout.EndVertical();
  1344. // Define the end of the selection region of the element.
  1345. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  1346. // Check for Item selection
  1347. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  1348. if (DoSelectionCheck(selectionArea))
  1349. {
  1350. if (m_SelectedMarkToBaseRecord == i)
  1351. {
  1352. m_SelectedMarkToBaseRecord = -1;
  1353. }
  1354. else
  1355. {
  1356. m_SelectedMarkToBaseRecord = i;
  1357. GUIUtility.keyboardControl = 0;
  1358. }
  1359. }
  1360. // Draw Selection Highlight and Kerning Pair Options
  1361. if (m_SelectedMarkToBaseRecord == i)
  1362. {
  1363. // Reset other selections
  1364. ResetSelections(RecordSelectionType.MarkToBaseRecord);
  1365. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  1366. // Draw Glyph management options
  1367. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  1368. float optionAreaWidth = controlRect.width;
  1369. float btnWidth = optionAreaWidth / 4;
  1370. Rect position = new Rect(controlRect.x + controlRect.width - btnWidth, controlRect.y, btnWidth, controlRect.height);
  1371. // Remove Mark to Base Record
  1372. GUI.enabled = true;
  1373. if (GUI.Button(position, "Remove"))
  1374. {
  1375. GUIUtility.keyboardControl = 0;
  1376. RemoveRecord(m_MarkToBaseAdjustmentRecords_prop, i);
  1377. isAssetDirty = true;
  1378. m_SelectedMarkToBaseRecord = -1;
  1379. m_isSearchDirty = true;
  1380. break;
  1381. }
  1382. }
  1383. }
  1384. }
  1385. DisplayAddRemoveButtons(m_MarkToBaseAdjustmentRecords_prop, m_SelectedMarkToBaseRecord, markToBaseAdjustmentRecordCount);
  1386. DisplayPageNavigation(ref m_CurrentMarkToBasePage, arraySize, itemsPerPage);
  1387. GUILayout.Space(5);
  1388. }
  1389. #endregion
  1390. // MARK TO MARK Font Feature Table
  1391. #region MARK TO MARK
  1392. EditorGUIUtility.labelWidth = labelWidth;
  1393. EditorGUIUtility.fieldWidth = fieldWidth;
  1394. EditorGUI.indentLevel = 0;
  1395. rect = EditorGUILayout.GetControlRect(false, 24);
  1396. int markToMarkAdjustmentRecordCount = m_fontAsset.fontFeatureTable.MarkToMarkAdjustmentRecords.Count;
  1397. if (GUI.Button(rect, new GUIContent("<b>Mark To Mark Adjustment Table</b> [" + markToMarkAdjustmentRecordCount + "]" + (rect.width > 340 ? " Records" : ""), "List of Mark to Mark adjustment records."), TMP_UIStyleManager.sectionHeader))
  1398. UI_PanelState.MarkToMarkTablePanel = !UI_PanelState.MarkToMarkTablePanel;
  1399. GUI.Label(rect, (UI_PanelState.MarkToMarkTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
  1400. if (UI_PanelState.MarkToMarkTablePanel)
  1401. {
  1402. int arraySize = m_MarkToMarkAdjustmentRecords_prop.arraySize;
  1403. int itemsPerPage = 20;
  1404. // Display Kerning Pair Management Tools
  1405. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  1406. {
  1407. // Search Bar implementation
  1408. #region DISPLAY SEARCH BAR
  1409. EditorGUILayout.BeginHorizontal();
  1410. {
  1411. EditorGUIUtility.labelWidth = 150f;
  1412. EditorGUI.BeginChangeCheck();
  1413. string searchPattern = EditorGUILayout.TextField("Mark to Mark Search", m_MarkToMarkTableSearchPattern, "SearchTextField");
  1414. if (EditorGUI.EndChangeCheck() || m_isSearchDirty)
  1415. {
  1416. if (string.IsNullOrEmpty(searchPattern) == false)
  1417. {
  1418. m_MarkToMarkTableSearchPattern = searchPattern;
  1419. // Search Glyph Table for potential matches
  1420. SearchMarkToMarkTable(m_MarkToMarkTableSearchPattern, ref m_MarkToMarkTableSearchList);
  1421. }
  1422. else
  1423. m_MarkToMarkTableSearchPattern = null;
  1424. m_isSearchDirty = false;
  1425. }
  1426. string styleName = string.IsNullOrEmpty(m_MarkToMarkTableSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
  1427. if (GUILayout.Button(GUIContent.none, styleName))
  1428. {
  1429. GUIUtility.keyboardControl = 0;
  1430. m_MarkToMarkTableSearchPattern = string.Empty;
  1431. }
  1432. }
  1433. EditorGUILayout.EndHorizontal();
  1434. #endregion
  1435. // Display Page Navigation
  1436. if (!string.IsNullOrEmpty(m_MarkToMarkTableSearchPattern))
  1437. arraySize = m_MarkToMarkTableSearchList.Count;
  1438. DisplayPageNavigation(ref m_CurrentMarkToMarkPage, arraySize, itemsPerPage);
  1439. }
  1440. EditorGUILayout.EndVertical();
  1441. if (arraySize > 0)
  1442. {
  1443. // Display each GlyphInfo entry using the GlyphInfo property drawer.
  1444. for (int i = itemsPerPage * m_CurrentMarkToMarkPage; i < arraySize && i < itemsPerPage * (m_CurrentMarkToMarkPage + 1); i++)
  1445. {
  1446. // Define the start of the selection region of the element.
  1447. Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  1448. int elementIndex = i;
  1449. if (!string.IsNullOrEmpty(m_MarkToMarkTableSearchPattern))
  1450. elementIndex = m_MarkToMarkTableSearchList[i];
  1451. SerializedProperty markToMarkPropertyRecord = m_MarkToMarkAdjustmentRecords_prop.GetArrayElementAtIndex(elementIndex);
  1452. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  1453. using (new EditorGUI.DisabledScope(i != m_SelectedMarkToMarkRecord))
  1454. {
  1455. EditorGUI.BeginChangeCheck();
  1456. EditorGUILayout.PropertyField(markToMarkPropertyRecord, new GUIContent("Selectable"));
  1457. if (EditorGUI.EndChangeCheck())
  1458. {
  1459. UpdateMarkToMarkAdjustmentRecordLookup(markToMarkPropertyRecord);
  1460. }
  1461. }
  1462. EditorGUILayout.EndVertical();
  1463. // Define the end of the selection region of the element.
  1464. Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
  1465. // Check for Item selection
  1466. Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
  1467. if (DoSelectionCheck(selectionArea))
  1468. {
  1469. if (m_SelectedMarkToMarkRecord == i)
  1470. {
  1471. m_SelectedMarkToMarkRecord = -1;
  1472. }
  1473. else
  1474. {
  1475. m_SelectedMarkToMarkRecord = i;
  1476. GUIUtility.keyboardControl = 0;
  1477. }
  1478. }
  1479. // Draw Selection Highlight and Kerning Pair Options
  1480. if (m_SelectedMarkToMarkRecord == i)
  1481. {
  1482. // Reset other selections
  1483. ResetSelections(RecordSelectionType.MarkToMarkRecord);
  1484. TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
  1485. // Draw Glyph management options
  1486. Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
  1487. float optionAreaWidth = controlRect.width;
  1488. float btnWidth = optionAreaWidth / 4;
  1489. Rect position = new Rect(controlRect.x + controlRect.width - btnWidth, controlRect.y, btnWidth, controlRect.height);
  1490. // Remove Mark to Base Record
  1491. GUI.enabled = true;
  1492. if (GUI.Button(position, "Remove"))
  1493. {
  1494. GUIUtility.keyboardControl = 0;
  1495. RemoveRecord(m_MarkToMarkAdjustmentRecords_prop, i);
  1496. isAssetDirty = true;
  1497. m_SelectedMarkToMarkRecord = -1;
  1498. m_isSearchDirty = true;
  1499. break;
  1500. }
  1501. }
  1502. }
  1503. }
  1504. DisplayAddRemoveButtons(m_MarkToMarkAdjustmentRecords_prop, m_SelectedMarkToMarkRecord, markToMarkAdjustmentRecordCount);
  1505. DisplayPageNavigation(ref m_CurrentMarkToMarkPage, arraySize, itemsPerPage);
  1506. GUILayout.Space(5);
  1507. }
  1508. #endregion
  1509. if (serializedObject.ApplyModifiedProperties() || evt_cmd == k_UndoRedo || isAssetDirty || m_IsFallbackGlyphCacheDirty)
  1510. {
  1511. // Delay callback until user has decided to Apply or Revert the changes.
  1512. if (m_DisplayDestructiveChangeWarning == false)
  1513. {
  1514. TMP_ResourceManager.RebuildFontAssetCache();
  1515. TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, m_fontAsset);
  1516. m_IsFallbackGlyphCacheDirty = false;
  1517. }
  1518. if (m_fontAsset.IsFontAssetLookupTablesDirty || evt_cmd == k_UndoRedo)
  1519. m_fontAsset.ReadFontAssetDefinition();
  1520. isAssetDirty = false;
  1521. EditorUtility.SetDirty(target);
  1522. }
  1523. // Clear selection if mouse event was not consumed.
  1524. GUI.enabled = true;
  1525. if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0)
  1526. {
  1527. m_SelectedAdjustmentRecord = -1;
  1528. m_SelectedMarkToBaseRecord = -1;
  1529. m_SelectedMarkToMarkRecord = -1;
  1530. }
  1531. }
  1532. /// <summary>
  1533. /// Overrided method from the Editor class.
  1534. /// </summary>
  1535. /// <returns></returns>
  1536. public override bool HasPreviewGUI()
  1537. {
  1538. return true;
  1539. }
  1540. /// <summary>
  1541. /// Overrided method to implement custom preview inspector.
  1542. /// </summary>
  1543. /// <param name="rect"></param>
  1544. /// <param name="background"></param>
  1545. public override void OnPreviewGUI(Rect rect, GUIStyle background)
  1546. {
  1547. if (m_SelectedMarkToBaseRecord != -1)
  1548. DrawMarkToBasePreview(m_SelectedMarkToBaseRecord, rect);
  1549. if (m_SelectedMarkToMarkRecord != -1)
  1550. DrawMarkToMarkPreview(m_SelectedMarkToMarkRecord, rect);
  1551. }
  1552. void ResetSelections(RecordSelectionType type)
  1553. {
  1554. switch (type)
  1555. {
  1556. case RecordSelectionType.CharacterRecord:
  1557. m_SelectedGlyphRecord = -1;
  1558. m_SelectedLigatureRecord = -1;
  1559. m_SelectedAdjustmentRecord = -1;
  1560. m_SelectedMarkToBaseRecord = -1;
  1561. m_SelectedMarkToMarkRecord = -1;
  1562. break;
  1563. case RecordSelectionType.GlyphRecord:
  1564. m_SelectedCharacterRecord = -1;
  1565. m_SelectedLigatureRecord = -1;
  1566. m_SelectedAdjustmentRecord = -1;
  1567. m_SelectedMarkToBaseRecord = -1;
  1568. m_SelectedMarkToMarkRecord = -1;
  1569. break;
  1570. case RecordSelectionType.LigatureSubstitutionRecord:
  1571. m_SelectedCharacterRecord = -1;
  1572. m_SelectedGlyphRecord = -1;
  1573. m_SelectedAdjustmentRecord = -1;
  1574. m_SelectedMarkToBaseRecord = -1;
  1575. m_SelectedMarkToMarkRecord = -1;
  1576. break;
  1577. case RecordSelectionType.AdjustmentPairRecord:
  1578. m_SelectedCharacterRecord = -1;
  1579. m_SelectedGlyphRecord = -1;
  1580. m_SelectedLigatureRecord = -1;
  1581. m_SelectedMarkToBaseRecord = -1;
  1582. m_SelectedMarkToMarkRecord = -1;
  1583. break;
  1584. case RecordSelectionType.MarkToBaseRecord:
  1585. m_SelectedCharacterRecord = -1;
  1586. m_SelectedGlyphRecord = -1;
  1587. m_SelectedLigatureRecord = -1;
  1588. m_SelectedAdjustmentRecord = -1;
  1589. m_SelectedMarkToMarkRecord = -1;
  1590. break;
  1591. case RecordSelectionType.MarkToMarkRecord:
  1592. m_SelectedCharacterRecord = -1;
  1593. m_SelectedGlyphRecord = -1;
  1594. m_SelectedLigatureRecord = -1;
  1595. m_SelectedAdjustmentRecord = -1;
  1596. m_SelectedMarkToBaseRecord = -1;
  1597. break;
  1598. }
  1599. }
  1600. string[] GetFontFaces()
  1601. {
  1602. return GetFontFaces(m_FontFaceIndex_prop.intValue);
  1603. }
  1604. string[] GetFontFaces(int faceIndex)
  1605. {
  1606. #if UNITY_2023_3_OR_NEWER
  1607. if (LoadFontFace((int)m_SamplingPointSize_prop.floatValue, faceIndex) == FontEngineError.Success)
  1608. #else
  1609. if (LoadFontFace(m_SamplingPointSize_prop.intValue, faceIndex) == FontEngineError.Success)
  1610. #endif
  1611. return FontEngine.GetFontFaces();
  1612. return k_InvalidFontFaces;
  1613. }
  1614. FontEngineError LoadFontFace(int pointSize, int faceIndex)
  1615. {
  1616. if (m_fontAsset.SourceFont_EditorRef != null)
  1617. {
  1618. if (FontEngine.LoadFontFace(m_fontAsset.SourceFont_EditorRef, pointSize, faceIndex) == FontEngineError.Success)
  1619. return FontEngineError.Success;
  1620. }
  1621. // Requires Unity 2018.4.35f1
  1622. return FontEngine.LoadFontFace(m_fontAsset.faceInfo.familyName, m_fontAsset.faceInfo.styleName, pointSize);
  1623. }
  1624. void CleanFallbackFontAssetTable()
  1625. {
  1626. SerializedProperty m_FallbackFontAsseTable = serializedObject.FindProperty("m_FallbackFontAssetTable");
  1627. bool isListDirty = false;
  1628. int elementCount = m_FallbackFontAsseTable.arraySize;
  1629. for (int i = 0; i < elementCount; i++)
  1630. {
  1631. SerializedProperty element = m_FallbackFontAsseTable.GetArrayElementAtIndex(i);
  1632. if (element.objectReferenceValue == null)
  1633. {
  1634. m_FallbackFontAsseTable.DeleteArrayElementAtIndex(i);
  1635. elementCount -= 1;
  1636. i -= 1;
  1637. isListDirty = true;
  1638. }
  1639. }
  1640. if (isListDirty)
  1641. {
  1642. serializedObject.ApplyModifiedProperties();
  1643. serializedObject.Update();
  1644. }
  1645. }
  1646. void SavedGenerationSettings()
  1647. {
  1648. m_GenerationSettings.faceIndex = m_FontFaceIndex_prop.intValue;
  1649. m_GenerationSettings.glyphRenderMode = (GlyphRenderMode)m_AtlasRenderMode_prop.intValue;
  1650. #if UNITY_2023_3_OR_NEWER
  1651. m_GenerationSettings.pointSize = (int)m_SamplingPointSize_prop.floatValue;
  1652. #else
  1653. m_GenerationSettings.pointSize = m_SamplingPointSize_prop.intValue;
  1654. #endif
  1655. m_GenerationSettings.padding = m_AtlasPadding_prop.intValue;
  1656. m_GenerationSettings.atlasWidth = m_AtlasWidth_prop.intValue;
  1657. m_GenerationSettings.atlasHeight = m_AtlasHeight_prop.intValue;
  1658. }
  1659. void RestoreGenerationSettings()
  1660. {
  1661. m_fontAsset.SourceFont_EditorRef = m_GenerationSettings.sourceFont;
  1662. m_FontFaceIndex_prop.intValue = m_GenerationSettings.faceIndex;
  1663. #if UNITY_2023_3_OR_NEWER
  1664. m_SamplingPointSize_prop.floatValue = m_GenerationSettings.pointSize;
  1665. #else
  1666. m_SamplingPointSize_prop.intValue = m_GenerationSettings.pointSize;
  1667. #endif
  1668. m_FontFaces = GetFontFaces();
  1669. m_AtlasRenderMode_prop.intValue = (int)m_GenerationSettings.glyphRenderMode;
  1670. m_AtlasPadding_prop.intValue = m_GenerationSettings.padding;
  1671. m_AtlasWidth_prop.intValue = m_GenerationSettings.atlasWidth;
  1672. m_AtlasHeight_prop.intValue = m_GenerationSettings.atlasHeight;
  1673. }
  1674. void UpdateFontAssetCreationSettings()
  1675. {
  1676. m_fontAsset.m_CreationSettings.faceIndex = m_FontFaceIndex_prop.intValue;
  1677. #if UNITY_2023_3_OR_NEWER
  1678. m_fontAsset.m_CreationSettings.pointSize = (int)m_SamplingPointSize_prop.floatValue;
  1679. #else
  1680. m_fontAsset.m_CreationSettings.pointSize = m_SamplingPointSize_prop.intValue;
  1681. #endif
  1682. m_fontAsset.m_CreationSettings.renderMode = m_AtlasRenderMode_prop.intValue;
  1683. m_fontAsset.m_CreationSettings.padding = m_AtlasPadding_prop.intValue;
  1684. m_fontAsset.m_CreationSettings.atlasWidth = m_AtlasWidth_prop.intValue;
  1685. m_fontAsset.m_CreationSettings.atlasHeight = m_AtlasHeight_prop.intValue;
  1686. }
  1687. void UpdateCharacterData(SerializedProperty property, int index)
  1688. {
  1689. TMP_Character character = m_fontAsset.characterTable[index];
  1690. character.unicode = (uint)property.FindPropertyRelative("m_Unicode").intValue;
  1691. character.scale = property.FindPropertyRelative("m_Scale").floatValue;
  1692. SerializedProperty glyphProperty = property.FindPropertyRelative("m_Glyph");
  1693. character.glyph.index = (uint)glyphProperty.FindPropertyRelative("m_Index").intValue;
  1694. SerializedProperty glyphRectProperty = glyphProperty.FindPropertyRelative("m_GlyphRect");
  1695. 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);
  1696. SerializedProperty glyphMetricsProperty = glyphProperty.FindPropertyRelative("m_Metrics");
  1697. 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);
  1698. character.glyph.scale = glyphProperty.FindPropertyRelative("m_Scale").floatValue;
  1699. character.glyph.atlasIndex = glyphProperty.FindPropertyRelative("m_AtlasIndex").intValue;
  1700. }
  1701. void UpdateGlyphData(SerializedProperty property, int index)
  1702. {
  1703. Glyph glyph = m_fontAsset.glyphTable[index];
  1704. glyph.index = (uint)property.FindPropertyRelative("m_Index").intValue;
  1705. SerializedProperty glyphRect = property.FindPropertyRelative("m_GlyphRect");
  1706. glyph.glyphRect = new GlyphRect(glyphRect.FindPropertyRelative("m_X").intValue, glyphRect.FindPropertyRelative("m_Y").intValue, glyphRect.FindPropertyRelative("m_Width").intValue, glyphRect.FindPropertyRelative("m_Height").intValue);
  1707. SerializedProperty glyphMetrics = property.FindPropertyRelative("m_Metrics");
  1708. 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);
  1709. glyph.scale = property.FindPropertyRelative("m_Scale").floatValue;
  1710. }
  1711. void DisplayAddRemoveButtons(SerializedProperty property, int selectedRecord, int recordCount)
  1712. {
  1713. Rect rect = EditorGUILayout.GetControlRect(false, 20);
  1714. rect.width /= 6;
  1715. // Add Style
  1716. rect.x = rect.width * 4 + 17;
  1717. if (GUI.Button(rect, "+"))
  1718. {
  1719. int index = selectedRecord == -1 ? 0 : selectedRecord;
  1720. if (index > recordCount)
  1721. index = recordCount;
  1722. // Copy selected element
  1723. property.InsertArrayElementAtIndex(index);
  1724. // Select newly inserted element
  1725. selectedRecord = index + 1;
  1726. serializedObject.ApplyModifiedProperties();
  1727. m_fontAsset.ReadFontAssetDefinition();
  1728. }
  1729. // Delete style
  1730. rect.x += rect.width;
  1731. if (selectedRecord == -1 || selectedRecord >= recordCount) GUI.enabled = false;
  1732. if (GUI.Button(rect, "-"))
  1733. {
  1734. int index = selectedRecord == -1 ? 0 : selectedRecord;
  1735. property.DeleteArrayElementAtIndex(index);
  1736. selectedRecord = -1;
  1737. serializedObject.ApplyModifiedProperties();
  1738. m_fontAsset.ReadFontAssetDefinition();
  1739. return;
  1740. }
  1741. GUI.enabled = true;
  1742. }
  1743. void DisplayPageNavigation(ref int currentPage, int arraySize, int itemsPerPage)
  1744. {
  1745. Rect pagePos = EditorGUILayout.GetControlRect(false, 20);
  1746. pagePos.width /= 3;
  1747. int shiftMultiplier = Event.current.shift ? 10 : 1; // Page + Shift goes 10 page forward
  1748. // Previous Page
  1749. GUI.enabled = currentPage > 0;
  1750. if (GUI.Button(pagePos, "Previous Page"))
  1751. currentPage -= 1 * shiftMultiplier;
  1752. // Page Counter
  1753. GUI.enabled = true;
  1754. pagePos.x += pagePos.width;
  1755. int totalPages = (int)(arraySize / (float)itemsPerPage + 0.999f);
  1756. GUI.Label(pagePos, "Page " + (currentPage + 1) + " / " + totalPages, TMP_UIStyleManager.centeredLabel);
  1757. // Next Page
  1758. pagePos.x += pagePos.width;
  1759. GUI.enabled = itemsPerPage * (currentPage + 1) < arraySize;
  1760. if (GUI.Button(pagePos, "Next Page"))
  1761. currentPage += 1 * shiftMultiplier;
  1762. // Clamp page range
  1763. currentPage = Mathf.Clamp(currentPage, 0, arraySize / itemsPerPage);
  1764. GUI.enabled = true;
  1765. }
  1766. /// <summary>
  1767. ///
  1768. /// </summary>
  1769. /// <param name="srcGlyphID"></param>
  1770. /// <param name="dstGlyphID"></param>
  1771. bool AddNewGlyph(int srcIndex, int dstGlyphID)
  1772. {
  1773. // Make sure Destination Glyph ID doesn't already contain a Glyph
  1774. if (m_fontAsset.glyphLookupTable.ContainsKey((uint)dstGlyphID))
  1775. return false;
  1776. // Add new element to glyph list.
  1777. m_GlyphTable_prop.arraySize += 1;
  1778. // Get a reference to the source glyph.
  1779. SerializedProperty sourceGlyph = m_GlyphTable_prop.GetArrayElementAtIndex(srcIndex);
  1780. int dstIndex = m_GlyphTable_prop.arraySize - 1;
  1781. // Get a reference to the target / destination glyph.
  1782. SerializedProperty targetGlyph = m_GlyphTable_prop.GetArrayElementAtIndex(dstIndex);
  1783. CopyGlyphSerializedProperty(sourceGlyph, ref targetGlyph);
  1784. // Update the ID of the glyph
  1785. targetGlyph.FindPropertyRelative("m_Index").intValue = dstGlyphID;
  1786. serializedObject.ApplyModifiedProperties();
  1787. m_fontAsset.SortGlyphTable();
  1788. m_fontAsset.ReadFontAssetDefinition();
  1789. return true;
  1790. }
  1791. /// <summary>
  1792. ///
  1793. /// </summary>
  1794. /// <param name="glyphID"></param>
  1795. void RemoveGlyphFromList(int index)
  1796. {
  1797. if (index > m_GlyphTable_prop.arraySize)
  1798. return;
  1799. int targetGlyphIndex = m_GlyphTable_prop.GetArrayElementAtIndex(index).FindPropertyRelative("m_Index").intValue;
  1800. m_GlyphTable_prop.DeleteArrayElementAtIndex(index);
  1801. // Remove all characters referencing this glyph.
  1802. for (int i = 0; i < m_CharacterTable_prop.arraySize; i++)
  1803. {
  1804. int glyphIndex = m_CharacterTable_prop.GetArrayElementAtIndex(i).FindPropertyRelative("m_GlyphIndex").intValue;
  1805. if (glyphIndex == targetGlyphIndex)
  1806. {
  1807. // Remove character
  1808. m_CharacterTable_prop.DeleteArrayElementAtIndex(i);
  1809. }
  1810. }
  1811. serializedObject.ApplyModifiedProperties();
  1812. m_fontAsset.ReadFontAssetDefinition();
  1813. }
  1814. bool AddNewCharacter(int srcIndex, int dstGlyphID)
  1815. {
  1816. // Make sure Destination Glyph ID doesn't already contain a Glyph
  1817. if (m_fontAsset.characterLookupTable.ContainsKey((uint)dstGlyphID))
  1818. return false;
  1819. // Add new element to glyph list.
  1820. m_CharacterTable_prop.arraySize += 1;
  1821. // Get a reference to the source glyph.
  1822. SerializedProperty sourceCharacter = m_CharacterTable_prop.GetArrayElementAtIndex(srcIndex);
  1823. int dstIndex = m_CharacterTable_prop.arraySize - 1;
  1824. // Get a reference to the target / destination glyph.
  1825. SerializedProperty targetCharacter = m_CharacterTable_prop.GetArrayElementAtIndex(dstIndex);
  1826. CopyCharacterSerializedProperty(sourceCharacter, ref targetCharacter);
  1827. // Update the ID of the glyph
  1828. targetCharacter.FindPropertyRelative("m_Unicode").intValue = dstGlyphID;
  1829. serializedObject.ApplyModifiedProperties();
  1830. m_fontAsset.SortCharacterTable();
  1831. m_fontAsset.ReadFontAssetDefinition();
  1832. return true;
  1833. }
  1834. void RemoveCharacterFromList(int index)
  1835. {
  1836. if (index > m_CharacterTable_prop.arraySize)
  1837. return;
  1838. m_CharacterTable_prop.DeleteArrayElementAtIndex(index);
  1839. serializedObject.ApplyModifiedProperties();
  1840. m_fontAsset.ReadFontAssetDefinition();
  1841. }
  1842. void AddNewGlyphsFromProperty(SerializedProperty property)
  1843. {
  1844. if (m_GlyphsToAdd == null)
  1845. m_GlyphsToAdd = new HashSet<uint>();
  1846. else
  1847. m_GlyphsToAdd.Clear();
  1848. string propertyType = property.type;
  1849. switch (propertyType)
  1850. {
  1851. case "LigatureSubstitutionRecord":
  1852. int componentCount = property.FindPropertyRelative("m_ComponentGlyphIDs").arraySize;
  1853. for (int i = 0; i < componentCount; i++)
  1854. {
  1855. uint glyphIndex = (uint)property.FindPropertyRelative("m_ComponentGlyphIDs").GetArrayElementAtIndex(i).intValue;
  1856. m_GlyphsToAdd.Add(glyphIndex);
  1857. }
  1858. m_GlyphsToAdd.Add((uint)property.FindPropertyRelative("m_LigatureGlyphID").intValue);
  1859. foreach (uint glyphIndex in m_GlyphsToAdd)
  1860. {
  1861. if (glyphIndex != 0)
  1862. m_fontAsset.AddGlyphInternal(glyphIndex);
  1863. }
  1864. break;
  1865. }
  1866. }
  1867. // Check if any of the Style elements were clicked on.
  1868. private bool DoSelectionCheck(Rect selectionArea)
  1869. {
  1870. Event currentEvent = Event.current;
  1871. switch (currentEvent.type)
  1872. {
  1873. case EventType.MouseDown:
  1874. if (selectionArea.Contains(currentEvent.mousePosition) && currentEvent.button == 0)
  1875. {
  1876. currentEvent.Use();
  1877. return true;
  1878. }
  1879. break;
  1880. }
  1881. return false;
  1882. }
  1883. private void UpdateLigatureSubstitutionRecordLookup(SerializedProperty property)
  1884. {
  1885. serializedObject.ApplyModifiedProperties();
  1886. AddNewGlyphsFromProperty(property);
  1887. m_fontAsset.InitializeLigatureSubstitutionLookupDictionary();
  1888. isAssetDirty = true;
  1889. }
  1890. void SetPropertyHolderGlyphIndexes()
  1891. {
  1892. uint firstCharacterUnicode = (uint)m_FirstCharacterUnicode_prop.intValue;
  1893. if (firstCharacterUnicode != 0)
  1894. {
  1895. uint glyphIndex = m_fontAsset.GetGlyphIndex(firstCharacterUnicode);
  1896. if (glyphIndex != 0)
  1897. m_EmptyGlyphPairAdjustmentRecord_prop.FindPropertyRelative("m_FirstAdjustmentRecord").FindPropertyRelative("m_GlyphIndex").intValue = (int)glyphIndex;
  1898. }
  1899. uint secondCharacterUnicode = (uint)m_SecondCharacterUnicode_prop.intValue;
  1900. if (secondCharacterUnicode != 0)
  1901. {
  1902. uint glyphIndex = m_fontAsset.GetGlyphIndex(secondCharacterUnicode);
  1903. if (glyphIndex != 0)
  1904. m_EmptyGlyphPairAdjustmentRecord_prop.FindPropertyRelative("m_SecondAdjustmentRecord").FindPropertyRelative("m_GlyphIndex").intValue = (int)glyphIndex;
  1905. }
  1906. }
  1907. private void UpdatePairAdjustmentRecordLookup(SerializedProperty property)
  1908. {
  1909. GlyphPairAdjustmentRecord pairAdjustmentRecord = GetGlyphPairAdjustmentRecord(property);
  1910. uint firstGlyphIndex = pairAdjustmentRecord.firstAdjustmentRecord.glyphIndex;
  1911. uint secondGlyphIndex = pairAdjustmentRecord.secondAdjustmentRecord.glyphIndex;
  1912. uint key = secondGlyphIndex << 16 | firstGlyphIndex;
  1913. // Lookup dictionary entry and update it
  1914. if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookup.ContainsKey(key))
  1915. m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookup[key] = pairAdjustmentRecord;
  1916. }
  1917. GlyphPairAdjustmentRecord GetGlyphPairAdjustmentRecord(SerializedProperty property)
  1918. {
  1919. GlyphPairAdjustmentRecord pairAdjustmentRecord = new GlyphPairAdjustmentRecord();
  1920. SerializedProperty firstAdjustmentRecordProperty = property.FindPropertyRelative("m_FirstAdjustmentRecord");
  1921. uint firstGlyphIndex = (uint)firstAdjustmentRecordProperty.FindPropertyRelative("m_GlyphIndex").intValue;
  1922. GlyphValueRecord firstValueRecord = GetValueRecord(firstAdjustmentRecordProperty.FindPropertyRelative("m_GlyphValueRecord"));
  1923. pairAdjustmentRecord.firstAdjustmentRecord = new GlyphAdjustmentRecord(firstGlyphIndex, firstValueRecord);
  1924. SerializedProperty secondAdjustmentRecordProperty = property.FindPropertyRelative("m_SecondAdjustmentRecord");
  1925. uint secondGlyphIndex = (uint)secondAdjustmentRecordProperty.FindPropertyRelative("m_GlyphIndex").intValue;
  1926. GlyphValueRecord secondValueRecord = GetValueRecord(secondAdjustmentRecordProperty.FindPropertyRelative("m_GlyphValueRecord"));
  1927. pairAdjustmentRecord.secondAdjustmentRecord = new GlyphAdjustmentRecord(secondGlyphIndex, secondValueRecord);
  1928. // TODO : Need to revise how Everything is handled in the event more enum values are added.
  1929. int flagValue = property.FindPropertyRelative("m_FeatureLookupFlags").intValue;
  1930. //pairAdjustmentRecord.featureLookupFlags = flagValue == -1 ? FontFeatureLookupFlags.IgnoreLigatures | FontFeatureLookupFlags.IgnoreSpacingAdjustments : (FontFeatureLookupFlags) flagValue;
  1931. return pairAdjustmentRecord;
  1932. }
  1933. void SwapCharacterElements(SerializedProperty property, int selectedIndex, int newIndex)
  1934. {
  1935. property.MoveArrayElement(selectedIndex, newIndex);
  1936. }
  1937. void RemoveRecord(SerializedProperty property, int index)
  1938. {
  1939. if (index > property.arraySize)
  1940. return;
  1941. property.DeleteArrayElementAtIndex(index);
  1942. serializedObject.ApplyModifiedProperties();
  1943. m_fontAsset.ReadFontAssetDefinition();
  1944. }
  1945. GlyphValueRecord GetValueRecord(SerializedProperty property)
  1946. {
  1947. GlyphValueRecord record = new GlyphValueRecord();
  1948. record.xPlacement = property.FindPropertyRelative("m_XPlacement").floatValue;
  1949. record.yPlacement = property.FindPropertyRelative("m_YPlacement").floatValue;
  1950. record.xAdvance = property.FindPropertyRelative("m_XAdvance").floatValue;
  1951. record.yAdvance = property.FindPropertyRelative("m_YAdvance").floatValue;
  1952. return record;
  1953. }
  1954. private void UpdateMarkToBaseAdjustmentRecordLookup(SerializedProperty property)
  1955. {
  1956. MarkToBaseAdjustmentRecord adjustmentRecord = GetMarkToBaseAdjustmentRecord(property);
  1957. uint firstGlyphIndex = adjustmentRecord.baseGlyphID;
  1958. uint secondGlyphIndex = adjustmentRecord.markGlyphID;
  1959. uint key = secondGlyphIndex << 16 | firstGlyphIndex;
  1960. // Lookup dictionary entry and update it
  1961. if (m_FontFeatureTable.m_MarkToBaseAdjustmentRecordLookup.ContainsKey(key))
  1962. m_FontFeatureTable.m_MarkToBaseAdjustmentRecordLookup[key] = adjustmentRecord;
  1963. }
  1964. MarkToBaseAdjustmentRecord GetMarkToBaseAdjustmentRecord(SerializedProperty property)
  1965. {
  1966. MarkToBaseAdjustmentRecord adjustmentRecord = new MarkToBaseAdjustmentRecord();
  1967. adjustmentRecord.baseGlyphID = (uint)property.FindPropertyRelative("m_BaseGlyphID").intValue;
  1968. SerializedProperty baseAnchorPointProperty = property.FindPropertyRelative("m_BaseGlyphAnchorPoint");
  1969. GlyphAnchorPoint baseAnchorPoint = new GlyphAnchorPoint();
  1970. baseAnchorPoint.xCoordinate = baseAnchorPointProperty.FindPropertyRelative("m_XCoordinate").floatValue;
  1971. baseAnchorPoint.yCoordinate = baseAnchorPointProperty.FindPropertyRelative("m_YCoordinate").floatValue;
  1972. adjustmentRecord.baseGlyphAnchorPoint = baseAnchorPoint;
  1973. adjustmentRecord.markGlyphID = (uint)property.FindPropertyRelative("m_MarkGlyphID").intValue;
  1974. SerializedProperty markAdjustmentRecordProperty = property.FindPropertyRelative("m_MarkPositionAdjustment");
  1975. MarkPositionAdjustment markAdjustmentRecord = new MarkPositionAdjustment();
  1976. markAdjustmentRecord.xPositionAdjustment = markAdjustmentRecordProperty.FindPropertyRelative("m_XPositionAdjustment").floatValue;
  1977. markAdjustmentRecord.yPositionAdjustment = markAdjustmentRecordProperty.FindPropertyRelative("m_YPositionAdjustment").floatValue;
  1978. adjustmentRecord.markPositionAdjustment = markAdjustmentRecord;
  1979. return adjustmentRecord;
  1980. }
  1981. private void UpdateMarkToMarkAdjustmentRecordLookup(SerializedProperty property)
  1982. {
  1983. MarkToMarkAdjustmentRecord adjustmentRecord = GetMarkToMarkAdjustmentRecord(property);
  1984. uint firstGlyphIndex = adjustmentRecord.baseMarkGlyphID;
  1985. uint secondGlyphIndex = adjustmentRecord.combiningMarkGlyphID;
  1986. uint key = secondGlyphIndex << 16 | firstGlyphIndex;
  1987. // Lookup dictionary entry and update it
  1988. if (m_FontFeatureTable.m_MarkToMarkAdjustmentRecordLookup.ContainsKey(key))
  1989. m_FontFeatureTable.m_MarkToMarkAdjustmentRecordLookup[key] = adjustmentRecord;
  1990. }
  1991. MarkToMarkAdjustmentRecord GetMarkToMarkAdjustmentRecord(SerializedProperty property)
  1992. {
  1993. MarkToMarkAdjustmentRecord adjustmentRecord = new MarkToMarkAdjustmentRecord();
  1994. adjustmentRecord.baseMarkGlyphID = (uint)property.FindPropertyRelative("m_BaseMarkGlyphID").intValue;
  1995. SerializedProperty baseAnchorPointProperty = property.FindPropertyRelative("m_BaseMarkGlyphAnchorPoint");
  1996. GlyphAnchorPoint baseAnchorPoint = new GlyphAnchorPoint();
  1997. baseAnchorPoint.xCoordinate = baseAnchorPointProperty.FindPropertyRelative("m_XCoordinate").floatValue;
  1998. baseAnchorPoint.yCoordinate = baseAnchorPointProperty.FindPropertyRelative("m_YCoordinate").floatValue;
  1999. adjustmentRecord.baseMarkGlyphAnchorPoint = baseAnchorPoint;
  2000. adjustmentRecord.combiningMarkGlyphID = (uint)property.FindPropertyRelative("m_CombiningMarkGlyphID").intValue;
  2001. SerializedProperty markAdjustmentRecordProperty = property.FindPropertyRelative("m_CombiningMarkPositionAdjustment");
  2002. MarkPositionAdjustment markAdjustment = new MarkPositionAdjustment();
  2003. markAdjustment.xPositionAdjustment = markAdjustmentRecordProperty.FindPropertyRelative("m_XPositionAdjustment").floatValue;
  2004. markAdjustment.yPositionAdjustment = markAdjustmentRecordProperty.FindPropertyRelative("m_YPositionAdjustment").floatValue;
  2005. adjustmentRecord.combiningMarkPositionAdjustment = markAdjustment;
  2006. return adjustmentRecord;
  2007. }
  2008. /// <summary>
  2009. ///
  2010. /// </summary>
  2011. /// <param name="srcGlyph"></param>
  2012. /// <param name="dstGlyph"></param>
  2013. void CopyGlyphSerializedProperty(SerializedProperty srcGlyph, ref SerializedProperty dstGlyph)
  2014. {
  2015. // TODO : Should make a generic function which copies each of the properties.
  2016. dstGlyph.FindPropertyRelative("m_Index").intValue = srcGlyph.FindPropertyRelative("m_Index").intValue;
  2017. // Glyph -> GlyphMetrics
  2018. SerializedProperty srcGlyphMetrics = srcGlyph.FindPropertyRelative("m_Metrics");
  2019. SerializedProperty dstGlyphMetrics = dstGlyph.FindPropertyRelative("m_Metrics");
  2020. dstGlyphMetrics.FindPropertyRelative("m_Width").floatValue = srcGlyphMetrics.FindPropertyRelative("m_Width").floatValue;
  2021. dstGlyphMetrics.FindPropertyRelative("m_Height").floatValue = srcGlyphMetrics.FindPropertyRelative("m_Height").floatValue;
  2022. dstGlyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue;
  2023. dstGlyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue;
  2024. dstGlyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue;
  2025. // Glyph -> GlyphRect
  2026. SerializedProperty srcGlyphRect = srcGlyph.FindPropertyRelative("m_GlyphRect");
  2027. SerializedProperty dstGlyphRect = dstGlyph.FindPropertyRelative("m_GlyphRect");
  2028. dstGlyphRect.FindPropertyRelative("m_X").intValue = srcGlyphRect.FindPropertyRelative("m_X").intValue;
  2029. dstGlyphRect.FindPropertyRelative("m_Y").intValue = srcGlyphRect.FindPropertyRelative("m_Y").intValue;
  2030. dstGlyphRect.FindPropertyRelative("m_Width").intValue = srcGlyphRect.FindPropertyRelative("m_Width").intValue;
  2031. dstGlyphRect.FindPropertyRelative("m_Height").intValue = srcGlyphRect.FindPropertyRelative("m_Height").intValue;
  2032. dstGlyph.FindPropertyRelative("m_Scale").floatValue = srcGlyph.FindPropertyRelative("m_Scale").floatValue;
  2033. dstGlyph.FindPropertyRelative("m_AtlasIndex").intValue = srcGlyph.FindPropertyRelative("m_AtlasIndex").intValue;
  2034. }
  2035. void CopyCharacterSerializedProperty(SerializedProperty source, ref SerializedProperty target)
  2036. {
  2037. // TODO : Should make a generic function which copies each of the properties.
  2038. int unicode = source.FindPropertyRelative("m_Unicode").intValue;
  2039. target.FindPropertyRelative("m_Unicode").intValue = unicode;
  2040. int srcGlyphIndex = source.FindPropertyRelative("m_GlyphIndex").intValue;
  2041. target.FindPropertyRelative("m_GlyphIndex").intValue = srcGlyphIndex;
  2042. target.FindPropertyRelative("m_Scale").floatValue = source.FindPropertyRelative("m_Scale").floatValue;
  2043. }
  2044. /// <summary>
  2045. ///
  2046. /// </summary>
  2047. /// <param name="searchPattern"></param>
  2048. /// <returns></returns>
  2049. void SearchGlyphTable(string searchPattern, ref List<int> searchResults)
  2050. {
  2051. if (searchResults == null) searchResults = new List<int>();
  2052. searchResults.Clear();
  2053. int arraySize = m_GlyphTable_prop.arraySize;
  2054. for (int i = 0; i < arraySize; i++)
  2055. {
  2056. SerializedProperty sourceGlyph = m_GlyphTable_prop.GetArrayElementAtIndex(i);
  2057. int id = sourceGlyph.FindPropertyRelative("m_Index").intValue;
  2058. // Check for potential match against a character.
  2059. //if (searchPattern.Length == 1 && id == searchPattern[0])
  2060. // searchResults.Add(i);
  2061. // Check for potential match against decimal id
  2062. if (id.ToString().Contains(searchPattern))
  2063. searchResults.Add(i);
  2064. //if (id.ToString("x").Contains(searchPattern))
  2065. // searchResults.Add(i);
  2066. //if (id.ToString("X").Contains(searchPattern))
  2067. // searchResults.Add(i);
  2068. }
  2069. }
  2070. void SearchCharacterTable(string searchPattern, ref List<int> searchResults)
  2071. {
  2072. if (searchResults == null) searchResults = new List<int>();
  2073. searchResults.Clear();
  2074. int arraySize = m_CharacterTable_prop.arraySize;
  2075. for (int i = 0; i < arraySize; i++)
  2076. {
  2077. SerializedProperty sourceCharacter = m_CharacterTable_prop.GetArrayElementAtIndex(i);
  2078. int id = sourceCharacter.FindPropertyRelative("m_Unicode").intValue;
  2079. // Check for potential match against a character.
  2080. if (searchPattern.Length == 1 && id == searchPattern[0])
  2081. searchResults.Add(i);
  2082. else if (id.ToString("x").Contains(searchPattern))
  2083. searchResults.Add(i);
  2084. else if (id.ToString("X").Contains(searchPattern))
  2085. searchResults.Add(i);
  2086. // Check for potential match against decimal id
  2087. //if (id.ToString().Contains(searchPattern))
  2088. // searchResults.Add(i);
  2089. }
  2090. }
  2091. void SearchLigatureTable(string searchPattern, ref List<int> searchResults)
  2092. {
  2093. if (searchResults == null) searchResults = new List<int>();
  2094. searchResults.Clear();
  2095. // Lookup glyph index of potential characters contained in the search pattern.
  2096. uint firstGlyphIndex = 0;
  2097. TMP_Character firstCharacterSearch;
  2098. if (searchPattern.Length > 0 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[0], out firstCharacterSearch))
  2099. firstGlyphIndex = firstCharacterSearch.glyphIndex;
  2100. uint secondGlyphIndex = 0;
  2101. TMP_Character secondCharacterSearch;
  2102. if (searchPattern.Length > 1 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[1], out secondCharacterSearch))
  2103. secondGlyphIndex = secondCharacterSearch.glyphIndex;
  2104. int arraySize = m_MarkToBaseAdjustmentRecords_prop.arraySize;
  2105. for (int i = 0; i < arraySize; i++)
  2106. {
  2107. SerializedProperty record = m_MarkToBaseAdjustmentRecords_prop.GetArrayElementAtIndex(i);
  2108. int baseGlyphIndex = record.FindPropertyRelative("m_BaseGlyphID").intValue;
  2109. int markGlyphIndex = record.FindPropertyRelative("m_MarkGlyphID").intValue;
  2110. if (firstGlyphIndex == baseGlyphIndex && secondGlyphIndex == markGlyphIndex)
  2111. searchResults.Add(i);
  2112. else if (searchPattern.Length == 1 && (firstGlyphIndex == baseGlyphIndex || firstGlyphIndex == markGlyphIndex))
  2113. searchResults.Add(i);
  2114. else if (baseGlyphIndex.ToString().Contains(searchPattern))
  2115. searchResults.Add(i);
  2116. else if (markGlyphIndex.ToString().Contains(searchPattern))
  2117. searchResults.Add(i);
  2118. }
  2119. }
  2120. void SearchKerningTable(string searchPattern, ref List<int> searchResults)
  2121. {
  2122. if (searchResults == null) searchResults = new List<int>();
  2123. searchResults.Clear();
  2124. // Lookup glyph index of potential characters contained in the search pattern.
  2125. uint firstGlyphIndex = 0;
  2126. TMP_Character firstCharacterSearch;
  2127. if (searchPattern.Length > 0 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[0], out firstCharacterSearch))
  2128. firstGlyphIndex = firstCharacterSearch.glyphIndex;
  2129. uint secondGlyphIndex = 0;
  2130. TMP_Character secondCharacterSearch;
  2131. if (searchPattern.Length > 1 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[1], out secondCharacterSearch))
  2132. secondGlyphIndex = secondCharacterSearch.glyphIndex;
  2133. int arraySize = m_GlyphPairAdjustmentRecords_prop.arraySize;
  2134. for (int i = 0; i < arraySize; i++)
  2135. {
  2136. SerializedProperty record = m_GlyphPairAdjustmentRecords_prop.GetArrayElementAtIndex(i);
  2137. SerializedProperty firstAdjustmentRecord = record.FindPropertyRelative("m_FirstAdjustmentRecord");
  2138. SerializedProperty secondAdjustmentRecord = record.FindPropertyRelative("m_SecondAdjustmentRecord");
  2139. int firstGlyph = firstAdjustmentRecord.FindPropertyRelative("m_GlyphIndex").intValue;
  2140. int secondGlyph = secondAdjustmentRecord.FindPropertyRelative("m_GlyphIndex").intValue;
  2141. if (firstGlyphIndex == firstGlyph && secondGlyphIndex == secondGlyph)
  2142. searchResults.Add(i);
  2143. else if (searchPattern.Length == 1 && (firstGlyphIndex == firstGlyph || firstGlyphIndex == secondGlyph))
  2144. searchResults.Add(i);
  2145. else if (firstGlyph.ToString().Contains(searchPattern))
  2146. searchResults.Add(i);
  2147. else if (secondGlyph.ToString().Contains(searchPattern))
  2148. searchResults.Add(i);
  2149. }
  2150. }
  2151. void SearchMarkToBaseTable(string searchPattern, ref List<int> searchResults)
  2152. {
  2153. if (searchResults == null) searchResults = new List<int>();
  2154. searchResults.Clear();
  2155. // Lookup glyph index of potential characters contained in the search pattern.
  2156. uint firstGlyphIndex = 0;
  2157. TMP_Character firstCharacterSearch;
  2158. if (searchPattern.Length > 0 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[0], out firstCharacterSearch))
  2159. firstGlyphIndex = firstCharacterSearch.glyphIndex;
  2160. uint secondGlyphIndex = 0;
  2161. TMP_Character secondCharacterSearch;
  2162. if (searchPattern.Length > 1 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[1], out secondCharacterSearch))
  2163. secondGlyphIndex = secondCharacterSearch.glyphIndex;
  2164. int arraySize = m_MarkToBaseAdjustmentRecords_prop.arraySize;
  2165. for (int i = 0; i < arraySize; i++)
  2166. {
  2167. SerializedProperty record = m_MarkToBaseAdjustmentRecords_prop.GetArrayElementAtIndex(i);
  2168. int baseGlyphIndex = record.FindPropertyRelative("m_BaseGlyphID").intValue;
  2169. int markGlyphIndex = record.FindPropertyRelative("m_MarkGlyphID").intValue;
  2170. if (firstGlyphIndex == baseGlyphIndex && secondGlyphIndex == markGlyphIndex)
  2171. searchResults.Add(i);
  2172. else if (searchPattern.Length == 1 && (firstGlyphIndex == baseGlyphIndex || firstGlyphIndex == markGlyphIndex))
  2173. searchResults.Add(i);
  2174. else if (baseGlyphIndex.ToString().Contains(searchPattern))
  2175. searchResults.Add(i);
  2176. else if (markGlyphIndex.ToString().Contains(searchPattern))
  2177. searchResults.Add(i);
  2178. }
  2179. }
  2180. void SearchMarkToMarkTable(string searchPattern, ref List<int> searchResults)
  2181. {
  2182. if (searchResults == null) searchResults = new List<int>();
  2183. searchResults.Clear();
  2184. // Lookup glyph index of potential characters contained in the search pattern.
  2185. uint firstGlyphIndex = 0;
  2186. TMP_Character firstCharacterSearch;
  2187. if (searchPattern.Length > 0 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[0], out firstCharacterSearch))
  2188. firstGlyphIndex = firstCharacterSearch.glyphIndex;
  2189. uint secondGlyphIndex = 0;
  2190. TMP_Character secondCharacterSearch;
  2191. if (searchPattern.Length > 1 && m_fontAsset.characterLookupTable.TryGetValue(searchPattern[1], out secondCharacterSearch))
  2192. secondGlyphIndex = secondCharacterSearch.glyphIndex;
  2193. int arraySize = m_MarkToMarkAdjustmentRecords_prop.arraySize;
  2194. for (int i = 0; i < arraySize; i++)
  2195. {
  2196. SerializedProperty record = m_MarkToMarkAdjustmentRecords_prop.GetArrayElementAtIndex(i);
  2197. int baseGlyphIndex = record.FindPropertyRelative("m_BaseMarkGlyphID").intValue;
  2198. int markGlyphIndex = record.FindPropertyRelative("m_CombiningMarkGlyphID").intValue;
  2199. if (firstGlyphIndex == baseGlyphIndex && secondGlyphIndex == markGlyphIndex)
  2200. searchResults.Add(i);
  2201. else if (searchPattern.Length == 1 && (firstGlyphIndex == baseGlyphIndex || firstGlyphIndex == markGlyphIndex))
  2202. searchResults.Add(i);
  2203. else if (baseGlyphIndex.ToString().Contains(searchPattern))
  2204. searchResults.Add(i);
  2205. else if (markGlyphIndex.ToString().Contains(searchPattern))
  2206. searchResults.Add(i);
  2207. }
  2208. }
  2209. void DrawMarkToBasePreview(int selectedRecord, Rect rect)
  2210. {
  2211. MarkToBaseAdjustmentRecord adjustmentRecord = m_fontAsset.fontFeatureTable.m_MarkToBaseAdjustmentRecords[selectedRecord];
  2212. uint baseGlyphIndex = adjustmentRecord.baseGlyphID;
  2213. uint markGlyphIndex = adjustmentRecord.markGlyphID;
  2214. if (baseGlyphIndex == 0 || markGlyphIndex == 0)
  2215. return;
  2216. float lineHeight = m_fontAsset.faceInfo.ascentLine - m_fontAsset.faceInfo.descentLine;
  2217. float scale = rect.width < rect.height ? rect.width / lineHeight : rect.height / lineHeight;
  2218. scale *= 0.9f;
  2219. Glyph baseGlyph;
  2220. m_fontAsset.glyphLookupTable.TryGetValue(baseGlyphIndex, out baseGlyph);
  2221. if (baseGlyph == null)
  2222. return;
  2223. Rect center = new Rect(rect.x + rect.width / 2, rect.y + rect.height / 2, rect.width, rect.height);
  2224. Vector2 origin = new Vector2(center.x, center.y);
  2225. origin.x = origin.x - (baseGlyph.metrics.horizontalBearingX + baseGlyph.metrics.width / 2) * scale;
  2226. origin.y = origin.y + (baseGlyph.metrics.horizontalBearingY - baseGlyph.metrics.height / 2) * scale;
  2227. // Draw Baseline
  2228. DrawBaseline(origin, rect.width, Color.grey);
  2229. // Draw Origin
  2230. DrawAnchorPoint(origin, Color.yellow);
  2231. Rect baseGlyphPosition = new Rect(origin.x + baseGlyph.metrics.horizontalBearingX * scale, origin.y - baseGlyph.metrics.horizontalBearingY * scale , rect.width, rect.height);
  2232. DrawGlyph(baseGlyph, baseGlyphPosition, scale);
  2233. Vector2 baseAnchorPosition = new Vector2(origin.x + adjustmentRecord.baseGlyphAnchorPoint.xCoordinate * scale, origin.y - adjustmentRecord.baseGlyphAnchorPoint.yCoordinate * scale);
  2234. DrawAnchorPoint(baseAnchorPosition, Color.green);
  2235. // Draw Mark
  2236. if (m_fontAsset.glyphLookupTable.ContainsKey(markGlyphIndex))
  2237. {
  2238. Glyph markGlyph = m_fontAsset.glyphLookupTable[markGlyphIndex];
  2239. Rect markGlyphPosition = new Rect(baseAnchorPosition.x + (markGlyph.metrics.horizontalBearingX - adjustmentRecord.markPositionAdjustment.xPositionAdjustment) * scale, baseAnchorPosition.y + (adjustmentRecord.markPositionAdjustment.yPositionAdjustment - markGlyph.metrics.horizontalBearingY) * scale, markGlyph.metrics.width, markGlyph.metrics.height);
  2240. // Draw Mark Origin
  2241. DrawGlyph(markGlyph, markGlyphPosition, scale);
  2242. }
  2243. }
  2244. void DrawMarkToMarkPreview(int selectedRecord, Rect rect)
  2245. {
  2246. MarkToMarkAdjustmentRecord adjustmentRecord = m_fontAsset.fontFeatureTable.m_MarkToMarkAdjustmentRecords[selectedRecord];
  2247. uint baseGlyphIndex = adjustmentRecord.baseMarkGlyphID;
  2248. uint markGlyphIndex = adjustmentRecord.combiningMarkGlyphID;
  2249. if (baseGlyphIndex == 0 || markGlyphIndex == 0)
  2250. return;
  2251. float lineHeight = m_fontAsset.faceInfo.ascentLine - m_fontAsset.faceInfo.descentLine;
  2252. float scale = rect.width < rect.height ? rect.width / lineHeight : rect.height / lineHeight;
  2253. scale *= 0.9f;
  2254. Glyph baseGlyph;
  2255. m_fontAsset.glyphLookupTable.TryGetValue(baseGlyphIndex, out baseGlyph);
  2256. if (baseGlyph == null)
  2257. return;
  2258. Rect center = new Rect(rect.x + rect.width / 2, rect.y + rect.height / 2, rect.width, rect.height);
  2259. Vector2 origin = new Vector2(center.x, center.y);
  2260. origin.x = origin.x - (baseGlyph.metrics.horizontalBearingX + baseGlyph.metrics.width / 2) * scale;
  2261. origin.y = origin.y + (baseGlyph.metrics.horizontalBearingY - baseGlyph.metrics.height / 2) * scale;
  2262. // Draw Baseline
  2263. DrawBaseline(origin, rect.width, Color.grey);
  2264. // Draw Origin
  2265. DrawAnchorPoint(origin, Color.yellow);
  2266. Rect baseGlyphPosition = new Rect(origin.x + baseGlyph.metrics.horizontalBearingX * scale, origin.y - baseGlyph.metrics.horizontalBearingY * scale , rect.width, rect.height);
  2267. DrawGlyph(baseGlyph, baseGlyphPosition, scale);
  2268. Vector2 baseAnchorPosition = new Vector2(origin.x + adjustmentRecord.baseMarkGlyphAnchorPoint.xCoordinate * scale, origin.y - adjustmentRecord.baseMarkGlyphAnchorPoint.yCoordinate * scale);
  2269. DrawAnchorPoint(baseAnchorPosition, Color.green);
  2270. // Draw Mark Glyph
  2271. if (m_fontAsset.glyphLookupTable.ContainsKey(markGlyphIndex))
  2272. {
  2273. Glyph markGlyph = m_fontAsset.glyphLookupTable[markGlyphIndex];
  2274. Rect markGlyphPosition = new Rect(baseAnchorPosition.x + (markGlyph.metrics.horizontalBearingX - adjustmentRecord.combiningMarkPositionAdjustment.xPositionAdjustment) * scale, baseAnchorPosition.y + (adjustmentRecord.combiningMarkPositionAdjustment.yPositionAdjustment - markGlyph.metrics.horizontalBearingY) * scale, markGlyph.metrics.width, markGlyph.metrics.height);
  2275. DrawGlyph(markGlyph, markGlyphPosition, scale);
  2276. }
  2277. }
  2278. void DrawBaseline(Vector2 position, float width, Color color)
  2279. {
  2280. Handles.color = color;
  2281. // Horizontal line
  2282. Handles.DrawLine(new Vector2(0f, position.y), new Vector2(width, position.y));
  2283. }
  2284. void DrawAnchorPoint(Vector2 position, Color color)
  2285. {
  2286. Handles.color = color;
  2287. // Horizontal line
  2288. Handles.DrawLine(new Vector2(position.x - 25, position.y), new Vector2(position.x + 25, position.y));
  2289. // Vertical line
  2290. Handles.DrawLine(new Vector2(position.x, position.y - 25), new Vector2(position.x, position.y + 25));
  2291. }
  2292. void DrawGlyph(Glyph glyph, Rect position, float scale)
  2293. {
  2294. // Get the atlas index of the glyph and lookup its atlas texture
  2295. int atlasIndex = glyph.atlasIndex;
  2296. Texture2D atlasTexture = m_fontAsset.atlasTextures.Length > atlasIndex ? m_fontAsset.atlasTextures[atlasIndex] : null;
  2297. if (atlasTexture == null)
  2298. return;
  2299. Material mat;
  2300. if (((GlyphRasterModes)m_fontAsset.atlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP)
  2301. {
  2302. #if TEXTCORE_FONT_ENGINE_1_5_OR_NEWER
  2303. if (m_fontAsset.atlasRenderMode == GlyphRenderMode.COLOR || m_fontAsset.atlasRenderMode == GlyphRenderMode.COLOR_HINTED)
  2304. mat = internalRGBABitmapMaterial;
  2305. else
  2306. mat = internalBitmapMaterial;
  2307. #else
  2308. mat = internalBitmapMaterial;
  2309. #endif
  2310. if (mat == null)
  2311. return;
  2312. mat.mainTexture = atlasTexture;
  2313. }
  2314. else
  2315. {
  2316. mat = internalSDFMaterial;
  2317. if (mat == null)
  2318. return;
  2319. mat.mainTexture = atlasTexture;
  2320. mat.SetFloat(ShaderUtilities.ID_GradientScale, m_fontAsset.atlasPadding + 1);
  2321. }
  2322. GlyphRect glyphRect = glyph.glyphRect;
  2323. int padding = m_fontAsset.atlasPadding;
  2324. int glyphOriginX = glyphRect.x - padding;
  2325. int glyphOriginY = glyphRect.y - padding;
  2326. int glyphWidth = glyphRect.width + padding * 2;
  2327. int glyphHeight = glyphRect.height + padding * 2;
  2328. // Compute the normalized texture coordinates
  2329. Rect texCoords = new Rect((float)glyphOriginX / atlasTexture.width, (float)glyphOriginY / atlasTexture.height, (float)glyphWidth / atlasTexture.width, (float)glyphHeight / atlasTexture.height);
  2330. if (Event.current.type == EventType.Repaint)
  2331. {
  2332. // Draw glyph from atlas texture.
  2333. Rect glyphDrawPosition = new Rect(position.x - padding * scale, position.y - padding * scale, position.width, position.height);
  2334. //glyphDrawPosition.x += (glyphDrawPosition.width - glyphWidth * scale); // / 2;
  2335. //glyphDrawPosition.y += (glyphDrawPosition.height - glyphHeight * scale); // / 2;
  2336. glyphDrawPosition.width = glyphWidth * scale;
  2337. glyphDrawPosition.height = glyphHeight * scale;
  2338. // Could switch to using the default material of the font asset which would require passing scale to the shader.
  2339. Graphics.DrawTexture(glyphDrawPosition, atlasTexture, texCoords, 0, 0, 0, 0, new Color(0.8f, 0.8f, 0.8f), mat);
  2340. }
  2341. }
  2342. }
  2343. }