using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace TKS.OutGame
{
///
/// 아웃게임 UI 도우미 — uGUI + Malgun Gothic(TextUtil) · 기준 1080×1920 · 배치 = 확정 목업(img03·05·06·07·08·11·13·14·16·17).
/// 부품·색 = UI 테마(PD #1100 · Layer Lab GUI Pro-SuperCasual 팩 · UISkin) · 테마가 없으면 기존 도형 와이어프레임.
/// 위치 인자는 전부 「부모 안 기준점(anchor) · 피벗 · 기준점에서의 거리 · 크기」(UI px).
///
public static class UiKit
{
// 팔레트 = 테마 색 id(ui_theme.csv) · 괄호 값 = 테마가 없을 때(구 와이어프레임)
public static Color Bg { get { return UISkin.Col("bg", new Color(0.95f, 0.92f, 0.85f)); } }
public static Color Paper { get { return UISkin.Col("paper", new Color(0.99f, 0.97f, 0.92f)); } }
public static Color Header { get { return UISkin.Col("header", new Color(0.92f, 0.87f, 0.78f)); } }
public static Color HeaderText { get { return UISkin.Col("header_text", Ink); } }
public static Color HeaderSub { get { return UISkin.Col("header_sub", InkSoft); } }
public static Color Ink { get { return UISkin.Col("ink", new Color(0.17f, 0.12f, 0.10f)); } }
public static Color InkSoft { get { return UISkin.Col("ink_soft", new Color(0.45f, 0.39f, 0.34f)); } }
public static Color Dark { get { return UISkin.Col("dark", new Color(0.21f, 0.16f, 0.14f)); } }
public static Color Red { get { return UISkin.Col("red", new Color(0.74f, 0.26f, 0.19f)); } }
public static Color Line { get { return UISkin.Col("line", new Color(0.33f, 0.26f, 0.22f)); } }
public static Color Slot { get { return UISkin.Col("slot", new Color(0.80f, 0.76f, 0.70f)); } }
public static Color Coin { get { return UISkin.Col("coin", new Color(0.88f, 0.67f, 0.20f)); } }
public static Color Jade { get { return UISkin.Col("jade", new Color(0.27f, 0.60f, 0.52f)); } }
public static Color Grain { get { return UISkin.Col("grain", new Color(0.76f, 0.58f, 0.38f)); } }
public static Color Ok { get { return UISkin.Col("ok", new Color(0.36f, 0.62f, 0.31f)); } }
public static Color Star { get { return UISkin.Col("star", new Color(0.93f, 0.68f, 0.13f)); } }
public static Color Disabled { get { return UISkin.Col("disabled", new Color(0.66f, 0.62f, 0.58f)); } }
public static Color Purple { get { return UISkin.Col("purple", new Color(0.58f, 0.36f, 0.70f)); } }
public static Color BarColor { get { return UISkin.Col("bar", new Color(0.15f, 0.11f, 0.09f)); } }
public static Color Stroke { get { return UISkin.Col("stroke", new Color(0.12f, 0.1f, 0.1f)); } }
public static readonly Color White = Color.white;
public static Color Col(string id, Color fallback)
{
return UISkin.Col(id, fallback);
}
static Sprite round;
/// 둥근 모서리 9-slice(모서리 22 px).
public static Sprite Round
{
get
{
if (round == null) round = MakeRound(64, 22);
return round;
}
}
public static Sprite Circle
{
get { return ProceduralSprites.Circle; }
}
static Sprite MakeRound(int size, int radius)
{
var tex = new Texture2D(size, size, TextureFormat.RGBA32, false);
tex.wrapMode = TextureWrapMode.Clamp;
tex.hideFlags = HideFlags.DontSave;
var px = new Color[size * size];
for (int y = 0; y < size; y++)
for (int x = 0; x < size; x++)
{
float cx = Mathf.Clamp(x + 0.5f, radius, size - radius);
float cy = Mathf.Clamp(y + 0.5f, radius, size - radius);
float d = Vector2.Distance(new Vector2(x + 0.5f, y + 0.5f), new Vector2(cx, cy));
px[y * size + x] = new Color(1f, 1f, 1f, Mathf.Clamp01(radius - d + 0.5f));
}
tex.SetPixels(px);
tex.Apply();
float b = radius + 2;
var sp = Sprite.Create(tex, new Rect(0, 0, size, size), new Vector2(0.5f, 0.5f), 100f, 0, SpriteMeshType.FullRect, new Vector4(b, b, b, b));
sp.hideFlags = HideFlags.DontSave;
return sp;
}
// ---------- 기본 ----------
public static RectTransform Rect(string name, Transform parent, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size)
{
var go = new GameObject(name, typeof(RectTransform));
go.transform.SetParent(parent, false);
var rt = (RectTransform)go.transform;
rt.anchorMin = rt.anchorMax = anchor;
rt.pivot = pivot;
rt.anchoredPosition = pos;
rt.sizeDelta = size;
return rt;
}
/// 부모 전체에서 안쪽 여백(왼·오·위·아래)만 뺀 영역.
public static RectTransform Fill(string name, Transform parent, float l = 0f, float r = 0f, float t = 0f, float b = 0f)
{
var go = new GameObject(name, typeof(RectTransform));
go.transform.SetParent(parent, false);
var rt = (RectTransform)go.transform;
rt.anchorMin = Vector2.zero;
rt.anchorMax = Vector2.one;
rt.pivot = new Vector2(0.5f, 0.5f);
rt.offsetMin = new Vector2(l, b);
rt.offsetMax = new Vector2(-r, -t);
return rt;
}
/// 위쪽 띠(부모 가로 전체 · 위에서 top 아래 · 높이 h).
public static RectTransform TopBand(string name, Transform parent, float top, float h, float l = 0f, float r = 0f)
{
var go = new GameObject(name, typeof(RectTransform));
go.transform.SetParent(parent, false);
var rt = (RectTransform)go.transform;
rt.anchorMin = new Vector2(0f, 1f);
rt.anchorMax = new Vector2(1f, 1f);
rt.pivot = new Vector2(0.5f, 1f);
rt.offsetMin = new Vector2(l, -top - h);
rt.offsetMax = new Vector2(-r, -top);
return rt;
}
///
/// 칠하기 — rounded = 팩 카드(흰 바탕 + 굵은 외곽선 · 색 틴트 · 반투명이면 외곽선 없는 판) · false = 평면 띠.
///
public static Image Paint(RectTransform rt, Color c, bool rounded = true, bool raycast = false)
{
var img = rt.gameObject.AddComponent();
img.color = c;
if (rounded && !UISkin.Apply(img, c.a >= 0.95f ? "card" : "soft"))
{
img.sprite = Round;
img.type = Image.Type.Sliced;
}
img.raycastTarget = raycast;
return img;
}
/// 스킨 id 로 칠하기(없으면 둥근 도형).
public static Image Skin(RectTransform rt, string skin, Color c, bool raycast = false)
{
var img = rt.gameObject.AddComponent();
img.color = c;
if (!UISkin.Apply(img, skin))
{
img.sprite = Round;
img.type = Image.Type.Sliced;
}
img.raycastTarget = raycast;
return img;
}
/// 아이콘(테마 id · 없으면 null).
public static Image Icon(Transform parent, string id, Vector2 anchor, Vector2 pivot, Vector2 pos, float size)
{
return UISkin.IconImage(parent, id, anchor, pivot, pos, new Vector2(size, size));
}
/// 아이콘이 있으면 아이콘 · 없으면 원 + 글자(구 표시).
public static Image IconOrDot(Transform parent, string id, string mark, Color c, Vector2 anchor, Vector2 pivot, Vector2 pos, float size)
{
var ic = Icon(parent, id, anchor, pivot, pos, size);
if (ic != null) return ic;
var dot = Dot("Icon", parent, anchor, pivot, pos, size, c);
FillLabel(dot.transform, mark, Mathf.RoundToInt(size * 0.5f), White);
return dot;
}
/// 제목 폰트(Sen-ExtraBold + 한글 폴백) + 흰 글자 외곽선.
public static Text Title(Text t, bool stroke = false)
{
t.font = UISkin.TitleFont;
if (stroke && UISkin.On) UISkin.Stroke(t, Stroke, 3f);
return t;
}
public static Image Box(string name, Transform parent, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size, Color c, bool rounded = true)
{
return Paint(Rect(name, parent, anchor, pivot, pos, size), c, rounded);
}
public static Image Dot(string name, Transform parent, Vector2 anchor, Vector2 pivot, Vector2 pos, float d, Color c)
{
var img = Rect(name, parent, anchor, pivot, pos, new Vector2(d, d)).gameObject.AddComponent();
if (d > 280f || !UISkin.Apply(img, "dot")) img.sprite = Circle; // 큰 원(후광 등)은 팩 외곽선이 흐려져서 평면 원
img.preserveAspect = true;
img.color = c;
img.raycastTarget = false;
return img;
}
/// 테두리(외곽선 효과 · 둥근 상자에 굵은 선처럼 보임) · 테마 카드는 외곽선을 이미 가져서 기본 선 색이면 생략.
public static void Border(Graphic g, Color c, float w = 4f)
{
if (UISkin.On && c == Line) return;
if (UISkin.On) w = Mathf.Min(w, 3f);
var o = g.gameObject.AddComponent();
o.effectColor = c;
o.effectDistance = new Vector2(w, -w);
o.useGraphicAlpha = false;
var o2 = g.gameObject.AddComponent();
o2.effectColor = c;
o2.effectDistance = new Vector2(-w, w);
o2.useGraphicAlpha = false;
}
public static Text Label(Transform parent, string s, int size, Color c, TextAnchor align, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 box, bool bold = true)
{
var rt = Rect("Text", parent, anchor, pivot, pos, box);
return Style(rt.gameObject.AddComponent(), s, size, c, align, bold);
}
/// 부모 전체에 꽉 찬 글자(가운데 정렬 기본).
public static Text FillLabel(Transform parent, string s, int size, Color c, TextAnchor align = TextAnchor.MiddleCenter, bool bold = true, float pad = 0f)
{
var rt = Fill("Text", parent, pad, pad, 0f, 0f);
return Style(rt.gameObject.AddComponent(), s, size, c, align, bold);
}
static Text Style(Text t, string s, int size, Color c, TextAnchor align, bool bold)
{
t.font = TextUtil.Font;
t.fontSize = size;
t.fontStyle = bold ? FontStyle.Bold : FontStyle.Normal;
t.alignment = align;
t.color = c;
t.horizontalOverflow = HorizontalWrapMode.Wrap;
t.verticalOverflow = VerticalWrapMode.Overflow;
t.supportRichText = true;
t.raycastTarget = false;
t.text = s;
return t;
}
public static Button Btn(string name, Transform parent, string label, int fontSize, Color bg, Color fg, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size, Action onClick)
{
var img = Skin(Rect(name, parent, anchor, pivot, pos, size), "button", bg, true);
var b = img.gameObject.AddComponent