using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using UnityEditor; using UnityEngine; using UnityEngine.TextCore; using TMPro; public static class SpriteAssetGenerator { [MenuItem("Tools/Generate Prize Sprite Assets")] public static void Generate() { string sourceDir = "Assets/Resources/Sprites/UI/Labels"; string destDir = "Assets/Resources/Sprite Assets"; if (!Directory.Exists(destDir)) { Directory.CreateDirectory(destDir); AssetDatabase.Refresh(); } if (!Directory.Exists(sourceDir)) { Debug.LogError($"[SpriteAssetGenerator] Source directory not found: {sourceDir}"); return; } string[] pngFiles = Directory.GetFiles(sourceDir, "*.png"); if (pngFiles.Length == 0) { Debug.LogWarning($"[SpriteAssetGenerator] No PNG files found in {sourceDir}"); return; } foreach (string pngPath in pngFiles) { try { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath); string assetPath = $"{destDir}/{fileNameWithoutExtension}.asset"; Texture2D sourceTex = AssetDatabase.LoadAssetAtPath(pngPath); if (sourceTex == null) { Debug.LogWarning($"[SpriteAssetGenerator] Failed to load Texture2D at: {pngPath}"); continue; } // Create new Sprite Asset TMP_SpriteAsset spriteAsset = ScriptableObject.CreateInstance(); spriteAsset.name = fileNameWithoutExtension; spriteAsset.spriteInfoList = new List(); // Set version to 1.1.0 to avoid UpgradeSpriteAsset trigger in Awake/UpdateLookupTables var versionField = typeof(TMP_Asset).GetField("m_Version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (versionField != null) { versionField.SetValue(spriteAsset, "1.1.0"); } spriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(fileNameWithoutExtension); spriteAsset.spriteSheet = sourceTex; // Populate tables List spriteGlyphTable = new List(); List spriteCharacterTable = new List(); // Get all sprites contained in this texture file Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(pngPath) .Select(x => x as Sprite) .Where(x => x != null) .OrderByDescending(x => x.rect.y) .ThenBy(x => x.rect.x) .ToArray(); if (sprites.Length == 0) { Debug.LogWarning($"[SpriteAssetGenerator] No sprites sliced inside texture {pngPath}. Make sure it is sliced as Sprite (Multiple) or Sprite (Single)."); continue; } // Configure FaceInfo to scale the sprites properly float baseHeight = sprites[0].rect.height; FaceInfo faceInfo = spriteAsset.faceInfo; faceInfo.pointSize = (int)baseHeight; faceInfo.scale = 1.0f; faceInfo.ascentLine = baseHeight; faceInfo.capLine = baseHeight * 0.7f; faceInfo.baseline = 0; faceInfo.descentLine = 0; spriteAsset.faceInfo = faceInfo; for (int i = 0; i < sprites.Length; i++) { Sprite sprite = sprites[i]; TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph(); spriteGlyph.index = (uint)i; float spriteHeight = sprite.rect.height; // Center the sprite vertically around the cap-height (70% of font size) float bearingY = spriteHeight * 0.85f; float bearingX = 0f; spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, bearingX, bearingY, sprite.rect.width); spriteGlyph.glyphRect = new GlyphRect(sprite.rect); spriteGlyph.scale = 1.0f; spriteGlyph.sprite = sprite; spriteGlyphTable.Add(spriteGlyph); TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0xFFFE, spriteGlyph); spriteCharacter.name = sprite.name; spriteCharacter.scale = 1.0f; spriteCharacterTable.Add(spriteCharacter); } spriteAsset.spriteCharacterTable.Clear(); spriteAsset.spriteCharacterTable.AddRange(spriteCharacterTable); spriteAsset.spriteGlyphTable.Clear(); spriteAsset.spriteGlyphTable.AddRange(spriteGlyphTable); // Add default material Shader shader = Shader.Find("TextMeshPro/Sprite"); if (shader == null) { shader = Shader.Find("UI/Default"); } if (shader == null) { Debug.LogError("[SpriteAssetGenerator] Shader not found!"); continue; } Material material = new Material(shader); material.SetTexture(ShaderUtilities.ID_MainTex, sourceTex); material.name = fileNameWithoutExtension + " Material"; AssetDatabase.CreateAsset(spriteAsset, assetPath); AssetDatabase.AddObjectToAsset(material, spriteAsset); spriteAsset.material = material; spriteAsset.UpdateLookupTables(); EditorUtility.SetDirty(spriteAsset); Debug.Log($"[SpriteAssetGenerator] Created Sprite Asset at: {assetPath} with {sprites.Length} sprites."); } catch (System.Exception ex) { Debug.LogException(ex); } } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } }