using System;
using System.Collections.Generic;
using UnityEngine;
namespace TKS
{
///
/// UI 테마(PD #1100 UI 리뉴얼 · 2026-11-06) — 색 팔레트 · 9-slice 부품(스킨) · 아이콘 id → 스프라이트 치환 테이블 · 제목 폰트.
/// SOT = Assets/Data/UI/ui_theme.csv → 메뉴 TKS/Import UI Theme → Resources/UI/UITheme.asset(에디터 UIThemeImporter).
/// 스킨·아이콘은 팩(Layer Lab GUI Pro-SuperCasual · Assets/UI/GUIPro) 기본 + 신규 제작 납품(Assets/UI/Samguk/**/<id>.png)이 있으면 그것으로 치환.
/// 화면 코드는 id 로만 묻는다(스프라이트 경로를 코드에 쓰지 않는다 · C45).
///
[CreateAssetMenu(menuName = "TKS/UI Theme")]
public class UITheme : ScriptableObject
{
public const string ResourcePath = "UI/UITheme";
[Serializable]
public class ColorEntry
{
public string id;
public Color color = Color.white;
}
[Serializable]
public class SkinEntry
{
public string id;
/// 팩 바탕(흰 계열 = 호출 색으로 틴트).
public Sprite pack;
/// 신규 제작 치환(있으면 pack 대신).
public Sprite samguk;
/// 위 덮개(광택·글리프 · 틴트 안 함).
public Sprite overlay;
/// 9-slice 배율(Image.pixelsPerUnitMultiplier · 클수록 테두리가 얇다).
public float ppu = 1f;
/// 덮개 안쪽 여백(px · 왼 · 위 · 오 · 아래).
public Vector4 inset;
/// 덮개 불투명도.
public float overlayAlpha = 1f;
public Sprite Sprite
{
get { return samguk != null ? samguk : pack; }
}
}
[Serializable]
public class IconEntry
{
public string id;
public Sprite pack;
public Sprite samguk;
/// 표시 색(흰 실루엣 아이콘용 · 기본 흰색 = 원색 그대로).
public Color tint = Color.white;
public Sprite Sprite
{
get { return samguk != null ? samguk : pack; }
}
}
public List colors = new List();
public List skins = new List();
public List icons = new List();
/// 제목·숫자 강조(Sen-ExtraBold · 한글 = 임포터 폴백 Malgun Gothic · PD 결정 전).
public Font titleFont;
Dictionary colorMap;
Dictionary skinMap;
Dictionary iconMap;
static UITheme current;
static bool tried;
/// Resources/UI/UITheme(없으면 null = 기존 도형 UI 로 동작).
public static UITheme Current
{
get
{
if (current == null && !tried)
{
tried = true;
current = Resources.Load(ResourcePath);
}
return current;
}
}
/// 테마 교체(임포트 뒤 · 테스트) — null = 다시 Resources 에서 읽음.
public static void Use(UITheme t)
{
current = t;
tried = t != null;
if (t != null) t.Rebuild();
}
public void Rebuild()
{
colorMap = new Dictionary();
foreach (var c in colors)
if (c != null && !string.IsNullOrEmpty(c.id)) colorMap[c.id] = c;
skinMap = new Dictionary();
foreach (var s in skins)
if (s != null && !string.IsNullOrEmpty(s.id)) skinMap[s.id] = s;
iconMap = new Dictionary();
foreach (var i in icons)
if (i != null && !string.IsNullOrEmpty(i.id)) iconMap[i.id] = i;
}
void OnEnable()
{
colorMap = null;
}
void Ensure()
{
if (colorMap == null || skinMap == null || iconMap == null) Rebuild();
}
public bool TryColor(string id, out Color c)
{
Ensure();
ColorEntry e;
if (id != null && colorMap.TryGetValue(id, out e))
{
c = e.color;
return true;
}
c = Color.white;
return false;
}
public SkinEntry Skin(string id)
{
Ensure();
SkinEntry e;
return id != null && skinMap.TryGetValue(id, out e) && e.Sprite != null ? e : null;
}
public IconEntry IconEntryOf(string id)
{
Ensure();
IconEntry e;
return id != null && iconMap.TryGetValue(id, out e) && e.Sprite != null ? e : null;
}
public Sprite Icon(string id)
{
var e = IconEntryOf(id);
return e != null ? e.Sprite : null;
}
}
}