Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Добавлен Editor-скрипт SpriteAssetGenerator для автоматической генерации TMP Sprite Asset'ов из текстур призов. - Сгенерированы TMP Sprite Asset'ы (Prize, Prize_Hopper, Prize_Marbles, Prize_QR, Prize_Tickets) в папке Assets/Resources/Sprite Assets. - Настроены FaceInfo и вертикальное центрирование спрайтов относительно текста. - Обновлен RulesPrizeListPage.cs: вместо текстовых названий призов выводятся соответствующие пиктограммы с помощью тегов <sprite>. - Добавлены новые файлы текстур призов и их мета-файлы в коммит.
163 lines
6.3 KiB
C#
163 lines
6.3 KiB
C#
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<Texture2D>(pngPath);
|
|
if (sourceTex == null)
|
|
{
|
|
Debug.LogWarning($"[SpriteAssetGenerator] Failed to load Texture2D at: {pngPath}");
|
|
continue;
|
|
}
|
|
|
|
// Create new Sprite Asset
|
|
TMP_SpriteAsset spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
|
|
spriteAsset.name = fileNameWithoutExtension;
|
|
spriteAsset.spriteInfoList = new List<TMP_Sprite>();
|
|
|
|
// 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<TMP_SpriteGlyph> spriteGlyphTable = new List<TMP_SpriteGlyph>();
|
|
List<TMP_SpriteCharacter> spriteCharacterTable = new List<TMP_SpriteCharacter>();
|
|
|
|
// 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();
|
|
}
|
|
}
|