TMP_SpriteCharacterPropertyDrawer.cs 11 KB

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