using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using VS.Sim; using Vector2 = UnityEngine.Vector2; // 의상 팝업 — 원작 ClosetPopup(미리보기 · 레벨 업그레이드 · 의상 칸 목록 · 장착) namespace VS.View { public partial class GameApp { public void OpenCloset() { var p = NewPopup("Closet", L("UI.Closet.Title", "의상"), 1640, Pal.Pink); var top = UI.Img(p.body, "Preview", Skin.Round, new Color32(255, 236, 246, 255)); top.rectTransform.Place(new Vector2(0, 1), new Vector2(1, 1), new Vector2(0, 0), new Vector2(0, 560), new Vector2(0.5f, 1)); var idol = UI.Img(top.transform, "Idol", null, Color.white); idol.preserveAspect = true; idol.rectTransform.Place(new Vector2(0, 0.5f), new Vector2(0, 0.5f), new Vector2(190, 0), new Vector2(340, 520)); var lv = UI.Txt(top.transform, "Level", "", 50, Pal.Ink, TextAnchor.MiddleLeft); lv.rectTransform.Place(new Vector2(0, 1), new Vector2(1, 1), new Vector2(380, -70), new Vector2(-400, 70), new Vector2(0, 0.5f)); var stat = UI.Txt(top.transform, "Stat", "", 36, Pal.PinkDark, TextAnchor.MiddleLeft); stat.rectTransform.Place(new Vector2(0, 1), new Vector2(1, 1), new Vector2(380, -150), new Vector2(-400, 60), new Vector2(0, 0.5f)); var cond = UI.Txt(top.transform, "Cond", "", 30, new Color32(120, 100, 140, 255), TextAnchor.MiddleLeft); cond.rectTransform.Place(new Vector2(0, 1), new Vector2(1, 1), new Vector2(380, -220), new Vector2(-400, 60), new Vector2(0, 0.5f)); var up = UI.TextBtn(top.transform, "Upgrade", "", Pal.Green, 38, () => { var r = G.UpgradeCloset(); if (r != BuyResult.Ok) Toast(r == BuyResult.Locked ? "랭크가 부족합니다" : BuyMsg(r)); RefreshAll(); }, out var upText); up.GetComponent().Place(new Vector2(0, 0), new Vector2(0, 0), new Vector2(620, 120), new Vector2(440, 150)); // 의상 칸 (5열) var grid = UI.Rect("Grid", p.body).Fill(0, 0, 0, 590); var sr = UI.Scroll(grid, "Scroll", out var content, 10); sr.GetComponent().Fill(); Object.DestroyImmediate(content.GetComponent()); var gl = content.gameObject.AddComponent(); gl.cellSize = new Vector2(170, 210); gl.spacing = new Vector2(14, 14); gl.padding = new RectOffset(6, 6, 6, 30); gl.constraint = GridLayoutGroup.Constraint.FixedColumnCount; gl.constraintCount = 5; var cells = new List<(OutfitRow o, Image bg, Image face, Text label, Image lockIcon)>(); foreach (var o in T.Cfg.closet.outfits) { var outfit = o; var b = UI.Btn(content, "Outfit" + o.Type, Skin.Round, Color.white, () => OnOutfitClick(outfit)); var face = UI.Img(b.transform, "Face", null, Color.white); face.preserveAspect = true; face.rectTransform.Place(new Vector2(0.5f, 1), new Vector2(0.5f, 1), new Vector2(0, -78), new Vector2(150, 150)); var lb = UI.Txt(b.transform, "Label", "", 24, Pal.Ink); lb.rectTransform.Place(new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 26), new Vector2(-6, 40)); var lk = UI.Icon(b.transform, "Lock", Skin.Icon("lock"), Color.white); lk.rectTransform.Place(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0, 18), new Vector2(80, 80)); cells.Add((o, b.GetComponent(), face, lb, lk)); } p.refresh = () => { int show = PreviewOutfit >= 0 ? PreviewOutfit : G.S.closetCurrent; idol.sprite = Art.Idol(show, 0); lv.text = $"의상 레벨 {G.S.closetLevel} / {G.ClosetMaxLevel}"; stat.text = $"전체 수익 x{G.ClosetStatRate(G.ClosetEffLevel()) / 10000f:0.##}"; var nx = G.ClosetNext; if (nx == null) { cond.text = "최대 레벨"; upText.text = "MAX"; up.interactable = false; } else { cond.text = $"다음: x{nx.StatRate / 10000f:0.##} · 랭크 {nx.RankDependency} 필요"; var price = G.ClosetNextPrice(); upText.text = "레벨 업\n" + Fmt.Num(price); up.interactable = G.ClosetRankOk() && price <= G.Coin && !G.ClosetUpgrading; } foreach (var (o, bg, face, label, lockIcon) in cells) { bool vis = o.UnlockType != ClosetUnlock.InEvent || G.OutfitUnlocked(o.Type); bg.gameObject.SetActive(vis); if (!vis) continue; bool un = G.OutfitUnlocked(o.Type); face.sprite = Art.Idol(o.Type, 0); face.color = un ? Color.white : new Color(0.35f, 0.3f, 0.45f, 1f); lockIcon.gameObject.SetActive(!un); bg.color = G.S.closetCurrent == o.Type ? new Color32(255, 214, 236, 255) : (PreviewOutfit == o.Type ? new Color32(236, 226, 255, 255) : Color.white); label.text = o.Type == 1000 ? "기본" : un ? (G.S.closetCurrent == o.Type ? "장착 중" : "장착") : (o.UnlockType == ClosetUnlock.Ticket ? (G.OutfitRankOk(o) ? $"티켓 {G.OutfitTicketPrice(o)}" : $"랭크 {o.VisibilityRank}") : $"Lv.{o.UnlockLevel}"); } }; p.refresh(); } void OnOutfitClick(OutfitRow o) { if (G.OutfitUnlocked(o.Type)) { G.EquipOutfit(o.Type); PreviewOutfit = -1; } else if (o.UnlockType == ClosetUnlock.Ticket && G.OutfitRankOk(o)) { var r = G.UnlockTicketOutfit(o.Type); if (r == BuyResult.Ok) { G.EquipOutfit(o.Type); Toast("새 의상을 얻었습니다"); } else { PreviewOutfit = o.Type; Toast(r == BuyResult.NoMoney ? "티켓이 부족합니다" : "잠겨 있습니다"); } } else { PreviewOutfit = o.Type; Toast($"의상 레벨 {o.UnlockLevel} 에 열립니다"); } RefreshAll(); } } }