using UnityEngine; using UnityEngine.UI; namespace TKS.OutGame { /// /// 본영 로비(Fable 제안서 §4-1 · PD 2026-11-09 「카피바라GO·탕탕특공대 참고 상업 수준」) — 키아트 + 위 비네트 · 진행 띠(지도 핀 · 장 이름 · 진행 바 n/m) · /// 좌우 세로 버튼 열(임무·우편·동맹 / 상점·상자·이벤트 · 미구현 = 잠금 자리) · 출전 편성 5인 · 아래 버튼 행(편성 원 · 출정 3층 · 연무장 원) + 뒤 어두운 띠 · 하단 탭 5. /// 본문 좌표 = 절대 y − 224. /// public class LobbyScreen : OutGameScreen { Text progress; Text progressNum; RectTransform progressFill; Text sortieSub; Text chestBadge; RectTransform field; /// 로비 출전 영웅 표준 키(px · 크기 표 size_px 가 이 높이) — 유비가 예전 칸 맞춤 때와 같은 크기(797×826 틀 → 196 칸 = ×0.246 · size 837 × 0.246 ≈ 206). const float LobbyUnitPx = 206f; static RectTransform At(Transform p, string name, float x, float y, float w, float h) { return UiKit.Rect(name, p, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(x, -y), new Vector2(w, h)); } public override void Build() { Header("본영", "", false); var outer = Body(); // 배경 = 테마 bg_lobby(키아트 · 어둡게) · 없으면 땅 색 판 var art = UISkin.Icon("bg_lobby"); if (art != null) { var clip = UiKit.Fill("LobbyBg", outer); clip.gameObject.AddComponent(); // 위쪽 맞춤 × 1.22 — 키아트 아래쪽 아군 5인은 잘라 내고(편성 5인과 겹치지 않게) 전장·적진만 보이게 var art2 = UiKit.Rect("Art", clip, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, Vector2.zero); art2.anchorMin = new Vector2(-0.11f, 1f); art2.anchorMax = new Vector2(1.11f, 1f); art2.offsetMin = art2.offsetMax = Vector2.zero; var bimg = art2.gameObject.AddComponent(); bimg.sprite = art; bimg.color = UISkin.Col("lobby_tint", Color.white); bimg.raycastTarget = false; var fit = bimg.gameObject.AddComponent(); fit.aspectMode = AspectRatioFitter.AspectMode.WidthControlsHeight; fit.aspectRatio = art.rect.width / Mathf.Max(1f, art.rect.height); } // 위 비네트(Glow_Panel01 = 위 불투명 → 아래 투명 · 실측) · 아래 버튼 뒤 어두운 띠 var vg = UiKit.Rect("Vignette", outer, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(0f, 180f)); vg.anchorMin = new Vector2(0f, 1f); vg.anchorMax = new Vector2(1f, 1f); vg.sizeDelta = new Vector2(0f, 180f); UiKit.Skin(vg, "scroll_fade", UiKit.Col("lobby_vignette", Color.clear)).enabled = UISkin.Has("scroll_fade"); var body = UiKit.Rect("Mock", outer, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(OutGameRoot.Reference.x, OutGameRoot.BodyH)); var band = At(body, "BottomBand", -40f, 1236f, 1160f, 330f); UiKit.Skin(band, "card", UiKit.Col("lobby_band", Color.clear)); // 진행 띠(절대 236~312) = 지도 핀 + 장 이름 + 진행 바 n/m var pb = At(body, "Progress", 24f, 12f, 1032f, 76f); UiKit.Skin(pb, "card", UiKit.Col("chip_dark", UiKit.Dark)); UiKit.DropShadow(UiKit.Icon(pb, "map_point", new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(18f, 2f), 50f), 3f); progress = UiKit.Title(UiKit.Label(pb, "", 34, UiKit.White, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(78f, 2f), new Vector2(560f, 60f)), true); progress.horizontalOverflow = HorizontalWrapMode.Overflow; var bar = UiKit.Rect("Bar", pb, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-104f, 0f), new Vector2(240f, 26f)); UiKit.Skin(bar, "lv_bar_bg", UiKit.White); progressFill = UiKit.Rect("Fill", bar, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(4f, 0f), new Vector2(0f, 16f)); UiKit.Skin(progressFill, "lv_fill", UiKit.Col("lv_fill", UiKit.Coin)); progressNum = UiKit.Title(UiKit.Label(pb, "", 26, UiKit.White, TextAnchor.MiddleRight, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-18f, 2f), new Vector2(80f, 50f)), true); // 좌우 세로 버튼 열(166×150 · 미구현 = 잠금 자리) SideButton(body, 24f, 106f, "lobby_mission", "임무", true, () => Root.ComingSoon("임무")); SideButton(body, 24f, 272f, "lobby_mail", "우편", true, () => Root.ComingSoon("우편")); SideButton(body, 24f, 438f, "lobby_alliance", "동맹", true, () => Root.ComingSoon("동맹", true)); SideButton(body, 890f, 106f, "lobby_shop", "상점", false, () => Root.Trade.OpenShop()); var chest = SideButton(body, 890f, 272f, "lobby_chest", "상자", false, () => { Root.Show(Root.Treasures); Root.Treasures.SetPage(2); }); var cb = UiKit.Skin(UiKit.Rect("Alert", chest, new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(-12f, -12f), new Vector2(44f, 46f)), "badge_circle", UiKit.Col("alert_red", UiKit.Red)); cb.preserveAspect = true; chestBadge = UiKit.Title(UiKit.FillLabel(cb.transform, "", 24, UiKit.White), true); SideButton(body, 890f, 438f, "lobby_event", "이벤트", true, () => Root.ComingSoon("이벤트")); // 전장 자리 · 출전 편성 5인 var ground = UiKit.Fill("Field", body, 24f, 24f, 140f, 520f); if (art == null) UiKit.Paint(ground, new Color(0.47f, 0.52f, 0.36f)); var shadow = UiKit.Box("Shadow", ground, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 70f), new Vector2(940f, 150f), new Color(0.2f, 0.18f, 0.14f, 0.55f), false); shadow.sprite = UiKit.Circle; shadow.type = Image.Type.Simple; field = UiKit.Fill("Lineup", ground, 20f, 20f, 40f, 40f); // 아래 버튼 행(절대 1500~1740) = 편성 원 · 출정 3층 · 연무장 원 RoundButton(body, 160f, "btn_formation", "편성", () => Root.Show(Root.Formation)); RoundButton(body, 920f, "btn_arena", "연무장", () => { Root.Arena.SetPage(0); Root.Show(Root.Arena); // 연무장(PD #1093 C) }); var so = At(body, "Sortie", 310f, 1290f, 460f, 160f); var soImg = UiKit.Skin(so, "tapered1", UiKit.Red, true); so.gameObject.AddComponent