diff --git a/Assets/Data/UI/ui_theme.csv b/Assets/Data/UI/ui_theme.csv index 4cabb233..edd393bc 100644 --- a/Assets/Data/UI/ui_theme.csv +++ b/Assets/Data/UI/ui_theme.csv @@ -430,7 +430,7 @@ color,row_label_strip,,,,,,#FFFFFF0A,편성 라벨 칸 세로 띠(흰 4 %) font,title,Assets/UI/GUIPro/ResourcesData/Fonts/Sen-ExtraBold.ttf,,,,,,제목·숫자(라틴 Sen · 한글 = 폴백 Malgun Gothic · PD 결정 전) color,text_on_yellow,,,,,,#1E1E2A,노랑 Primary 위 글자(Fable §5-8) color,ribbon_glow,,,,,,#FFD24AFF,결과 리본 뒤 금빛(그림 자체가 가운데 α 0.5 라 틴트 α 1 · Fable §4-2 α 0.35 는 안 보임 실측) -color,row_on_field,,,,,,#3F4262,필드 위 행 판(필드보다 밝게 · 팝업 교환 행) +color,row_on_field,,,,,,#FFFFFF14,필드 위 행 판(흰 8 % · 전 화면 밝은 행 통일 · Fable 검수 나머지1 결함 6) skin,btn_l_yellow,Button/Button01_l_Yellow.png,,1.3,,,,Primary 노랑 h110(확인·10연·열기 · Fable §5-5) skin,btn_l_red,Button/Button01_l_White_Bg.png,Button/Button01_l_White_Light1.png,1.35,5;5;5;18,0.35,,Primary 붉은 h104(출정 · 틴트 red) skin,title_divider_l,Label/Title_Line01_Divider_Left.png,,1,,,,소제목 왼쪽 선(Fable §5-2) @@ -493,3 +493,5 @@ icon,hud_ally,Icon_PictoIcons/128/PictoIcon_Helmet_1.Png,,,,,,전투 HUD 아군 icon,hud_enemy,Icon_PictoIcons/128/PictoIcon_Boss.Png,,,,,,전투 HUD 적 수 아이콘 color,skill_glow,,,,,,#FFD24AFF,스킬 버튼 뒤 빛(사용 가능 · 금빛 · 붉은 버튼·모래 바탕과 대비) icon,shield,IconMisc/Icon_Shield.png,,,,,,방어 스탯(Fable §5-8) +color,popup_band,,,,,,#1F2138,팝업 제목 띠(공용 · 스테이지 팝업 통일 · 검수 결함 6) +skin,btn_green,Button/Button01_s_Green.png,,1.22,,,,Secondary 녹 h100(광고 보기 · btn_sky 와 같은 비율) diff --git a/Assets/Resources/UI/UITheme.asset b/Assets/Resources/UI/UITheme.asset index c6ac134c..95ae38bd 100644 --- a/Assets/Resources/UI/UITheme.asset +++ b/Assets/Resources/UI/UITheme.asset @@ -504,7 +504,7 @@ MonoBehaviour: - id: ribbon_glow color: {r: 1, g: 0.8235294, b: 0.2901961, a: 1} - id: row_on_field - color: {r: 0.24705882, g: 0.25882354, b: 0.38431373, a: 1} + color: {r: 1, g: 1, b: 1, a: 0.078431375} - id: banner_pattern color: {r: 1, g: 1, b: 1, a: 0.078431375} - id: chest_bronze @@ -569,6 +569,8 @@ MonoBehaviour: color: {r: 1, g: 1, b: 1, a: 0.2509804} - id: skill_glow color: {r: 1, g: 0.8235294, b: 0.2901961, a: 1} + - id: popup_band + color: {r: 0.12156863, g: 0.12941177, b: 0.21960784, a: 1} skins: - id: card pack: {fileID: 21300000, guid: 3070a6f23e6ca4273897acf1b7e8c5ce, type: 3} @@ -1340,6 +1342,13 @@ MonoBehaviour: ppu: 1.5 inset: {x: 0, y: 0, z: 0, w: 0} overlayAlpha: 1 + - id: btn_green + pack: {fileID: 21300000, guid: 2d734a17e89824d30b1f014a9c1f5f60, type: 3} + samguk: {fileID: 0} + overlay: {fileID: 0} + ppu: 1.22 + inset: {x: 0, y: 0, z: 0, w: 0} + overlayAlpha: 1 icons: - id: cur_gold pack: {fileID: 21300000, guid: 6d5687fb0dd3a428d9cd26a6f36c6d78, type: 3} diff --git a/Assets/Scripts/OutGame/UI/BattleResultPanel.cs b/Assets/Scripts/OutGame/UI/BattleResultPanel.cs index 6a5da559..2f1b7395 100644 --- a/Assets/Scripts/OutGame/UI/BattleResultPanel.cs +++ b/Assets/Scripts/OutGame/UI/BattleResultPanel.cs @@ -14,7 +14,7 @@ namespace TKS.OutGame { // 패널 배치(UI px · 패널 왼쪽 위 기준) const float PW = 920f; - const float PH = 1180f; + const float PH = 1080f; const float Side = 60f; const float RowW = PW - Side * 2f; const float RowH = 64f; @@ -32,6 +32,7 @@ namespace TKS.OutGame readonly Text plain; readonly Button retry; readonly Button ok; + readonly Text retryCost; string rewardsText = ""; public bool Visible @@ -50,8 +51,8 @@ namespace TKS.OutGame var dim = UiKit.Fill("Result", canvas); UiKit.Paint(dim, UISkin.Col("dim", new Color(0f, 0f, 0f, 0.55f)), false); go = dim.gameObject; - Image panel; - if (UISkin.Has("popup")) + Image panel = null; + if (UISkin.Has("popup") && UISkin.Has("panel_frame")) { // 리본 뒤 금빛(승리만 · 팩 Glow_Circle01 · 호흡) → 팩 팝업 틀 → 제목 리본(승리 붉은 · 패배 회색) if (UISkin.Has("glow_circle")) @@ -61,13 +62,17 @@ namespace TKS.OutGame pulse.min = 0.65f; pulse.period = 1.6f; } - panel = UiKit.Skin(UiKit.Rect("Panel", dim, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 20f), new Vector2(PW, PH)), "popup", UiKit.Paper); - var rib = UiKit.Rect("Ribbon", panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 0.5f), new Vector2(0f, 10f), new Vector2(1000f, 200f)); + // 패널 = 섹션 패널 층(그림자 · 밝은 프레임 #3F4262 · 필드 #262840 · 윗면 광택 · 검수 결함 10) + var holder = UiKit.Rect("Panel", dim, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 20f), new Vector2(PW, PH)); + RectTransform froot; + UiKit.SectionPanel(holder, "Frame", 0f, 0f, PW, PH, false, false, out froot); + var pt = (Transform)holder; + var rib = UiKit.Rect("Ribbon", pt, new Vector2(0.5f, 1f), new Vector2(0.5f, 0.5f), new Vector2(0f, 10f), new Vector2(1000f, 200f)); ribbon = UiKit.Skin(rib, "ribbon", Color.white); title = UiKit.Title(UiKit.FillLabel(rib, "", 88, UiKit.White, TextAnchor.MiddleCenter, true, 150f), true); title.rectTransform.offsetMin = new Vector2(150f, 34f); // 별 3 = 받침 원(Circle78 chip_dark) + 별(가운데 크게 · 위로) · 0.15 s 간격 튀김 - starRow = UiKit.At(panel.transform, "StarRow", 0f, 120f, PW, 190f); + starRow = UiKit.At(pt, "StarRow", 0f, 120f, PW, 190f); for (int i = 0; i < 3; i++) { bool mid = i == 1; @@ -79,9 +84,10 @@ namespace TKS.OutGame UiKit.DropShadow(starImg[i], 5f); starImg[i].gameObject.AddComponent().delay = 0.15f * i; } - body = UiKit.Fill("Body", panel.transform); - retry = UiKit.SkinBtn(panel.transform, "Retry", "round08", UiKit.Col("menu_btn", UiKit.Dark), "다시", 40, UiKit.White, Side, BtnY, 260f, 110f, () => root.RetryStage()); - ok = UiKit.SkinBtn(panel.transform, "Ok", UISkin.Has("btn_l_yellow") ? "btn_l_yellow" : "button", UISkin.Has("btn_l_yellow") ? UiKit.White : UiKit.Coin, "확인", 46, UiKit.Col("text_on_yellow", UiKit.Ink), PW - Side - 520f, BtnY, 520f, 110f, null); + body = UiKit.Fill("Body", pt); + retry = UiKit.SkinBtn(pt, "Retry", "round08", UiKit.Col("menu_btn", UiKit.Dark), "다시", 34, UiKit.White, Side, BtnY, 260f, 110f, () => root.RetryStage()); + retryCost = UiKit.BtnCost(retry, "cur_stamina", "", 36f, 28); // 재도전 = 군량 소모 표시(검수 결함 2) + ok = UiKit.SkinBtn(pt, "Ok", UISkin.Has("btn_l_yellow") ? "btn_l_yellow" : "button", UISkin.Has("btn_l_yellow") ? UiKit.White : UiKit.Coin, "확인", 46, UiKit.Col("text_on_yellow", UiKit.Ink), PW - Side - 520f, BtnY, 520f, 110f, null); } else { @@ -117,6 +123,12 @@ namespace TKS.OutGame title.text = (r.win ? "승리" : "패배") + " " + r.chapter + "-" + r.stage + (r.boss ? " 보스" : "") + ""; ShowStars(r.win ? r.stars : 0, r.win); SetButtons(true); + if (retryCost != null && root.Battle != null && root.Battle.Config != null && root.Battle.StageIndex >= 0 && root.Battle.StageIndex < root.Battle.Config.stages.Length) + { + int cost = EconomyRules.StageCost(s.Db, s.Save, root.Battle.Config.stages[root.Battle.StageIndex]); + retryCost.text = cost.ToString(); + retry.GetComponent().color = s.Save.stamina >= cost ? UiKit.Col("menu_btn", UiKit.Dark) : UiKit.Col("disabled", UiKit.Disabled); + } if (body == null) { plain.text = (r.win ? "별 " + UiKit.Stars(r.stars, 3) + "\n\n" : "아군이 전멸했습니다\n\n") + rewardsText; @@ -146,14 +158,14 @@ namespace TKS.OutGame return; } Tiles(s, r, y); - Notes(s, r, y + Tile + 60f); + Notes(s, r, y + Tile + 62f); } /// 보상 타일 행(가운데 정렬 · 칸 아래 이름) — 골드 · 경험 · 보옥(있을 때) · 장비(등급 칸 · 있을 때) · 상자(있을 때). void Tiles(OutGameSession s, StageReward r, float y) { var list = new List(); // 아이콘 · 수량 · 칸 색 접두 · 이름 - list.Add(new[] { "cur_gold", r.gold.ToString("N0"), "gear_white_", "골드" }); + list.Add(new[] { "cur_gold", r.gold.ToString("N0"), "gear_white_", r.first ? "골드" : "골드 ×" + s.Db.Economy.RepeatRewardMult }); list.Add(new[] { "cur_exp", r.exp.ToString("N0"), "gear_white_", "경험 · " + r.expTo.Count + "명" }); if (r.gem > 0) list.Add(new[] { "cur_gem", r.gem.ToString("N0"), "gear_blue_", "보옥" }); if (!string.IsNullOrEmpty(r.gearId)) @@ -170,22 +182,33 @@ namespace TKS.OutGame { var e = list[i]; float tx = x + i * (Tile + gap); - UiKit.RewardTile(body, "Tile" + i, tx, y, Tile, e[2], e[0], e[1], e[2] != "gear_white_"); + var cell = UiKit.RewardTile(body, "Tile" + i, tx, y, Tile, e[2], e[0], e[1], e[2] != "gear_white_"); + if (r.first && (e[0] == "cur_gold" || e[0] == "cur_gem")) FirstBadge(cell); // 첫 클리어 = 뱃지(스테이지 팝업과 같은 표현 · 검수 결함 8) var n = UiKit.Label(body, e[3], 26, UiKit.Col("text_soft", UiKit.InkSoft), TextAnchor.UpperCenter, new Vector2(0f, 1f), new Vector2(0.5f, 1f), new Vector2(tx + Tile * 0.5f, -y - Tile - 12f), new Vector2(Tile + gap, 36f), false); n.horizontalOverflow = HorizontalWrapMode.Overflow; } } - /// 타일 아래 한두 줄 — 첫 클리어/반복 배율 · 레벨업 가능 영웅 · 소탕. + /// 「첫」 뱃지(Label_Badge01_Yellow · 칸 오른쪽 위). + public static void FirstBadge(Transform cell) + { + var b = UiKit.Icon(cell, "badge_first", new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(-8f, -6f), 58f); + if (b != null) UiKit.Title(UiKit.FillLabel(b.transform, "첫", 24, UiKit.White), true); + } + + /// 타일 아래 = 레벨업 가능 칩(위 화살표 + 노란 글자 · 검수 결함 8) · 없으면 비움. void Notes(OutGameSession s, StageReward r, float y) { - var e = s.Db.Economy; - var sb = new StringBuilder(r.first ? "첫 클리어 보상" + (r.boss ? " + 보스" : "") : "반복 보상 ×" + e.RepeatRewardMult); - if (r.sweep) sb.Append(" · 소탕(군량 ").Append(r.stamina).Append(")"); var ready = ReadyNames(s, r); - if (ready.Length > 0) sb.Append("\n레벨업 가능 ").Append(ready).Append(""); - var t = UiKit.Label(body, sb.ToString(), 30, UiKit.White, TextAnchor.UpperCenter, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(Side, -y), new Vector2(RowW, 100f), false); - t.lineSpacing = 1.2f; + if (ready.Length == 0) return; + string text = "레벨업 가능 " + ready; + var t = UiKit.InfoChip(body, "LevelUp", Side, y, RowW, 56f, "up_green", text, 28); + t.color = UiKit.Col("select_line", UiKit.Coin); + float w = Mathf.Min(RowW, Mathf.Ceil(t.preferredWidth) + 110f); + var c = (RectTransform)t.transform.parent; + c.anchoredPosition = new Vector2((PW - w) * 0.5f, -y); + c.sizeDelta = new Vector2(w, 56f); + t.rectTransform.sizeDelta = new Vector2(w - 80f, 56f); } /// 연무장 결과(탑 · 던전 · 투기장 · 적장 토벌 · PD #1093 C) — 별 없음 · 결과 행 · 탭 = 연무장. diff --git a/Assets/Scripts/OutGame/UI/OutGameRoot.cs b/Assets/Scripts/OutGame/UI/OutGameRoot.cs index c2be40a1..93ce0364 100644 --- a/Assets/Scripts/OutGame/UI/OutGameRoot.cs +++ b/Assets/Scripts/OutGame/UI/OutGameRoot.cs @@ -173,6 +173,7 @@ namespace TKS.OutGame { Battle = b; hud = h; + if (h != null) h.HideOnResult = true; sling = s; Map = wm; Cam = cam; @@ -557,7 +558,7 @@ namespace TKS.OutGame // 팩 팝업: 흰 틀 + 위 제목 띠(진남 틴트 · 광택) + 닫기 X panel = UiKit.Skin(UiKit.Rect("Panel", dim, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 20f), new Vector2(940f, h)), "popup", UiKit.Paper, true); head = UiKit.TopBand("Head", panel.transform, 6f, 110f, 7f, 7f); - UiKit.Skin(head, "popup_head", UiKit.Header); + UiKit.Skin(head, "popup_head", UiKit.Col("popup_band", UiKit.Header)); // 팝업 제목 띠 통일(검수 결함 6) var tt = UiKit.Title(UiKit.FillLabel(head, title, 44, UiKit.HeaderText, TextAnchor.MiddleCenter, true, 110f), true); tt.resizeTextForBestFit = true; tt.resizeTextMinSize = 28; @@ -694,8 +695,8 @@ namespace TKS.OutGame StaminaModal(r ?? "군량 +" + e.GemStaminaAmount, r == null); if (Map != null) Map.RefreshPopup(); }); - ExchangeRow(field, 1, 286f + 160f, w, "ad", "광고", e.AdStamina, "오늘 " + d.adsUsed.stamina + " / " + e.AdStaminaDaily + " · 광고 SDK 미연동(시험 지급)", - d.adsUsed.stamina < e.AdStaminaDaily, "btn_s_green", "보기", () => + ExchangeRow(field, 1, 286f + 160f, w, "ad", "광고", e.AdStamina, "오늘 " + d.adsUsed.stamina + " / " + e.AdStaminaDaily, + d.adsUsed.stamina < e.AdStaminaDaily, UISkin.Has("btn_green") ? "btn_green" : "btn_s_green", "보기", () => { var r = Session.AdStamina(); StaminaModal(r ?? "군량 +" + e.AdStamina, r == null); @@ -721,7 +722,7 @@ namespace TKS.OutGame bt.horizontalOverflow = HorizontalWrapMode.Overflow; UiKit.Label(row, note, 24, UiKit.Col("text_soft", UiKit.InkSoft), TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(30f, -96f), new Vector2(w - 380f, 36f), false); var btn = UiKit.SkinBtn(row, "Btn", can || !UISkin.Has("btn_gray") ? skin : "btn_gray", UiKit.White, label, 38, UiKit.White, w - Pad * 2f - 24f - 250f, 20f, 250f, 100f, onClick); - if (skin == "btn_s_green" && can) UiKit.BtnCost(btn, "ad", "", 36f, 24); + if (skin.Contains("green") && can) UiKit.BtnCost(btn, "ad", "", 36f, 24); } // ---------- 월드맵 연결 ---------- @@ -800,7 +801,7 @@ namespace TKS.OutGame var n = UiKit.Title(UiKit.Label(field, "x" + counts[kinds[k]], 36, UiKit.White, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2(cx + 50f, -y - 94f), new Vector2(100f, 50f)), true); n.horizontalOverflow = HorizontalWrapMode.Overflow; } - y += 140f; + y += 128f; if (lead.Count > 0) { string names = string.Join(" · ", lead.ToArray()); diff --git a/Assets/Scripts/OutGame/UI/TradeScreen.cs b/Assets/Scripts/OutGame/UI/TradeScreen.cs index 52d58f36..409d2438 100644 --- a/Assets/Scripts/OutGame/UI/TradeScreen.cs +++ b/Assets/Scripts/OutGame/UI/TradeScreen.cs @@ -100,37 +100,37 @@ namespace TKS.OutGame { var g = S.Db.Gacha; // 배너 - var banner = UiKit.At(p, "Banner", 24f, 12f, 1032f, 470f); + var banner = UiKit.At(p, "Banner", 24f, 12f, 1032f, 600f); UiKit.Skin(banner, "banner", Color.white); if (UISkin.Has("banner_pattern")) { - var pat = UiKit.Skin(UiKit.At(banner, "Pattern", 18f, 470f - 112f, 1032f - 36f, 90f), "banner_pattern", UiKit.Col("banner_pattern", Color.clear)); + var pat = UiKit.Skin(UiKit.At(banner, "Pattern", 18f, 600f - 112f, 1032f - 36f, 90f), "banner_pattern", UiKit.Col("banner_pattern", Color.clear)); pat.type = Image.Type.Tiled; } - UiKit.InfoChip(banner, "Period", 30f, 26f, 220f, 52f, null, "픽업 · 2주", 28); + UiKit.InfoChip(banner, "Period", 30f, 26f, 180f, 52f, null, "기간 2주", 28); // 「픽업」 = 오른쪽 위 뱃지 하나만(검수 결함 3) UiKit.Title(UiKit.Label(banner, "영웅·유닛 뽑기", 60, UiKit.White, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(36f, -100f), new Vector2(600f, 90f)), true); UiKit.Label(banner, "모든 영웅·병사 유닛\n= 뽑기로 획득", 32, UiKit.Col("text_soft", UiKit.InkSoft), TextAnchor.UpperLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(36f, -200f), new Vector2(520f, 110f), false); - var free = UiKit.Skin(UiKit.At(banner, "Free", 36f, 470f - 104f, 300f, 64f), "tail", UiKit.Col("tail_red", UiKit.Red)); + var free = UiKit.Skin(UiKit.At(banner, "Free", 36f, 600f - 104f, 300f, 64f), "tail", UiKit.Col("tail_red", UiKit.Red)); UiKit.Title(UiKit.FillLabel(free.transform, "첫 10연 무료", 30, UiKit.White), true); freeChip = free.gameObject; - pickupArt = UiKit.Rect("PickupArt", banner, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-20f, 22f), new Vector2(440f, 420f)); - var hot = UiKit.Icon(banner, "badge_hot", new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(-34f, -30f), 120f); + pickupArt = UiKit.Rect("PickupArt", banner, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-20f, 20f), new Vector2(560f, 560f)); + var hot = UiKit.Icon(banner, "badge_hot", new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(-52f, -44f), 88f); // 배너 안쪽(검수 결함 3) if (hot != null) { UiKit.DropShadow(hot, 4f); - UiKit.Title(UiKit.FillLabel(hot.transform, "픽업", 30, UiKit.White), true); + UiKit.Title(UiKit.FillLabel(hot.transform, "픽업", 24, UiKit.White), true); } // 천장 게이지 RectTransform pr; - var pf = UiKit.SectionPanel(p, "Pity", 24f, 504f, 1032f, 156f, false, false, out pr); + var pf = UiKit.SectionPanel(p, "Pity", 24f, 632f, 1032f, 176f, false, false, out pr); UiKit.Title(UiKit.Label(pf, "천장", 34, UiKit.White, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(26f, -12f), new Vector2(200f, 50f)), true); pityText = UiKit.Label(pf, "", 28, UiKit.Col("text_soft", UiKit.InkSoft), TextAnchor.MiddleRight, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-26f, -12f), new Vector2(620f, 50f), false); - pityBar = UiKit.Gauge(pf, "Gauge", 20f, 52f, GaugeW + 60f, "lv_badge_y", "lv_fill", out pityBadge); + pityBar = UiKit.Gauge(pf, "Gauge", 20f, 62f, GaugeW + 60f, "lv_badge_y", "lv_fill", out pityBadge); // 확률 공개 RectTransform probRoot; - var prob = UiKit.SectionPanel(p, "Prob", 24f, 682f, 1032f, 330f, false, false, out probRoot); + var prob = UiKit.SectionPanel(p, "Prob", 24f, 828f, 1032f, 400f, false, false, out probRoot); UiKit.SectionTitle(probRoot, "확률 공개"); var info = UiKit.Rect("Info", probRoot, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-16f, -12f), new Vector2(64f, 64f)); UiKit.Skin(info, "badge_circle", UiKit.Col("chip_dark", UiKit.Dark), true); @@ -139,8 +139,8 @@ namespace TKS.OutGame info.gameObject.AddComponent