123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- using UnityEngine;
- using UnityEngine.TextCore;
- using UnityEngine.TextCore.LowLevel;
- using UnityEditor;
- using System.Collections;
- using System.Text.RegularExpressions;
- namespace TMPro.EditorUtilities
- {
- [CustomPropertyDrawer(typeof(TMP_GlyphPairAdjustmentRecord))]
- public class TMP_GlyphPairAdjustmentRecordPropertyDrawer : PropertyDrawer
- {
- private bool isEditingEnabled = false;
- private bool isSelectable = false;
- private string m_FirstCharacter = string.Empty;
- private string m_SecondCharacter = string.Empty;
- private string m_PreviousInput;
- static GUIContent s_CharacterTextFieldLabel = new GUIContent("Char:", "Enter the character or its UTF16 or UTF32 Unicode character escape sequence. For UTF16 use \"\\uFF00\" and for UTF32 use \"\\UFF00FF00\" representation.");
- public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
- {
- SerializedProperty prop_FirstAdjustmentRecord = property.FindPropertyRelative("m_FirstAdjustmentRecord");
- SerializedProperty prop_SecondAdjustmentRecord = property.FindPropertyRelative("m_SecondAdjustmentRecord");
- SerializedProperty prop_FirstGlyphIndex = prop_FirstAdjustmentRecord.FindPropertyRelative("m_GlyphIndex");
- SerializedProperty prop_FirstGlyphValueRecord = prop_FirstAdjustmentRecord.FindPropertyRelative("m_GlyphValueRecord");
- SerializedProperty prop_SecondGlyphIndex = prop_SecondAdjustmentRecord.FindPropertyRelative("m_GlyphIndex");
- SerializedProperty prop_SecondGlyphValueRecord = prop_SecondAdjustmentRecord.FindPropertyRelative("m_GlyphValueRecord");
- SerializedProperty prop_FontFeatureLookupFlags = property.FindPropertyRelative("m_FeatureLookupFlags");
- position.yMin += 2;
- float width = position.width / 2;
- float padding = 5.0f;
- Rect rect;
- isEditingEnabled = GUI.enabled;
- isSelectable = label.text == "Selectable" ? true : false;
- if (isSelectable)
- GUILayoutUtility.GetRect(position.width, 75);
- else
- GUILayoutUtility.GetRect(position.width, 55);
- GUIStyle style = new GUIStyle(EditorStyles.label);
- style.richText = true;
- // First Glyph
- GUI.enabled = isEditingEnabled;
- if (isSelectable)
- {
- rect = new Rect(position.x + 70, position.y, position.width, 49);
- float labelWidth = GUI.skin.label.CalcSize(new GUIContent("ID: " + prop_FirstGlyphIndex.intValue)).x;
- EditorGUI.LabelField(new Rect(position.x + (64 - labelWidth) / 2, position.y + 60, 64f, 18f), new GUIContent("ID: <color=#FFFF80>" + prop_FirstGlyphIndex.intValue + "</color>"), style);
- GUI.enabled = isEditingEnabled;
- EditorGUIUtility.labelWidth = 30f;
- rect = new Rect(position.x + 70, position.y + 10, (width - 70) - padding, 18);
- EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_XPlacement"), new GUIContent("OX:"));
- rect.y += 20;
- EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_YPlacement"), new GUIContent("OY:"));
- rect.y += 20;
- EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_XAdvance"), new GUIContent("AX:"));
- //rect.y += 20;
- //EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_YAdvance"), new GUIContent("AY:"));
- DrawGlyph((uint)prop_FirstGlyphIndex.intValue, new Rect(position.x, position.y, position.width, position.height), property);
- }
- else
- {
- rect = new Rect(position.x, position.y, width / 2 * 0.8f - padding, 18);
- EditorGUIUtility.labelWidth = 40f;
- // First Character Lookup
- GUI.SetNextControlName("FirstCharacterField");
- EditorGUI.BeginChangeCheck();
- string firstCharacter = EditorGUI.TextField(rect, s_CharacterTextFieldLabel, m_FirstCharacter);
- if (GUI.GetNameOfFocusedControl() == "FirstCharacterField")
- {
- if (ValidateInput(firstCharacter))
- {
- //Debug.Log("1st Unicode value: [" + firstCharacter + "]");
- uint unicode = GetUnicodeCharacter(firstCharacter);
- // Lookup glyph index
- TMP_SerializedPropertyHolder propertyHolder = property.serializedObject.targetObject as TMP_SerializedPropertyHolder;
- TMP_FontAsset fontAsset = propertyHolder.fontAsset;
- if (fontAsset != null)
- {
- prop_FirstGlyphIndex.intValue = (int)fontAsset.GetGlyphIndex(unicode);
- propertyHolder.firstCharacter = unicode;
- }
- }
- }
- if (EditorGUI.EndChangeCheck())
- m_FirstCharacter = firstCharacter;
- // First Glyph Index
- rect.x += width / 2 * 0.8f;
- EditorGUIUtility.labelWidth = 25f;
- EditorGUI.BeginChangeCheck();
- EditorGUI.PropertyField(rect, prop_FirstGlyphIndex, new GUIContent("ID:"));
- if (EditorGUI.EndChangeCheck())
- {
- }
- GUI.enabled = isEditingEnabled;
- EditorGUIUtility.labelWidth = 25f;
- rect = new Rect(position.x, position.y + 20, width * 0.5f - padding, 18);
- EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_XPlacement"), new GUIContent("OX"));
- rect.x += width * 0.5f;
- EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_YPlacement"), new GUIContent("OY"));
- rect.x = position.x;
- rect.y += 20;
- EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_XAdvance"), new GUIContent("AX"));
- //rect.x += width * 0.5f;
- //EditorGUI.PropertyField(rect, prop_FirstGlyphAdjustment.FindPropertyRelative("m_YAdvance"), new GUIContent("AY"));
- }
- // Second Glyph
- GUI.enabled = isEditingEnabled;
- if (isSelectable)
- {
- float labelWidth = GUI.skin.label.CalcSize(new GUIContent("ID: " + prop_SecondGlyphIndex.intValue)).x;
- EditorGUI.LabelField(new Rect(position.width / 2 + 20 + (64 - labelWidth) / 2, position.y + 60, 64f, 18f), new GUIContent("ID: <color=#FFFF80>" + prop_SecondGlyphIndex.intValue + "</color>"), style);
- GUI.enabled = isEditingEnabled;
- EditorGUIUtility.labelWidth = 30f;
- rect = new Rect(position.width / 2 + 20 + 70, position.y + 10, (width - 70) - padding, 18);
- EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_XPlacement"), new GUIContent("OX:"));
- rect.y += 20;
- EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_YPlacement"), new GUIContent("OY:"));
- rect.y += 20;
- EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_XAdvance"), new GUIContent("AX:"));
- //rect.y += 20;
- //EditorGUI.PropertyField(rect, prop_SecondGlyphAdjustment.FindPropertyRelative("m_YAdvance"), new GUIContent("AY"));
- DrawGlyph((uint)prop_SecondGlyphIndex.intValue, new Rect(position.width / 2 + 20, position.y, position.width, position.height), property);
- }
- else
- {
- rect = new Rect(position.width / 2 + 20, position.y, width / 2 * 0.8f - padding, 18);
- EditorGUIUtility.labelWidth = 40f;
- // Second Character Lookup
- GUI.SetNextControlName("SecondCharacterField");
- EditorGUI.BeginChangeCheck();
- string secondCharacter = EditorGUI.TextField(rect, s_CharacterTextFieldLabel, m_SecondCharacter);
- if (GUI.GetNameOfFocusedControl() == "SecondCharacterField")
- {
- if (ValidateInput(secondCharacter))
- {
- //Debug.Log("2nd Unicode value: [" + secondCharacter + "]");
- uint unicode = GetUnicodeCharacter(secondCharacter);
- // Lookup glyph index
- TMP_SerializedPropertyHolder propertyHolder = property.serializedObject.targetObject as TMP_SerializedPropertyHolder;
- TMP_FontAsset fontAsset = propertyHolder.fontAsset;
- if (fontAsset != null)
- {
- prop_SecondGlyphIndex.intValue = (int)fontAsset.GetGlyphIndex(unicode);
- propertyHolder.secondCharacter = unicode;
- }
- }
- }
- if (EditorGUI.EndChangeCheck())
- m_SecondCharacter = secondCharacter;
- // Second Glyph Index
- rect.x += width / 2 * 0.8f;
- EditorGUIUtility.labelWidth = 25f;
- EditorGUI.BeginChangeCheck();
- EditorGUI.PropertyField(rect, prop_SecondGlyphIndex, new GUIContent("ID:"));
- if (EditorGUI.EndChangeCheck())
- {
- }
- GUI.enabled = isEditingEnabled;
- EditorGUIUtility.labelWidth = 25f;
- rect = new Rect(position.width / 2 + 20, position.y + 20, width * 0.5f - padding, 18);
- EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_XPlacement"), new GUIContent("OX"));
- rect.x += width * 0.5f;
- EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_YPlacement"), new GUIContent("OY"));
- rect.x = position.width / 2 + 20;
- rect.y += 20;
- EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_XAdvance"), new GUIContent("AX"));
- //rect.x += width * 0.5f;
- //EditorGUI.PropertyField(rect, prop_SecondGlyphAdjustment.FindPropertyRelative("m_YAdvance"), new GUIContent("AY"));
- }
- // Font Feature Lookup Flags
- if (isSelectable)
- {
- EditorGUIUtility.labelWidth = 55f;
- rect.x = position.width - 255;
- rect.y += 23;
- rect.width = 270; // width - 70 - padding;
- FontFeatureLookupFlags flags = (FontFeatureLookupFlags)prop_FontFeatureLookupFlags.intValue;
- EditorGUI.BeginChangeCheck();
- flags = (FontFeatureLookupFlags)EditorGUI.EnumFlagsField(rect, new GUIContent("Options:"), flags);
- if (EditorGUI.EndChangeCheck())
- {
- prop_FontFeatureLookupFlags.intValue = (int)flags;
- }
- }
- }
- bool ValidateInput(string source)
- {
- int length = string.IsNullOrEmpty(source) ? 0 : source.Length;
- ////Filter out unwanted characters.
- Event evt = Event.current;
- char c = evt.character;
- if (c != '\0')
- {
- switch (length)
- {
- case 0:
- break;
- case 1:
- if (source != m_PreviousInput)
- return true;
- if ((source[0] == '\\' && (c == 'u' || c == 'U')) == false)
- evt.character = '\0';
- break;
- case 2:
- case 3:
- case 4:
- case 5:
- if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F'))
- evt.character = '\0';
- break;
- case 6:
- case 7:
- case 8:
- case 9:
- if (source[1] == 'u' || (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F'))
- evt.character = '\0';
- // Validate input
- if (length == 6 && source[1] == 'u' && source != m_PreviousInput)
- return true;
- break;
- case 10:
- if (source != m_PreviousInput)
- return true;
- evt.character = '\0';
- break;
- }
- }
- m_PreviousInput = source;
- return false;
- }
- uint GetUnicodeCharacter (string source)
- {
- uint unicode;
- if (source.Length == 1)
- unicode = source[0];
- else if (source.Length == 6)
- unicode = (uint)TMP_TextUtilities.StringHexToInt(source.Replace("\\u", ""));
- else
- unicode = (uint)TMP_TextUtilities.StringHexToInt(source.Replace("\\U", ""));
- return unicode;
- }
- void DrawGlyph(uint glyphIndex, Rect position, SerializedProperty property)
- {
- // Get a reference to the sprite texture
- TMP_FontAsset fontAsset = property.serializedObject.targetObject as TMP_FontAsset;
- if (fontAsset == null)
- return;
- // Check if glyph currently exists in the atlas texture.
- if (!fontAsset.glyphLookupTable.TryGetValue(glyphIndex, out Glyph glyph))
- return;
- // Get reference to atlas texture.
- int atlasIndex = fontAsset.m_AtlasTextureIndex;
- Texture2D atlasTexture = fontAsset.atlasTextures.Length > atlasIndex ? fontAsset.atlasTextures[atlasIndex] : null;
- if (atlasTexture == null)
- return;
- Material mat;
- if (((GlyphRasterModes)fontAsset.atlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP)
- {
- mat = TMP_FontAssetEditor.internalBitmapMaterial;
- if (mat == null)
- return;
- mat.mainTexture = atlasTexture;
- }
- else
- {
- mat = TMP_FontAssetEditor.internalSDFMaterial;
- if (mat == null)
- return;
- mat.mainTexture = atlasTexture;
- mat.SetFloat(ShaderUtilities.ID_GradientScale, fontAsset.atlasPadding + 1);
- }
- // Draw glyph from atlas texture.
- Rect glyphDrawPosition = new Rect(position.x, position.y + 2, 64, 60);
- GlyphRect glyphRect = glyph.glyphRect;
- float normalizedHeight = fontAsset.faceInfo.ascentLine - fontAsset.faceInfo.descentLine;
- float scale = glyphDrawPosition.width / normalizedHeight;
- // Compute the normalized texture coordinates
- Rect texCoords = new Rect((float)glyphRect.x / atlasTexture.width, (float)glyphRect.y / atlasTexture.height, (float)glyphRect.width / atlasTexture.width, (float)glyphRect.height / atlasTexture.height);
- if (Event.current.type == EventType.Repaint)
- {
- glyphDrawPosition.x += (glyphDrawPosition.width - glyphRect.width * scale) / 2;
- glyphDrawPosition.y += (glyphDrawPosition.height - glyphRect.height * scale) / 2;
- glyphDrawPosition.width = glyphRect.width * scale;
- glyphDrawPosition.height = glyphRect.height * scale;
- // Could switch to using the default material of the font asset which would require passing scale to the shader.
- Graphics.DrawTexture(glyphDrawPosition, atlasTexture, texCoords, 0, 0, 0, 0, new Color(1f, 1f, 1f), mat);
- }
- }
- }
- }
|