VSClone/Assets/Scripts/View/GameApp.Closet.cs

92 lines
6.1 KiB
C#

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<RectTransform>().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<RectTransform>().Fill();
Object.DestroyImmediate(content.GetComponent<VerticalLayoutGroup>());
var gl = content.gameObject.AddComponent<GridLayoutGroup>();
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<Image>(), 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();
}
}
}