fix(deck): 카드 picker 표시·클릭 복구 + UIGroup 렌더 순서/덱 레이아웃 조정

덱창(카드 picker)의 카드가 표시·클릭되지 않던 두 버그를 근본 수정.

표시 버그: 덱뷰 render(RenderAllDeck/RenderClassDeckTabs/RenderDeckInspect)가
비-DefaultGroup(DeckUIGroup) 카드를 직접 e.Enable로 켰는데, 깊게 중첩된
ExecSpace 6 호출이라 .Enable 토글이 스코프 상실로 무효(문서화된 afac34d 버그).
Maker 저작 DeckAllHud 카드는 기본 enable=false라 안 보였음. → SetEntityEnabled
(ExecSpace 2 ClientOnly, 인라인 실행) 경유로 변경(전투 HUD와 동일 패턴).

클릭 버그: Maker 저작 DeckAllHud 카드 120장의 SpriteGUIRendererComponent.
RaycastTarget=false라 클릭 레이를 못 받아 런타임 부착 ButtonComponent에 클릭이
도달 못함(같은 패널 탭/Close는 raycast=true라 정상이던 게 결정적 단서). →
BindButtons 카드 루프에서 RaycastTarget=true 런타임 주입.

README: 디버그 단축키 섹션 추가(Ctrl+Shift+C 카드 picker / Ctrl+Shift+E 에너지).

Maker UI 저작(메이커 편집분 동반): 6개 UIGroup GroupOrder 재배치
(DeckUIGroup 최상단 4→6 등) + DeckUIGroup 카드 그리드 위치 조정(180장).

산출물 재생성: SlayDeckController.codeblock.
검증: cbgap GAP 0, JS 미러 41/41, 인게임 클릭 동작 확인.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-18 01:33:26 +09:00
parent 491833b025
commit db76870d4e
10 changed files with 413 additions and 411 deletions

View File

