TMP_SpriteCharacterPropertyDrawer.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using UnityEngine;
  2. using UnityEngine.TextCore;
  3. using UnityEditor;
  4. using System.Collections;
  5. namespace TMPro.EditorUtilities
  6. {
  7. [CustomPropertyDrawer(typeof(TMP_SpriteCharacter))]
  8. public class TMP_SpriteCharacterPropertyDrawer : PropertyDrawer
  9. {
  10. int m_GlyphSelectedForEditing = -1;
  11. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
  12. {
  13. SerializedProperty prop_SpriteName = property.FindPropertyRelative("m_Name");
  14. SerializedProperty prop_SpriteNameHashCode = property.FindPropertyRelative("m_HashCode");
  15. SerializedProperty prop_SpriteUnicode = property.FindPropertyRelative("m_Unicode");
  16. SerializedProperty prop_SpriteGlyphIndex = property.FindPropertyRelative("m_GlyphIndex");
  17. SerializedProperty prop_SpriteScale = property.FindPropertyRelative("m_Scale");
  18. GUIStyle style = new GUIStyle(EditorStyles.label);
  19. style.richText = true;
  20. EditorGUIUtility.labelWidth = 40f;
  21. EditorGUIUtility.fieldWidth = 50;
  22. Rect rect = new Rect(position.x + 60, position.y, position.width, 49);
  23. // Display non-editable fields
  24. if (GUI.enabled == false)
  25. {
  26. // Sprite Character Index
  27. int.TryParse(property.displayName.Split(' ')[1], out int spriteCharacterIndex);
  28. EditorGUI.LabelField(new Rect(rect.x, rect.y, 75f, 18), new GUIContent("Index: <color=#FFFF80>" + spriteCharacterIndex + "</color>"), style);
  29. EditorGUI.LabelField(new Rect(rect.x + 75f, rect.y, 120f, 18), new GUIContent("Unicode: <color=#FFFF80>0x" + prop_SpriteUnicode.intValue.ToString("X") + "</color>"), style);
  30. EditorGUI.LabelField(new Rect(rect.x + 195f, rect.y, rect.width - 255, 18), new GUIContent("Name: <color=#FFFF80>" + prop_SpriteName.stringValue + "</color>"), style);
  31. EditorGUI.LabelField(new Rect(rect.x, rect.y + 18, 120, 18), new GUIContent("Glyph ID: <color=#FFFF80>" + prop_SpriteGlyphIndex.intValue + "</color>"), style);
  32. // Draw Sprite Glyph (if exists)
  33. DrawSpriteGlyph(position, property);
  34. EditorGUI.LabelField(new Rect(rect.x, rect.y + 36, 80, 18), new GUIContent("Scale: <color=#FFFF80>" + prop_SpriteScale.floatValue + "</color>"), style);
  35. }
  36. else // Display editable fields
  37. {
  38. // Get a reference to the underlying Sprite Asset
  39. TMP_SpriteAsset spriteAsset = property.serializedObject.targetObject as TMP_SpriteAsset;
  40. // Sprite Character Index
  41. int.TryParse(property.displayName.Split(' ')[1], out int spriteCharacterIndex);
  42. EditorGUI.LabelField(new Rect(rect.x, rect.y, 75f, 18), new GUIContent("Index: <color=#FFFF80>" + spriteCharacterIndex + "</color>"), style);
  43. EditorGUIUtility.labelWidth = 55f;
  44. GUI.SetNextControlName("Unicode Input");
  45. EditorGUI.BeginChangeCheck();
  46. string unicode = EditorGUI.DelayedTextField(new Rect(rect.x + 75f, rect.y, 120, 18), "Unicode:", prop_SpriteUnicode.intValue.ToString("X"));
  47. if (GUI.GetNameOfFocusedControl() == "Unicode Input")
  48. {
  49. //Filter out unwanted characters.
  50. char chr = Event.current.character;
  51. if ((chr < '0' || chr > '9') && (chr < 'a' || chr > 'f') && (chr < 'A' || chr > 'F'))
  52. {
  53. Event.current.character = '\0';
  54. }
  55. }
  56. if (EditorGUI.EndChangeCheck())
  57. {
  58. // Update Unicode value
  59. prop_SpriteUnicode.intValue = TMP_TextUtilities.StringHexToInt(unicode);
  60. spriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
  61. }
  62. EditorGUIUtility.labelWidth = 41f;
  63. EditorGUI.BeginChangeCheck();
  64. EditorGUI.DelayedTextField(new Rect(rect.x + 195f, rect.y, rect.width - 255, 18), prop_SpriteName, new GUIContent("Name:"));
  65. if (EditorGUI.EndChangeCheck())
  66. {
  67. // Recompute hashCode for new name
  68. prop_SpriteNameHashCode.intValue = TMP_TextUtilities.GetSimpleHashCode(prop_SpriteName.stringValue);
  69. spriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
  70. }
  71. EditorGUIUtility.labelWidth = 59f;
  72. EditorGUI.BeginChangeCheck();
  73. EditorGUI.DelayedIntField(new Rect(rect.x, rect.y + 18, 100, 18), prop_SpriteGlyphIndex, new GUIContent("Glyph ID:"));
  74. if (EditorGUI.EndChangeCheck())
  75. {
  76. spriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
  77. }
  78. // Draw Sprite Glyph (if exists)
  79. DrawSpriteGlyph(position, property);
  80. int glyphIndex = prop_SpriteGlyphIndex.intValue;
  81. // Reset glyph selection if new character has been selected.
  82. if (GUI.enabled && m_GlyphSelectedForEditing != glyphIndex)
  83. m_GlyphSelectedForEditing = -1;
  84. // Display button to edit the glyph data.
  85. if (GUI.Button(new Rect(rect.x + 120, rect.y + 18, 75, 18), new GUIContent("Edit Glyph")))
  86. {
  87. if (m_GlyphSelectedForEditing == -1)
  88. m_GlyphSelectedForEditing = glyphIndex;
  89. else
  90. m_GlyphSelectedForEditing = -1;
  91. // Button clicks should not result in potential change.
  92. GUI.changed = false;
  93. }
  94. // Show the glyph property drawer if selected
  95. if (glyphIndex == m_GlyphSelectedForEditing && GUI.enabled)
  96. {
  97. if (spriteAsset != null)
  98. {
  99. // Lookup glyph and draw glyph (if available)
  100. int elementIndex = spriteAsset.spriteGlyphTable.FindIndex(item => item.index == glyphIndex);
  101. if (elementIndex != -1)
  102. {
  103. // Get a reference to the Sprite Glyph Table
  104. SerializedProperty prop_SpriteGlyphTable = property.serializedObject.FindProperty("m_SpriteGlyphTable");
  105. SerializedProperty prop_SpriteGlyph = prop_SpriteGlyphTable.GetArrayElementAtIndex(elementIndex);
  106. SerializedProperty prop_GlyphMetrics = prop_SpriteGlyph.FindPropertyRelative("m_Metrics");
  107. SerializedProperty prop_GlyphRect = prop_SpriteGlyph.FindPropertyRelative("m_GlyphRect");
  108. Rect newRect = EditorGUILayout.GetControlRect(false, 115);
  109. EditorGUI.DrawRect(new Rect(newRect.x + 62, newRect.y - 20, newRect.width - 62, newRect.height - 5), new Color(0.1f, 0.1f, 0.1f, 0.45f));
  110. EditorGUI.DrawRect(new Rect(newRect.x + 63, newRect.y - 19, newRect.width - 64, newRect.height - 7), new Color(0.3f, 0.3f, 0.3f, 0.8f));
  111. // Display GlyphRect
  112. newRect.x += 65;
  113. newRect.y -= 18;
  114. newRect.width += 5;
  115. EditorGUI.PropertyField(newRect, prop_GlyphRect);
  116. // Display GlyphMetrics
  117. newRect.y += 45;
  118. EditorGUI.PropertyField(newRect, prop_GlyphMetrics);
  119. rect.y += 120;
  120. }
  121. }
  122. }
  123. EditorGUIUtility.labelWidth = 39f;
  124. EditorGUI.PropertyField(new Rect(rect.x, rect.y + 36, 80, 18), prop_SpriteScale, new GUIContent("Scale:"));
  125. }
  126. }
  127. public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
  128. {
  129. return 58;
  130. }
  131. void DrawSpriteGlyph(Rect position, SerializedProperty property)
  132. {
  133. // Get a reference to the sprite glyph table
  134. TMP_SpriteAsset spriteAsset = property.serializedObject.targetObject as TMP_SpriteAsset;
  135. if (spriteAsset == null)
  136. return;
  137. int glyphIndex = property.FindPropertyRelative("m_GlyphIndex").intValue;
  138. // Lookup glyph and draw glyph (if available)
  139. int elementIndex = spriteAsset.spriteGlyphTable.FindIndex(item => item.index == glyphIndex);
  140. if (elementIndex != -1)
  141. {
  142. // Get a reference to the Sprite Glyph Table
  143. SerializedProperty prop_SpriteGlyphTable = property.serializedObject.FindProperty("m_SpriteGlyphTable");
  144. SerializedProperty prop_SpriteGlyph = prop_SpriteGlyphTable.GetArrayElementAtIndex(elementIndex);
  145. SerializedProperty prop_GlyphRect = prop_SpriteGlyph.FindPropertyRelative("m_GlyphRect");
  146. // Get a reference to the sprite texture
  147. Texture tex = spriteAsset.spriteSheet;
  148. // Return if we don't have a texture assigned to the sprite asset.
  149. if (tex == null)
  150. {
  151. Debug.LogWarning("Please assign a valid Sprite Atlas texture to the [" + spriteAsset.name + "] Sprite Asset.", spriteAsset);
  152. return;
  153. }
  154. Vector2 spriteTexPosition = new Vector2(position.x, position.y);
  155. Vector2 spriteSize = new Vector2(48, 48);
  156. Vector2 alignmentOffset = new Vector2((58 - spriteSize.x) / 2, (58 - spriteSize.y) / 2);
  157. float x = prop_GlyphRect.FindPropertyRelative("m_X").intValue;
  158. float y = prop_GlyphRect.FindPropertyRelative("m_Y").intValue;
  159. float spriteWidth = prop_GlyphRect.FindPropertyRelative("m_Width").intValue;
  160. float spriteHeight = prop_GlyphRect.FindPropertyRelative("m_Height").intValue;
  161. if (spriteWidth >= spriteHeight)
  162. {
  163. spriteSize.y = spriteHeight * spriteSize.x / spriteWidth;
  164. spriteTexPosition.y += (spriteSize.x - spriteSize.y) / 2;
  165. }
  166. else
  167. {
  168. spriteSize.x = spriteWidth * spriteSize.y / spriteHeight;
  169. spriteTexPosition.x += (spriteSize.y - spriteSize.x) / 2;
  170. }
  171. // Compute the normalized texture coordinates
  172. Rect texCoords = new Rect(x / tex.width, y / tex.height, spriteWidth / tex.width, spriteHeight / tex.height);
  173. GUI.DrawTextureWithTexCoords(new Rect(spriteTexPosition.x + alignmentOffset.x, spriteTexPosition.y + alignmentOffset.y, spriteSize.x, spriteSize.y), tex, texCoords, true);
  174. }
  175. }
  176. }
  177. }