using System; using System.Globalization; using System.Numerics; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.UI; using Vector2 = UnityEngine.Vector2; using Vector3 = UnityEngine.Vector3; using Vector4 = UnityEngine.Vector4; // 코드로 만드는 uGUI 도우미 (기준 해상도 1080×1920 · 원작 GamePlayUI 좌표계와 같음) namespace VS.View { public static class Pal { public static readonly Color Ink = new Color32(44, 48, 80, 255); // 남색 잉크(GUI Pro-SuperCasual 테두리 계열) public static readonly Color Navy = new Color32(38, 44, 72, 255); // 어두운 판·탭 바 public static readonly Color NavyLight = new Color32(78, 90, 136, 255); // 선택된 탭 public static readonly Color Outline = new Color(0.14f, 0.16f, 0.28f, 0.95f); public static readonly Color White = Color.white; public static readonly Color Pink = new Color32(255, 105, 170, 255); public static readonly Color PinkDark = new Color32(214, 62, 132, 255); public static readonly Color Purple = new Color32(126, 87, 214, 255); public static readonly Color PurpleDark = new Color32(84, 56, 160, 255); public static readonly Color Yellow = new Color32(255, 206, 64, 255); public static readonly Color Green = new Color32(78, 200, 120, 255); public static readonly Color GreenDark = new Color32(42, 150, 84, 255); public static readonly Color Gray = new Color32(170, 170, 185, 255); public static readonly Color Panel = new Color32(255, 255, 255, 255); public static readonly Color PanelEdge = new Color32(236, 240, 252, 255); public static readonly Color Row = new Color32(241, 243, 252, 255); // 팝업 안 줄(행) 바탕 public static readonly Color Dim = new Color(0.08f, 0.04f, 0.12f, 0.62f); public static readonly Color Blue = new Color32(84, 170, 255, 255); public static readonly Color Orange = new Color32(255, 150, 60, 255); public static readonly Color Red = new Color32(240, 72, 84, 255); } public static class Fmt { // NSHTool.Utilities.NumberShortFormatter (.cctor RVA 0x252D820) 접미사 표 그대로 · 소수점 = '.'(원작은 vi-VN ',') static readonly string[] Suf = { "", "k", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc" }; static decimal Trunc(decimal d, int n) { decimal p = 1m; for (int i = 0; i < n; i++) p *= 10m; return decimal.Truncate(d * p) / p; } public static string Num(BigInteger v, int decimals = 1) { if (v < 0) return "-" + Num(-v, decimals); if (v < 1000) return v.ToString(CultureInfo.InvariantCulture); int e = 0; BigInteger t = v; while (t >= 1000 && e < Suf.Length - 1) { t /= 1000; e++; } decimal d = (decimal)(v / BigInteger.Pow(1000, Math.Max(0, e - 1))) / 1000m; if (d >= 1000m && e == Suf.Length - 1) return t.ToString(CultureInfo.InvariantCulture) + Suf[e]; decimal r = Trunc(d, decimals); return r.ToString("0." + new string('#', decimals), CultureInfo.InvariantCulture) + Suf[e]; } public static string Num(decimal v, int decimals = 1) { if (v < 1000m) { if (v < 10m) return Trunc(v, 2).ToString("0.##", CultureInfo.InvariantCulture); return Trunc(v, 1).ToString("0.#", CultureInfo.InvariantCulture); } return Num(new BigInteger(decimal.Truncate(v)), decimals); } public static string Time(double sec) { if (sec < 0) sec = 0; int s = (int)Math.Ceiling(sec); if (s >= 3600) return $"{s / 3600}:{(s / 60) % 60:00}:{s % 60:00}"; return $"{s / 60:00}:{s % 60:00}"; } } public static class UI { static Font font; public static Font Font { get { if (font == null) font = Resources.Load("Fonts/MaplestoryBold"); if (font == null) font = Resources.GetBuiltinResource("LegacyRuntime.ttf"); return font; } } public static RectTransform Rect(string name, Transform parent) { var go = new GameObject(name, typeof(RectTransform)); go.layer = 5; var rt = (RectTransform)go.transform; rt.SetParent(parent, false); return rt; } public static RectTransform Place(this RectTransform rt, Vector2 aMin, Vector2 aMax, Vector2 pos, Vector2 size, Vector2? pivot = null) { rt.anchorMin = aMin; rt.anchorMax = aMax; rt.pivot = pivot ?? new Vector2(0.5f, 0.5f); rt.anchoredPosition = pos; rt.sizeDelta = size; return rt; } public static RectTransform Fill(this RectTransform rt, float l = 0, float b = 0, float r = 0, float t = 0) { 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; } public static Image Img(Transform parent, string name, Sprite sp, Color c, bool raycast = false) { var rt = Rect(name, parent); var im = rt.gameObject.AddComponent(); im.sprite = sp; im.color = c; im.raycastTarget = raycast; if (sp != null && sp.border != Vector4.zero) im.type = Image.Type.Sliced; return im; } public static Text Txt(Transform parent, string name, string s, int size, Color c, TextAnchor a = TextAnchor.MiddleCenter, bool outline = false) { var rt = Rect(name, parent); var t = rt.gameObject.AddComponent(); t.font = Font; t.text = s; t.fontSize = size; t.color = c; t.alignment = a; t.raycastTarget = false; t.horizontalOverflow = HorizontalWrapMode.Wrap; t.verticalOverflow = VerticalWrapMode.Truncate; t.resizeTextForBestFit = true; t.resizeTextMinSize = Math.Max(10, size / 2); t.resizeTextMaxSize = size; if (outline) { var o = rt.gameObject.AddComponent(); o.effectColor = Pal.Outline; float d = Mathf.Clamp(size / 15f, 1.5f, 3f); o.effectDistance = new Vector2(d, -d); } // 작은 글자는 얇게 return t; } /// 아이콘 그림 (비율 유지) public static Image Icon(Transform parent, string name, Sprite sp, Color c) { var im = Img(parent, name, sp, c); im.preserveAspect = true; return im; } public static Button Btn(Transform parent, string name, Sprite sp, Color c, UnityAction onClick) { var im = Img(parent, name, sp, c, true); var b = im.gameObject.AddComponent