@@ -157,6 +157,17 @@ c:AdjustAscension(1) -- 메뉴에서 승천 단계 +1
밸런스 검증: `node tools/balance/sim-balance.mjs [N] [--seed S]` · 테스트: `node --test tools/balance/sim-balance.test.mjs tools/map/rogue-map.test.mjs`.
상세 설계는 [`docs/slaymaple_basic_framework.md`](docs/slaymaple_basic_framework.md) 및 `docs/superpowers/specs/` 참조.
### 디버그 단축키
개발·QA용 키보드 단축키. **전투 중**(런 활성 + 전투 진행 중)에만 동작합니다.
| 단축키 | 기능 |
|---|---|
| **Ctrl + Shift + C** | **카드 picker** — 직업 전체 카드 패널을 띄우고, 카드를 클릭하면 **즉시 손패에 추가**. 상단 탭(전사/도적/마법사)으로 직업별 카드 풀 전환. 카드 효과·메커니즘 즉석 테스트용 |
| **Ctrl + Shift + E** | **에너지 치트** — 현재 에너지를 최대치로 회복 |
> 카드 picker는 메이커 저작 UI `DeckUIGroup/DeckAllHud`(120 슬롯 그리드 + 직업 탭 3종)를 사용하고, 컨트롤러가 런타임에 카드 비주얼·버튼을 바인딩합니다. 구현: 키 바인딩 `tools/deck/cb/boot.mjs`, picker 로직 `tools/deck/cb/deckview.mjs`(`OpenDebugCardPicker`/`OnAllDeckCardButton`), 버튼 바인딩 `tools/deck/cb/deckturn.mjs`(`BindButtons`). 옛 picker UI 생성기 `tools/deck/legacy/hud/deckall.mjs`는 UI 메이커-저작 전환 후 **휴면**(Maker UI가 대체).
### 산출물 재생성
```bash
node tools/deck/gen-slaydeck.mjs # 컨트롤러+common (UI는 메이커 저작 — 미생성)

File diff suppressed because one or more lines are too long

View File

@@ -70,6 +70,9 @@ self:BindClassDeckTabs()
for i = 1, 120 do
local allCard = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i))
if allCard ~= nil and (allCard.ButtonComponent ~= nil or allCard:AddComponent("ButtonComponent") ~= nil) then
if allCard.SpriteGUIRendererComponent ~= nil then
allCard.SpriteGUIRendererComponent.RaycastTarget = true
end
local slot = i
allCard:ConnectEvent(ButtonClickEvent, function() self:OnAllDeckCardButton(slot) end)
end

View File

@@ -42,24 +42,19 @@ if count > 60 then
suffix = suffix .. " - 60장까지 표시"
end
self:SetText("/ui/DeckUIGroup/DeckInspectHud/Title", title .. suffix)
local empty = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Empty")
if empty ~= nil then
empty.Enable = count <= 0
end
self:SetEntityEnabled("/ui/DeckUIGroup/DeckInspectHud/Empty", count <= 0)
for i = 1, 60 do
local e = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(i))
if e ~= nil then
local path = "/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(i)
local cardId = nil
if pile ~= nil then
cardId = pile[i]
end
if cardId == nil then
e.Enable = false
self:SetEntityEnabled(path, false)
else
e.Enable = true
self:SetEntityEnabled(path, true)
self:ApplyInspectCardVisual(i, cardId)
end
end
end`, [
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pile' },
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'title' },
@@ -171,17 +166,15 @@ self:RenderClassDeckTabs()`, [{ Type: 'string', DefaultValue: null, SyncDirectio
{ path = "/ui/DeckUIGroup/DeckAllHud/MageTab", cls = "magician" },
}
for i = 1, #tabs do
self:SetEntityEnabled(tabs[i].path, self.ClassDeckMode == true)
local e = _EntityService:GetEntityByPath(tabs[i].path)
if e ~= nil then
e.Enable = self.ClassDeckMode == true
if e.SpriteGUIRendererComponent ~= nil then
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
if self.ClassDeckClass == tabs[i].cls then
e.SpriteGUIRendererComponent.Color = Color(0.22, 0.28, 0.34, 1)
else
e.SpriteGUIRendererComponent.Color = Color(0.11, 0.13, 0.16, 1)
end
end
end
end`),
method('OpenAllDeck', `local inspectHud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud")
if inspectHud ~= nil then
@@ -230,21 +223,16 @@ end
local count = #pile
self:SetText("/ui/DeckUIGroup/DeckAllHud/Title", title .. " (" .. tostring(count) .. ")")
self:RenderClassDeckTabs()
local empty = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Empty")
if empty ~= nil then
empty.Enable = count <= 0
end
self:SetEntityEnabled("/ui/DeckUIGroup/DeckAllHud/Empty", count <= 0)
for i = 1, 120 do
local e = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i))
if e ~= nil then
local path = "/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i)
local cardId = pile[i]
if cardId == nil then
e.Enable = false
self:SetEntityEnabled(path, false)
else
e.Enable = true
self:SetEntityEnabled(path, true)
self:ApplyAllDeckCardVisual(i, cardId)
end
end
end`),
method('ApplyAllDeckCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(slot), cardId)`, [
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@
"nameEditable": true,
"enable": true,
"visible": true,
"localize": false,
"localize": true,
"displayOrder": 5,
"pathConstraints": "//",
"revision": 1,
@@ -86,7 +86,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 5,
"GroupOrder": 1,
"GroupType": 2,
"Enable": true
},

View File

@@ -97,7 +97,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 1,
"GroupOrder": 2,
"GroupType": 1,
"Enable": true
},

View File

@@ -23,7 +23,7 @@
"nameEditable": true,
"enable": true,
"visible": true,
"localize": false,
"localize": true,
"displayOrder": 6,
"pathConstraints": "//",
"revision": 1,
@@ -86,7 +86,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 6,
"GroupOrder": 5,
"GroupType": 2,
"Enable": true
},

View File

@@ -23,7 +23,7 @@
"nameEditable": true,
"enable": true,
"visible": true,
"localize": false,
"localize": true,
"displayOrder": 3,
"pathConstraints": "//",
"revision": 1,
@@ -86,7 +86,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 3,
"GroupOrder": 4,
"GroupType": 2,
"Enable": true
},

View File

@@ -97,7 +97,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 2,
"GroupOrder": 3,
"GroupType": 1,
"Enable": true
},