UI 리뉴얼 A-2~A-4 화면 적용(PD #1100) — 팩 부품 + UI 테마(id 치환) · 화면 10종 · 인박스 ui kind
- 테마: SOT Assets/Data/UI/ui_theme.csv(색 57 · 스킨 32 · 아이콘 63 · 제목 폰트) → 메뉴 TKS/Import UI Theme → Resources/UI/UITheme.asset (Runtime/UI/UITheme · UISkin · Editor/UIThemeImporter · ProjectSetup 에서도 임포트) · 화면 코드는 id 로만 묻는다(스프라이트 경로 0) - 신규 제작(B) 치환: Assets/UI/Samguk/**/<id>.png → 임포트 시 같은 id 스킨·아이콘 자동 치환(팩 보존 · 새 id = 아이콘 추가) · Tools/apply_delivery.py ui kind(md5 → Samguk/<group> · gim_* → Resources/Gimmicks/Art · ui_delivered.csv) - 공통: UiKit(카드 = BorderFrame_Round20 틴트 · 버튼 = Button01_s + 광택 · 원 · 진행 바 = Slider_Basic01 · 초상 틀 · 등급 칸 ItemFrame02 · 별 줄 · 병종 배지) · 재화 바(ResourceBar + cur_* 아이콘) · 하단 탭(선택 판 + PictoIcon) · 제목 띠 · 팝업(Popup Topber + 닫기 X) · 토스트 - 화면: 로비(키아트 04 배경 위쪽 ×1.22 · 출정·편성·연무장 아이콘) · 영웅(등급 칸 + 장비 아이콘 · 체크/알림 점 · 별 아이콘) · 편성 · 거래(배너 · 상자 아이콘) · 보물(상자 아이콘 · 포인트 배지) · 내정(보상 줄 · 도면·골드 아이콘) · 연무장 · 결과(리본 · 별) · 월드맵 스테이지 팝업만 팩(거점 kit 유지) - 전투: HUD 칩 · 턴 띠 · 원형 스킬 버튼 + 쿨 라디얼 · 유닛 체력 바 · 기믹 내구 핍 = 팩 슬라이더(월드 9-slice 사본 · 가운데 2 px) · 조준선 색 유지 - 3:4(1536×2048): 본문 비율 축소(UiFitHeight · 1080×1920 = 그대로) - 검증: 플레이모드 116/116(기존 115 + UIThemeTests 1) · 컴파일 0 · error 0 · 캡처 = DataImporter.CaptureUI(UICaptureDriver · 15장) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
43856e70cb
commit
d73c606e46
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bf00b201586bf2a48beb4f0b0ffe0d9c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
kind,id,path,overlay,ppu,inset,alpha,color,note
|
||||
color,bg,,,,,,#EFE5CF,화면 바탕(양피지)
|
||||
color,paper,,,,,,#FFF9EC,패널·카드 바탕
|
||||
color,header,,,,,,#2E3349,제목 띠(팩 진남)
|
||||
color,header_text,,,,,,#FFFFFF,제목 띠 글자
|
||||
color,header_sub,,,,,,#C9C3D6,제목 띠 보조 글자
|
||||
color,ink,,,,,,#2A2230,글자(먹)
|
||||
color,ink_soft,,,,,,#6F6470,보조 글자
|
||||
color,dark,,,,,,#3A4060,어두운 버튼(팩 진남)
|
||||
color,red,,,,,,#D8412F,붉은 옻칠(주 버튼·강조)
|
||||
color,line,,,,,,#1E2535,외곽선
|
||||
color,slot,,,,,,#DCD0B9,빈 칸
|
||||
color,coin,,,,,,#F3B72E,금
|
||||
color,jade,,,,,,#23B394,보옥(옥)
|
||||
color,grain,,,,,,#D9963F,군량
|
||||
color,ok,,,,,,#47B53F,완료
|
||||
color,star,,,,,,#FFC21A,별
|
||||
color,disabled,,,,,,#9E98A3,비활성
|
||||
color,purple,,,,,,#9A57D8,보라
|
||||
color,white,,,,,,#FFFFFF,흰색
|
||||
color,bar,,,,,,#1E2535,상단 재화 바·하단 탭 바
|
||||
color,pill,,,,,,#353B57,상단 재화 칩 바탕(흰 칩 틴트)
|
||||
color,bar_text,,,,,,#FFFFFF,바 글자
|
||||
color,bar_text_off,,,,,,#8D93A8,바 글자(비활성)
|
||||
color,tab_off,,,,,,#3A4060,하단 탭 아이콘 바탕(꺼짐)
|
||||
color,stroke,,,,,,#1E2535,흰 글자 외곽선
|
||||
color,dim,,,,,,#000000A0,팝업 뒤 어둡게
|
||||
color,lobby_tint,,,,,,#9C95A8,로비 배경 어둡게(곱)
|
||||
color,bar_track,,,,,,#FFFFFF,진행 바 바탕(스킨 원색 · 곱)
|
||||
color,grade_white,,,,,,#D9D6CF,등급 흰
|
||||
color,grade_green,,,,,,#47B53F,등급 녹
|
||||
color,grade_blue,,,,,,#3C7BE0,등급 청
|
||||
color,grade_purple,,,,,,#9A57D8,등급 자
|
||||
color,grade_orange,,,,,,#F08A24,등급 주
|
||||
color,grade_gold,,,,,,#F3C12E,등급 금
|
||||
color,type_infantry,,,,,,#C8553A,병종 보병
|
||||
color,type_spear,,,,,,#3E9A4A,병종 창병
|
||||
color,type_cavalry,,,,,,#3C67C8,병종 기병
|
||||
color,type_archer,,,,,,#D99A2B,병종 궁병
|
||||
color,type_strategist,,,,,,#9A57D8,병종 책사
|
||||
color,faction_shu,,,,,,#D8412F,세력 촉(적)
|
||||
color,faction_wei,,,,,,#3C7BE0,세력 위(청)
|
||||
color,faction_wu,,,,,,#2FA84F,세력 오(녹)
|
||||
color,faction_other,,,,,,#8C8C96,세력 군웅(회)
|
||||
color,hp_bg,,,,,,#FFFFFF,유닛 체력 바 바탕(스킨 원색)
|
||||
color,hp_hi,,,,,,#52D148,체력 50 % 초과
|
||||
color,hp_mid,,,,,,#FFC52B,체력 25~50 %
|
||||
color,hp_low,,,,,,#F2453A,체력 25 % 이하
|
||||
color,pip_on,,,,,,#FFC21A,기믹 내구 핍(남음)
|
||||
color,pip_off,,,,,,#2B2F40CC,기믹 내구 핍(깎임)
|
||||
color,hud_panel,,,,,,#1E2535D9,전투 HUD 판
|
||||
color,hud_turn_player,,,,,,#3C7BE0,턴 띠(아군)
|
||||
color,hud_turn_enemy,,,,,,#D8412F,턴 띠(적군)
|
||||
color,skill_ready,,,,,,#D8412F,스킬 사용 가능
|
||||
color,skill_reserved,,,,,,#F3B72E,스킬 예약
|
||||
color,skill_off,,,,,,#5A5E70,스킬 불가
|
||||
color,skill_passive,,,,,,#3A4060,패시브만
|
||||
color,skill_cool,,,,,,#000000A8,스킬 쿨 라디얼 덮개
|
||||
skin,card,Frame/BorderFrame_Round20_White_Bg.png,,1,,,,패널·카드(흰 바탕 + 굵은 외곽선 · 호출 색 틴트)
|
||||
skin,soft,Frame/BasicFrame_Round20.png,,1,,,,외곽선 없는 둥근 칸(반투명 판)
|
||||
skin,button,Button/Button01_s_White_Bg.png,Button/Button01_s_White_Light1.png,1,5;5;5;18,0.35,,버튼(흰 바탕 틴트 + 윗면 광택)
|
||||
skin,dot,Frame/BorderFrame_Circle60.png,,1,,,,원(외곽선)
|
||||
skin,bar_bg,Slider/Slider_Basic01_Bg_Single.png,,1,,,,진행 바 바탕
|
||||
skin,bar_fill,Slider/Slider_Basic01_FillMask.png,,1,,,,진행 바 채움(틴트)
|
||||
skin,pill,UI_Etc/ResourceBar_Single_Bg.png,,1,,,,상단 재화 칩
|
||||
skin,plus,UI_Etc/ResourceBar_Single_Btn_Yellow1.png,UI_Etc/ResourceBar_Single_Btn_Yellow2.png,1,14;14;14;16,1,,재화 + 버튼
|
||||
skin,tabbar,Button/Menu_BottomBtn_Bg.png,,1,,,,하단 탭 바
|
||||
skin,tab_focus,Frame/BorderFrame_Round20_White_Bg.png,Frame/BorderFrame_Round20_White_Light.png,1,6;4;6;30,0.45,,하단 탭 선택(틴트)
|
||||
skin,popup,Popup/Popup02~09_Topber_White_Bg.png,,1,,,,팝업 틀
|
||||
skin,popup_head,Popup/Popup02~09_Topber_White_BgTop.png,Popup/Popup02~09_Topber_White_BgTopLight.png,1,0;0;0;60,0.25,,팝업 제목 띠(틴트)
|
||||
skin,close,Button/Button_Round06_Red.png,IconMisc/Icon_Close01.png,1,22;22;22;26,1,,팝업 닫기 X
|
||||
skin,ribbon,Label/Title_Ribbon01_Red.png,,1,,,,결과 제목 리본
|
||||
skin,ribbon_gray,Label/Title_Ribbon01_Gray.png,,1,,,,결과 제목 리본(패배)
|
||||
skin,toast,Frame/BorderFrame_Round20_White_Bg.png,,1,,,,알림(틴트)
|
||||
skin,portrait_mask,Frame/BasicFrame_Round20.png,,1,,,,초상 마스크
|
||||
skin,circle_frame,Frame/BorderFrame_Circle78.png,,1,,,,원형 자리(편성)
|
||||
skin,skill_btn,Button/Button_Circle122.png,,1,,,,전투 스킬 버튼(원형)
|
||||
skin,skill_cool,Frame/BasicFrame_Circle160.png,,1,,,,스킬 쿨 라디얼
|
||||
skin,hp_bg,Slider/Slider_Basic02_Bg.png,,1,,,,유닛 체력 바 바탕(월드)
|
||||
skin,hp_fill,Slider/Slider_Basic01_FillMask.png,,1,,,,유닛 체력 바 채움(월드)
|
||||
skin,pip,Frame/BorderFrame_Round20_White_Bg.png,,1,,,,기믹 내구 핍(월드)
|
||||
skin,hud_pill,UI_Etc/ResourceBar_Single_Bg.png,,1,,,,전투 HUD 칩
|
||||
skin,banner,Frame/BannerFrame04_Single.png,,1,,,,뽑기 배너 틀
|
||||
skin,flag,Frame/BorderFrame_Flag_White_Bg.png,,1,,,,세력 깃발(틴트)
|
||||
skin,frame_white,Frame/ItemFrame02_Single_OffWhite.png,,1,,,,등급 칸 흰(B frame_* 오면 치환)
|
||||
skin,frame_green,Frame/ItemFrame02_Single_Green.png,,1,,,,등급 칸 녹
|
||||
skin,frame_blue,Frame/ItemFrame02_Single_Blue.png,,1,,,,등급 칸 청
|
||||
skin,frame_purple,Frame/ItemFrame02_Single_Purple.png,,1,,,,등급 칸 자
|
||||
skin,frame_orange,Frame/ItemFrame02_Single_Red.png,,1,,,,등급 칸 주(팩에 주황 없음 → 적색)
|
||||
skin,frame_gold,Frame/ItemFrame02_Single_Yellow.png,,1,,,,등급 칸 금
|
||||
icon,cur_gold,Icon_ItemIcons/128/ItemIcon_Money_Coin.Png,,,,,,골드(임시 · B cur_gold)
|
||||
icon,cur_gem,Icon_ItemIcons/128/ItemIcon_Gem_Circle.Png,,,,,,보옥(임시)
|
||||
icon,cur_stamina,Icon_ItemIcons/128/ItemIcon_Bag_Brown.Png,,,,,,군량(임시)
|
||||
icon,cur_shard,Icon_ItemIcons/128/ItemIcon_Star_Purple.Png,,,,,,영웅 조각(임시)
|
||||
icon,cur_iron,Icon_ItemIcons/128/ItemIcon_Gear.Png,,,,,,운철(임시)
|
||||
icon,cur_blueprint,Icon_ItemIcons/128/ItemIcon_MemoPad.Png,,,,,,도면(임시)
|
||||
icon,cur_ticket,Icon_ItemIcons/128/ItemIcon_Ticket_Gold.Png,,,,,,입장권(임시)
|
||||
icon,cur_skillbook,Icon_ItemIcons/128/ItemIcon_Book_1_Wine.Png,,,,,,스킬서(임시)
|
||||
icon,cur_exp,Icon_ItemIcons/128/ItemIcon_Star_Blue.Png,,,,,,경험(임시)
|
||||
icon,cur_gear,Icon_ItemIcons/128/ItemIcon_Gear_Sword.Png,,,,,,장비(임시)
|
||||
icon,tab_hero,Icon_PictoIcons/128/PictoIcon_Helmet_1.Png,,,,,,하단 탭 영웅(임시)
|
||||
icon,tab_treasure,Icon_PictoIcons/128/PictoIcon_Chest.Png,,,,,,하단 탭 보물(임시)
|
||||
icon,tab_domestic,Icon_PictoIcons/128/PictoIcon_Castle.Png,,,,,,하단 탭 내정(임시)
|
||||
icon,tab_alliance,Icon_PictoIcons/128/PictoIcon_Lock_1.Png,,,,,,하단 탭 동맹(잠금 · 임시)
|
||||
icon,tab_trade,Icon_PictoIcons/128/PictoIcon_Scale.Png,,,,,,하단 탭 거래(임시)
|
||||
icon,btn_sortie,Icon_PictoIcons/128/PictoIcon_Battle.Png,,,,,,로비 출정(임시)
|
||||
icon,btn_formation,Icon_PictoIcons/128/PictoIcon_Flag.Png,,,,,,로비 편성(임시)
|
||||
icon,btn_arena,Icon_PictoIcons/128/PictoIcon_Target.Png,,,,,,로비 연무장(임시)
|
||||
icon,cls_infantry,Icon_PictoIcons/128/PictoIcon_Sword_1.Png,,,,,,병종 보병(임시)
|
||||
icon,cls_spear,Icon_PictoIcons/128/PictoIcon_Pick.Png,,,,,,병종 창병(임시)
|
||||
icon,cls_cavalry,Icon_PictoIcons/128/PictoIcon_Paw.Png,,,,,,병종 기병(임시)
|
||||
icon,cls_archer,Icon_PictoIcons/128/PictoIcon_Bow.Png,,,,,,병종 궁병(임시)
|
||||
icon,cls_strategist,Icon_PictoIcons/128/PictoIcon_Pen_Feather.Png,,,,,,병종 책사(임시)
|
||||
icon,chest_bronze,Icon_ItemIcons/128/ItemIcon_Chest_Wood.Png,,,,,,청동 상자(임시)
|
||||
icon,chest_silver,Icon_ItemIcons/128/ItemIcon_Chest_Skull.png,,,,,,은 상자(임시)
|
||||
icon,chest_gold,Icon_ItemIcons/128/ItemIcon_Chest_Gold.Png,,,,,,금 상자(임시)
|
||||
icon,chest_general,Icon_ItemIcons/128/ItemIcon_Chest_Premium.Png,,,,,,명장 상자(임시)
|
||||
icon,chest_gem,Icon_ItemIcons/128/ItemIcon_Chest_Gem.Png,,,,,,보옥 상자(임시)
|
||||
icon,chest_point,Icon_ItemIcons/128/ItemIcon_Badge_Gold.png,,,,,,상자 포인트(임시)
|
||||
icon,gear_sword,Icon_ItemIcons/128/ItemIcon_Gear_Sword.Png,,,,,,청동 검(임시)
|
||||
icon,gear_spear,Icon_ItemIcons/128/ItemIcon_Battle.Png,,,,,,철 창(임시)
|
||||
icon,gear_bow,Icon_PictoIcons/128/PictoIcon_Bow.Png,,,,,#8A5A2B,각궁(임시 · 실루엣 틴트)
|
||||
icon,gear_armor,Icon_ItemIcons/128/ItemIcon_Gear_Armor_Top.Png,,,,,,가죽 갑주(임시)
|
||||
icon,gear_helmet,IconMisc/Icon_Helmet.png,,,,,,철 투구(임시)
|
||||
icon,gear_horse,Icon_ItemIcons/128/ItemIcon_Gear_Boots.Png,,,,,,마구(임시)
|
||||
icon,gear_banner,Icon_PictoIcons/128/PictoIcon_Flag.Png,,,,,#D8412F,군령기(임시 · 실루엣 틴트)
|
||||
icon,gear_book,Icon_ItemIcons/128/ItemIcon_Book_1_Purple.Png,,,,,,병서(임시)
|
||||
icon,gear_potion,Icon_ItemIcons/128/ItemIcon_Pot.Png,,,,,,약낭(임시)
|
||||
icon,gear_shield,IconMisc/Icon_Shield.png,,,,,,방패(임시)
|
||||
icon,gear_charm,Icon_ItemIcons/128/ItemIcon_Clover_Gold.Png,,,,,,부적(임시)
|
||||
icon,gear_flag,Icon_ItemIcons/128/ItemIcon_Medal_Gold_1.png,,,,,,전고(임시)
|
||||
icon,flag_shu,Frame/BorderFrame_Flag_Red.png,,,,,,세력 촉(임시)
|
||||
icon,flag_wei,Frame/BorderFrame_Flag_Blue.png,,,,,,세력 위(임시)
|
||||
icon,flag_wu,Frame/BorderFrame_Flag_Green.png,,,,,,세력 오(임시)
|
||||
icon,flag_other,Frame/BorderFrame_Flag_White_Bg.png,,,,,#8C8C96,세력 군웅(임시)
|
||||
icon,rank_1,Icon_GradeBadge/128/Icon_GradeBadge_Beginner.Png,,,,,,훈련 랭크 1(임시)
|
||||
icon,rank_2,Icon_GradeBadge/128/Icon_GradeBadge_Iron.Png,,,,,,훈련 랭크 2(임시)
|
||||
icon,rank_3,Icon_GradeBadge/128/Icon_GradeBadge_Bronze.Png,,,,,,훈련 랭크 3(임시)
|
||||
icon,rank_4,Icon_GradeBadge/128/Icon_GradeBadge_Silver.Png,,,,,,훈련 랭크 4(임시)
|
||||
icon,rank_5,Icon_GradeBadge/128/Icon_GradeBadge_Gold.Png,,,,,,훈련 랭크 5(임시)
|
||||
icon,rank_6,Icon_GradeBadge/128/Icon_GradeBadge_Platinum.Png,,,,,,훈련 랭크 6(임시)
|
||||
icon,rank_7,Icon_GradeBadge/128/Icon_GradeBadge_Diamond.Png,,,,,,훈련 랭크 7(임시)
|
||||
icon,star_on,IconMisc/GradeIcon_Star_s_Yellow.png,,,,,,별(켜짐)
|
||||
icon,star_off,IconMisc/Icon_Star_Off.png,,,,,,별(꺼짐)
|
||||
icon,lock,IconMisc/Icon_Lock03.png,,,,,,잠금
|
||||
icon,check,IconMisc/Icon_Check03_s.png,,,,,,체크
|
||||
icon,arrow_prev,IconMisc/Icon_Arrow_Prev1.png,,,,,,이전
|
||||
icon,arrow_next,IconMisc/Icon_Arrow_Next1.png,,,,,,다음
|
||||
icon,arrow_back,IconMisc/Icon_Arrow_Back.png,,,,,,뒤로
|
||||
icon,new_dot,UI_Etc/Alert_Dot_Bg.png,,,,,#F2453A,새 알림 점
|
||||
icon,tut_hand,Icon_TutorialHand/128/tutorial_hand_1.png,,,,,,튜토리얼 손가락
|
||||
icon,shop_pack,Icon_ShopItem/ShopItem_l_GemPack_3.png,,,,,,상점 패키지(준비 중 칸)
|
||||
icon,bg_lobby,Assets/UI/Lobby/keyart_04.png,,,,,,로비 배경(키아트 04 · B bg_lobby 오면 치환)
|
||||
font,title,Assets/UI/GUIPro/ResourcesData/Fonts/Sen-ExtraBold.ttf,,,,,,제목·숫자(라틴 Sen · 한글 = 폴백 Malgun Gothic · PD 결정 전)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b79aa3573c2bd824eb781e9385791aad
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b327fe546ab27674db7aebf2c7c51f6c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,608 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 63b0a8e358e193740883a84a0bfe1325, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: TKS.Runtime::TKS.UITheme
|
||||
colors:
|
||||
- id: bg
|
||||
color: {r: 0.9372549, g: 0.8980392, b: 0.8117647, a: 1}
|
||||
- id: paper
|
||||
color: {r: 1, g: 0.9764706, b: 0.9254902, a: 1}
|
||||
- id: header
|
||||
color: {r: 0.18039216, g: 0.2, b: 0.28627452, a: 1}
|
||||
- id: header_text
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: header_sub
|
||||
color: {r: 0.7882353, g: 0.7647059, b: 0.8392157, a: 1}
|
||||
- id: ink
|
||||
color: {r: 0.16470589, g: 0.13333334, b: 0.1882353, a: 1}
|
||||
- id: ink_soft
|
||||
color: {r: 0.43529412, g: 0.39215687, b: 0.4392157, a: 1}
|
||||
- id: dark
|
||||
color: {r: 0.22745098, g: 0.2509804, b: 0.3764706, a: 1}
|
||||
- id: red
|
||||
color: {r: 0.84705883, g: 0.25490198, b: 0.18431373, a: 1}
|
||||
- id: line
|
||||
color: {r: 0.11764706, g: 0.14509805, b: 0.20784314, a: 1}
|
||||
- id: slot
|
||||
color: {r: 0.8627451, g: 0.8156863, b: 0.7254902, a: 1}
|
||||
- id: coin
|
||||
color: {r: 0.9529412, g: 0.7176471, b: 0.18039216, a: 1}
|
||||
- id: jade
|
||||
color: {r: 0.13725491, g: 0.7019608, b: 0.5803922, a: 1}
|
||||
- id: grain
|
||||
color: {r: 0.8509804, g: 0.5882353, b: 0.24705882, a: 1}
|
||||
- id: ok
|
||||
color: {r: 0.2784314, g: 0.70980394, b: 0.24705882, a: 1}
|
||||
- id: star
|
||||
color: {r: 1, g: 0.7607843, b: 0.101960786, a: 1}
|
||||
- id: disabled
|
||||
color: {r: 0.61960787, g: 0.59607846, b: 0.6392157, a: 1}
|
||||
- id: purple
|
||||
color: {r: 0.6039216, g: 0.34117648, b: 0.84705883, a: 1}
|
||||
- id: white
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: bar
|
||||
color: {r: 0.11764706, g: 0.14509805, b: 0.20784314, a: 1}
|
||||
- id: pill
|
||||
color: {r: 0.20784314, g: 0.23137255, b: 0.34117648, a: 1}
|
||||
- id: bar_text
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: bar_text_off
|
||||
color: {r: 0.5529412, g: 0.5764706, b: 0.65882355, a: 1}
|
||||
- id: tab_off
|
||||
color: {r: 0.22745098, g: 0.2509804, b: 0.3764706, a: 1}
|
||||
- id: stroke
|
||||
color: {r: 0.11764706, g: 0.14509805, b: 0.20784314, a: 1}
|
||||
- id: dim
|
||||
color: {r: 0, g: 0, b: 0, a: 0.627451}
|
||||
- id: lobby_tint
|
||||
color: {r: 0.6117647, g: 0.58431375, b: 0.65882355, a: 1}
|
||||
- id: bar_track
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: grade_white
|
||||
color: {r: 0.8509804, g: 0.8392157, b: 0.8117647, a: 1}
|
||||
- id: grade_green
|
||||
color: {r: 0.2784314, g: 0.70980394, b: 0.24705882, a: 1}
|
||||
- id: grade_blue
|
||||
color: {r: 0.23529412, g: 0.48235294, b: 0.8784314, a: 1}
|
||||
- id: grade_purple
|
||||
color: {r: 0.6039216, g: 0.34117648, b: 0.84705883, a: 1}
|
||||
- id: grade_orange
|
||||
color: {r: 0.9411765, g: 0.5411765, b: 0.14117648, a: 1}
|
||||
- id: grade_gold
|
||||
color: {r: 0.9529412, g: 0.75686276, b: 0.18039216, a: 1}
|
||||
- id: type_infantry
|
||||
color: {r: 0.78431374, g: 0.33333334, b: 0.22745098, a: 1}
|
||||
- id: type_spear
|
||||
color: {r: 0.24313726, g: 0.6039216, b: 0.2901961, a: 1}
|
||||
- id: type_cavalry
|
||||
color: {r: 0.23529412, g: 0.40392157, b: 0.78431374, a: 1}
|
||||
- id: type_archer
|
||||
color: {r: 0.8509804, g: 0.6039216, b: 0.16862746, a: 1}
|
||||
- id: type_strategist
|
||||
color: {r: 0.6039216, g: 0.34117648, b: 0.84705883, a: 1}
|
||||
- id: faction_shu
|
||||
color: {r: 0.84705883, g: 0.25490198, b: 0.18431373, a: 1}
|
||||
- id: faction_wei
|
||||
color: {r: 0.23529412, g: 0.48235294, b: 0.8784314, a: 1}
|
||||
- id: faction_wu
|
||||
color: {r: 0.18431373, g: 0.65882355, b: 0.30980393, a: 1}
|
||||
- id: faction_other
|
||||
color: {r: 0.54901963, g: 0.54901963, b: 0.5882353, a: 1}
|
||||
- id: hp_bg
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: hp_hi
|
||||
color: {r: 0.32156864, g: 0.81960785, b: 0.28235295, a: 1}
|
||||
- id: hp_mid
|
||||
color: {r: 1, g: 0.77254903, b: 0.16862746, a: 1}
|
||||
- id: hp_low
|
||||
color: {r: 0.9490196, g: 0.27058825, b: 0.22745098, a: 1}
|
||||
- id: pip_on
|
||||
color: {r: 1, g: 0.7607843, b: 0.101960786, a: 1}
|
||||
- id: pip_off
|
||||
color: {r: 0.16862746, g: 0.18431373, b: 0.2509804, a: 0.8}
|
||||
- id: hud_panel
|
||||
color: {r: 0.11764706, g: 0.14509805, b: 0.20784314, a: 0.8509804}
|
||||
- id: hud_turn_player
|
||||
color: {r: 0.23529412, g: 0.48235294, b: 0.8784314, a: 1}
|
||||
- id: hud_turn_enemy
|
||||
color: {r: 0.84705883, g: 0.25490198, b: 0.18431373, a: 1}
|
||||
- id: skill_ready
|
||||
color: {r: 0.84705883, g: 0.25490198, b: 0.18431373, a: 1}
|
||||
- id: skill_reserved
|
||||
color: {r: 0.9529412, g: 0.7176471, b: 0.18039216, a: 1}
|
||||
- id: skill_off
|
||||
color: {r: 0.3529412, g: 0.36862746, b: 0.4392157, a: 1}
|
||||
- id: skill_passive
|
||||
color: {r: 0.22745098, g: 0.2509804, b: 0.3764706, a: 1}
|
||||
- id: skill_cool
|
||||
color: {r: 0, g: 0, b: 0, a: 0.65882355}
|
||||
skins:
|
||||
- id: card
|
||||
pack: {fileID: 21300000, guid: 3070a6f23e6ca4273897acf1b7e8c5ce, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: soft
|
||||
pack: {fileID: 21300000, guid: 6c9211bc1d90b4e35a3a080121e93d05, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: button
|
||||
pack: {fileID: 21300000, guid: 615459ca724384003a91b93533033ab1, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 21300000, guid: 1047c0bcbda25440faf8332b872b3529, type: 3}
|
||||
ppu: 1
|
||||
inset: {x: 5, y: 5, z: 5, w: 18}
|
||||
overlayAlpha: 0.35
|
||||
- id: dot
|
||||
pack: {fileID: 21300000, guid: b31cc26b044a54db88302afadc39ed11, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: bar_bg
|
||||
pack: {fileID: 21300000, guid: 6332433fb34294d58bfc835736ee8ac3, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: bar_fill
|
||||
pack: {fileID: 21300000, guid: 3fceb536486e040c99fac1bb7f353cf6, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: pill
|
||||
pack: {fileID: 21300000, guid: 83aedc4dd182a4b859ab60b44189cda6, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: plus
|
||||
pack: {fileID: 21300000, guid: 77db17572c3694c38812470f80f4009b, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 21300000, guid: a707b1e1252f042c58519d2882ee2651, type: 3}
|
||||
ppu: 1
|
||||
inset: {x: 14, y: 14, z: 14, w: 16}
|
||||
overlayAlpha: 1
|
||||
- id: tabbar
|
||||
pack: {fileID: 21300000, guid: 03cc62a06f5fc44639b0a7ec241ee65f, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: tab_focus
|
||||
pack: {fileID: 21300000, guid: 3070a6f23e6ca4273897acf1b7e8c5ce, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 21300000, guid: d332162b7f97a44c8968e3570e42e325, type: 3}
|
||||
ppu: 1
|
||||
inset: {x: 6, y: 4, z: 6, w: 30}
|
||||
overlayAlpha: 0.45
|
||||
- id: popup
|
||||
pack: {fileID: 21300000, guid: 2bd06dd44f28c41ebac87b908313e284, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: popup_head
|
||||
pack: {fileID: 21300000, guid: 620879c9ab62c447b82f0c54e1e88fee, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 21300000, guid: ab01a2531c35a4aafb31413b44dd1bcb, type: 3}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 60}
|
||||
overlayAlpha: 0.25
|
||||
- id: close
|
||||
pack: {fileID: 21300000, guid: ac729c6a63c5c46578bef27ddfc3c0fe, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 21300000, guid: c7c98a2b50d944d2d933ad3c1f60ad39, type: 3}
|
||||
ppu: 1
|
||||
inset: {x: 22, y: 22, z: 22, w: 26}
|
||||
overlayAlpha: 1
|
||||
- id: ribbon
|
||||
pack: {fileID: 21300000, guid: 2495840c8944f4f05b1d8aa2a409ad7c, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: ribbon_gray
|
||||
pack: {fileID: 21300000, guid: 46d72fa068f1c473cacf5009c97a9b9c, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: toast
|
||||
pack: {fileID: 21300000, guid: 3070a6f23e6ca4273897acf1b7e8c5ce, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: portrait_mask
|
||||
pack: {fileID: 21300000, guid: 6c9211bc1d90b4e35a3a080121e93d05, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: circle_frame
|
||||
pack: {fileID: 21300000, guid: 555b142732e774962897f672b89e14a9, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: skill_btn
|
||||
pack: {fileID: 21300000, guid: c8638447d0c4a40fd9a7e32c25783d96, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: skill_cool
|
||||
pack: {fileID: 21300000, guid: d8a3e7288e03247ec8f56796382ec1a1, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: hp_bg
|
||||
pack: {fileID: 21300000, guid: 1dfa4588cbf5d4c8eb9ecaf11c55c88b, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: hp_fill
|
||||
pack: {fileID: 21300000, guid: 3fceb536486e040c99fac1bb7f353cf6, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: pip
|
||||
pack: {fileID: 21300000, guid: 3070a6f23e6ca4273897acf1b7e8c5ce, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: hud_pill
|
||||
pack: {fileID: 21300000, guid: 83aedc4dd182a4b859ab60b44189cda6, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: banner
|
||||
pack: {fileID: 21300000, guid: 0386c61d06bee46feb8e6bca9882cb40, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: flag
|
||||
pack: {fileID: 21300000, guid: 6f23dee49868b4ee4bb927e2eebe0f5a, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: frame_white
|
||||
pack: {fileID: 21300000, guid: f0bdcf4700e3143dd941fff695e8c391, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: frame_green
|
||||
pack: {fileID: 21300000, guid: 9f5976efc00a04bbf9d3a01ac0219c63, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: frame_blue
|
||||
pack: {fileID: 21300000, guid: 63128e5af0cdc46bfbd4a90aac012629, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: frame_purple
|
||||
pack: {fileID: 21300000, guid: 7878a4afed4e6465c9785efcd828aaec, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: frame_orange
|
||||
pack: {fileID: 21300000, guid: e628dc11848744b1c8b2cf768e50aaeb, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
- id: frame_gold
|
||||
pack: {fileID: 21300000, guid: bf3e36f58b7084484bf9b2cf2fb6f142, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
overlay: {fileID: 0}
|
||||
ppu: 1
|
||||
inset: {x: 0, y: 0, z: 0, w: 0}
|
||||
overlayAlpha: 1
|
||||
icons:
|
||||
- id: cur_gold
|
||||
pack: {fileID: 21300000, guid: 6d5687fb0dd3a428d9cd26a6f36c6d78, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_gem
|
||||
pack: {fileID: 21300000, guid: 42854c0d5a9654da395ed40f0e7443ed, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_stamina
|
||||
pack: {fileID: 21300000, guid: a6832029756c14e05a79241b3ab8bfd5, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_shard
|
||||
pack: {fileID: 21300000, guid: a480ffcca13b444cc828ffb178e72a88, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_iron
|
||||
pack: {fileID: 21300000, guid: d3aad013ac9a74286a3cf57df76f510f, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_blueprint
|
||||
pack: {fileID: 21300000, guid: 3cadefdd2c8ef4523bd35390bab0359e, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_ticket
|
||||
pack: {fileID: 21300000, guid: 1ca4b50341717411f9ad901950edfc2b, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_skillbook
|
||||
pack: {fileID: 21300000, guid: c16591869b2474a649dac6761e3e4b7e, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_exp
|
||||
pack: {fileID: 21300000, guid: 99225861569984f349a535e76bfe9902, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cur_gear
|
||||
pack: {fileID: 21300000, guid: 41bc376691e7a4aef8398c3f84ee249f, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: tab_hero
|
||||
pack: {fileID: 21300000, guid: 6fcf7bcb2b29e4b589e82ab74f31c79e, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: tab_treasure
|
||||
pack: {fileID: 21300000, guid: 3654b5c84fc0440f786a4918b576d3bb, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: tab_domestic
|
||||
pack: {fileID: 21300000, guid: ad90f1e81df3442d3b8fc40036d24cd3, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: tab_alliance
|
||||
pack: {fileID: 21300000, guid: 1eb0217bf1f784956bbb96cf1663c557, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: tab_trade
|
||||
pack: {fileID: 21300000, guid: 6add04477e44d48508df9a7dabad0134, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: btn_sortie
|
||||
pack: {fileID: 21300000, guid: 7f272d61d71ea41479651113f8ec2456, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: btn_formation
|
||||
pack: {fileID: 21300000, guid: 816d14bb0d767435585a0bb55886aaef, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: btn_arena
|
||||
pack: {fileID: 21300000, guid: d3112ce909bbc4504bdadf79eb35726d, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cls_infantry
|
||||
pack: {fileID: 21300000, guid: 3d059bda0f1cb4181a080c8258995348, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cls_spear
|
||||
pack: {fileID: 21300000, guid: 16edef63d3f7646d9bcf5f86b0e476ec, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cls_cavalry
|
||||
pack: {fileID: 21300000, guid: 6200d1a117bb34c21ae7b0265c0027c3, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cls_archer
|
||||
pack: {fileID: 21300000, guid: 21efa6791000e47f2b2b3d493c5d34f0, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: cls_strategist
|
||||
pack: {fileID: 21300000, guid: 244985ea9313545a38c1aec6679972a9, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: chest_bronze
|
||||
pack: {fileID: 21300000, guid: fd7a2020060844292b286576606000ab, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: chest_silver
|
||||
pack: {fileID: 21300000, guid: 52bd6c820cae24fbbbb577594c4cb085, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: chest_gold
|
||||
pack: {fileID: 21300000, guid: 145874fd002594d928ac4f1cc9046b3d, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: chest_general
|
||||
pack: {fileID: 21300000, guid: 9de9bb779c7694b08bf5aabc148b1dd3, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: chest_gem
|
||||
pack: {fileID: 21300000, guid: 05b4c15e805fa4156812361f1797f526, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: chest_point
|
||||
pack: {fileID: 21300000, guid: b23fb0df2c4474124bcec7b152ff27d9, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_sword
|
||||
pack: {fileID: 21300000, guid: 41bc376691e7a4aef8398c3f84ee249f, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_spear
|
||||
pack: {fileID: 21300000, guid: d031f4b21493c4841914d4257119a4e3, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_bow
|
||||
pack: {fileID: 21300000, guid: 21efa6791000e47f2b2b3d493c5d34f0, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 0.5411765, g: 0.3529412, b: 0.16862746, a: 1}
|
||||
- id: gear_armor
|
||||
pack: {fileID: 21300000, guid: 3a3a5d970e2d94998818421e4e0e384b, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_helmet
|
||||
pack: {fileID: 21300000, guid: a52e1372e66954bcf8dfac5f52044251, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_horse
|
||||
pack: {fileID: 21300000, guid: e07c16cced13542f59c7400aff52d8a7, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_banner
|
||||
pack: {fileID: 21300000, guid: 816d14bb0d767435585a0bb55886aaef, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 0.84705883, g: 0.25490198, b: 0.18431373, a: 1}
|
||||
- id: gear_book
|
||||
pack: {fileID: 21300000, guid: 4ea16497cec35499e8fcb6e48452aa29, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_potion
|
||||
pack: {fileID: 21300000, guid: 67f5e0fdd0f6b4952a22b99269db6096, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_shield
|
||||
pack: {fileID: 21300000, guid: 09135c198f8744fcd89493b169d11bd8, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_charm
|
||||
pack: {fileID: 21300000, guid: 5d49c0aac30764cde93957570569f245, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: gear_flag
|
||||
pack: {fileID: 21300000, guid: 36c378f3ccf8c40fe8c6a3ae69624bae, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: flag_shu
|
||||
pack: {fileID: 21300000, guid: 0f8c944da644b42e09c7342aa5735ff9, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: flag_wei
|
||||
pack: {fileID: 21300000, guid: ca6ab62179a66442588aacd94b454ffe, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: flag_wu
|
||||
pack: {fileID: 21300000, guid: b625cd3838cc0477ca073199439588b5, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: flag_other
|
||||
pack: {fileID: 21300000, guid: 6f23dee49868b4ee4bb927e2eebe0f5a, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 0.54901963, g: 0.54901963, b: 0.5882353, a: 1}
|
||||
- id: rank_1
|
||||
pack: {fileID: 21300000, guid: 8ae43bb338f6c4486b21b6220a1cac9d, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: rank_2
|
||||
pack: {fileID: 21300000, guid: cbe57c0243cf5440e9934cffa4681019, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: rank_3
|
||||
pack: {fileID: 21300000, guid: 4b3a9b4d9f2ed4a92996c71af3ba0c42, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: rank_4
|
||||
pack: {fileID: 21300000, guid: 0e3e88c80644941acab7b5bfc3d02d78, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: rank_5
|
||||
pack: {fileID: 21300000, guid: 7f4622e1fadad4b7680182e7309efca3, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: rank_6
|
||||
pack: {fileID: 21300000, guid: 1054306ffb8884ea8a2e142d780c85cb, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: rank_7
|
||||
pack: {fileID: 21300000, guid: 65172c8f38641400dbb8dea2f06a5fcd, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: star_on
|
||||
pack: {fileID: 21300000, guid: 39afaf3c0b490422ea5f07aac1dcfbe1, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: star_off
|
||||
pack: {fileID: 21300000, guid: d228604ab6373411fac2dbf1e0e215d1, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: lock
|
||||
pack: {fileID: 21300000, guid: 899da40fa9ae1462c8e7e40a89da5ca1, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: check
|
||||
pack: {fileID: 21300000, guid: 598c081bd6eaf40bfba9db8c9e2862a9, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: arrow_prev
|
||||
pack: {fileID: 21300000, guid: a9d09d9a3d0d442079a130341db6be90, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: arrow_next
|
||||
pack: {fileID: 21300000, guid: 84c3adc90c0da4f009a1cfa76fa9363c, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: arrow_back
|
||||
pack: {fileID: 21300000, guid: 26459d86a13194dc1ab0997e73d7c594, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: new_dot
|
||||
pack: {fileID: 21300000, guid: 9209a152c6b45453e9b98b6a1f1f2084, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 0.9490196, g: 0.27058825, b: 0.22745098, a: 1}
|
||||
- id: tut_hand
|
||||
pack: {fileID: 21300000, guid: acfcced52c2a44ec78ff53f2b51971b2, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: shop_pack
|
||||
pack: {fileID: 21300000, guid: 33f163c49b488460ea0182825ae1600e, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
- id: bg_lobby
|
||||
pack: {fileID: 21300000, guid: 604887b577dfd2e4aacb8cf8509a5878, type: 3}
|
||||
samguk: {fileID: 0}
|
||||
tint: {r: 1, g: 1, b: 1, a: 1}
|
||||
titleFont: {fileID: 12800000, guid: c8e065a266a274eeebccb4ae0f64b3d9, type: 3}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0944e51b3c366294b95f0b4b93cfe4c5
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -121,6 +121,24 @@ namespace TKS.EditorTools
|
|||
EditorApplication.EnterPlaymode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UI 리뉴얼 검증 캡처(GUI 에디터 · 사본 프로젝트 권장 · 세이브 = 메모리 전용 · PD #1100):
|
||||
/// Unity.exe -projectPath <copy> -executeMethod TKS.EditorTools.DataImporter.CaptureUI -uiDir <dir>
|
||||
/// 화면 10종 + 팝업(1080×1920) + 1536×2048 2장 PNG + log · 끝나면 스스로 종료.
|
||||
/// </summary>
|
||||
public static void CaptureUI()
|
||||
{
|
||||
string dir = GetArg("-uiDir");
|
||||
if (string.IsNullOrEmpty(dir)) dir = Path.Combine(Directory.GetCurrentDirectory(), "Logs", "ui_capture");
|
||||
ImportAll();
|
||||
UIThemeImporter.Import();
|
||||
EditorSceneManager.OpenScene(ProjectSetup.ScenePath, OpenSceneMode.Single);
|
||||
SessionState.SetBool(SaveStore.MemoryFlagKey, true);
|
||||
SessionState.SetString(UICaptureDriver.DirKey, dir);
|
||||
Debug.Log("[TKS] UI 캡처 시작 → " + dir);
|
||||
EditorApplication.EnterPlaymode();
|
||||
}
|
||||
|
||||
static string GetArg(string name)
|
||||
{
|
||||
var args = System.Environment.GetCommandLineArgs();
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ namespace TKS.EditorTools
|
|||
BuildScene(cfg);
|
||||
ApplySettings();
|
||||
UnitArtImporter.ReimportAll();
|
||||
UIThemeImporter.Import();
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("[TKS] Setup 완료 · " + ConfigPath + " · " + ScenePath);
|
||||
|
|
@ -41,6 +42,7 @@ namespace TKS.EditorTools
|
|||
BuildScene(cfg);
|
||||
ApplySettings();
|
||||
UnitArtImporter.ReimportAll();
|
||||
UIThemeImporter.Import();
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("[TKS] BuildFresh 완료 · 기본값 재시드 · " + ScenePath);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,234 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TKS.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// UI 테마 임포트(PD #1100) — Assets/Data/UI/ui_theme.csv(SOT) → Assets/Resources/UI/UITheme.asset.
|
||||
/// 경로 = 팩 Components 기준 상대 경로(Assets/ 로 시작하면 그대로) · 오류가 있으면 자산을 바꾸지 않는다.
|
||||
/// 신규 제작 납품(Assets/UI/Samguk/**/<id>.png)은 같은 id 의 스킨·아이콘을 치환하고 표에 없는 id 는 아이콘으로 추가한다(코드 변경 없이 교체).
|
||||
/// </summary>
|
||||
public static class UIThemeImporter
|
||||
{
|
||||
public const string CsvPath = "Assets/Data/UI/ui_theme.csv";
|
||||
public const string AssetPath = "Assets/Resources/UI/UITheme.asset";
|
||||
public const string PackRoot = "Assets/UI/GUIPro/ResourcesData/Sprites/Components/";
|
||||
public const string SamgukRoot = "Assets/UI/Samguk";
|
||||
|
||||
[MenuItem("TKS/Import UI Theme (UI 테마 임포트)")]
|
||||
public static void Menu()
|
||||
{
|
||||
Import();
|
||||
}
|
||||
|
||||
public static bool Import()
|
||||
{
|
||||
var errors = new List<string>();
|
||||
var theme = ScriptableObject.CreateInstance<UITheme>();
|
||||
if (!File.Exists(CsvPath))
|
||||
{
|
||||
Debug.LogError("[TKS] UI 테마 표 없음: " + CsvPath);
|
||||
return false;
|
||||
}
|
||||
var lines = File.ReadAllText(CsvPath, Encoding.UTF8).TrimStart('').Replace("\r", "").Split('\n');
|
||||
for (int n = 1; n < lines.Length; n++)
|
||||
{
|
||||
var line = lines[n];
|
||||
if (string.IsNullOrWhiteSpace(line)) continue;
|
||||
var f = line.Split(',');
|
||||
if (f.Length < 8)
|
||||
{
|
||||
errors.Add((n + 1) + "행: 열 부족");
|
||||
continue;
|
||||
}
|
||||
string kind = f[0].Trim(), id = f[1].Trim(), path = f[2].Trim(), overlay = f[3].Trim(), color = f[7].Trim();
|
||||
switch (kind)
|
||||
{
|
||||
case "color":
|
||||
{
|
||||
Color c;
|
||||
if (!ColorUtility.TryParseHtmlString(color, out c)) errors.Add((n + 1) + "행 " + id + ": 색 형식 " + color);
|
||||
else theme.colors.Add(new UITheme.ColorEntry { id = id, color = c });
|
||||
break;
|
||||
}
|
||||
case "skin":
|
||||
{
|
||||
var s = new UITheme.SkinEntry { id = id, pack = LoadSprite(path, n, errors) };
|
||||
if (overlay.Length > 0) s.overlay = LoadSprite(overlay, n, errors);
|
||||
s.ppu = ParseF(f[4], 1f);
|
||||
s.inset = ParseInset(f[5]);
|
||||
s.overlayAlpha = ParseF(f[6], 1f);
|
||||
theme.skins.Add(s);
|
||||
break;
|
||||
}
|
||||
case "icon":
|
||||
{
|
||||
var e = new UITheme.IconEntry { id = id, pack = LoadSprite(path, n, errors) };
|
||||
Color c;
|
||||
if (color.Length > 0 && ColorUtility.TryParseHtmlString(color, out c)) e.tint = c;
|
||||
theme.icons.Add(e);
|
||||
break;
|
||||
}
|
||||
case "font":
|
||||
if (id == "title")
|
||||
{
|
||||
theme.titleFont = AssetDatabase.LoadAssetAtPath<Font>(path);
|
||||
if (theme.titleFont == null) errors.Add((n + 1) + "행: 폰트 없음 " + path);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
errors.Add((n + 1) + "행: 알 수 없는 kind " + kind);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (errors.Count > 0)
|
||||
{
|
||||
foreach (var e in errors) Debug.LogError("[TKS] UI 테마 표 오류 · " + e);
|
||||
Debug.LogError("[TKS] UI 테마 임포트 중단(오류 " + errors.Count + ") · 자산 변경 없음");
|
||||
Object.DestroyImmediate(theme);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 신규 제작 치환(파일 이름 = id)
|
||||
var samguk = SamgukSprites();
|
||||
int replaced = 0, added = 0;
|
||||
var used = new HashSet<string>();
|
||||
foreach (var s in theme.skins)
|
||||
{
|
||||
Sprite sp;
|
||||
if (samguk.TryGetValue(s.id, out sp))
|
||||
{
|
||||
s.samguk = sp;
|
||||
used.Add(s.id);
|
||||
replaced++;
|
||||
}
|
||||
}
|
||||
foreach (var e in theme.icons)
|
||||
{
|
||||
Sprite sp;
|
||||
if (samguk.TryGetValue(e.id, out sp))
|
||||
{
|
||||
e.samguk = sp;
|
||||
used.Add(e.id);
|
||||
replaced++;
|
||||
}
|
||||
}
|
||||
foreach (var kv in samguk)
|
||||
{
|
||||
if (used.Contains(kv.Key)) continue;
|
||||
theme.icons.Add(new UITheme.IconEntry { id = kv.Key, samguk = kv.Value });
|
||||
added++;
|
||||
}
|
||||
|
||||
if (!AssetDatabase.IsValidFolder("Assets/Resources")) AssetDatabase.CreateFolder("Assets", "Resources");
|
||||
if (!AssetDatabase.IsValidFolder("Assets/Resources/UI")) AssetDatabase.CreateFolder("Assets/Resources", "UI");
|
||||
var asset = AssetDatabase.LoadAssetAtPath<UITheme>(AssetPath);
|
||||
if (asset == null)
|
||||
{
|
||||
AssetDatabase.CreateAsset(theme, AssetPath);
|
||||
asset = theme;
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.CopySerialized(theme, asset);
|
||||
Object.DestroyImmediate(theme);
|
||||
}
|
||||
asset.Rebuild();
|
||||
EditorUtility.SetDirty(asset);
|
||||
AssetDatabase.SaveAssets();
|
||||
UITheme.Use(asset);
|
||||
Debug.Log("[TKS] UI 테마 임포트 · 색 " + asset.colors.Count + " · 스킨 " + asset.skins.Count + " · 아이콘 " + asset.icons.Count +
|
||||
" · 신규 제작 치환 " + replaced + " · 추가 " + added + " → " + AssetPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Assets/UI/Samguk/**/<id>.png → 스프라이트(같은 id 가 둘이면 경로 순 마지막).</summary>
|
||||
public static Dictionary<string, Sprite> SamgukSprites()
|
||||
{
|
||||
var map = new Dictionary<string, Sprite>();
|
||||
if (!AssetDatabase.IsValidFolder(SamgukRoot)) return map;
|
||||
var guids = AssetDatabase.FindAssets("t:Sprite", new[] { SamgukRoot });
|
||||
var paths = new List<string>();
|
||||
foreach (var g in guids) paths.Add(AssetDatabase.GUIDToAssetPath(g));
|
||||
paths.Sort(System.StringComparer.Ordinal);
|
||||
foreach (var p in paths)
|
||||
{
|
||||
var sp = AssetDatabase.LoadAssetAtPath<Sprite>(p);
|
||||
if (sp != null) map[Path.GetFileNameWithoutExtension(p)] = sp;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static Sprite LoadSprite(string path, int n, List<string> errors)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
errors.Add((n + 1) + "행: 경로 없음");
|
||||
return null;
|
||||
}
|
||||
string full = path.StartsWith("Assets/") ? path : PackRoot + path;
|
||||
var sp = AssetDatabase.LoadAssetAtPath<Sprite>(full);
|
||||
if (sp == null) errors.Add((n + 1) + "행: 스프라이트 없음 " + full);
|
||||
return sp;
|
||||
}
|
||||
|
||||
static float ParseF(string s, float def)
|
||||
{
|
||||
float v;
|
||||
return float.TryParse(s.Trim(), System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out v) ? v : def;
|
||||
}
|
||||
|
||||
static Vector4 ParseInset(string s)
|
||||
{
|
||||
s = s.Trim();
|
||||
if (s.Length == 0) return Vector4.zero;
|
||||
var p = s.Split(';');
|
||||
if (p.Length == 1)
|
||||
{
|
||||
float v = ParseF(p[0], 0f);
|
||||
return new Vector4(v, v, v, v);
|
||||
}
|
||||
return new Vector4(ParseF(p[0], 0f), p.Length > 1 ? ParseF(p[1], 0f) : 0f, p.Length > 2 ? ParseF(p[2], 0f) : 0f, p.Length > 3 ? ParseF(p[3], 0f) : 0f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>신규 제작 UI(Assets/UI/Samguk) · 로비 배경(Assets/UI/Lobby) 임포트 설정 = Sprite(2D) · 납품 파일이 들어오면 테마 치환 테이블 자동 갱신.</summary>
|
||||
public class UIThemeAssetPostprocessor : AssetPostprocessor
|
||||
{
|
||||
static bool pending;
|
||||
|
||||
static bool Ours(string path)
|
||||
{
|
||||
return path.StartsWith(UIThemeImporter.SamgukRoot + "/") || path.StartsWith("Assets/UI/Lobby/");
|
||||
}
|
||||
|
||||
void OnPreprocessTexture()
|
||||
{
|
||||
if (!Ours(assetPath)) return;
|
||||
var ti = (TextureImporter)assetImporter;
|
||||
ti.textureType = TextureImporterType.Sprite;
|
||||
ti.spriteImportMode = SpriteImportMode.Single;
|
||||
ti.alphaIsTransparency = true;
|
||||
ti.mipmapEnabled = false;
|
||||
ti.spritePixelsPerUnit = 100f;
|
||||
ti.maxTextureSize = assetPath.StartsWith("Assets/UI/Lobby/") ? 2048 : 1024;
|
||||
}
|
||||
|
||||
static void OnPostprocessAllAssets(string[] imported, string[] deleted, string[] moved, string[] movedFrom)
|
||||
{
|
||||
bool hit = false;
|
||||
foreach (var p in imported) hit |= p.StartsWith(UIThemeImporter.SamgukRoot + "/") && p.EndsWith(".png");
|
||||
foreach (var p in deleted) hit |= p.StartsWith(UIThemeImporter.SamgukRoot + "/") && p.EndsWith(".png");
|
||||
if (!hit || pending) return;
|
||||
pending = true;
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
pending = false;
|
||||
UIThemeImporter.Import();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 30f8ad8437cad284d831742184f31c39
|
||||
|
|
@ -225,10 +225,12 @@ namespace TKS.OutGame
|
|||
PatrolRules.ChestPerHour(db, d).ToString("0.##") + " / 시간",
|
||||
};
|
||||
Color[] rc = { UiKit.Coin, new Color(0.8f, 0.48f, 0.38f), UiKit.Ok, new Color(0.7f, 0.48f, 0.3f) };
|
||||
string[] rIcon = { "cur_gold", "cur_exp", "cur_gear", "chest_bronze" };
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
var line = UiKit.Box("Row" + i, rate, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -76f - i * 78f), new Vector2(980f, 68f), new Color(0.95f, 0.92f, 0.86f));
|
||||
UiKit.Dot("Dot", line.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(16f, 0f), 50f, rc[i]);
|
||||
if (UiKit.Icon(line.transform, rIcon[i], new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(12f, 0f), 58f) == null)
|
||||
UiKit.Dot("Dot", line.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(16f, 0f), 50f, rc[i]);
|
||||
UiKit.Label(line.transform, rn[i], 34, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(86f, 0f), new Vector2(400f, 56f));
|
||||
UiKit.Label(line.transform, rv[i], 30, UiKit.Ink, TextAnchor.MiddleRight, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-20f, 0f), new Vector2(520f, 56f), false);
|
||||
}
|
||||
|
|
@ -370,11 +372,9 @@ namespace TKS.OutGame
|
|||
|
||||
var foot = UiKit.Box("Foot", p, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 16f), new Vector2(1032f, 150f), UiKit.Paper);
|
||||
UiKit.Border(foot, UiKit.Line, 3f);
|
||||
var bp = UiKit.Dot("Bp", foot.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(20f, 0f), 76f, new Color(0.33f, 0.45f, 0.62f));
|
||||
UiKit.FillLabel(bp.transform, "도", 36, UiKit.White);
|
||||
UiKit.IconOrDot(foot.transform, "cur_blueprint", "도", new Color(0.33f, 0.45f, 0.62f), new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(20f, 0f), 76f);
|
||||
UiKit.Label(foot.transform, "도면 ×" + d.inv.blueprint, 38, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(110f, 0f), new Vector2(260f, 60f));
|
||||
var gd = UiKit.Dot("Gold", foot.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(380f, 0f), 76f, UiKit.Coin);
|
||||
UiKit.FillLabel(gd.transform, "골", 36, UiKit.White);
|
||||
UiKit.IconOrDot(foot.transform, "cur_gold", "골", UiKit.Coin, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(380f, 0f), 76f);
|
||||
UiKit.Label(foot.transform, d.gold.ToString("N0"), 38, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(470f, 0f), new Vector2(220f, 60f));
|
||||
UiKit.Btn("Reset", foot.transform, "트리 초기화\n<size=24>보옥 " + db.Economy.DevResetGem + " · 도면 환급</size>", 34, UiKit.Dark, UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-16f, 0f), new Vector2(320f, 120f), () =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ namespace TKS.OutGame
|
|||
var cell = UiKit.Cell(parent, "T_" + it.id, owned ? UiKit.Paper : new Color(0.85f, 0.82f, 0.77f), owned ? (System.Action)(() => Detail(it.id)) : null);
|
||||
UiKit.Border(cell, owned ? GradeColor(it.grade) : new Color(0.7f, 0.66f, 0.62f), 3f);
|
||||
var icon = UiKit.Dot("Icon", cell.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -14f), 120f, owned ? new Color(0.94f, 0.9f, 0.83f) : new Color(0.78f, 0.74f, 0.69f));
|
||||
UiKit.FillLabel(icon.transform, owned ? it.nameKo.Substring(0, 1) : "?", 60, owned ? GradeColor(it.grade) : new Color(0.6f, 0.56f, 0.52f));
|
||||
if (owned && UiKit.HasFinalIcon("tre_" + it.id)) UiKit.Icon(icon.transform, "tre_" + it.id, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 100f);
|
||||
else UiKit.FillLabel(icon.transform, owned ? it.nameKo.Substring(0, 1) : "?", 60, owned ? GradeColor(it.grade) : new Color(0.6f, 0.56f, 0.52f));
|
||||
if (owned)
|
||||
{
|
||||
if (showShards && st.star < it.starMax)
|
||||
|
|
@ -255,8 +256,8 @@ namespace TKS.OutGame
|
|||
var goalBox = UiKit.TopBand("Points", p, 6f, 150f, 24f, 24f);
|
||||
var gimg = UiKit.Paint(goalBox, UiKit.Paper);
|
||||
UiKit.Border(gimg, UiKit.Line, 3f);
|
||||
var pd = UiKit.Dot("P", goalBox, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(20f, 0f), 90f, UiKit.Coin);
|
||||
UiKit.FillLabel(pd.transform, "P", 44, UiKit.Ink);
|
||||
if (UiKit.Icon(goalBox, "chest_point", new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(16f, 0f), 100f) == null)
|
||||
UiKit.FillLabel(UiKit.Dot("P", goalBox, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(20f, 0f), 90f, UiKit.Coin).transform, "P", 44, UiKit.Ink);
|
||||
var reward = db.Chests.Get(e.ChestPointReward);
|
||||
UiKit.Label(goalBox, (e.ChestPointGoal - d.inv.chestPoints) + "포인트 더 모으면 " + (reward != null ? reward.nameKo : ""), 34, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(130f, -12f), new Vector2(800f, 54f));
|
||||
var fill = UiKit.Bar("Bar", goalBox, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(130f, 52f), new Vector2(700f, 30f), new Color(0.88f, 0.84f, 0.77f), UiKit.Coin);
|
||||
|
|
@ -268,7 +269,8 @@ namespace TKS.OutGame
|
|||
int count = TreasureRules.ChestCount(d, c.id);
|
||||
var banner = UiKit.Box("Banner", p, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -180f), new Vector2(560f, 470f), ChestColor(c.id));
|
||||
UiKit.Border(banner, new Color(0.25f, 0.2f, 0.18f), 4f);
|
||||
UiKit.Label(banner.transform, c.nameKo, 60, UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -40f), new Vector2(520f, 90f));
|
||||
UiKit.Title(UiKit.Label(banner.transform, c.nameKo, 60, UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -40f), new Vector2(520f, 90f)), true);
|
||||
UiKit.Icon(banner.transform, "chest_" + c.id, new Vector2(0f, 1f), new Vector2(0.5f, 0.5f), new Vector2(10f, -10f), 150f);
|
||||
int line = 0;
|
||||
for (int i = 0; i < ChestDb.ProbGrades.Length; i++)
|
||||
{
|
||||
|
|
@ -305,6 +307,7 @@ namespace TKS.OutGame
|
|||
UiKit.Border(b.GetComponent<Image>(), i == chestIdx ? UiKit.Coin : UiKit.Line, i == chestIdx ? 5f : 2f);
|
||||
var box = UiKit.Box("Icon", b.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -20f), new Vector2(w * 0.7f, 90f), ChestColor(ch.id));
|
||||
box.raycastTarget = false;
|
||||
UiKit.Icon(box.transform, "chest_" + ch.id, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 4f), 96f);
|
||||
UiKit.Label(b.transform, ch.nameKo + "\n<size=34>×" + TreasureRules.ChestCount(d, ch.id) + "</size>", 26, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 14f), new Vector2(w, 100f));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ namespace TKS.OutGame
|
|||
readonly Text conds;
|
||||
readonly Text rewards;
|
||||
readonly Text hint;
|
||||
readonly Image ribbon;
|
||||
readonly RectTransform starRow;
|
||||
readonly Image[] starImg = new Image[3];
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
|
|
@ -32,13 +35,32 @@ namespace TKS.OutGame
|
|||
{
|
||||
root = r;
|
||||
var dim = UiKit.Fill("Result", canvas);
|
||||
UiKit.Paint(dim, new Color(0f, 0f, 0f, 0.55f), false);
|
||||
UiKit.Paint(dim, UISkin.Col("dim", new Color(0f, 0f, 0f, 0.55f)), false);
|
||||
go = dim.gameObject;
|
||||
var panel = UiKit.Box("Panel", dim, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 40f), new Vector2(920f, 1180f), UiKit.Paper);
|
||||
UiKit.Border(panel, UiKit.Line, 4f);
|
||||
var head = UiKit.TopBand("Head", panel.transform, 0f, 170f);
|
||||
UiKit.Paint(head, UiKit.Dark);
|
||||
title = UiKit.FillLabel(head, "", 96, UiKit.White);
|
||||
Image panel;
|
||||
if (UISkin.Has("popup"))
|
||||
{
|
||||
// 팩 팝업 틀 + 제목 리본(승리 = 붉은 · 패배 = 회색) + 별 아이콘 3
|
||||
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(920f, 1180f)), "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));
|
||||
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);
|
||||
starRow = UiKit.Rect("StarRow", panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -150f), new Vector2(600f, 190f));
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
float s = i == 1 ? 190f : 150f;
|
||||
starImg[i] = UiKit.Icon(starRow, "star_on", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2((i - 1) * 180f, i == 1 ? 14f : -10f), s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
panel = UiKit.Box("Panel", dim, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 40f), new Vector2(920f, 1180f), UiKit.Paper);
|
||||
UiKit.Border(panel, UiKit.Line, 4f);
|
||||
var head = UiKit.TopBand("Head", panel.transform, 0f, 170f);
|
||||
UiKit.Paint(head, UiKit.Dark);
|
||||
title = UiKit.FillLabel(head, "", 96, UiKit.White);
|
||||
}
|
||||
stars = UiKit.Label(panel.transform, "", 120, UiKit.Star, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -190f), new Vector2(800f, 150f));
|
||||
conds = UiKit.Label(panel.transform, "", 34, UiKit.Ink, TextAnchor.UpperLeft, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -350f), new Vector2(760f, 180f), false);
|
||||
conds.lineSpacing = 1.15f;
|
||||
|
|
@ -61,6 +83,7 @@ namespace TKS.OutGame
|
|||
hint.text = "화면을 탭하면 월드맵으로";
|
||||
title.text = (r.win ? "승리" : "패배") + " <size=44>" + r.chapter + "-" + r.stage + (r.boss ? " 보스" : "") + "</size>";
|
||||
stars.text = r.win ? UiKit.Stars(r.stars, 3) : UiKit.Stars(0, 3);
|
||||
ShowStars(r.win ? r.stars : 0, r.win);
|
||||
if (r.win)
|
||||
{
|
||||
conds.text = Mark(r.conds[0]) + " 클리어\n" +
|
||||
|
|
@ -87,10 +110,22 @@ namespace TKS.OutGame
|
|||
}
|
||||
title.text = r.kind == ArenaRules.Raid ? "토벌 종료" : r.win ? "승리" : "패배";
|
||||
stars.text = "";
|
||||
ShowStars(-1, r.win || r.kind == ArenaRules.Raid);
|
||||
conds.text = "<size=44>" + r.title + "</size>";
|
||||
rewards.text = string.Join("\n", r.lines.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>별 아이콘(n < 0 = 숨김) · 리본 색(승리 붉은 · 패배 회색) · 테마가 없으면 글자 별만.</summary>
|
||||
void ShowStars(int n, bool win)
|
||||
{
|
||||
if (starRow == null) return;
|
||||
stars.gameObject.SetActive(false);
|
||||
starRow.gameObject.SetActive(n >= 0);
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (starImg[i] != null) starImg[i].sprite = UISkin.Icon(i < n ? "star_on" : "star_off") ?? starImg[i].sprite;
|
||||
if (ribbon != null && !UISkin.Apply(ribbon, win ? "ribbon" : "ribbon_gray")) ribbon.color = win ? Color.white : UiKit.Disabled;
|
||||
}
|
||||
|
||||
static string Mark(bool ok)
|
||||
{
|
||||
return ok ? "<color=#3a6a30>○</color>" : "<color=#a03a22>×</color>";
|
||||
|
|
|
|||
|
|
@ -15,22 +15,25 @@ namespace TKS.OutGame
|
|||
var hs = s.Save.Hero(h.id);
|
||||
UiKit.Portrait("Face", cell.transform, h, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(12f, 8f), new Vector2(116f, 108f), false, 2f, new Color(0.9f, 0.86f, 0.8f));
|
||||
int star = hs != null ? hs.star : h.rarity;
|
||||
UiKit.Label(cell.transform, UiKit.Stars(star, star), 22, UiKit.Star, TextAnchor.MiddleCenter, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(12f, 2f), new Vector2(116f, 30f));
|
||||
if (UISkin.Icon("star_on") != null) UiKit.StarRow(cell.transform, star, star, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(14f, 2f), 24f);
|
||||
else UiKit.Label(cell.transform, UiKit.Stars(star, star), 22, UiKit.Star, TextAnchor.MiddleCenter, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(12f, 2f), new Vector2(116f, 30f));
|
||||
UiKit.TypeBadge(cell.transform, h.type, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(142f, -16f), 40f);
|
||||
UiKit.Label(cell.transform, owned ? "Lv " + (lv != null ? lv.lv : 1) : "미보유", 30, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(204f, -12f), new Vector2(150f, 48f));
|
||||
UiKit.Title(UiKit.Label(cell.transform, owned ? "Lv " + (lv != null ? lv.lv : 1) : "미보유", 30, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(204f, -12f), new Vector2(150f, 48f)));
|
||||
if (deployed)
|
||||
{
|
||||
var b = UiKit.Box("Deployed", cell.transform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-12f, -14f), new Vector2(124f, 44f), UiKit.Red);
|
||||
UiKit.FillLabel(b.transform, "출전 중", 24, UiKit.White);
|
||||
UiKit.Title(UiKit.FillLabel(b.transform, "출전 중", 24, UiKit.White), true);
|
||||
}
|
||||
if (hs != null)
|
||||
{
|
||||
var g = UiKit.Box("Grade", cell.transform, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-12f, 14f), new Vector2(56f, 40f), UiKit.GradeColor(hs.grade));
|
||||
UiKit.FillLabel(g.transform, UiKit.GradeKo(hs.grade), 24, UiKit.White);
|
||||
var g = UiKit.Box("Grade", cell.transform, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-12f, 14f), new Vector2(56f, 48f), UiKit.GradeColor(hs.grade));
|
||||
UiKit.GradeFrame(g, hs.grade);
|
||||
UiKit.Title(UiKit.FillLabel(g.transform, UiKit.GradeKo(hs.grade), 24, UiKit.White), true);
|
||||
}
|
||||
var name = UiKit.Label(cell.transform, h.nameKo, 44, owned ? UiKit.Ink : UiKit.InkSoft, TextAnchor.MiddleLeft, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(142f, 12f), new Vector2(290f, 66f));
|
||||
var name = UiKit.Title(UiKit.Label(cell.transform, h.nameKo, 44, owned ? UiKit.Ink : UiKit.InkSoft, TextAnchor.MiddleLeft, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(142f, 12f), new Vector2(290f, 66f)));
|
||||
name.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
if (owned && s.CanGrowAny(h.id)) UiKit.Dot("New", cell.transform, new Vector2(0f, 1f), new Vector2(0.5f, 0.5f), new Vector2(14f, -10f), 26f, UiKit.Red);
|
||||
if (owned && s.CanGrowAny(h.id) && UiKit.Icon(cell.transform, "new_dot", new Vector2(0f, 1f), new Vector2(0.5f, 0.5f), new Vector2(14f, -10f), 34f) == null)
|
||||
UiKit.Dot("New", cell.transform, new Vector2(0f, 1f), new Vector2(0.5f, 0.5f), new Vector2(14f, -10f), 26f, UiKit.Red);
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
|
@ -102,6 +105,9 @@ namespace TKS.OutGame
|
|||
readonly Image[] slotImg = new Image[6];
|
||||
readonly Text[] slotName = new Text[6];
|
||||
readonly Text[] slotState = new Text[6];
|
||||
readonly Image[] slotIcon = new Image[6];
|
||||
readonly Image[] slotMark = new Image[6];
|
||||
RectTransform starRow;
|
||||
Image typeDot;
|
||||
Text typeMark;
|
||||
Text nameText;
|
||||
|
|
@ -158,8 +164,24 @@ namespace TKS.OutGame
|
|||
var b = UiKit.Btn("Slot" + i, card, "", 24, UiKit.Slot, UiKit.Ink, a, a, new Vector2(left ? 22f : -22f, -104f - row * 172f), new Vector2(196f, 156f), () => OnSlot(k));
|
||||
slotImg[i] = b.GetComponent<Image>();
|
||||
UiKit.LabelOf(b).text = "";
|
||||
slotName[i] = UiKit.Label(b.transform, "", 30, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -12f), new Vector2(186f, 84f));
|
||||
slotState[i] = UiKit.Label(b.transform, "", 24, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 10f), new Vector2(186f, 44f), false);
|
||||
if (UISkin.On)
|
||||
{
|
||||
// 팩 등급 칸(ItemFrame) + 장비 아이콘(테마 gear_<kind> · 임시) + 이름 한 줄 + 상태
|
||||
slotIcon[i] = UiKit.Rect("GearIcon", b.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 8f), new Vector2(72f, 72f)).gameObject.AddComponent<Image>();
|
||||
slotIcon[i].preserveAspect = true;
|
||||
slotIcon[i].raycastTarget = false;
|
||||
slotMark[i] = UiKit.Rect("Mark", b.transform, new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(-14f, -14f), new Vector2(44f, 44f)).gameObject.AddComponent<Image>();
|
||||
slotMark[i].preserveAspect = true;
|
||||
slotMark[i].raycastTarget = false;
|
||||
slotName[i] = UiKit.Label(b.transform, "", 28, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -6f), new Vector2(186f, 40f));
|
||||
slotState[i] = UiKit.Label(b.transform, "", 22, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 10f), new Vector2(186f, 34f));
|
||||
UISkin.Stroke(slotState[i], UiKit.White, 1.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
slotName[i] = UiKit.Label(b.transform, "", 30, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -12f), new Vector2(186f, 84f));
|
||||
slotState[i] = UiKit.Label(b.transform, "", 24, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 10f), new Vector2(186f, 44f), false);
|
||||
}
|
||||
}
|
||||
var band = UiKit.Rect("NameBand", card, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), Vector2.zero, new Vector2(0f, 116f));
|
||||
band.anchorMin = new Vector2(0f, 0f);
|
||||
|
|
@ -173,6 +195,8 @@ namespace TKS.OutGame
|
|||
nameText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
subText = UiKit.Label(band, "", 28, new Color(0.85f, 0.8f, 0.75f), TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(420f, 0f), new Vector2(330f, 80f), false);
|
||||
starText = UiKit.Label(band, "", 52, UiKit.Star, TextAnchor.MiddleRight, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-24f, 0f), new Vector2(300f, 80f));
|
||||
if (UISkin.Icon("star_on") != null) starRow = UiKit.Rect("StarRow", band, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-20f, 0f), new Vector2(300f, 60f));
|
||||
UiKit.Title(nameText, true);
|
||||
|
||||
// ② 스킬 정보
|
||||
var skill = UiKit.TopBand("Skill", body, 752f, 400f, 24f, 24f);
|
||||
|
|
@ -205,8 +229,7 @@ namespace TKS.OutGame
|
|||
|
||||
// ④ 조각 · 진화
|
||||
var shRow = UiKit.TopBand("Shard", body, 1290f, 96f, 24f, 24f);
|
||||
var sd = UiKit.Dot("ShardDot", shRow, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(0f, -14f), 54f, UiKit.Purple);
|
||||
UiKit.FillLabel(sd.transform, "조", 28, UiKit.White);
|
||||
UiKit.IconOrDot(shRow, "cur_shard", "조", UiKit.Purple, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(0f, -14f), 58f);
|
||||
UiKit.Label(shRow, "영웅 조각", 32, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(64f, 0f), new Vector2(300f, 46f));
|
||||
shardBar = UiKit.Bar("ShardBar", shRow, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(64f, 4f), new Vector2(690f, 42f), new Color(0.86f, 0.82f, 0.75f), UiKit.Purple);
|
||||
shardText = UiKit.Label(shardBar.parent, "", 28, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(680f, 42f));
|
||||
|
|
@ -250,6 +273,24 @@ namespace TKS.OutGame
|
|||
slotImg[i].gameObject.SetActive(need != null);
|
||||
if (need == null) continue;
|
||||
slotName[i].text = g != null ? g.nameKo : need;
|
||||
if (slotIcon[i] != null)
|
||||
{
|
||||
// 등급 칸 + 아이콘 · 장착 = 체크 · 가방 보유 = 알림 점 · 없음 = 아이콘 흐리게(글자 = 흰 + 외곽선)
|
||||
UiKit.GradeFrame(slotImg[i], g != null ? g.grade : "white");
|
||||
var gs = UISkin.Icon(g != null ? "gear_" + g.kind : null);
|
||||
var ge = gs != null ? UISkin.Theme.IconEntryOf("gear_" + g.kind) : null;
|
||||
slotIcon[i].sprite = gs;
|
||||
slotIcon[i].enabled = gs != null;
|
||||
var tint = ge != null && ge.samguk == null ? ge.tint : Color.white;
|
||||
slotIcon[i].color = new Color(tint.r, tint.g, tint.b, on || have > 0 ? 1f : 0.4f);
|
||||
slotMark[i].sprite = UISkin.Icon(on ? "check" : "new_dot");
|
||||
slotMark[i].enabled = (on || have > 0) && slotMark[i].sprite != null;
|
||||
slotMark[i].color = on ? Color.white : UISkin.Theme.IconEntryOf("new_dot") != null ? UISkin.Theme.IconEntryOf("new_dot").tint : UiKit.Red;
|
||||
string gk = UiKit.GradeKo(g != null ? g.grade : "");
|
||||
slotState[i].color = on ? UiKit.Ok : have > 0 ? UiKit.Red : UiKit.InkSoft;
|
||||
slotState[i].text = on ? "장착 · " + gk : have > 0 ? "탭하여 장착 ×" + have : "없음 · " + gk;
|
||||
continue;
|
||||
}
|
||||
if (on)
|
||||
{
|
||||
slotImg[i].color = new Color(0.9f, 0.95f, 0.86f);
|
||||
|
|
@ -272,6 +313,13 @@ namespace TKS.OutGame
|
|||
nameText.text = h.nameKo;
|
||||
subText.text = UnitTypeInfo.Korean(h.type) + " · " + (h.isSoldier ? "병사 유닛" : UiKit.GradeKo(hs.grade) + " 등급");
|
||||
starText.text = h.isSoldier ? UiKit.Stars(h.rarity, 3) : UiKit.Stars(hs.star, db.Evolve.MaxStar);
|
||||
if (starRow != null)
|
||||
{
|
||||
starText.text = "";
|
||||
UiKit.Clear(starRow);
|
||||
int max = h.isSoldier ? 3 : db.Evolve.MaxStar;
|
||||
UiKit.StarRow(starRow, h.isSoldier ? h.rarity : hs.star, max, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), Vector2.zero, 56f);
|
||||
}
|
||||
|
||||
var skills = new[] { db.Skills.Get(h.skillActive), db.Skills.Get(h.skillPassive) };
|
||||
for (int i = 0; i < 2; i++)
|
||||
|
|
|
|||
|
|
@ -16,14 +16,34 @@ namespace TKS.OutGame
|
|||
Header("본영", "로비", false);
|
||||
var body = Body();
|
||||
|
||||
// 배경 = 테마 bg_lobby(키아트 04 · 어둡게 · 신규 제작 로비 배경이 오면 치환) · 없으면 땅 색 판
|
||||
var art = UISkin.Icon("bg_lobby");
|
||||
if (art != null)
|
||||
{
|
||||
var clip = UiKit.Fill("LobbyBg", body);
|
||||
clip.gameObject.AddComponent<RectMask2D>();
|
||||
// 위쪽 맞춤 × 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<Image>();
|
||||
bimg.sprite = art;
|
||||
bimg.color = UISkin.Col("lobby_tint", Color.white);
|
||||
bimg.raycastTarget = false;
|
||||
var fit = bimg.gameObject.AddComponent<AspectRatioFitter>();
|
||||
fit.aspectMode = AspectRatioFitter.AspectMode.WidthControlsHeight;
|
||||
fit.aspectRatio = art.rect.width / Mathf.Max(1f, art.rect.height);
|
||||
}
|
||||
|
||||
var chip = UiKit.Box("Progress", body, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -28f), new Vector2(760f, 84f), UiKit.Paper);
|
||||
UiKit.Border(chip, UiKit.Line, 2f);
|
||||
progress = UiKit.FillLabel(chip.transform, "", 34, UiKit.Ink);
|
||||
|
||||
// 전장 자리(배경 아트 없음 → 땅 색 판) · 출전 편성 5인
|
||||
// 전장 자리 · 출전 편성 5인
|
||||
var ground = UiKit.Fill("Field", body, 24f, 24f, 140f, 520f);
|
||||
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));
|
||||
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);
|
||||
|
|
@ -32,28 +52,30 @@ namespace TKS.OutGame
|
|||
var sortie = UiKit.Btn("Sortie", body, "", 40, UiKit.Red, UiKit.White, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, y), new Vector2(440f, 400f), () => Root.OpenWorldMap());
|
||||
UiKit.Border(sortie.GetComponent<Image>(), new Color(0.98f, 0.86f, 0.7f), 5f);
|
||||
UiKit.LabelOf(sortie).text = "";
|
||||
UiKit.Label(sortie.transform, "로비 중앙", 28, new Color(1f, 0.85f, 0.8f), TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -22f), new Vector2(400f, 50f), false);
|
||||
UiKit.Label(sortie.transform, "출정", 120, UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 30f), new Vector2(420f, 170f));
|
||||
var si = UiKit.Icon(sortie.transform, "btn_sortie", new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -26f), 92f);
|
||||
if (si != null) UISkin.Stroke(si, UiKit.Stroke, 3f);
|
||||
else UiKit.Label(sortie.transform, "로비 중앙", 28, new Color(1f, 0.85f, 0.8f), TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -22f), new Vector2(400f, 50f), false);
|
||||
UiKit.Title(UiKit.Label(sortie.transform, "출정", 120, UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 30f), new Vector2(420f, 170f)), true);
|
||||
int stages = Root.Battle != null ? Root.Battle.Config.stages.Length : 0;
|
||||
UiKit.Label(sortie.transform, "챕터 월드맵\n" + stages + " 스테이지", 34, UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 30f), new Vector2(420f, 100f), false);
|
||||
UiKit.Title(UiKit.Label(sortie.transform, "챕터 월드맵\n" + stages + " 스테이지", 34, UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 34f), new Vector2(420f, 100f), false), true);
|
||||
|
||||
SideButton(body, "Formation", "편", "편성", "출정 좌측", -1, () => Root.Show(Root.Formation));
|
||||
SideButton(body, "Arena", "연", "연무장", "출정 우측", 1, () =>
|
||||
SideButton(body, "Formation", "btn_formation", "편", "편성", "출정 좌측", -1, () => Root.Show(Root.Formation));
|
||||
SideButton(body, "Arena", "btn_arena", "연", "연무장", "출정 우측", 1, () =>
|
||||
{
|
||||
Root.Arena.SetPage(0);
|
||||
Root.Show(Root.Arena); // 연무장(PD #1093 C)
|
||||
});
|
||||
}
|
||||
|
||||
void SideButton(RectTransform body, string name, string mark, string title, string sub, int side, System.Action onClick)
|
||||
void SideButton(RectTransform body, string name, string icon, string mark, string title, string sub, int side, System.Action onClick)
|
||||
{
|
||||
float x = side * (220f + 160f);
|
||||
var b = UiKit.Btn(name, body, "", 30, UiKit.Paper, UiKit.Ink, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(x, 70f), new Vector2(290f, 340f), onClick);
|
||||
UiKit.Border(b.GetComponent<Image>(), UiKit.Line, 3f);
|
||||
var dot = UiKit.Dot("Mark", b.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -36f), 110f, UiKit.Dark);
|
||||
UiKit.FillLabel(dot.transform, mark, 50, UiKit.White);
|
||||
UiKit.Label(b.transform, title, 52, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -40f), new Vector2(280f, 80f));
|
||||
UiKit.Label(b.transform, sub, 28, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 30f), new Vector2(280f, 50f), false);
|
||||
if (UiKit.Icon(dot.transform, icon, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 66f) == null) UiKit.FillLabel(dot.transform, mark, 50, UiKit.White);
|
||||
UiKit.Title(UiKit.Label(b.transform, title, 52, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -40f), new Vector2(280f, 80f)));
|
||||
UiKit.Label(b.transform, sub, 28, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 34f), new Vector2(280f, 50f), false);
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
|
|
|
|||
|
|
@ -32,18 +32,24 @@ namespace TKS.OutGame
|
|||
float x = 36f;
|
||||
if (back)
|
||||
{
|
||||
UiKit.Btn("Back", band, "◀", 44, UiKit.Dark, UiKit.White, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(24f, 0f), new Vector2(100f, 76f), () => Root.Back());
|
||||
var b = UiKit.Btn("Back", band, "◀", 44, UISkin.On ? UiKit.Red : UiKit.Dark, UiKit.White, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(24f, 0f), new Vector2(100f, 80f), () => Root.Back());
|
||||
if (UiKit.Icon(b.transform, "arrow_back", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 6f), 50f) != null) UiKit.LabelOf(b).text = "";
|
||||
x = 146f;
|
||||
}
|
||||
var t = UiKit.Label(band, title, 52, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(x, 0f), new Vector2(360f, 90f));
|
||||
var t = UiKit.Title(UiKit.Label(band, title, 52, UiKit.HeaderText, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(x, 0f), new Vector2(360f, 90f)), true);
|
||||
t.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
UiKit.Label(band, sub, 30, UiKit.InkSoft, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(x + t.preferredWidth + 18f, -4f), new Vector2(700f, 60f), false);
|
||||
UiKit.Label(band, sub, 30, UiKit.HeaderSub, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(x + t.preferredWidth + 18f, -4f), new Vector2(700f, 60f), false);
|
||||
}
|
||||
|
||||
/// <summary>제목 띠 아래 ~ 하단 탭 위 본문.</summary>
|
||||
/// <summary>
|
||||
/// 제목 띠 아래 ~ 하단 탭 위 본문 — 기준(1080×1920)의 본문 높이보다 화면이 낮으면(예 1536×2048 = 3:4) 본문 전체를 같은 비율로 줄여 탭 바 밑으로 숨지 않게 한다(PD #1100 · 배치는 그대로).
|
||||
/// </summary>
|
||||
protected RectTransform Body(string name = "Body")
|
||||
{
|
||||
return UiKit.Fill(name, Rt, 0f, 0f, OutGameRoot.TopBarH + OutGameRoot.HeaderH, OutGameRoot.TabBarH);
|
||||
var outer = UiKit.Fill(name, Rt, 0f, 0f, OutGameRoot.TopBarH + OutGameRoot.HeaderH, OutGameRoot.TabBarH);
|
||||
var inner = UiKit.Rect("Fit", outer, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(OutGameRoot.Reference.x, OutGameRoot.BodyH));
|
||||
inner.gameObject.AddComponent<UiFitHeight>().designHeight = OutGameRoot.BodyH;
|
||||
return inner;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,6 +66,11 @@ namespace TKS.OutGame
|
|||
public const float HeaderH = 104f;
|
||||
public const float TabBarH = 150f;
|
||||
public static readonly Vector2 Reference = new Vector2(1080f, 1920f);
|
||||
/// <summary>기준 화면의 본문 높이(재화 바 · 제목 띠 · 하단 탭 제외).</summary>
|
||||
public static float BodyH
|
||||
{
|
||||
get { return Reference.y - TopBarH - HeaderH - TabBarH; }
|
||||
}
|
||||
|
||||
public OutGameSession Session { get; private set; }
|
||||
public BattleManager Battle { get; private set; }
|
||||
|
|
@ -246,7 +257,8 @@ namespace TKS.OutGame
|
|||
for (int i = 0; i < tabImages.Count; i++)
|
||||
{
|
||||
bool on = scr.Tab == i;
|
||||
tabImages[i].color = on ? UiKit.Red : UiKit.Dark;
|
||||
if (UISkin.On) tabImages[i].gameObject.SetActive(on);
|
||||
else tabImages[i].color = on ? UiKit.Red : UiKit.Dark;
|
||||
}
|
||||
scr.OnShow();
|
||||
scr.Refresh();
|
||||
|
|
@ -334,24 +346,32 @@ namespace TKS.OutGame
|
|||
void BuildCurrencyBar()
|
||||
{
|
||||
barRoot = UiKit.TopBand("CurrencyBar", TopRoot, 0f, TopBarH);
|
||||
UiKit.Paint(barRoot, new Color(0.15f, 0.11f, 0.09f), false, true);
|
||||
goldText = Pill(0, "골", "골드", UiKit.Coin, () => Toast("골드 = 스테이지 보상 · 거래 > 상점 · (구매 상점 준비 중)"));
|
||||
gemText = Pill(1, "보", "보옥", UiKit.Jade, () => Toast("보옥 구매(과금) = 준비 중 · 첫 클리어 · 보스 보상"));
|
||||
staminaText = Pill(2, "군", "군량", UiKit.Grain, StaminaModal);
|
||||
UiKit.Paint(barRoot, UISkin.On ? UiKit.BarColor : new Color(0.15f, 0.11f, 0.09f), false, true);
|
||||
goldText = Pill(0, "cur_gold", "골", "골드", UiKit.Coin, () => Toast("골드 = 스테이지 보상 · 거래 > 상점 · (구매 상점 준비 중)"));
|
||||
gemText = Pill(1, "cur_gem", "보", "보옥", UiKit.Jade, () => Toast("보옥 구매(과금) = 준비 중 · 첫 클리어 · 보스 보상"));
|
||||
staminaText = Pill(2, "cur_stamina", "군", "군량", UiKit.Grain, StaminaModal);
|
||||
staminaTimer = staminaText.transform.parent.Find("Name").GetComponent<Text>();
|
||||
}
|
||||
|
||||
Text Pill(int i, string mark, string name, Color c, Action plus)
|
||||
/// <summary>재화 칩(팩 ResourceBar · 아이콘 = 테마 cur_* · 「+」 = 팩 노란 단추).</summary>
|
||||
Text Pill(int i, string icon, string mark, string name, Color c, Action plus)
|
||||
{
|
||||
float w = 336f;
|
||||
var p = UiKit.Box("Pill" + i, barRoot, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(18f + i * (w + 18f), 0f), new Vector2(w, 84f), new Color(0.27f, 0.21f, 0.18f));
|
||||
var dot = UiKit.Dot("Icon", p.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(8f, 0f), 64f, c);
|
||||
UiKit.FillLabel(dot.transform, mark, 32, UiKit.White);
|
||||
var n = UiKit.Label(p.transform, name, 26, new Color(0.85f, 0.8f, 0.75f), TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(80f, 0f), new Vector2(110f, 60f), false);
|
||||
var p = UiKit.Rect("Pill" + i, barRoot, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(18f + i * (w + 18f), 0f), new Vector2(w, 84f));
|
||||
UiKit.Skin(p, "pill", UISkin.Col("pill", new Color(0.27f, 0.21f, 0.18f)));
|
||||
UiKit.IconOrDot(p, icon, mark, c, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(-4f, 0f), 76f);
|
||||
var n = UiKit.Label(p, name, 26, UISkin.Col("bar_text_off", new Color(0.85f, 0.8f, 0.75f)), TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(80f, 0f), new Vector2(110f, 60f), false);
|
||||
n.gameObject.name = "Name";
|
||||
var v = UiKit.Label(p.transform, "", 34, UiKit.White, TextAnchor.MiddleRight, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-70f, 0f), new Vector2(170f, 60f));
|
||||
if (i != 2 && UISkin.Icon(icon) != null) n.text = ""; // 아이콘이 이름을 대신(군량 칸은 회복 타이머 자리)
|
||||
var v = UiKit.Title(UiKit.Label(p, "", 36, UISkin.Col("bar_text", UiKit.White), TextAnchor.MiddleRight, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-70f, 0f), new Vector2(170f, 60f)), true);
|
||||
v.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
UiKit.Btn("Plus", p.transform, "+", 40, new Color(0.42f, 0.35f, 0.31f), UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-8f, 0f), new Vector2(56f, 56f), plus);
|
||||
if (UISkin.Has("plus"))
|
||||
{
|
||||
var pb = UiKit.Rect("Plus", p, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-6f, 0f), new Vector2(60f, 62f));
|
||||
UiKit.Skin(pb, "plus", Color.white, true);
|
||||
pb.gameObject.AddComponent<Button>().onClick.AddListener(() => plus());
|
||||
}
|
||||
else UiKit.Btn("Plus", p, "+", 40, new Color(0.42f, 0.35f, 0.31f), UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-8f, 0f), new Vector2(56f, 56f), plus);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
@ -375,9 +395,12 @@ namespace TKS.OutGame
|
|||
bar.anchorMax = new Vector2(1f, 0f);
|
||||
bar.offsetMin = new Vector2(0f, 0f);
|
||||
bar.offsetMax = new Vector2(0f, TabBarH);
|
||||
UiKit.Paint(bar, UiKit.Dark, false, true);
|
||||
UiKit.Paint(bar, UISkin.On ? UiKit.BarColor : UiKit.Dark, false, true);
|
||||
if (UISkin.On) UiKit.Box("TopLine", bar, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(Reference.x * 2f, 6f), UiKit.Line, false);
|
||||
string[] names = { "영웅", "보물", "내정", "동맹", "거래" };
|
||||
string[] marks = { "영", "보", "내", "잠", "거" };
|
||||
string[] icons = { "tab_hero", "tab_treasure", "tab_domestic", "tab_alliance", "tab_trade" };
|
||||
Color off = UISkin.Col("bar_text_off", new Color(0.62f, 0.58f, 0.55f));
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
int k = i;
|
||||
|
|
@ -385,12 +408,33 @@ namespace TKS.OutGame
|
|||
cell.anchorMin = new Vector2(i / 5f, 0f);
|
||||
cell.anchorMax = new Vector2((i + 1) / 5f, 1f);
|
||||
cell.offsetMin = cell.offsetMax = Vector2.zero;
|
||||
var img = UiKit.Paint(cell, UiKit.Dark, false, true);
|
||||
var hit = cell.gameObject.AddComponent<Image>();
|
||||
hit.color = new Color(0f, 0f, 0f, 0f);
|
||||
var btn = cell.gameObject.AddComponent<Button>();
|
||||
btn.onClick.AddListener(() => OnTab(k));
|
||||
var dot = UiKit.Dot("Icon", cell, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -18f), 66f, i == 3 ? new Color(0.35f, 0.3f, 0.28f) : new Color(0.38f, 0.31f, 0.28f));
|
||||
UiKit.FillLabel(dot.transform, marks[i], 32, i == 3 ? new Color(0.7f, 0.66f, 0.62f) : UiKit.White);
|
||||
var t = UiKit.Label(cell, names[i], 32, i == 3 ? new Color(0.62f, 0.58f, 0.55f) : UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 14f), new Vector2(200f, 48f));
|
||||
Image img;
|
||||
if (UISkin.On)
|
||||
{
|
||||
// 선택 탭 = 팩 둥근 판(붉은 옻칠 틴트 · 위로 솟음) · 아이콘 = 테마 tab_*(흰 실루엣)
|
||||
var focus = UiKit.Fill("Focus", cell, 8f, 8f, -18f, 6f);
|
||||
img = UiKit.Skin(focus, "tab_focus", UiKit.Red);
|
||||
var ic = UiKit.Icon(cell, icons[i], new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -14f), 74f);
|
||||
if (ic != null)
|
||||
{
|
||||
if (i == 3) ic.color = off;
|
||||
UISkin.Stroke(ic, UiKit.Line, 3f);
|
||||
}
|
||||
else UiKit.FillLabel(UiKit.Dot("Icon", cell, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -18f), 66f, UISkin.Col("tab_off", UiKit.Dark)).transform, marks[i], 32, UiKit.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
img = hit;
|
||||
img.color = UiKit.Dark;
|
||||
var dot = UiKit.Dot("Icon", cell, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -18f), 66f, i == 3 ? new Color(0.35f, 0.3f, 0.28f) : new Color(0.38f, 0.31f, 0.28f));
|
||||
UiKit.FillLabel(dot.transform, marks[i], 32, i == 3 ? new Color(0.7f, 0.66f, 0.62f) : UiKit.White);
|
||||
}
|
||||
var t = UiKit.Label(cell, names[i], 32, i == 3 ? off : UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 14f), new Vector2(200f, 48f));
|
||||
if (UISkin.On) UiKit.Title(t, i != 3);
|
||||
tabImages.Add(img);
|
||||
tabTexts.Add(t);
|
||||
}
|
||||
|
|
@ -441,16 +485,35 @@ namespace TKS.OutGame
|
|||
{
|
||||
CloseModal();
|
||||
var dim = UiKit.Fill("Modal", TopRoot);
|
||||
var dimImg = UiKit.Paint(dim, new Color(0f, 0f, 0f, 0.6f), false, true);
|
||||
var dimImg = UiKit.Paint(dim, UISkin.Col("dim", new Color(0f, 0f, 0f, 0.6f)), false, true);
|
||||
dimImg.raycastTarget = true;
|
||||
modal = dim.gameObject;
|
||||
float h = height > 0f ? height : 600f;
|
||||
var panel = UiKit.Box("Panel", dim, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 20f), new Vector2(940f, h), UiKit.Paper);
|
||||
panel.raycastTarget = true;
|
||||
UiKit.Border(panel, UiKit.Line, 4f);
|
||||
var head = UiKit.TopBand("Head", panel.transform, 0f, 110f);
|
||||
UiKit.Paint(head, UiKit.Dark);
|
||||
UiKit.FillLabel(head, title, 44, UiKit.White);
|
||||
Image panel;
|
||||
RectTransform head;
|
||||
if (UISkin.Has("popup"))
|
||||
{
|
||||
// 팩 팝업: 흰 틀 + 위 제목 띠(진남 틴트 · 광택) + 닫기 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);
|
||||
var tt = UiKit.Title(UiKit.FillLabel(head, title, 44, UiKit.HeaderText, TextAnchor.MiddleCenter, true, 110f), true);
|
||||
tt.resizeTextForBestFit = true;
|
||||
tt.resizeTextMinSize = 28;
|
||||
tt.resizeTextMaxSize = 44;
|
||||
var x = UiKit.Rect("Close", panel.transform, new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(-58f, -60f), new Vector2(86f, 88f));
|
||||
UiKit.Skin(x, "close", Color.white, true);
|
||||
x.gameObject.AddComponent<Button>().onClick.AddListener(CloseModal);
|
||||
}
|
||||
else
|
||||
{
|
||||
panel = UiKit.Box("Panel", dim, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 20f), new Vector2(940f, h), UiKit.Paper);
|
||||
panel.raycastTarget = true;
|
||||
UiKit.Border(panel, UiKit.Line, 4f);
|
||||
head = UiKit.TopBand("Head", panel.transform, 0f, 110f);
|
||||
UiKit.Paint(head, UiKit.Dark);
|
||||
UiKit.FillLabel(head, title, 44, UiKit.White);
|
||||
}
|
||||
var content = UiKit.Fill("Content", panel.transform, 40f, 40f, 130f, 160f);
|
||||
int n = Mathf.Max(1, buttons.Length);
|
||||
float bw = Mathf.Min(400f, (860f - (n - 1) * 20f) / n);
|
||||
|
|
@ -479,7 +542,9 @@ namespace TKS.OutGame
|
|||
{
|
||||
if (toast == null)
|
||||
{
|
||||
var img = UiKit.Box("Toast", TopRoot, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, TabBarH + 40f), new Vector2(940f, 110f), new Color(0.1f, 0.08f, 0.07f, 0.92f));
|
||||
var img = UISkin.Has("toast")
|
||||
? UiKit.Skin(UiKit.Rect("Toast", TopRoot, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, TabBarH + 40f), new Vector2(940f, 110f)), "toast", UiKit.BarColor)
|
||||
: UiKit.Box("Toast", TopRoot, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, TabBarH + 40f), new Vector2(940f, 110f), new Color(0.1f, 0.08f, 0.07f, 0.92f));
|
||||
toast = img.gameObject;
|
||||
toastText = UiKit.FillLabel(img.transform, "", 32, UiKit.White, TextAnchor.MiddleCenter, false, 16f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,10 +104,11 @@ namespace TKS.OutGame
|
|||
{
|
||||
var g = S.Db.Gacha;
|
||||
var banner = UiKit.TopBand("Banner", p, 12f, 440f, 24f, 24f);
|
||||
UiKit.Paint(banner, new Color(0.27f, 0.14f, 0.12f));
|
||||
if (UISkin.Has("banner")) UiKit.Skin(banner, "banner", Color.white); // 팩 배너 틀(PD #1100)
|
||||
else UiKit.Paint(banner, new Color(0.27f, 0.14f, 0.12f));
|
||||
var pick = UiKit.Box("Pickup", banner, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(30f, -24f), new Vector2(230f, 62f), UiKit.Red);
|
||||
UiKit.FillLabel(pick.transform, "픽업 (2주)", 30, UiKit.White);
|
||||
UiKit.Label(banner, "영웅·유닛 뽑기", 60, UiKit.White, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(36f, -110f), new Vector2(600f, 90f));
|
||||
UiKit.Title(UiKit.Label(banner, "영웅·유닛 뽑기", 60, UiKit.White, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(36f, -110f), new Vector2(600f, 90f)), true);
|
||||
UiKit.Label(banner, "모든 영웅·병사 유닛\n= 뽑기로 획득", 32, new Color(0.9f, 0.82f, 0.78f), TextAnchor.UpperLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(36f, -210f), new Vector2(520f, 110f), false);
|
||||
var free = UiKit.Box("Free", banner, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(36f, 28f), new Vector2(300f, 78f), new Color(0.93f, 0.75f, 0.24f));
|
||||
UiKit.FillLabel(free.transform, "첫 10연 무료", 34, UiKit.Ink);
|
||||
|
|
@ -370,7 +371,9 @@ namespace TKS.OutGame
|
|||
var img = UiKit.Paint(row, UiKit.Paper);
|
||||
UiKit.Border(img, UiKit.Line, 3f);
|
||||
var icon = UiKit.Box("Icon", row, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(20f, 0f), new Vector2(170f, 140f), TreasureScreen.ChestColor(c.id));
|
||||
UiKit.FillLabel(icon.transform, "×" + TreasureRules.ChestCount(d, c.id), 40, UiKit.White);
|
||||
if (UiKit.Icon(icon.transform, "chest_" + c.id, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 8f), 120f) != null)
|
||||
UiKit.Title(UiKit.Label(icon.transform, "×" + TreasureRules.ChestCount(d, c.id), 36, UiKit.White, TextAnchor.LowerRight, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-8f, 2f), new Vector2(150f, 50f)), true);
|
||||
else UiKit.FillLabel(icon.transform, "×" + TreasureRules.ChestCount(d, c.id), 40, UiKit.White);
|
||||
var probs = new List<string>();
|
||||
for (int g = 0; g < ChestDb.ProbGrades.Length; g++)
|
||||
if (c.p[g] > 0f) probs.Add(TreasureRules.GradeKo(ChestDb.ProbGrades[g]) + " " + (c.p[g] * 100f).ToString("0.#") + "%");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace TKS.OutGame
|
||||
{
|
||||
/// <summary>
|
||||
/// 본문 높이 맞춤(PD #1100) — 부모가 기준 높이보다 낮으면(3:4 등) 같은 비율로 줄이고 가로는 부모를 꽉 채운다 · 높거나 같으면 부모와 같은 크기(기존 늘림과 같음).
|
||||
/// </summary>
|
||||
public class UiFitHeight : MonoBehaviour
|
||||
{
|
||||
public float designHeight = 1546f;
|
||||
Vector2 last = new Vector2(-1f, -1f);
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
last = new Vector2(-1f, -1f);
|
||||
Apply();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
Apply();
|
||||
}
|
||||
|
||||
public float Scale
|
||||
{
|
||||
get { return transform.localScale.x; }
|
||||
}
|
||||
|
||||
void Apply()
|
||||
{
|
||||
var rt = (RectTransform)transform;
|
||||
var parent = rt.parent as RectTransform;
|
||||
if (parent == null || designHeight <= 0f) return;
|
||||
var size = parent.rect.size;
|
||||
if (size == last || size.y <= 0f) return;
|
||||
last = size;
|
||||
float s = Mathf.Min(1f, size.y / designHeight);
|
||||
rt.anchorMin = rt.anchorMax = new Vector2(0.5f, 1f);
|
||||
rt.pivot = new Vector2(0.5f, 1f);
|
||||
rt.localScale = new Vector3(s, s, 1f);
|
||||
rt.sizeDelta = s < 1f ? new Vector2(size.x / s, designHeight) : size;
|
||||
rt.anchoredPosition = Vector2.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fa2cf3b7e2917044da9dd68acfd5a663
|
||||
|
|
@ -7,29 +7,40 @@ using UnityEngine.UI;
|
|||
namespace TKS.OutGame
|
||||
{
|
||||
/// <summary>
|
||||
/// 아웃게임 와이어프레임 UI 도우미 — uGUI + Malgun Gothic(TextUtil) · 아트 없음 = 도형 + 글자 · 기준 1080×1920 · 색 = 목업 img03·06·08·11.
|
||||
/// 아웃게임 UI 도우미 — uGUI + Malgun Gothic(TextUtil) · 기준 1080×1920 · 배치 = 확정 목업(img03·05·06·07·08·11·13·14·16·17).
|
||||
/// 부품·색 = UI 테마(PD #1100 · Layer Lab GUI Pro-SuperCasual 팩 · UISkin) · 테마가 없으면 기존 도형 와이어프레임.
|
||||
/// 위치 인자는 전부 「부모 안 기준점(anchor) · 피벗 · 기준점에서의 거리 · 크기」(UI px).
|
||||
/// </summary>
|
||||
public static class UiKit
|
||||
{
|
||||
public static readonly Color Bg = new Color(0.95f, 0.92f, 0.85f);
|
||||
public static readonly Color Paper = new Color(0.99f, 0.97f, 0.92f);
|
||||
public static readonly Color Header = new Color(0.92f, 0.87f, 0.78f);
|
||||
public static readonly Color Ink = new Color(0.17f, 0.12f, 0.10f);
|
||||
public static readonly Color InkSoft = new Color(0.45f, 0.39f, 0.34f);
|
||||
public static readonly Color Dark = new Color(0.21f, 0.16f, 0.14f);
|
||||
public static readonly Color Red = new Color(0.74f, 0.26f, 0.19f);
|
||||
public static readonly Color Line = new Color(0.33f, 0.26f, 0.22f);
|
||||
public static readonly Color Slot = new Color(0.80f, 0.76f, 0.70f);
|
||||
public static readonly Color Coin = new Color(0.88f, 0.67f, 0.20f);
|
||||
public static readonly Color Jade = new Color(0.27f, 0.60f, 0.52f);
|
||||
public static readonly Color Grain = new Color(0.76f, 0.58f, 0.38f);
|
||||
public static readonly Color Ok = new Color(0.36f, 0.62f, 0.31f);
|
||||
public static readonly Color Star = new Color(0.93f, 0.68f, 0.13f);
|
||||
public static readonly Color Disabled = new Color(0.66f, 0.62f, 0.58f);
|
||||
public static readonly Color Purple = new Color(0.58f, 0.36f, 0.70f);
|
||||
// 팔레트 = 테마 색 id(ui_theme.csv) · 괄호 값 = 테마가 없을 때(구 와이어프레임)
|
||||
public static Color Bg { get { return UISkin.Col("bg", new Color(0.95f, 0.92f, 0.85f)); } }
|
||||
public static Color Paper { get { return UISkin.Col("paper", new Color(0.99f, 0.97f, 0.92f)); } }
|
||||
public static Color Header { get { return UISkin.Col("header", new Color(0.92f, 0.87f, 0.78f)); } }
|
||||
public static Color HeaderText { get { return UISkin.Col("header_text", Ink); } }
|
||||
public static Color HeaderSub { get { return UISkin.Col("header_sub", InkSoft); } }
|
||||
public static Color Ink { get { return UISkin.Col("ink", new Color(0.17f, 0.12f, 0.10f)); } }
|
||||
public static Color InkSoft { get { return UISkin.Col("ink_soft", new Color(0.45f, 0.39f, 0.34f)); } }
|
||||
public static Color Dark { get { return UISkin.Col("dark", new Color(0.21f, 0.16f, 0.14f)); } }
|
||||
public static Color Red { get { return UISkin.Col("red", new Color(0.74f, 0.26f, 0.19f)); } }
|
||||
public static Color Line { get { return UISkin.Col("line", new Color(0.33f, 0.26f, 0.22f)); } }
|
||||
public static Color Slot { get { return UISkin.Col("slot", new Color(0.80f, 0.76f, 0.70f)); } }
|
||||
public static Color Coin { get { return UISkin.Col("coin", new Color(0.88f, 0.67f, 0.20f)); } }
|
||||
public static Color Jade { get { return UISkin.Col("jade", new Color(0.27f, 0.60f, 0.52f)); } }
|
||||
public static Color Grain { get { return UISkin.Col("grain", new Color(0.76f, 0.58f, 0.38f)); } }
|
||||
public static Color Ok { get { return UISkin.Col("ok", new Color(0.36f, 0.62f, 0.31f)); } }
|
||||
public static Color Star { get { return UISkin.Col("star", new Color(0.93f, 0.68f, 0.13f)); } }
|
||||
public static Color Disabled { get { return UISkin.Col("disabled", new Color(0.66f, 0.62f, 0.58f)); } }
|
||||
public static Color Purple { get { return UISkin.Col("purple", new Color(0.58f, 0.36f, 0.70f)); } }
|
||||
public static Color BarColor { get { return UISkin.Col("bar", new Color(0.15f, 0.11f, 0.09f)); } }
|
||||
public static Color Stroke { get { return UISkin.Col("stroke", new Color(0.12f, 0.1f, 0.1f)); } }
|
||||
public static readonly Color White = Color.white;
|
||||
|
||||
public static Color Col(string id, Color fallback)
|
||||
{
|
||||
return UISkin.Col(id, fallback);
|
||||
}
|
||||
|
||||
static Sprite round;
|
||||
|
||||
/// <summary>둥근 모서리 9-slice(모서리 22 px).</summary>
|
||||
|
|
@ -111,11 +122,14 @@ namespace TKS.OutGame
|
|||
return rt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 칠하기 — rounded = 팩 카드(흰 바탕 + 굵은 외곽선 · 색 틴트 · 반투명이면 외곽선 없는 판) · false = 평면 띠.
|
||||
/// </summary>
|
||||
public static Image Paint(RectTransform rt, Color c, bool rounded = true, bool raycast = false)
|
||||
{
|
||||
var img = rt.gameObject.AddComponent<Image>();
|
||||
img.color = c;
|
||||
if (rounded)
|
||||
if (rounded && !UISkin.Apply(img, c.a >= 0.95f ? "card" : "soft"))
|
||||
{
|
||||
img.sprite = Round;
|
||||
img.type = Image.Type.Sliced;
|
||||
|
|
@ -124,6 +138,44 @@ namespace TKS.OutGame
|
|||
return img;
|
||||
}
|
||||
|
||||
/// <summary>스킨 id 로 칠하기(없으면 둥근 도형).</summary>
|
||||
public static Image Skin(RectTransform rt, string skin, Color c, bool raycast = false)
|
||||
{
|
||||
var img = rt.gameObject.AddComponent<Image>();
|
||||
img.color = c;
|
||||
if (!UISkin.Apply(img, skin))
|
||||
{
|
||||
img.sprite = Round;
|
||||
img.type = Image.Type.Sliced;
|
||||
}
|
||||
img.raycastTarget = raycast;
|
||||
return img;
|
||||
}
|
||||
|
||||
/// <summary>아이콘(테마 id · 없으면 null).</summary>
|
||||
public static Image Icon(Transform parent, string id, Vector2 anchor, Vector2 pivot, Vector2 pos, float size)
|
||||
{
|
||||
return UISkin.IconImage(parent, id, anchor, pivot, pos, new Vector2(size, size));
|
||||
}
|
||||
|
||||
/// <summary>아이콘이 있으면 아이콘 · 없으면 원 + 글자(구 표시).</summary>
|
||||
public static Image IconOrDot(Transform parent, string id, string mark, Color c, Vector2 anchor, Vector2 pivot, Vector2 pos, float size)
|
||||
{
|
||||
var ic = Icon(parent, id, anchor, pivot, pos, size);
|
||||
if (ic != null) return ic;
|
||||
var dot = Dot("Icon", parent, anchor, pivot, pos, size, c);
|
||||
FillLabel(dot.transform, mark, Mathf.RoundToInt(size * 0.5f), White);
|
||||
return dot;
|
||||
}
|
||||
|
||||
/// <summary>제목 폰트(Sen-ExtraBold + 한글 폴백) + 흰 글자 외곽선.</summary>
|
||||
public static Text Title(Text t, bool stroke = false)
|
||||
{
|
||||
t.font = UISkin.TitleFont;
|
||||
if (stroke && UISkin.On) UISkin.Stroke(t, Stroke, 3f);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Image Box(string name, Transform parent, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size, Color c, bool rounded = true)
|
||||
{
|
||||
return Paint(Rect(name, parent, anchor, pivot, pos, size), c, rounded);
|
||||
|
|
@ -132,15 +184,18 @@ namespace TKS.OutGame
|
|||
public static Image Dot(string name, Transform parent, Vector2 anchor, Vector2 pivot, Vector2 pos, float d, Color c)
|
||||
{
|
||||
var img = Rect(name, parent, anchor, pivot, pos, new Vector2(d, d)).gameObject.AddComponent<Image>();
|
||||
img.sprite = Circle;
|
||||
if (d > 280f || !UISkin.Apply(img, "dot")) img.sprite = Circle; // 큰 원(후광 등)은 팩 외곽선이 흐려져서 평면 원
|
||||
img.preserveAspect = true;
|
||||
img.color = c;
|
||||
img.raycastTarget = false;
|
||||
return img;
|
||||
}
|
||||
|
||||
/// <summary>테두리(외곽선 효과 · 둥근 상자에 굵은 선처럼 보임).</summary>
|
||||
/// <summary>테두리(외곽선 효과 · 둥근 상자에 굵은 선처럼 보임) · 테마 카드는 외곽선을 이미 가져서 기본 선 색이면 생략.</summary>
|
||||
public static void Border(Graphic g, Color c, float w = 4f)
|
||||
{
|
||||
if (UISkin.On && c == Line) return;
|
||||
if (UISkin.On) w = Mathf.Min(w, 3f);
|
||||
var o = g.gameObject.AddComponent<Outline>();
|
||||
o.effectColor = c;
|
||||
o.effectDistance = new Vector2(w, -w);
|
||||
|
|
@ -181,14 +236,22 @@ namespace TKS.OutGame
|
|||
|
||||
public static Button Btn(string name, Transform parent, string label, int fontSize, Color bg, Color fg, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size, Action onClick)
|
||||
{
|
||||
var img = Box(name, parent, anchor, pivot, pos, size, bg);
|
||||
img.raycastTarget = true;
|
||||
var img = Skin(Rect(name, parent, anchor, pivot, pos, size), "button", bg, true);
|
||||
var b = img.gameObject.AddComponent<Button>();
|
||||
var cb = b.colors;
|
||||
cb.disabledColor = new Color(0.75f, 0.75f, 0.75f, 0.85f);
|
||||
b.colors = cb;
|
||||
if (onClick != null) b.onClick.AddListener(() => onClick());
|
||||
FillLabel(img.transform, label, fontSize, fg, TextAnchor.MiddleCenter, true, 6f);
|
||||
var t = FillLabel(img.transform, label, fontSize, fg, TextAnchor.MiddleCenter, true, 6f);
|
||||
if (UISkin.On)
|
||||
{
|
||||
// 팩 버튼 = 아래 턱(약 16 px)이 있어 글자를 조금 올리고 흰 글자는 외곽선
|
||||
var trt = t.rectTransform;
|
||||
float side = Mathf.Min(16f, size.x * 0.08f); // 팩 버튼 외곽선 안쪽으로
|
||||
trt.offsetMin = new Vector2(side, Mathf.Min(10f, size.y * 0.1f));
|
||||
trt.offsetMax = new Vector2(-side, trt.offsetMax.y);
|
||||
Title(t, fg.r + fg.g + fg.b > 2.4f);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
|
@ -200,8 +263,19 @@ namespace TKS.OutGame
|
|||
/// <summary>둥근 막대 게이지 · 반환 = 채움(SetBar 로 0~1).</summary>
|
||||
public static RectTransform Bar(string name, Transform parent, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size, Color bg, Color fg)
|
||||
{
|
||||
var back = Box(name, parent, anchor, pivot, pos, size, bg);
|
||||
var fill = Fill("Fill", back.transform);
|
||||
if (UISkin.Has("bar_bg"))
|
||||
{
|
||||
// 팩 슬라이더: 어두운 홈(스킨 원색) + 안쪽 홈에 채움(용도 색 틴트)
|
||||
var back = Skin(Rect(name, parent, anchor, pivot, pos, size), "bar_bg", Col("bar_track", White));
|
||||
float pad = Mathf.Clamp(size.y * 0.16f, 3f, 6f);
|
||||
var track = Fill("Track", back.transform, pad, pad, pad, pad);
|
||||
var f = Fill("Fill", track);
|
||||
f.anchorMax = new Vector2(0f, 1f);
|
||||
Skin(f, "bar_fill", fg);
|
||||
return f;
|
||||
}
|
||||
var b0 = Box(name, parent, anchor, pivot, pos, size, bg);
|
||||
var fill = Fill("Fill", b0.transform);
|
||||
fill.anchorMax = new Vector2(0f, 1f);
|
||||
Paint(fill, fg);
|
||||
return fill;
|
||||
|
|
@ -278,15 +352,36 @@ namespace TKS.OutGame
|
|||
{
|
||||
switch (t)
|
||||
{
|
||||
case UnitType.Infantry: return new Color(0.62f, 0.33f, 0.22f);
|
||||
case UnitType.Spear: return new Color(0.30f, 0.50f, 0.30f);
|
||||
case UnitType.Cavalry: return new Color(0.28f, 0.32f, 0.45f);
|
||||
case UnitType.Archer: return new Color(0.70f, 0.52f, 0.20f);
|
||||
case UnitType.Strategist: return Purple;
|
||||
case UnitType.Infantry: return Col("type_infantry", new Color(0.62f, 0.33f, 0.22f));
|
||||
case UnitType.Spear: return Col("type_spear", new Color(0.30f, 0.50f, 0.30f));
|
||||
case UnitType.Cavalry: return Col("type_cavalry", new Color(0.28f, 0.32f, 0.45f));
|
||||
case UnitType.Archer: return Col("type_archer", new Color(0.70f, 0.52f, 0.20f));
|
||||
case UnitType.Strategist: return Col("type_strategist", Purple);
|
||||
}
|
||||
return Dark;
|
||||
}
|
||||
|
||||
/// <summary>병종 아이콘 id(테마 · 신규 제작 cls_*).</summary>
|
||||
public static string TypeIconId(UnitType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case UnitType.Infantry: return "cls_infantry";
|
||||
case UnitType.Spear: return "cls_spear";
|
||||
case UnitType.Cavalry: return "cls_cavalry";
|
||||
case UnitType.Archer: return "cls_archer";
|
||||
case UnitType.Strategist: return "cls_strategist";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>신규 제작(B) 치환이 들어온 아이콘인가(임시 팩 아이콘이 뜻과 어긋나는 곳은 그때만 아이콘을 쓴다 · 예: 병종).</summary>
|
||||
public static bool HasFinalIcon(string id)
|
||||
{
|
||||
var e = UISkin.Theme != null ? UISkin.Theme.IconEntryOf(id) : null;
|
||||
return e != null && e.samguk != null;
|
||||
}
|
||||
|
||||
/// <summary>등급(승급 green… · 장비 white…) 표시 이름.</summary>
|
||||
public static string GradeKo(string g)
|
||||
{
|
||||
|
|
@ -306,16 +401,42 @@ namespace TKS.OutGame
|
|||
{
|
||||
switch (g)
|
||||
{
|
||||
case "white": return new Color(0.80f, 0.79f, 0.76f);
|
||||
case "green": return new Color(0.38f, 0.64f, 0.33f);
|
||||
case "blue": return new Color(0.29f, 0.48f, 0.78f);
|
||||
case "purple": return Purple;
|
||||
case "orange": return new Color(0.90f, 0.50f, 0.18f);
|
||||
case "gold": return new Color(0.92f, 0.74f, 0.16f);
|
||||
case "white": return Col("grade_white", new Color(0.80f, 0.79f, 0.76f));
|
||||
case "green": return Col("grade_green", new Color(0.38f, 0.64f, 0.33f));
|
||||
case "blue": return Col("grade_blue", new Color(0.29f, 0.48f, 0.78f));
|
||||
case "purple": return Col("grade_purple", Purple);
|
||||
case "orange": return Col("grade_orange", new Color(0.90f, 0.50f, 0.18f));
|
||||
case "gold": return Col("grade_gold", new Color(0.92f, 0.74f, 0.16f));
|
||||
}
|
||||
return Slot;
|
||||
}
|
||||
|
||||
/// <summary>등급 칸(팩 ItemFrame 등급 색 · 신규 제작 frame_* 오면 치환) — 스킨이 없으면 등급 색 카드.</summary>
|
||||
public static Image GradeFrame(Image img, string grade)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(grade) && UISkin.Apply(img, "frame_" + grade))
|
||||
{
|
||||
img.color = White;
|
||||
return img;
|
||||
}
|
||||
UISkin.Apply(img, "card");
|
||||
img.color = GradeColor(grade);
|
||||
return img;
|
||||
}
|
||||
|
||||
/// <summary>별 줄(★ 아이콘 n개 · 테마 없으면 글자).</summary>
|
||||
public static void StarRow(Transform parent, int n, int max, Vector2 anchor, Vector2 pivot, Vector2 pos, float size)
|
||||
{
|
||||
if (UISkin.Icon("star_on") == null)
|
||||
{
|
||||
Label(parent, Stars(n, max), Mathf.RoundToInt(size), Star, TextAnchor.MiddleCenter, anchor, pivot, pos, new Vector2(size * max, size + 6f));
|
||||
return;
|
||||
}
|
||||
var row = Rect("Stars", parent, anchor, pivot, pos, new Vector2(size * max * 0.92f, size));
|
||||
for (int i = 0; i < max; i++)
|
||||
Icon(row, i < n ? "star_on" : "star_off", new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(i * size * 0.92f, 0f), size);
|
||||
}
|
||||
|
||||
public static string Stars(int n, int max)
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
|
|
@ -350,12 +471,30 @@ namespace TKS.OutGame
|
|||
/// </summary>
|
||||
public static RectTransform Portrait(string name, Transform parent, HeroDb.Hero h, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size, bool circle, float zoom, Color frame)
|
||||
{
|
||||
var rt = Rect(name, parent, anchor, pivot, pos, size);
|
||||
var outer = Rect(name, parent, anchor, pivot, pos, size);
|
||||
var rt = outer;
|
||||
bool framed = frame.a > 0.01f && UISkin.On;
|
||||
if (framed)
|
||||
{
|
||||
// 팩 틀(외곽선) 바깥 + 안쪽 마스크(외곽선 안으로 그림이 들어가게)
|
||||
var fimg = outer.gameObject.AddComponent<Image>();
|
||||
fimg.color = frame;
|
||||
fimg.raycastTarget = false;
|
||||
if (circle)
|
||||
{
|
||||
if (!UISkin.Apply(fimg, "circle_frame")) fimg.sprite = Circle;
|
||||
fimg.preserveAspect = true;
|
||||
}
|
||||
else UISkin.Apply(fimg, "card");
|
||||
float pad = Mathf.Max(5f, Mathf.Min(size.x, size.y) * 0.05f);
|
||||
rt = Fill("Mask", outer, pad, pad, pad, pad + (circle ? 0f : 2f));
|
||||
size = new Vector2(size.x - pad * 2f, size.y - pad * 2f);
|
||||
}
|
||||
var bg = rt.gameObject.AddComponent<Image>();
|
||||
bg.color = frame;
|
||||
bg.color = framed ? new Color(frame.r * 0.9f, frame.g * 0.9f, frame.b * 0.9f, 1f) : frame;
|
||||
bg.raycastTarget = false;
|
||||
if (circle) bg.sprite = Circle;
|
||||
else
|
||||
else if (!framed || !UISkin.Apply(bg, "portrait_mask"))
|
||||
{
|
||||
bg.sprite = Round;
|
||||
bg.type = Image.Type.Sliced;
|
||||
|
|
@ -380,16 +519,18 @@ namespace TKS.OutGame
|
|||
{
|
||||
float d = Mathf.Min(size.x, size.y) * 0.72f;
|
||||
var dot = Dot("Shape", rt, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, d, TypeColor(h.type));
|
||||
FillLabel(dot.transform, UnitTypeInfo.Mark(h.type), Mathf.RoundToInt(d * 0.5f), White);
|
||||
Title(FillLabel(dot.transform, UnitTypeInfo.Mark(h.type), Mathf.RoundToInt(d * 0.5f), White), true);
|
||||
}
|
||||
return rt;
|
||||
return outer;
|
||||
}
|
||||
|
||||
/// <summary>병종 배지(어두운 둥근 칸 + 글자).</summary>
|
||||
/// <summary>병종 배지(병종 색 칩 + 글자 · 신규 제작 cls_* 아이콘이 오면 아이콘).</summary>
|
||||
public static Image TypeBadge(Transform parent, UnitType t, Vector2 anchor, Vector2 pivot, Vector2 pos, float h)
|
||||
{
|
||||
var b = Box("Type", parent, anchor, pivot, pos, new Vector2(h * 1.3f, h), Dark);
|
||||
FillLabel(b.transform, UnitTypeInfo.Mark(t), Mathf.RoundToInt(h * 0.62f), White);
|
||||
var b = Box("Type", parent, anchor, pivot, pos, new Vector2(h * 1.3f, h), UISkin.On ? TypeColor(t) : Dark);
|
||||
string icon = TypeIconId(t);
|
||||
if (HasFinalIcon(icon)) Icon(b.transform, icon, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 1f), h * 0.8f);
|
||||
else Title(FillLabel(b.transform, UnitTypeInfo.Mark(t), Mathf.RoundToInt(h * 0.62f), White), true);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TKS.OutGame
|
||||
{
|
||||
/// <summary>
|
||||
/// UI 리뉴얼 검증 캡처(PD #1100 · 에디터 DataImporter.CaptureUI 가 SessionState 로 출력 폴더를 넘기면 생성 · 세이브 = 메모리 전용 신규 유저).
|
||||
/// 1080×1920 = 로비 · 영웅 목록 · 영웅 상세 · 편성 · 거래 · 보물 · 내정 · 연무장 · 월드맵 팝업 · 전투 HUD · 전투 결과 · 팝업 + 1536×2048 = 로비 · 영웅 상세(겹침 확인) · 끝나면 스스로 종료.
|
||||
/// </summary>
|
||||
public class UICaptureDriver : MonoBehaviour
|
||||
{
|
||||
public const string DirKey = "TKS_UI_CAPTURE_DIR";
|
||||
public string OutputDir;
|
||||
const int W = 1080, H = 1920, W2 = 1536, H2 = 2048;
|
||||
|
||||
readonly List<string> log = new List<string>();
|
||||
int shot = 1;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
||||
static void AutoSpawn()
|
||||
{
|
||||
string dir = UnityEditor.SessionState.GetString(DirKey, "");
|
||||
if (string.IsNullOrEmpty(dir)) return;
|
||||
UnityEditor.SessionState.EraseString(DirKey);
|
||||
var d = new GameObject("UICaptureDriver").AddComponent<UICaptureDriver>();
|
||||
d.OutputDir = dir;
|
||||
}
|
||||
#endif
|
||||
|
||||
IEnumerator Start()
|
||||
{
|
||||
Directory.CreateDirectory(OutputDir);
|
||||
yield return null;
|
||||
yield return null;
|
||||
var root = OutGameRoot.Instance;
|
||||
var cam = Camera.main;
|
||||
if (root == null || cam == null)
|
||||
{
|
||||
Log("FAIL: OutGameRoot 또는 카메라 없음");
|
||||
Finish(1);
|
||||
yield break;
|
||||
}
|
||||
var s = root.Session;
|
||||
var db = s.Db;
|
||||
var d = s.Save;
|
||||
Log("theme=" + (UITheme.Current != null) + " titleFont=" + (UISkin.TitleFont != null ? UISkin.TitleFont.name : "-") + " memoryOnly=" + SaveStore.MemoryOnly);
|
||||
|
||||
// 캡처용 진행(메모리 세이브만): 재화 · 장비 · 보물 · 상자 · 순찰
|
||||
d.gold = 124500;
|
||||
d.gem = 1280;
|
||||
var id = db.Economy.StartHeroes.Length > 1 ? db.Economy.StartHeroes[1] : db.Economy.StartHeroes[0];
|
||||
var h = s.Def(id);
|
||||
var hs = s.Save.Hero(id);
|
||||
for (int i = 0; i < 4; i++) d.inv.AddGear(HeroRules.RequiredGear(db, h, hs, i), 1);
|
||||
for (int i = 0; i < 3; i++) s.Equip(id, i);
|
||||
HeroRules.GrantExp(hs, db.Levels.Get(1).expToNext + 5);
|
||||
var rng = new System.Random(1100);
|
||||
Counts.Set(d.inv.chests, "gold", 6);
|
||||
for (int i = 0; i < 6; i++) TreasureRules.Open(db, d, "gold", rng);
|
||||
Counts.Set(d.inv.chests, "bronze", 4);
|
||||
Counts.Set(d.inv.chests, "silver", 18);
|
||||
Counts.Set(d.inv.chests, "general", 1);
|
||||
d.inv.chestPoints = 35;
|
||||
d.patrol.startAt = SaveStore.Iso(s.Now.AddHours(-7));
|
||||
s.Commit();
|
||||
|
||||
root.ShowLobby();
|
||||
yield return Shot(cam, "lobby", W, H);
|
||||
root.Show(root.HeroList);
|
||||
yield return Shot(cam, "hero_list", W, H);
|
||||
root.ShowHero(id);
|
||||
yield return Shot(cam, "hero_detail", W, H);
|
||||
root.Show(root.Formation);
|
||||
yield return Shot(cam, "formation", W, H);
|
||||
root.Show(root.Trade);
|
||||
root.Trade.SetPage(0);
|
||||
yield return Shot(cam, "trade_gacha", W, H);
|
||||
root.Show(root.Treasures);
|
||||
root.Treasures.SetPage(2);
|
||||
root.Treasures.SelectChest("gold");
|
||||
yield return Shot(cam, "treasure_chests", W, H);
|
||||
root.Treasures.SetPage(0);
|
||||
yield return Shot(cam, "treasure_owned", W, H);
|
||||
root.Show(root.Domestic);
|
||||
root.Domestic.SetTrainType(UnitType.Infantry);
|
||||
root.Domestic.SetPage(1);
|
||||
yield return Shot(cam, "domestic_patrol", W, H);
|
||||
root.Arena.SetPage(0);
|
||||
root.Show(root.Arena);
|
||||
yield return Shot(cam, "arena", W, H);
|
||||
root.StaminaModal();
|
||||
yield return Shot(cam, "popup_stamina", W, H);
|
||||
root.CloseModal();
|
||||
|
||||
root.ShowLobby();
|
||||
root.ShowHero(id);
|
||||
yield return Shot(cam, "hero_detail_1536x2048", W2, H2);
|
||||
root.ShowLobby();
|
||||
yield return Shot(cam, "lobby_1536x2048", W2, H2);
|
||||
|
||||
root.OpenWorldMap();
|
||||
yield return Wait();
|
||||
var wm = root.Map;
|
||||
wm.OpenPopup(0);
|
||||
yield return Shot(cam, "worldmap_popup", W, H);
|
||||
wm.ConfirmPopup();
|
||||
var bm = root.Battle;
|
||||
float t0 = Time.realtimeSinceStartup;
|
||||
while (bm.Phase != BattlePhase.PlayerTurn && Time.realtimeSinceStartup - t0 < 10f) yield return null;
|
||||
yield return new WaitForSecondsRealtime(0.6f);
|
||||
Unit pick = null;
|
||||
foreach (var u in bm.AliveUnits(Faction.Player))
|
||||
if (bm.Skills != null && bm.Skills.Of(u) != null && bm.Skills.Of(u).Active != null)
|
||||
{
|
||||
pick = u;
|
||||
break;
|
||||
}
|
||||
if (pick != null) bm.Sling.Select(pick);
|
||||
Log("hud select=" + (pick != null ? pick.DisplayName : "-") + " skill=" + bm.Hud.SkillButtonText);
|
||||
yield return Shot(cam, "battle_hud", W, H);
|
||||
foreach (var e in bm.AliveUnits(Faction.Enemy)) e.TakeDamage(e.Hp);
|
||||
bm.CheckBattleEnd();
|
||||
yield return new WaitForSecondsRealtime(0.6f);
|
||||
yield return Shot(cam, "battle_result", W, H);
|
||||
Finish(0);
|
||||
}
|
||||
|
||||
static IEnumerator Wait()
|
||||
{
|
||||
yield return null;
|
||||
yield return new WaitForSecondsRealtime(0.3f);
|
||||
}
|
||||
|
||||
IEnumerator Shot(Camera cam, string name, int w, int h)
|
||||
{
|
||||
yield return Wait();
|
||||
string file = Path.Combine(OutputDir, shot.ToString("00") + "_" + name + ".png");
|
||||
shot++;
|
||||
yield return CaptureUtil.Capture(cam, w, h, file);
|
||||
Log("shot " + file);
|
||||
}
|
||||
|
||||
void Log(string s)
|
||||
{
|
||||
log.Add(s);
|
||||
Debug.Log("[UICapture] " + s);
|
||||
try
|
||||
{
|
||||
File.WriteAllLines(Path.Combine(OutputDir, "capture_log.txt"), log.ToArray());
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void Finish(int code)
|
||||
{
|
||||
Log("finish code=" + code);
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.Exit(code);
|
||||
#else
|
||||
Application.Quit(code);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b6ebc17a46c965c4790f198d64167444
|
||||
|
|
@ -8,10 +8,11 @@ namespace TKS
|
|||
/// <summary>화면 HUD(uGUI · 코드 생성): 스테이지·턴·유닛 수·안내·선택 유닛 정보·미니맵·스킬 버튼(PD #1093 B)·스킬 발동 한 줄·결과 오버레이.</summary>
|
||||
public class BattleHUD : MonoBehaviour
|
||||
{
|
||||
static readonly Color SkillReadyColor = new Color(0.72f, 0.2f, 0.14f, 0.94f);
|
||||
static readonly Color SkillReservedColor = new Color(0.96f, 0.76f, 0.22f, 0.97f);
|
||||
static readonly Color SkillOffColor = new Color(0.3f, 0.3f, 0.33f, 0.88f);
|
||||
static readonly Color SkillPassiveOnlyColor = new Color(0.18f, 0.2f, 0.26f, 0.85f);
|
||||
// 색 = UI 테마(PD #1100 · ui_theme.csv skill_*) · 괄호 값 = 테마 없을 때
|
||||
static Color SkillReadyColor { get { return UISkin.Col("skill_ready", new Color(0.72f, 0.2f, 0.14f, 0.94f)); } }
|
||||
static Color SkillReservedColor { get { return UISkin.Col("skill_reserved", new Color(0.96f, 0.76f, 0.22f, 0.97f)); } }
|
||||
static Color SkillOffColor { get { return UISkin.Col("skill_off", new Color(0.3f, 0.3f, 0.33f, 0.88f)); } }
|
||||
static Color SkillPassiveOnlyColor { get { return UISkin.Col("skill_passive", new Color(0.18f, 0.2f, 0.26f, 0.85f)); } }
|
||||
static readonly Color SkillLogColor = new Color(0.6f, 1f, 0.85f);
|
||||
const float SkillLogSeconds = 3f;
|
||||
|
||||
|
|
@ -30,6 +31,8 @@ namespace TKS
|
|||
Unit selected;
|
||||
|
||||
Image skillPanel;
|
||||
Image skillCool;
|
||||
Image turnBadge;
|
||||
Text skillName;
|
||||
Text skillState;
|
||||
Text skillPassive;
|
||||
|
|
@ -62,6 +65,15 @@ namespace TKS
|
|||
es.AddComponent<StandaloneInputModule>();
|
||||
}
|
||||
|
||||
if (UISkin.On)
|
||||
{
|
||||
// 팩 칩(PD #1100): 스테이지 · 유닛 수 · 턴 띠 · 선택 유닛 정보 판 — 글자 뒤(먼저 만든다) · 반투명 진남
|
||||
Color panelCol = UISkin.Col("hud_panel", new Color(0.12f, 0.15f, 0.21f, 0.85f));
|
||||
Chip("StageChip", new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(14f, -14f), new Vector2(730f, 86f), panelCol);
|
||||
Chip("CountChip", new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-14f, -14f), new Vector2(330f, 86f), panelCol);
|
||||
turnBadge = Chip("TurnBadge", new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -106f), new Vector2(440f, 84f), UISkin.Col("hud_turn_player", Color.blue));
|
||||
Chip("UnitPanel", new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(14f, 96f), new Vector2(790f, 196f), panelCol);
|
||||
}
|
||||
stageText = MakeText("Stage", new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(30f, -28f), new Vector2(700f, 70f), 40, TextAnchor.UpperLeft);
|
||||
// 스테이지 표 제목(최대 ~20자)이 오른쪽 위 적 수와 겹치지 않게 칸 안에서 글자 크기를 줄인다
|
||||
stageText.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
|
|
@ -72,8 +84,15 @@ namespace TKS
|
|||
countText = MakeText("Count", new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-30f, -28f), new Vector2(520f, 70f), 36, TextAnchor.UpperRight);
|
||||
turnText = MakeText("Turn", new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -92f), new Vector2(700f, 70f), 46, TextAnchor.UpperCenter);
|
||||
turnText.color = new Color(1f, 0.95f, 0.6f);
|
||||
if (UISkin.On)
|
||||
{
|
||||
turnText.color = Color.white;
|
||||
turnText.font = UISkin.TitleFont;
|
||||
turnText.rectTransform.anchoredPosition = new Vector2(0f, -114f);
|
||||
}
|
||||
messageText = MakeText("Message", new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -160f), new Vector2(1040f, 60f), 30, TextAnchor.UpperCenter);
|
||||
messageText.color = new Color(0.9f, 0.95f, 1f);
|
||||
if (UISkin.On) messageText.rectTransform.anchoredPosition = new Vector2(0f, -206f); // 턴 띠 아래
|
||||
|
||||
hintText = MakeText("Hint", new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 36f), new Vector2(1040f, 60f), 28, TextAnchor.LowerCenter);
|
||||
hintText.color = new Color(0.85f, 0.85f, 0.85f);
|
||||
|
|
@ -94,6 +113,37 @@ namespace TKS
|
|||
skillPassive.transform.SetParent(skillPanel.transform, false);
|
||||
skillPassive.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
skillPassive.color = new Color(0.8f, 0.9f, 1f);
|
||||
if (UISkin.Apply(skillPanel, "skill_btn"))
|
||||
{
|
||||
// 원형 스킬 버튼(팩 Button_Circle · PD #1100) + 쿨 라디얼 · 이름·상태 = 원 안 · 패시브 한 줄 = 원 위
|
||||
var rt = skillPanel.rectTransform;
|
||||
rt.sizeDelta = new Vector2(250f, 250f);
|
||||
rt.anchoredPosition = new Vector2(-24f, 100f);
|
||||
skillPanel.preserveAspect = true;
|
||||
skillCool = MakeImage("Cool", skillPanel.transform, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(-26f, -26f), UISkin.Col("skill_cool", new Color(0f, 0f, 0f, 0.6f)));
|
||||
if (UISkin.Apply(skillCool, "skill_cool"))
|
||||
{
|
||||
skillCool.type = Image.Type.Filled;
|
||||
skillCool.fillMethod = Image.FillMethod.Radial360;
|
||||
skillCool.fillOrigin = (int)Image.Origin360.Top;
|
||||
skillCool.fillClockwise = false;
|
||||
skillCool.fillAmount = 0f;
|
||||
}
|
||||
skillCool.transform.SetAsFirstSibling();
|
||||
Place(skillName, new Vector2(0f, -54f), new Vector2(196f, 56f));
|
||||
skillName.font = UISkin.TitleFont;
|
||||
Place(skillState, new Vector2(0f, -10f), new Vector2(200f, 80f));
|
||||
skillState.resizeTextForBestFit = true;
|
||||
skillState.verticalOverflow = VerticalWrapMode.Truncate;
|
||||
skillState.resizeTextMinSize = 18;
|
||||
skillState.resizeTextMaxSize = 26;
|
||||
var pr = skillPassive.rectTransform;
|
||||
pr.anchorMin = pr.anchorMax = new Vector2(0.5f, 1f);
|
||||
pr.pivot = new Vector2(0.5f, 0f);
|
||||
pr.anchoredPosition = new Vector2(-20f, 6f);
|
||||
pr.sizeDelta = new Vector2(320f, 40f);
|
||||
skillPassive.alignment = TextAnchor.LowerCenter;
|
||||
}
|
||||
skillPanel.gameObject.SetActive(false);
|
||||
|
||||
// 스킬 발동 한 줄(액티브·패시브 · 최근 몇 초)
|
||||
|
|
@ -113,6 +163,7 @@ namespace TKS
|
|||
resultOverlay = MakeImage("ResultOverlay", transform, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), Vector2.zero, Vector2.zero, new Color(0f, 0f, 0f, 0.65f)).gameObject;
|
||||
resultTitle = MakeText("Title", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 60f), new Vector2(1000f, 160f), 110, TextAnchor.MiddleCenter);
|
||||
resultTitle.transform.SetParent(resultOverlay.transform, false);
|
||||
if (UISkin.On) resultTitle.font = UISkin.TitleFont;
|
||||
resultSub = MakeText("Sub", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -80f), new Vector2(1000f, 120f), 40, TextAnchor.MiddleCenter);
|
||||
resultSub.transform.SetParent(resultOverlay.transform, false);
|
||||
resultOverlay.SetActive(false);
|
||||
|
|
@ -158,6 +209,20 @@ namespace TKS
|
|||
return img;
|
||||
}
|
||||
|
||||
/// <summary>테마 칩(팩 카드 틀 · 색 틴트) — 글자보다 먼저 만들어 뒤에 깔린다.</summary>
|
||||
Image Chip(string name, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size, Color color)
|
||||
{
|
||||
var img = MakeImage(name, transform, anchor, anchor, pivot, pos, size, color);
|
||||
UISkin.Apply(img, "card");
|
||||
return img;
|
||||
}
|
||||
|
||||
static void Place(Text t, Vector2 pos, Vector2 size)
|
||||
{
|
||||
t.rectTransform.anchoredPosition = pos;
|
||||
t.rectTransform.sizeDelta = size;
|
||||
}
|
||||
|
||||
public void SetSelected(Unit u)
|
||||
{
|
||||
selected = u;
|
||||
|
|
@ -207,6 +272,12 @@ namespace TKS
|
|||
bool show = s != null && (s.Active != null || s.Passive != null);
|
||||
if (skillPanel.gameObject.activeSelf != show) skillPanel.gameObject.SetActive(show);
|
||||
if (!show) return;
|
||||
if (skillCool != null)
|
||||
{
|
||||
// 쿨 라디얼 = 남은 턴 / 쿨(쿨 중일 때만)
|
||||
bool cooling = s.Active != null && selected.Faction == Faction.Player && sys.StateOf(selected) == SkillSystem.ActiveState.Cooldown && s.Active.Cooldown > 0;
|
||||
skillCool.fillAmount = cooling ? Mathf.Clamp01(s.CooldownLeft(battle.TurnNumber) / (float)s.Active.Cooldown) : 0f;
|
||||
}
|
||||
|
||||
skillPassive.text = s.Passive != null ? "패 · " + s.Passive.NameKo + (s.PassiveMult > 1f ? " ★" : "") : "";
|
||||
if (s.Active == null || selected.Faction != Faction.Player)
|
||||
|
|
@ -296,6 +367,14 @@ namespace TKS
|
|||
default: turnText.text = ""; break;
|
||||
}
|
||||
messageText.text = battle.LastMessage;
|
||||
if (turnBadge != null)
|
||||
{
|
||||
bool on = turnText.text.Length > 0;
|
||||
if (turnBadge.gameObject.activeSelf != on) turnBadge.gameObject.SetActive(on);
|
||||
turnBadge.color = battle.Phase == BattlePhase.EnemyTurn || battle.Phase == BattlePhase.Defeat
|
||||
? UISkin.Col("hud_turn_enemy", Color.red)
|
||||
: UISkin.Col("hud_turn_player", Color.blue);
|
||||
}
|
||||
|
||||
if (battle.Skills != null && battle.Skills.PendingTeleport != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -127,6 +127,14 @@ namespace TKS
|
|||
var p = ProceduralSprites.NewSprite(body, "Pip", ProceduralSprites.Square, Color.white, 1f, LabelOrder);
|
||||
p.transform.localPosition = new Vector3(-total * 0.5f + w * 0.5f + i * (w + gap), top, 0f);
|
||||
p.transform.localScale = new Vector3(w, 0.1f, 1f);
|
||||
var ps = UISkin.WorldSprite("pip", 460f); // 팩 둥근 칸 핍(PD #1100 · 외곽선)
|
||||
if (ps != null)
|
||||
{
|
||||
p.sprite = ps;
|
||||
p.drawMode = SpriteDrawMode.Sliced;
|
||||
p.transform.localScale = Vector3.one;
|
||||
p.size = new Vector2(w, 0.12f);
|
||||
}
|
||||
pips.Add(p);
|
||||
}
|
||||
}
|
||||
|
|
@ -236,7 +244,7 @@ namespace TKS
|
|||
if (label != null) label.text = text;
|
||||
for (int i = 0; i < pips.Count; i++)
|
||||
{
|
||||
pips[i].color = i < g.Hp ? new Color(1f, 0.85f, 0.3f) : new Color(0.15f, 0.15f, 0.15f, 0.8f);
|
||||
pips[i].color = i < g.Hp ? UISkin.Col("pip_on", new Color(1f, 0.85f, 0.3f)) : UISkin.Col("pip_off", new Color(0.15f, 0.15f, 0.15f, 0.8f));
|
||||
pips[i].gameObject.SetActive(!g.Broken);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8d3e18def507e7d43a5def42775218f9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace TKS
|
||||
{
|
||||
/// <summary>
|
||||
/// UI 테마 적용 도우미(PD #1100) — 아웃게임 UiKit · 전투 HUD · 월드맵 팝업이 같이 쓴다.
|
||||
/// 테마가 없으면 모든 함수가 false/null 을 돌려주고 호출부는 기존 도형으로 그린다.
|
||||
/// </summary>
|
||||
public static class UISkin
|
||||
{
|
||||
public const string OverlayName = "Gloss";
|
||||
|
||||
public static UITheme Theme
|
||||
{
|
||||
get { return UITheme.Current; }
|
||||
}
|
||||
|
||||
public static bool On
|
||||
{
|
||||
get { return Theme != null; }
|
||||
}
|
||||
|
||||
public static Color Col(string id, Color fallback)
|
||||
{
|
||||
Color c;
|
||||
return Theme != null && Theme.TryColor(id, out c) ? c : fallback;
|
||||
}
|
||||
|
||||
public static Font TitleFont
|
||||
{
|
||||
get { return Theme != null && Theme.titleFont != null ? Theme.titleFont : TextUtil.Font; }
|
||||
}
|
||||
|
||||
public static bool Has(string skinId)
|
||||
{
|
||||
return Theme != null && Theme.Skin(skinId) != null;
|
||||
}
|
||||
|
||||
/// <summary>이미지에 스킨(9-slice 바탕 + 덮개) 적용 · 색은 호출부(img.color)가 정한다.</summary>
|
||||
public static bool Apply(Image img, string skinId)
|
||||
{
|
||||
var s = Theme != null ? Theme.Skin(skinId) : null;
|
||||
if (s == null || img == null) return false;
|
||||
var sp = s.Sprite;
|
||||
img.sprite = sp;
|
||||
img.type = sp.border != Vector4.zero ? Image.Type.Sliced : Image.Type.Simple;
|
||||
img.pixelsPerUnitMultiplier = s.ppu > 0f ? s.ppu : 1f;
|
||||
img.fillCenter = true;
|
||||
var old = img.transform.Find(OverlayName);
|
||||
if (old != null) Object.Destroy(old.gameObject);
|
||||
if (s.overlay != null) Overlay(img.transform, s.overlay, s.inset, s.ppu).color = new Color(1f, 1f, 1f, s.overlayAlpha);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>부모를 꽉 채우는 덮개(광택 등 · 첫 자식 = 내용 아래) · inset = 왼 · 위 · 오 · 아래.</summary>
|
||||
public static Image Overlay(Transform parent, Sprite sp, Vector4 inset, float ppu = 1f)
|
||||
{
|
||||
var go = new GameObject(OverlayName, typeof(RectTransform));
|
||||
go.transform.SetParent(parent, false);
|
||||
go.transform.SetAsFirstSibling();
|
||||
var rt = (RectTransform)go.transform;
|
||||
rt.anchorMin = Vector2.zero;
|
||||
rt.anchorMax = Vector2.one;
|
||||
rt.offsetMin = new Vector2(inset.x, inset.w);
|
||||
rt.offsetMax = new Vector2(-inset.z, -inset.y);
|
||||
var img = go.AddComponent<Image>();
|
||||
img.sprite = sp;
|
||||
img.type = sp.border != Vector4.zero ? Image.Type.Sliced : Image.Type.Simple;
|
||||
img.pixelsPerUnitMultiplier = ppu > 0f ? ppu : 1f;
|
||||
img.preserveAspect = sp.border == Vector4.zero;
|
||||
img.raycastTarget = false;
|
||||
return img;
|
||||
}
|
||||
|
||||
public static Sprite Icon(string id)
|
||||
{
|
||||
return Theme != null ? Theme.Icon(id) : null;
|
||||
}
|
||||
|
||||
/// <summary>아이콘 이미지(테마에 id 가 없으면 null) · 비율 유지 · 표 tint 적용.</summary>
|
||||
public static Image IconImage(Transform parent, string id, Vector2 anchor, Vector2 pivot, Vector2 pos, Vector2 size)
|
||||
{
|
||||
var e = Theme != null ? Theme.IconEntryOf(id) : null;
|
||||
if (e == null) return null;
|
||||
var go = new GameObject("Icon_" + id, typeof(RectTransform));
|
||||
go.transform.SetParent(parent, false);
|
||||
var rt = (RectTransform)go.transform;
|
||||
rt.anchorMin = rt.anchorMax = anchor;
|
||||
rt.pivot = pivot;
|
||||
rt.anchoredPosition = pos;
|
||||
rt.sizeDelta = size;
|
||||
var img = go.AddComponent<Image>();
|
||||
img.sprite = e.Sprite;
|
||||
img.color = e.samguk != null ? Color.white : e.tint;
|
||||
img.preserveAspect = true;
|
||||
img.raycastTarget = false;
|
||||
return img;
|
||||
}
|
||||
|
||||
/// <summary>글자 외곽선(팩 버튼 글자처럼 굵은 어두운 선).</summary>
|
||||
public static void Stroke(Graphic g, Color c, float d = 2.5f)
|
||||
{
|
||||
if (g == null || g.GetComponent<Outline>() != null) return;
|
||||
var t = g as Text;
|
||||
if (t != null && t.fontSize < 40) d = Mathf.Min(d, t.fontSize < 30 ? 1.5f : 2f); // 작은 글자는 얇게(굵으면 한글이 뭉개짐)
|
||||
var o = g.gameObject.AddComponent<Outline>();
|
||||
o.effectColor = c;
|
||||
o.effectDistance = new Vector2(d, -d);
|
||||
}
|
||||
|
||||
static readonly Dictionary<string, Sprite> worldCache = new Dictionary<string, Sprite>();
|
||||
|
||||
/// <summary>
|
||||
/// 월드 공간(SpriteRenderer · 9-slice)용 스킨 사본 — 같은 텍스처를 ppu 만 바꿔 다시 만든다(체력 바처럼 월드 크기가 작은 막대가 테두리보다 작아 깨지지 않게).
|
||||
/// </summary>
|
||||
public static Sprite WorldSprite(string skinId, float ppu)
|
||||
{
|
||||
var s = Theme != null ? Theme.Skin(skinId) : null;
|
||||
if (s == null) return null;
|
||||
string key = skinId + "@" + ppu;
|
||||
Sprite sp;
|
||||
if (worldCache.TryGetValue(key, out sp) && sp != null) return sp;
|
||||
var src = s.Sprite;
|
||||
// SpriteRenderer 9-slice 는 가운데 칸이 0 px 이면 가운데를 그리지 않는다(팩 슬라이더 = 테두리가 전부) → 가운데 2 px 를 남긴다
|
||||
var b = src.border;
|
||||
float w = src.rect.width, h = src.rect.height;
|
||||
if (b.x + b.z > w - 2f)
|
||||
{
|
||||
float k = Mathf.Max(0f, w - 2f) / Mathf.Max(1f, b.x + b.z);
|
||||
b.x = Mathf.Floor(b.x * k);
|
||||
b.z = Mathf.Floor(b.z * k);
|
||||
}
|
||||
if (b.y + b.w > h - 2f)
|
||||
{
|
||||
float k = Mathf.Max(0f, h - 2f) / Mathf.Max(1f, b.y + b.w);
|
||||
b.y = Mathf.Floor(b.y * k);
|
||||
b.w = Mathf.Floor(b.w * k);
|
||||
}
|
||||
sp = Sprite.Create(src.texture, src.rect, new Vector2(0.5f, 0.5f), ppu, 0, SpriteMeshType.FullRect, b);
|
||||
sp.name = key;
|
||||
sp.hideFlags = HideFlags.DontSave;
|
||||
worldCache[key] = sp;
|
||||
return sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8c3088b2ae40c174280af74a99269105
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TKS
|
||||
{
|
||||
/// <summary>
|
||||
/// UI 테마(PD #1100 UI 리뉴얼 · 2026-11-06) — 색 팔레트 · 9-slice 부품(스킨) · 아이콘 id → 스프라이트 치환 테이블 · 제목 폰트.
|
||||
/// SOT = Assets/Data/UI/ui_theme.csv → 메뉴 TKS/Import UI Theme → Resources/UI/UITheme.asset(에디터 UIThemeImporter).
|
||||
/// 스킨·아이콘은 팩(Layer Lab GUI Pro-SuperCasual · Assets/UI/GUIPro) 기본 + 신규 제작 납품(Assets/UI/Samguk/**/<id>.png)이 있으면 그것으로 치환.
|
||||
/// 화면 코드는 id 로만 묻는다(스프라이트 경로를 코드에 쓰지 않는다 · C45).
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "TKS/UI Theme")]
|
||||
public class UITheme : ScriptableObject
|
||||
{
|
||||
public const string ResourcePath = "UI/UITheme";
|
||||
|
||||
[Serializable]
|
||||
public class ColorEntry
|
||||
{
|
||||
public string id;
|
||||
public Color color = Color.white;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class SkinEntry
|
||||
{
|
||||
public string id;
|
||||
/// <summary>팩 바탕(흰 계열 = 호출 색으로 틴트).</summary>
|
||||
public Sprite pack;
|
||||
/// <summary>신규 제작 치환(있으면 pack 대신).</summary>
|
||||
public Sprite samguk;
|
||||
/// <summary>위 덮개(광택·글리프 · 틴트 안 함).</summary>
|
||||
public Sprite overlay;
|
||||
/// <summary>9-slice 배율(Image.pixelsPerUnitMultiplier · 클수록 테두리가 얇다).</summary>
|
||||
public float ppu = 1f;
|
||||
/// <summary>덮개 안쪽 여백(px · 왼 · 위 · 오 · 아래).</summary>
|
||||
public Vector4 inset;
|
||||
/// <summary>덮개 불투명도.</summary>
|
||||
public float overlayAlpha = 1f;
|
||||
|
||||
public Sprite Sprite
|
||||
{
|
||||
get { return samguk != null ? samguk : pack; }
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class IconEntry
|
||||
{
|
||||
public string id;
|
||||
public Sprite pack;
|
||||
public Sprite samguk;
|
||||
/// <summary>표시 색(흰 실루엣 아이콘용 · 기본 흰색 = 원색 그대로).</summary>
|
||||
public Color tint = Color.white;
|
||||
|
||||
public Sprite Sprite
|
||||
{
|
||||
get { return samguk != null ? samguk : pack; }
|
||||
}
|
||||
}
|
||||
|
||||
public List<ColorEntry> colors = new List<ColorEntry>();
|
||||
public List<SkinEntry> skins = new List<SkinEntry>();
|
||||
public List<IconEntry> icons = new List<IconEntry>();
|
||||
/// <summary>제목·숫자 강조(Sen-ExtraBold · 한글 = 임포터 폴백 Malgun Gothic · PD 결정 전).</summary>
|
||||
public Font titleFont;
|
||||
|
||||
Dictionary<string, ColorEntry> colorMap;
|
||||
Dictionary<string, SkinEntry> skinMap;
|
||||
Dictionary<string, IconEntry> iconMap;
|
||||
|
||||
static UITheme current;
|
||||
static bool tried;
|
||||
|
||||
/// <summary>Resources/UI/UITheme(없으면 null = 기존 도형 UI 로 동작).</summary>
|
||||
public static UITheme Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (current == null && !tried)
|
||||
{
|
||||
tried = true;
|
||||
current = Resources.Load<UITheme>(ResourcePath);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>테마 교체(임포트 뒤 · 테스트) — null = 다시 Resources 에서 읽음.</summary>
|
||||
public static void Use(UITheme t)
|
||||
{
|
||||
current = t;
|
||||
tried = t != null;
|
||||
if (t != null) t.Rebuild();
|
||||
}
|
||||
|
||||
public void Rebuild()
|
||||
{
|
||||
colorMap = new Dictionary<string, ColorEntry>();
|
||||
foreach (var c in colors)
|
||||
if (c != null && !string.IsNullOrEmpty(c.id)) colorMap[c.id] = c;
|
||||
skinMap = new Dictionary<string, SkinEntry>();
|
||||
foreach (var s in skins)
|
||||
if (s != null && !string.IsNullOrEmpty(s.id)) skinMap[s.id] = s;
|
||||
iconMap = new Dictionary<string, IconEntry>();
|
||||
foreach (var i in icons)
|
||||
if (i != null && !string.IsNullOrEmpty(i.id)) iconMap[i.id] = i;
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
colorMap = null;
|
||||
}
|
||||
|
||||
void Ensure()
|
||||
{
|
||||
if (colorMap == null || skinMap == null || iconMap == null) Rebuild();
|
||||
}
|
||||
|
||||
public bool TryColor(string id, out Color c)
|
||||
{
|
||||
Ensure();
|
||||
ColorEntry e;
|
||||
if (id != null && colorMap.TryGetValue(id, out e))
|
||||
{
|
||||
c = e.color;
|
||||
return true;
|
||||
}
|
||||
c = Color.white;
|
||||
return false;
|
||||
}
|
||||
|
||||
public SkinEntry Skin(string id)
|
||||
{
|
||||
Ensure();
|
||||
SkinEntry e;
|
||||
return id != null && skinMap.TryGetValue(id, out e) && e.Sprite != null ? e : null;
|
||||
}
|
||||
|
||||
public IconEntry IconEntryOf(string id)
|
||||
{
|
||||
Ensure();
|
||||
IconEntry e;
|
||||
return id != null && iconMap.TryGetValue(id, out e) && e.Sprite != null ? e : null;
|
||||
}
|
||||
|
||||
public Sprite Icon(string id)
|
||||
{
|
||||
var e = IconEntryOf(id);
|
||||
return e != null ? e.Sprite : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 63b0a8e358e193740883a84a0bfe1325
|
||||
|
|
@ -29,6 +29,10 @@ namespace TKS
|
|||
SpriteRenderer overwatchArea;
|
||||
SpriteRenderer hpBg;
|
||||
SpriteRenderer hpFill;
|
||||
bool packHp;
|
||||
// 체력 바 9-slice 월드 배율(테두리 px → 월드 = px / ppu · 바 높이 0.22 / 0.13 안에 테두리가 들어가게)
|
||||
const float HpBgPpu = 240f;
|
||||
const float HpFillPpu = 420f;
|
||||
TextMesh mark;
|
||||
TextMesh nameLabel;
|
||||
TextMesh badge;
|
||||
|
|
@ -154,6 +158,22 @@ namespace TKS
|
|||
hpFill = ProceduralSprites.NewSprite(transform, "HpFill", ProceduralSprites.Square, new Color(0.35f, 0.9f, 0.35f), 1f, 3);
|
||||
hpFill.transform.localPosition = hpBg.transform.localPosition;
|
||||
hpFill.transform.localScale = new Vector3(HpBarWidth, 0.12f, 1f);
|
||||
// 팩 슬라이더 체력 바(PD #1100 · 테마 hp_bg·hp_fill · 9-slice 월드 사본) — 테마가 없으면 위 도형 그대로
|
||||
var bgSp = UISkin.WorldSprite("hp_bg", HpBgPpu);
|
||||
var fillSp = UISkin.WorldSprite("hp_fill", HpFillPpu);
|
||||
if (bgSp != null && fillSp != null)
|
||||
{
|
||||
packHp = true;
|
||||
hpBg.sprite = bgSp;
|
||||
hpBg.drawMode = SpriteDrawMode.Sliced;
|
||||
hpBg.transform.localScale = Vector3.one;
|
||||
hpBg.size = new Vector2(HpBarWidth + 0.1f, 0.22f);
|
||||
hpBg.color = UISkin.Col("hp_bg", Color.white);
|
||||
hpFill.sprite = fillSp;
|
||||
hpFill.drawMode = SpriteDrawMode.Sliced;
|
||||
hpFill.transform.localScale = Vector3.one;
|
||||
hpFill.size = new Vector2(HpBarWidth, 0.13f);
|
||||
}
|
||||
|
||||
mark = TextUtil.CreateWorldText(transform, UnitTypeInfo.Mark(u.Type), u.Radius * 1.1f, Color.white, 4);
|
||||
if (anim != null) mark.gameObject.SetActive(false); // 아트가 있으면 병종은 이름 옆에
|
||||
|
|
@ -190,9 +210,20 @@ namespace TKS
|
|||
if (Sim.Active) return; // 가상 실행(적 AI 예측) = 표시 그대로
|
||||
if (unit == null || hpFill == null) return;
|
||||
float ratio = unit.MaxHp > 0 ? Mathf.Clamp01((float)unit.Hp / unit.MaxHp) : 0f;
|
||||
hpFill.transform.localScale = new Vector3(HpBarWidth * ratio, 0.12f, 1f);
|
||||
hpFill.transform.localPosition = new Vector3(-HpBarWidth * 0.5f + HpBarWidth * ratio * 0.5f, hpBg.transform.localPosition.y, 0f);
|
||||
hpFill.color = ratio > 0.5f ? new Color(0.35f, 0.9f, 0.35f) : (ratio > 0.25f ? new Color(0.95f, 0.8f, 0.2f) : new Color(0.95f, 0.3f, 0.2f));
|
||||
if (packHp)
|
||||
{
|
||||
float w = HpBarWidth * ratio;
|
||||
hpFill.enabled = w > 0.045f;
|
||||
hpFill.size = new Vector2(Mathf.Max(0.045f, w), 0.13f);
|
||||
hpFill.transform.localPosition = new Vector3(-HpBarWidth * 0.5f + w * 0.5f, hpBg.transform.localPosition.y + 0.015f, 0f);
|
||||
hpFill.color = ratio > 0.5f ? UISkin.Col("hp_hi", Color.green) : ratio > 0.25f ? UISkin.Col("hp_mid", Color.yellow) : UISkin.Col("hp_low", Color.red);
|
||||
}
|
||||
else
|
||||
{
|
||||
hpFill.transform.localScale = new Vector3(HpBarWidth * ratio, 0.12f, 1f);
|
||||
hpFill.transform.localPosition = new Vector3(-HpBarWidth * 0.5f + HpBarWidth * ratio * 0.5f, hpBg.transform.localPosition.y, 0f);
|
||||
hpFill.color = ratio > 0.5f ? new Color(0.35f, 0.9f, 0.35f) : (ratio > 0.25f ? new Color(0.95f, 0.8f, 0.2f) : new Color(0.95f, 0.3f, 0.2f));
|
||||
}
|
||||
|
||||
bool dim = unit.Faction == Faction.Player && unit.ActedThisTurn;
|
||||
if (flash == null)
|
||||
|
|
|
|||
|
|
@ -735,20 +735,39 @@ namespace TKS
|
|||
var panel = Img("Panel", popup.transform, Sprite("plate"), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 40f), new Vector2(900f, 1080f));
|
||||
panel.type = Image.Type.Sliced;
|
||||
panel.raycastTarget = true;
|
||||
var head = Img("Head", panel.transform, Sprite("banner"), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), new Vector2(760f, 112f));
|
||||
head.type = Image.Type.Sliced;
|
||||
var bk = data.Kit("banner");
|
||||
popupTitle = Label(head.transform, "", 34, Paper, new Vector2(0.5f, 1f - (bk != null ? bk.numberCenter[1] : 0.4f)));
|
||||
// 스테이지 팝업만 팩 Popup(PD #1100 · 거점 kit 유지) · 테마가 없으면 kit plate·banner
|
||||
bool pack = UISkin.Apply(panel, "popup");
|
||||
if (pack)
|
||||
{
|
||||
panel.color = UISkin.Col("paper", Color.white);
|
||||
var band = Img("Head", panel.transform, null, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -6f), new Vector2(-14f, 150f));
|
||||
UISkin.Apply(band, "popup_head");
|
||||
band.color = UISkin.Col("header", Ink);
|
||||
popupTitle = Label(band.transform, "", 38, Color.white, new Vector2(0.5f, 0.5f));
|
||||
popupTitle.font = UISkin.TitleFont;
|
||||
popupTitle.GetComponent<Outline>().effectColor = UISkin.Col("stroke", Ink);
|
||||
var x = Img("Close", panel.transform, null, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(-58f, -60f), new Vector2(86f, 88f));
|
||||
UISkin.Apply(x, "close");
|
||||
x.raycastTarget = true;
|
||||
x.gameObject.AddComponent<Button>().onClick.AddListener(ClosePopup);
|
||||
}
|
||||
else
|
||||
{
|
||||
var head = Img("Head", panel.transform, Sprite("banner"), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), new Vector2(760f, 112f));
|
||||
head.type = Image.Type.Sliced;
|
||||
var bk = data.Kit("banner");
|
||||
popupTitle = Label(head.transform, "", 34, Paper, new Vector2(0.5f, 1f - (bk != null ? bk.numberCenter[1] : 0.4f)));
|
||||
}
|
||||
popupTitle.lineSpacing = 0.9f;
|
||||
popupBody = Label(panel.transform, "", 30, new Color(0.25f, 0.15f, 0.1f), new Vector2(0.5f, 0.56f));
|
||||
popupBody = Label(panel.transform, "", 30, pack ? UISkin.Col("ink", new Color(0.25f, 0.15f, 0.1f)) : new Color(0.25f, 0.15f, 0.1f), new Vector2(0.5f, pack ? 0.545f : 0.56f));
|
||||
popupBody.GetComponent<Outline>().enabled = false;
|
||||
popupBody.rectTransform.sizeDelta = new Vector2(800f, 720f);
|
||||
popupBody.rectTransform.sizeDelta = new Vector2(800f, pack ? 640f : 720f);
|
||||
popupBody.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
popupBody.supportRichText = true;
|
||||
popupGo = WideButton("Go", panel.transform, "출전", new Vector2(-180f, 80f), new Color(0.89f, 0.33f, 0.23f), ConfirmPopup, out popupGoLabel);
|
||||
popupGo = WideButton("Go", panel.transform, "출전", new Vector2(-180f, 80f), UISkin.Col("red", new Color(0.89f, 0.33f, 0.23f)), ConfirmPopup, out popupGoLabel);
|
||||
Text closeLabel;
|
||||
WideButton("Close", panel.transform, "닫기", new Vector2(180f, 80f), new Color(0.6f, 0.55f, 0.5f), ClosePopup, out closeLabel);
|
||||
popupSweep = WideButton("Sweep", panel.transform, "소탕", new Vector2(0f, 200f), new Color(0.35f, 0.5f, 0.35f), OnSweepClicked, out popupSweepLabel);
|
||||
WideButton("Close", panel.transform, "닫기", new Vector2(180f, 80f), UISkin.Col("dark", new Color(0.6f, 0.55f, 0.5f)), ClosePopup, out closeLabel);
|
||||
popupSweep = WideButton("Sweep", panel.transform, "소탕", new Vector2(0f, 200f), UISkin.Col("ok", new Color(0.35f, 0.5f, 0.35f)), OnSweepClicked, out popupSweepLabel);
|
||||
popupSweep.gameObject.SetActive(false);
|
||||
popup.SetActive(false);
|
||||
}
|
||||
|
|
@ -849,11 +868,18 @@ namespace TKS
|
|||
{
|
||||
var img = Img(name, parent, Sprite("plate"), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0.5f), pos, new Vector2(300f, 100f));
|
||||
img.type = Image.Type.Sliced;
|
||||
bool pack = UISkin.Apply(img, "button");
|
||||
if (pack) img.rectTransform.sizeDelta = new Vector2(320f, 112f);
|
||||
img.color = tint;
|
||||
img.raycastTarget = true;
|
||||
var b = img.gameObject.AddComponent<Button>();
|
||||
b.onClick.AddListener(() => onClick());
|
||||
labelText = Label(img.transform, label, 42, Paper, new Vector2(0.5f, 0.55f));
|
||||
labelText = Label(img.transform, label, 42, pack ? Color.white : Paper, new Vector2(0.5f, pack ? 0.6f : 0.55f));
|
||||
if (pack)
|
||||
{
|
||||
labelText.font = UISkin.TitleFont;
|
||||
labelText.GetComponent<Outline>().effectColor = UISkin.Col("stroke", Ink);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace TKS.Tests
|
||||
{
|
||||
/// <summary>UI 테마(PD #1100) — 팩 부품이 실려 있고 신규 제작(B) 스프라이트가 같은 id 를 코드 변경 없이 치환한다.</summary>
|
||||
public class UIThemeTests
|
||||
{
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
UITheme.Use(null); // 다음 테스트는 Resources 테마로
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Theme_PackParts_AndSamgukReplacesById()
|
||||
{
|
||||
var theme = Resources.Load<UITheme>(UITheme.ResourcePath);
|
||||
Assert.IsNotNull(theme, "Resources/UI/UITheme 없음 — 메뉴 TKS/Import UI Theme");
|
||||
foreach (var skin in new[] { "card", "button", "popup", "bar_bg", "bar_fill", "tab_focus", "skill_btn", "hp_bg" })
|
||||
Assert.IsNotNull(theme.Skin(skin), "스킨 " + skin);
|
||||
foreach (var icon in new[] { "cur_gold", "cur_gem", "cur_stamina", "tab_hero", "chest_gold", "gear_sword", "star_on" })
|
||||
Assert.IsNotNull(theme.Icon(icon), "아이콘 " + icon);
|
||||
Assert.IsNotNull(theme.titleFont, "제목 폰트");
|
||||
|
||||
// 신규 제작 납품 = 같은 id 의 samguk 칸 → 아이콘·스킨 모두 그 스프라이트로(팩은 보존)
|
||||
var copy = Object.Instantiate(theme);
|
||||
var tex = new Texture2D(8, 8);
|
||||
var sp = Sprite.Create(tex, new Rect(0, 0, 8, 8), new Vector2(0.5f, 0.5f), 100f);
|
||||
var pack = copy.Icon("cur_gold");
|
||||
copy.IconEntryOf("cur_gold").samguk = sp;
|
||||
copy.Skin("card").samguk = sp;
|
||||
UITheme.Use(copy);
|
||||
Assert.AreSame(sp, UISkin.Icon("cur_gold"), "아이콘 치환");
|
||||
Assert.AreSame(pack, copy.IconEntryOf("cur_gold").pack, "팩 원본 보존");
|
||||
var go = new GameObject("ThemeProbe", typeof(RectTransform));
|
||||
var img = go.AddComponent<Image>();
|
||||
Assert.IsTrue(UISkin.Apply(img, "card"));
|
||||
Assert.AreSame(sp, img.sprite, "스킨 치환");
|
||||
var ic = UISkin.IconImage(go.transform, "cur_gold", Vector2.zero, Vector2.zero, Vector2.zero, Vector2.one * 10f);
|
||||
Assert.AreSame(sp, ic.sprite);
|
||||
Object.DestroyImmediate(go);
|
||||
Object.DestroyImmediate(copy);
|
||||
Object.DestroyImmediate(tex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1641ce4b59f119248ba07d28ec2907bc
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 029e5a94b4c61a549b044c385b6d3623
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
|
|
@ -0,0 +1,168 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 604887b577dfd2e4aacb8cf8509a5878
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 2710779485955313897
|
||||
second: keyart_04_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: keyart_04_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 768
|
||||
height: 1344
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 9e058c4849f9e9520800000000000000
|
||||
internalID: 2710779485955313897
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eefa21a8edc415a44aba5b194c834e98
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# Assets/UI/Samguk — 신규 제작 UI 리소스(PD #1100 B · 세션 tks-ui-art)
|
||||
|
||||
- 파일 이름 = 테마 id (`cur_gold.png` · `tab_hero.png` · `frame_gold.png` · `bg_lobby.png` · `tre_<id>.png` …) · 하위 폴더 = 묶음(group).
|
||||
- 들어오면 임포트 설정(Sprite 2D)과 테마 치환 테이블(`Assets/Resources/UI/UITheme.asset`)이 자동 갱신된다(`Editor/UIThemeImporter` · 수동 = 메뉴 `TKS/Import UI Theme`).
|
||||
- 반영 = `Tools/apply_delivery.py apply --all --kind ui`(납품 인박스 `C:\ArtRnD\samguk_game\deliveries\*_ui_*.json`) · 기믹 `gim_*` 는 `Assets/Resources/Gimmicks/Art/` 로 간다.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 582dcc0b9fc441c4abe1945fea18f576
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -6,7 +6,7 @@ PD 2026-11-05: 「매번 수신하지 않아도, 요청한 작업이 완전히
|
|||
인박스 = C:\\ArtRnD\\samguk_game\\deliveries\\<YYYYMMDD_HHMM>_<batch>.json
|
||||
{
|
||||
"batch": "bg" | "hgj" | "heroes_back" | "dz" | "cc" | "wei" | …,
|
||||
"kind": "bg" | "poses",
|
||||
"kind": "bg" | "poses" | "worldmap" | "ui",
|
||||
"qa": "PASS",
|
||||
"session": "<만든 세션 이름>",
|
||||
# kind == "bg"
|
||||
|
|
@ -21,6 +21,15 @@ PD 2026-11-05: 「매번 수신하지 않아도, 요청한 작업이 완전히
|
|||
"maps": [{"chapter": 3, "id": "ch03", "ko": "군웅할거", "nodes": 15,
|
||||
"map": "maps/ch03.png", "map_md5": "<md5>", "anchors": "anchors/ch03.json", "anchors_md5": "<md5>"}]
|
||||
}
|
||||
# kind == "ui" (UI 리뉴얼 B 신규 제작 · 세션 tks-ui-art · PD #1100 · 2026-11-06)
|
||||
"root": "C:/ArtRnD/samguk_ui/<group>", # files 의 기준
|
||||
"files": ["cur_gold.png", …] 또는 [{"file": "cur_gold.png", "md5": "<md5>"}, …], # 파일 이름(확장자 앞) = 테마 id
|
||||
"md5_list": "C:/ArtRnD/samguk_ui/<group>/md5.txt" # 선택 · <root> 기준 상대 경로 · md5sum 형식
|
||||
}
|
||||
ui = <root>/<file> → Assets/UI/Samguk/<group>/<id>.png (group = batch 의 「ui_」 뒤 · 없으면 root 폴더 이름) ·
|
||||
기믹 그림(id 가 gim_ 로 시작) → Assets/Resources/Gimmicks/Art/<id>.png(GimmickView 가 읽는 자리) ·
|
||||
치환 기록 = Assets/UI/Samguk/ui_delivered.csv(id · group · 경로 · md5 · batch) · 테마 치환 테이블(Resources/UI/UITheme.asset)은
|
||||
Unity 가 Samguk PNG 임포트 때 자동 갱신(Editor/UIThemeImporter · 수동 = 메뉴 TKS/Import UI Theme) — 화면 코드 변경 없음.
|
||||
worldmap = 맵 PNG → Assets/Resources/ChapterMap/Maps/<id>.png · 좌표 json → Data/<id>.json(게임 노드 = stages[].at) ·
|
||||
Data/world.json 의 같은 id 항목(길 roadX·roadY · 장소)을 좌표 json 으로 교체. 게임 챕터 → 맵 연결 = Assets/Data/Stages/chapters.csv map 열.
|
||||
같은 맵 id 를 더 늦게 다시 납품한 json(_r2 등)이 미반영으로 있으면 앞의 것은 반영하지 않고 .superseded.json 으로 바꾼다.
|
||||
|
|
@ -46,6 +55,9 @@ UNITS = os.path.join(PROJECT, "Assets", "Resources", "Units")
|
|||
BOARD = os.path.join(PROJECT, "Assets", "Resources", "Board", "battlefield_01.png")
|
||||
CHAPMAP = os.path.join(PROJECT, "Assets", "Resources", "ChapterMap")
|
||||
WORLDMAP_ROOT = r"C:\ArtRnD\samguk_chapmap\plan"
|
||||
SAMGUK_UI = os.path.join(PROJECT, "Assets", "UI", "Samguk")
|
||||
GIMMICK_ART = os.path.join(PROJECT, "Assets", "Resources", "Gimmicks", "Art")
|
||||
THEME_CSV = os.path.join(PROJECT, "Assets", "Data", "UI", "ui_theme.csv")
|
||||
|
||||
|
||||
def md5_of(path):
|
||||
|
|
@ -159,6 +171,56 @@ def apply_worldmap(d):
|
|||
open(world_path, "w", encoding="utf-8").write(json.dumps(world, ensure_ascii=False, indent=1))
|
||||
|
||||
|
||||
def apply_ui(d):
|
||||
root = d["root"]
|
||||
if d.get("md5_list"):
|
||||
ok, bad = check_md5_list(root, d["md5_list"])
|
||||
if bad:
|
||||
sys.exit("md5 불일치 %d: %s" % (len(bad), ", ".join(bad[:5])))
|
||||
print("md5 OK", ok)
|
||||
batch = str(d.get("batch", ""))
|
||||
group = batch[3:] if batch.startswith("ui_") else os.path.basename(os.path.normpath(root))
|
||||
known = set()
|
||||
if os.path.exists(THEME_CSV):
|
||||
for line in open(THEME_CSV, encoding="utf-8-sig"):
|
||||
f = line.split(",")
|
||||
if len(f) > 1 and f[0] in ("skin", "icon"):
|
||||
known.add(f[1])
|
||||
log_path = os.path.join(SAMGUK_UI, "ui_delivered.csv")
|
||||
rows = {}
|
||||
if os.path.exists(log_path):
|
||||
for line in open(log_path, encoding="utf-8-sig").read().splitlines()[1:]:
|
||||
if line.strip():
|
||||
rows[line.split(",")[0]] = line
|
||||
replaced, added = [], []
|
||||
for item in d["files"]:
|
||||
rel, digest = (item, None) if isinstance(item, str) else (item["file"], item.get("md5"))
|
||||
src = os.path.join(root, rel.replace("/", os.sep))
|
||||
if not rel.lower().endswith(".png"):
|
||||
sys.exit("PNG 가 아님: " + rel)
|
||||
if digest and md5_of(src) != digest.lower():
|
||||
sys.exit("ui md5 불일치: " + src)
|
||||
uid = os.path.splitext(os.path.basename(rel))[0]
|
||||
dst = os.path.join(GIMMICK_ART, uid + ".png") if uid.startswith("gim_") else os.path.join(SAMGUK_UI, group, uid + ".png")
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
shutil.copyfile(src, dst)
|
||||
m = md5_of(dst)
|
||||
if digest and m != digest.lower():
|
||||
sys.exit("복사 뒤 md5 불일치: " + dst)
|
||||
(replaced if uid in known else added).append(uid)
|
||||
try:
|
||||
shown = os.path.relpath(dst, PROJECT)
|
||||
except ValueError: # 다른 드라이브(시험)
|
||||
shown = dst
|
||||
rows[uid] = ",".join([uid, group, shown.replace(os.sep, "/"), m, batch])
|
||||
os.makedirs(SAMGUK_UI, exist_ok=True)
|
||||
with open(log_path, "w", encoding="utf-8-sig", newline="\n") as f:
|
||||
f.write("id,group,path,md5,batch\n")
|
||||
for k in sorted(rows):
|
||||
f.write(rows[k] + "\n")
|
||||
print("ui", group, "· 팩 치환", len(replaced), "· 새 id", len(added), (added[:8] if added else ""), "→", log_path)
|
||||
|
||||
|
||||
def cmd_list(a):
|
||||
files = pending()
|
||||
old = superseded(files)
|
||||
|
|
@ -195,13 +257,16 @@ def cmd_apply(a):
|
|||
apply_poses(d)
|
||||
elif d["kind"] == "worldmap":
|
||||
apply_worldmap(d)
|
||||
elif d["kind"] == "ui":
|
||||
apply_ui(d)
|
||||
else:
|
||||
sys.exit("모르는 kind: " + str(d.get("kind")))
|
||||
os.replace(p, p[:-5] + ".applied.json")
|
||||
print("\n다음(Unity · PD 에디터 Play 중이면 먼저 editor.playmode stop):")
|
||||
print(" unity command --project-path . editor invoke_menu --path 'TKS/Reimport Unit Art (유닛 아트 재임포트)' --result-only (Units·Board·ChapterMap)")
|
||||
print(" unity command --project-path . editor invoke_menu --path 'TKS/Import UI Theme (UI 테마 임포트)' --result-only (ui · Samguk PNG 임포트 때 자동 · 확인용)")
|
||||
print(" unity command --project-path . test run --mode playmode --async-tests --timeout 600 --result-only ; unity command --project-path . test status --result-only")
|
||||
print(" git add -A && git commit (끝줄 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>)")
|
||||
print(" git add -A && git commit (끝줄 Co-Authored-By: <실제 모델> <noreply@anthropic.com>)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
@ -212,7 +277,7 @@ if __name__ == "__main__":
|
|||
ap = sp.add_parser("apply")
|
||||
ap.add_argument("json", nargs="?", default="")
|
||||
ap.add_argument("--all", action="store_true")
|
||||
ap.add_argument("--kind", default="", help="이 kind 만(bg · poses · worldmap)")
|
||||
ap.add_argument("--kind", default="", help="이 kind 만(bg · poses · worldmap · ui)")
|
||||
ap.set_defaults(fn=cmd_apply)
|
||||
a = p.parse_args()
|
||||
if a.cmd == "apply" and not a.all and not a.json:
|
||||
|
|
|
|||
Loading…
Reference in New Issue