TMP_SpriteAssetImporter.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.TextCore;
  4. using UnityEditor;
  5. using System.IO;
  6. using System.Collections.Generic;
  7. using TMPro.EditorUtilities;
  8. using TMPro.SpriteAssetUtilities;
  9. namespace TMPro
  10. {
  11. public class TMP_SpriteAssetImporter : EditorWindow
  12. {
  13. // Create Sprite Asset Editor Window
  14. [MenuItem("Window/TextMeshPro/Sprite Importer", false, 2026)]
  15. public static void ShowFontAtlasCreatorWindow()
  16. {
  17. var window = GetWindow<TMP_SpriteAssetImporter>();
  18. window.titleContent = new GUIContent("Sprite Importer");
  19. window.Focus();
  20. }
  21. Texture2D m_SpriteAtlas;
  22. SpriteAssetImportFormats m_SpriteDataFormat = SpriteAssetImportFormats.TexturePackerJsonArray;
  23. TextAsset m_JsonFile;
  24. string m_CreationFeedback;
  25. TMP_SpriteAsset m_SpriteAsset;
  26. List<TMP_Sprite> m_SpriteInfoList = new List<TMP_Sprite>();
  27. /// <summary>
  28. ///
  29. /// </summary>
  30. void OnEnable()
  31. {
  32. // Set Editor Window Size
  33. SetEditorWindowSize();
  34. }
  35. /// <summary>
  36. ///
  37. /// </summary>
  38. public void OnGUI()
  39. {
  40. DrawEditorPanel();
  41. }
  42. /// <summary>
  43. ///
  44. /// </summary>
  45. private void OnDisable()
  46. {
  47. // Clean up sprite asset object that may have been created and not saved.
  48. if (m_SpriteAsset != null && !EditorUtility.IsPersistent(m_SpriteAsset))
  49. DestroyImmediate(m_SpriteAsset);
  50. }
  51. /// <summary>
  52. ///
  53. /// </summary>
  54. void DrawEditorPanel()
  55. {
  56. // label
  57. GUILayout.Label("Import Settings", EditorStyles.boldLabel);
  58. EditorGUI.BeginChangeCheck();
  59. // Sprite Texture Selection
  60. m_JsonFile = EditorGUILayout.ObjectField("Sprite Data Source", m_JsonFile, typeof(TextAsset), false) as TextAsset;
  61. m_SpriteDataFormat = (SpriteAssetImportFormats)EditorGUILayout.EnumPopup("Import Format", m_SpriteDataFormat);
  62. // Sprite Texture Selection
  63. m_SpriteAtlas = EditorGUILayout.ObjectField("Sprite Texture Atlas", m_SpriteAtlas, typeof(Texture2D), false) as Texture2D;
  64. if (EditorGUI.EndChangeCheck())
  65. {
  66. m_CreationFeedback = string.Empty;
  67. }
  68. GUILayout.Space(10);
  69. GUI.enabled = m_JsonFile != null && m_SpriteAtlas != null && m_SpriteDataFormat != SpriteAssetImportFormats.None;
  70. // Create Sprite Asset
  71. if (GUILayout.Button("Create Sprite Asset"))
  72. {
  73. m_CreationFeedback = string.Empty;
  74. // Clean up sprite asset object that may have been previously created.
  75. if (m_SpriteAsset != null && !EditorUtility.IsPersistent(m_SpriteAsset))
  76. DestroyImmediate(m_SpriteAsset);
  77. // Read json data file
  78. if (m_JsonFile != null)
  79. {
  80. switch (m_SpriteDataFormat)
  81. {
  82. case SpriteAssetImportFormats.TexturePackerJsonArray:
  83. TexturePacker_JsonArray.SpriteDataObject jsonData = null;
  84. try
  85. {
  86. jsonData = JsonUtility.FromJson<TexturePacker_JsonArray.SpriteDataObject>(m_JsonFile.text);
  87. }
  88. catch
  89. {
  90. m_CreationFeedback = "The Sprite Data Source file [" + m_JsonFile.name + "] appears to be invalid or incorrectly formatted.";
  91. }
  92. if (jsonData != null && jsonData.frames != null && jsonData.frames.Count > 0)
  93. {
  94. int spriteCount = jsonData.frames.Count;
  95. // Update import results
  96. m_CreationFeedback = "<b>Import Results</b>\n--------------------\n";
  97. m_CreationFeedback += "<color=#C0ffff><b>" + spriteCount + "</b></color> Sprites were imported from file.";
  98. // Create new Sprite Asset
  99. m_SpriteAsset = CreateInstance<TMP_SpriteAsset>();
  100. // Assign sprite sheet / atlas texture to sprite asset
  101. m_SpriteAsset.spriteSheet = m_SpriteAtlas;
  102. List<TMP_SpriteGlyph> spriteGlyphTable = new List<TMP_SpriteGlyph>();
  103. List<TMP_SpriteCharacter> spriteCharacterTable = new List<TMP_SpriteCharacter>();
  104. PopulateSpriteTables(jsonData, spriteCharacterTable, spriteGlyphTable);
  105. m_SpriteAsset.spriteCharacterTable = spriteCharacterTable;
  106. m_SpriteAsset.spriteGlyphTable = spriteGlyphTable;
  107. }
  108. break;
  109. }
  110. }
  111. }
  112. GUI.enabled = true;
  113. // Creation Feedback
  114. GUILayout.Space(5);
  115. GUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Height(60));
  116. {
  117. EditorGUILayout.TextArea(m_CreationFeedback, TMP_UIStyleManager.label);
  118. }
  119. GUILayout.EndVertical();
  120. GUILayout.Space(5);
  121. GUI.enabled = m_JsonFile != null && m_SpriteAtlas && m_SpriteInfoList != null && m_SpriteAsset != null;
  122. if (GUILayout.Button("Save Sprite Asset") && m_JsonFile != null)
  123. {
  124. string filePath = EditorUtility.SaveFilePanel("Save Sprite Asset File", new FileInfo(AssetDatabase.GetAssetPath(m_JsonFile)).DirectoryName, m_JsonFile.name, "asset");
  125. if (filePath.Length == 0)
  126. return;
  127. SaveSpriteAsset(filePath);
  128. }
  129. GUI.enabled = true;
  130. }
  131. /// <summary>
  132. ///
  133. /// </summary>
  134. /// <param name="spriteDataObject"></param>
  135. /// <param name="spriteCharacterTable"></param>
  136. /// <param name="spriteGlyphTable"></param>
  137. private static void PopulateSpriteTables(TexturePacker_JsonArray.SpriteDataObject spriteDataObject, List<TMP_SpriteCharacter> spriteCharacterTable, List<TMP_SpriteGlyph> spriteGlyphTable)
  138. {
  139. List<TexturePacker_JsonArray.Frame> importedSprites = spriteDataObject.frames;
  140. float atlasHeight = spriteDataObject.meta.size.h;
  141. for (int i = 0; i < importedSprites.Count; i++)
  142. {
  143. TexturePacker_JsonArray.Frame spriteData = importedSprites[i];
  144. TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph();
  145. spriteGlyph.index = (uint)i;
  146. spriteGlyph.metrics = new GlyphMetrics((int)spriteData.frame.w, (int)spriteData.frame.h, -spriteData.frame.w * spriteData.pivot.x, spriteData.frame.h * spriteData.pivot.y, (int)spriteData.frame.w);
  147. spriteGlyph.glyphRect = new GlyphRect((int)spriteData.frame.x, (int)(atlasHeight - spriteData.frame.h - spriteData.frame.y), (int)spriteData.frame.w, (int)spriteData.frame.h);
  148. spriteGlyph.scale = 1.0f;
  149. spriteGlyphTable.Add(spriteGlyph);
  150. TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0, spriteGlyph);
  151. spriteCharacter.name = spriteData.filename.Split('.')[0];
  152. spriteCharacter.unicode = 0xFFFE;
  153. spriteCharacter.scale = 1.0f;
  154. spriteCharacterTable.Add(spriteCharacter);
  155. }
  156. }
  157. /// <summary>
  158. ///
  159. /// </summary>
  160. /// <param name="filePath"></param>
  161. void SaveSpriteAsset(string filePath)
  162. {
  163. filePath = filePath.Substring(0, filePath.Length - 6); // Trim file extension from filePath.
  164. string dataPath = Application.dataPath;
  165. if (filePath.IndexOf(dataPath, System.StringComparison.InvariantCultureIgnoreCase) == -1)
  166. {
  167. Debug.LogError("You're saving the font asset in a directory outside of this project folder. This is not supported. Please select a directory under \"" + dataPath + "\"");
  168. return;
  169. }
  170. string relativeAssetPath = filePath.Substring(dataPath.Length - 6);
  171. string dirName = Path.GetDirectoryName(relativeAssetPath);
  172. string fileName = Path.GetFileNameWithoutExtension(relativeAssetPath);
  173. string pathNoExt = dirName + "/" + fileName;
  174. // Save Sprite Asset
  175. AssetDatabase.CreateAsset(m_SpriteAsset, pathNoExt + ".asset");
  176. // Set version number
  177. m_SpriteAsset.version = "1.1.0";
  178. // Compute the hash code for the sprite asset.
  179. m_SpriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(m_SpriteAsset.name);
  180. // Add new default material for sprite asset.
  181. AddDefaultMaterial(m_SpriteAsset);
  182. }
  183. /// <summary>
  184. /// Create and add new default material to sprite asset.
  185. /// </summary>
  186. /// <param name="spriteAsset"></param>
  187. static void AddDefaultMaterial(TMP_SpriteAsset spriteAsset)
  188. {
  189. Shader shader = Shader.Find("TextMeshPro/Sprite");
  190. Material material = new Material(shader);
  191. material.SetTexture(ShaderUtilities.ID_MainTex, spriteAsset.spriteSheet);
  192. spriteAsset.material = material;
  193. material.hideFlags = HideFlags.HideInHierarchy;
  194. AssetDatabase.AddObjectToAsset(material, spriteAsset);
  195. }
  196. /// <summary>
  197. /// Limits the minimum size of the editor window.
  198. /// </summary>
  199. void SetEditorWindowSize()
  200. {
  201. EditorWindow editorWindow = this;
  202. Vector2 currentWindowSize = editorWindow.minSize;
  203. editorWindow.minSize = new Vector2(Mathf.Max(230, currentWindowSize.x), Mathf.Max(300, currentWindowSize.y));
  204. }
  205. }
  206. }