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.

240 lines
9.6 KiB

  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Linq;
  4. using System.IO;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. namespace TMPro.EditorUtilities
  8. {
  9. public static class TMP_SpriteAssetMenu
  10. {
  11. // Add a Context Menu to the Sprite Asset Editor Panel to Create and Add a Default Material.
  12. [MenuItem("CONTEXT/TMP_SpriteAsset/Add Default Material", false, 2000)]
  13. static void CopyTexture(MenuCommand command)
  14. {
  15. TMP_SpriteAsset spriteAsset = (TMP_SpriteAsset)command.context;
  16. // Make sure the sprite asset already contains a default material
  17. if (spriteAsset != null && spriteAsset.material == null)
  18. {
  19. // Add new default material for sprite asset.
  20. AddDefaultMaterial(spriteAsset);
  21. }
  22. }
  23. [MenuItem("Assets/Create/TextMeshPro/Sprite Asset", false, 100)]
  24. public static void CreateTextMeshProObjectPerform()
  25. {
  26. Object target = Selection.activeObject;
  27. // Make sure the selection is a texture.
  28. if (target == null || target.GetType() != typeof(Texture2D))
  29. {
  30. Debug.LogWarning("A texture which contains sprites must first be selected in order to create a TextMesh Pro Sprite Asset.");
  31. return;
  32. }
  33. Texture2D sourceTex = target as Texture2D;
  34. // Get the path to the selected texture.
  35. string filePathWithName = AssetDatabase.GetAssetPath(sourceTex);
  36. string fileNameWithExtension = Path.GetFileName(filePathWithName);
  37. string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePathWithName);
  38. string filePath = filePathWithName.Replace(fileNameWithExtension, "");
  39. // Check if Sprite Asset already exists
  40. TMP_SpriteAsset spriteAsset = AssetDatabase.LoadAssetAtPath(filePath + fileNameWithoutExtension + ".asset", typeof(TMP_SpriteAsset)) as TMP_SpriteAsset;
  41. bool isNewAsset = spriteAsset == null ? true : false;
  42. if (isNewAsset)
  43. {
  44. // Create new Sprite Asset using this texture
  45. spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
  46. AssetDatabase.CreateAsset(spriteAsset, filePath + fileNameWithoutExtension + ".asset");
  47. // Compute the hash code for the sprite asset.
  48. spriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(spriteAsset.name);
  49. // Assign new Sprite Sheet texture to the Sprite Asset.
  50. spriteAsset.spriteSheet = sourceTex;
  51. spriteAsset.spriteInfoList = GetSpriteInfo(sourceTex);
  52. // Add new default material for sprite asset.
  53. AddDefaultMaterial(spriteAsset);
  54. }
  55. else
  56. {
  57. spriteAsset.spriteInfoList = UpdateSpriteInfo(spriteAsset);
  58. // Make sure the sprite asset already contains a default material
  59. if (spriteAsset.material == null)
  60. {
  61. // Add new default material for sprite asset.
  62. AddDefaultMaterial(spriteAsset);
  63. }
  64. }
  65. // Get the Sprites contained in the Sprite Sheet
  66. EditorUtility.SetDirty(spriteAsset);
  67. //spriteAsset.sprites = sprites;
  68. // Set source texture back to Not Readable.
  69. //texImporter.isReadable = false;
  70. AssetDatabase.SaveAssets();
  71. AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(spriteAsset)); // Re-import font asset to get the new updated version.
  72. //AssetDatabase.Refresh();
  73. }
  74. private static List<TMP_Sprite> GetSpriteInfo(Texture source)
  75. {
  76. //Debug.Log("Creating new Sprite Asset.");
  77. string filePath = AssetDatabase.GetAssetPath(source);
  78. // Get all the Sprites sorted by Index
  79. Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).OrderByDescending(x => x.rect.y).ThenBy(x => x.rect.x).ToArray();
  80. List<TMP_Sprite> spriteInfoList = new List<TMP_Sprite>();
  81. for (int i = 0; i < sprites.Length; i++)
  82. {
  83. TMP_Sprite spriteInfo = new TMP_Sprite();
  84. Sprite sprite = sprites[i];
  85. //spriteInfo.fileID = UnityEditor.Unsupported.GetLocalIdentifierInFile(sprite.GetInstanceID());
  86. spriteInfo.id = i;
  87. spriteInfo.name = sprite.name;
  88. spriteInfo.hashCode = TMP_TextUtilities.GetSimpleHashCode(spriteInfo.name);
  89. Rect spriteRect = sprite.rect;
  90. spriteInfo.x = spriteRect.x;
  91. spriteInfo.y = spriteRect.y;
  92. spriteInfo.width = spriteRect.width;
  93. spriteInfo.height = spriteRect.height;
  94. // Compute Sprite pivot position
  95. Vector2 pivot = new Vector2(0 - (sprite.bounds.min.x) / (sprite.bounds.extents.x * 2), 0 - (sprite.bounds.min.y) / (sprite.bounds.extents.y * 2));
  96. spriteInfo.pivot = new Vector2(0 - pivot.x * spriteRect.width, spriteRect.height - pivot.y * spriteRect.height);
  97. spriteInfo.sprite = sprite;
  98. // Properties the can be modified
  99. spriteInfo.xAdvance = spriteRect.width;
  100. spriteInfo.scale = 1.0f;
  101. spriteInfo.xOffset = spriteInfo.pivot.x;
  102. spriteInfo.yOffset = spriteInfo.pivot.y;
  103. spriteInfoList.Add(spriteInfo);
  104. }
  105. return spriteInfoList;
  106. }
  107. /// <summary>
  108. /// Create and add new default material to sprite asset.
  109. /// </summary>
  110. /// <param name="spriteAsset"></param>
  111. private static void AddDefaultMaterial(TMP_SpriteAsset spriteAsset)
  112. {
  113. Shader shader = Shader.Find("TextMeshPro/Sprite");
  114. Material material = new Material(shader);
  115. material.SetTexture(ShaderUtilities.ID_MainTex, spriteAsset.spriteSheet);
  116. spriteAsset.material = material;
  117. material.hideFlags = HideFlags.HideInHierarchy;
  118. AssetDatabase.AddObjectToAsset(material, spriteAsset);
  119. }
  120. // Update existing SpriteInfo
  121. private static List<TMP_Sprite> UpdateSpriteInfo(TMP_SpriteAsset spriteAsset)
  122. {
  123. //Debug.Log("Updating Sprite Asset.");
  124. string filePath = AssetDatabase.GetAssetPath(spriteAsset.spriteSheet);
  125. // Get all the Sprites sorted Left to Right / Top to Bottom
  126. Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).OrderByDescending(x => x.rect.y).ThenBy(x => x.rect.x).ToArray();
  127. for (int i = 0; i < sprites.Length; i++)
  128. {
  129. Sprite sprite = sprites[i];
  130. // Check if the sprite is already contained in the SpriteInfoList
  131. int index = -1;
  132. if (spriteAsset.spriteInfoList.Count > i && spriteAsset.spriteInfoList[i].sprite != null)
  133. index = spriteAsset.spriteInfoList.FindIndex(item => item.sprite.GetInstanceID() == sprite.GetInstanceID());
  134. // Use existing SpriteInfo if it already exists
  135. TMP_Sprite spriteInfo = index == -1 ? new TMP_Sprite() : spriteAsset.spriteInfoList[index];
  136. Rect spriteRect = sprite.rect;
  137. spriteInfo.x = spriteRect.x;
  138. spriteInfo.y = spriteRect.y;
  139. spriteInfo.width = spriteRect.width;
  140. spriteInfo.height = spriteRect.height;
  141. // Get Sprite Pivot
  142. Vector2 pivot = new Vector2(0 - (sprite.bounds.min.x) / (sprite.bounds.extents.x * 2), 0 - (sprite.bounds.min.y) / (sprite.bounds.extents.y * 2));
  143. // The position of the pivot influences the Offset position.
  144. spriteInfo.pivot = new Vector2(0 - pivot.x * spriteRect.width, spriteRect.height - pivot.y * spriteRect.height);
  145. if (index == -1)
  146. {
  147. // Find the next available index for this Sprite
  148. int[] ids = spriteAsset.spriteInfoList.Select(item => item.id).ToArray();
  149. int id = 0;
  150. for (int j = 0; j < ids.Length; j++ )
  151. {
  152. if (ids[0] != 0) break;
  153. if (j > 0 && (ids[j] - ids[j - 1]) > 1)
  154. {
  155. id = ids[j - 1] + 1;
  156. break;
  157. }
  158. id = j + 1;
  159. }
  160. spriteInfo.sprite = sprite;
  161. spriteInfo.name = sprite.name;
  162. spriteInfo.hashCode = TMP_TextUtilities.GetSimpleHashCode(spriteInfo.name);
  163. spriteInfo.id = id;
  164. spriteInfo.xAdvance = spriteRect.width;
  165. spriteInfo.scale = 1.0f;
  166. spriteInfo.xOffset = spriteInfo.pivot.x;
  167. spriteInfo.yOffset = spriteInfo.pivot.y;
  168. spriteAsset.spriteInfoList.Add(spriteInfo);
  169. // Sort the Sprites by ID
  170. spriteAsset.spriteInfoList = spriteAsset.spriteInfoList.OrderBy(s => s.id).ToList();
  171. }
  172. else
  173. {
  174. spriteAsset.spriteInfoList[index] = spriteInfo;
  175. }
  176. }
  177. return spriteAsset.spriteInfoList;
  178. }
  179. }
  180. }