using System; using System.Collections.Generic; using TMPro; using UnityEngine; namespace BrewMonster.Scripts.Chat.EmotionData { /// /// Snapshot một bộ Emotions{N} (dùng embed trong EmotionLibrarySO hoặc copy sang EmotionSetDataSO). /// One Emotions{N} snapshot (embedded in EmotionLibrarySO or copied to EmotionSetDataSO). /// [Serializable] public class EmotionSetSnapshot { public int EmotionSetIndex; public int CellWidth = 32; public int CellHeight = 32; public Texture2D SourceAtlas; public string SourceTxtAssetPath = ""; [Tooltip("TMP_SpriteAsset tương ứng với atlas này (cell_0000…). Bắt buộc cho emoji động (nhiều frame). " + "TMP_SpriteAsset matching this atlas (cell_0000…). Required for animated emoji (multi-frame).")] public TMP_SpriteAsset TmpSpriteAsset; [Tooltip("Bản sao tên asset (khớp TmpSpriteAsset.name) — dùng khi build tag chat từ thread mạng; không được đọc TmpSpriteAsset.name ngoài main thread. " + "Cached asset name (matches TmpSpriteAsset.name) — used when building chat tags from the network thread; never read TmpSpriteAsset.name off the main thread.")] public string TmpSpriteAssetName = ""; public List Entries = new List(); } /// /// Một ScriptableObject chứa nhiều bộ emotion (vd. emotions0–emotions7). /// Single SO holding multiple emotion sets (e.g. all 8 atlases). /// [CreateAssetMenu(fileName = "EmotionLibrary", menuName = "Perfect World/Chat/Emotion Library (All Sets)", order = 1)] public class EmotionLibrarySO : ScriptableObject { [Tooltip("Danh sách các bộ theo EmotionSetIndex (0,1,2,…).")] public List Sets = new List(); private void OnValidate() { SyncCachedTmpSpriteAssetNamesFromObjects(); } /// /// 把各 set 的 TmpSpriteAsset.name 写入 TmpSpriteAssetName(仅应在主线程调用,例如 Awake / OnValidate)。 /// Writes each set's TmpSpriteAsset.name into TmpSpriteAssetName (call from main thread only, e.g. Awake / OnValidate). /// public void SyncCachedTmpSpriteAssetNamesFromObjects() { if (Sets == null) return; foreach (EmotionSetSnapshot s in Sets) { if (s == null) continue; s.TmpSpriteAssetName = s.TmpSpriteAsset != null ? s.TmpSpriteAsset.name : string.Empty; } } public EmotionSetSnapshot GetSetOrNull(int emotionSetIndex) { if (Sets == null) return null; foreach (var s in Sets) { if (s != null && s.EmotionSetIndex == emotionSetIndex) return s; } return null; } } }