iter44-卡1:卡①(组合根注册面批): ui_registry+三域容器建件·main.gd 49→15(28迁出+7别名消灭+ui新增)·六转发方法+flush退役·全消费面(探针11件/系统测试/流程件/冒烟)改址main.ui.*·V1d全目录重锚〔注册面V1〕·V6改串〔注册面V2〕·行为零变化四闸主证

This commit is contained in:
DKChan committed 2026-10-30 07:11:40 +08:00
1 parent 14054d9dfb
commit 9fa93787b7
41 files changed
+1073 -1070

No files matched your search

+68 -68
View File
@@ -28,13 +28,13 @@ func _ready() -> void:
# ---- 菜单簇(开始层可见态;逐屏开→采样→关,模态恢复走组合根真实路径)----
ProbeUiUtil.isolate_save(main, "smoke_ui_struct_probe_menu", true, false, true)
_settle()
await _audit("start", [main._start_overlay])
await _audit("start", [main.ui.screens.start_overlay])
_start_columns_contract(main)
_modal_registry_contract(main)
main._open_settings()
_settle()
await _audit("settings", [main.settings_overlay])
await _audit("settings", [main.ui.modals.settings_overlay])
main._on_settings_closed()
_settle()
@@ -42,7 +42,7 @@ func _ready() -> void:
problems.append("[camp] 营地入口缺失(选档层新档钮——mn9 新路径驱动中断)")
else:
_settle()
await _audit("camp", [main.camp_overlay])
await _audit("camp", [main.ui.modals.camp_overlay])
# 营地灰字源 token 扫描(迭代36 wc4 静态半——源内零裸 UiKit.STONE;判别式=
# STONE 出现次数 == STONE_DEEP 出现次数,即每处 STONE 都带 _DEEP 后缀)
var camp_src := FileAccess.get_file_as_string("res://presentation/views/camp_overlay_view.gd")
@@ -59,15 +59,15 @@ func _ready() -> void:
# 生涯页驱动=函数直调中间态(卡② mn9/mn10——careerbtn 已撤,卡④ 营地笔记本改挂前无 UI 路径)
main._open_career()
_settle()
if not main.career_overlay.visible or main._start_overlay.visible:
if not main.ui.modals.career_overlay.visible or main.ui.screens.start_overlay.visible:
problems.append("[career] 生涯页未打开或开始层未隐藏(函数直调中间态断裂)")
await _audit("career", [main.career_overlay])
await _audit("career", [main.ui.modals.career_overlay])
_career_readonly_contract(main)
_career_zero_motion_contract(main)
_career_nojump_contract(main)
main._on_career_closed()
_settle()
if main.career_overlay.visible or not main._start_overlay.visible:
if main.ui.modals.career_overlay.visible or not main.ui.screens.start_overlay.visible:
problems.append("[career] 关闭后页未隐藏或开始层未恢复(模态栈单口失守)")
# ---- 选档界面(迭代 33 卡③):函数直调开层(「进入存档」钮归卡② mn3——点击链在卡② 承接),
@@ -93,39 +93,39 @@ func _ready() -> void:
problems.append("[savesel] 开层前激活态非零(sl9 重启链——boot/注入面后应无激活)")
main._open_save_select()
_settle()
if not main.save_select_overlay.visible or main._start_overlay.visible:
if not main.ui.modals.save_select_overlay.visible or main.ui.screens.start_overlay.visible:
problems.append("[savesel] 选档层未打开或开始层未隐藏(开层函数断裂)")
await _audit("savesel", [main.save_select_overlay])
await _audit("savesel", [main.ui.modals.save_select_overlay])
_save_select_contract(main, ssel_tpl)
main._on_save_select_closed()
_settle()
if main.save_select_overlay.visible or not main._start_overlay.visible:
if main.ui.modals.save_select_overlay.visible or not main.ui.screens.start_overlay.visible:
problems.append("[savesel] 关闭后层未隐藏或开始层未恢复(模态栈单口失守)")
main.confirm_dialog.open("结构探针采样", "确认")
main.ui.modals.confirm_dialog.open("结构探针采样", "确认")
_settle()
await _audit("confirm", [main.confirm_dialog])
main.confirm_dialog.close()
await _audit("confirm", [main.ui.modals.confirm_dialog])
main.ui.modals.confirm_dialog.close()
_settle()
main._show_debug_overlay()
_settle()
await _audit("debug", [main.debug_overlay])
await _audit("debug", [main.ui.modals.debug_overlay])
main._close_debug_overlay()
_settle()
# ---- 冒险簇(真流推进:开冒险→地图选路态→选战斗节点→战斗 HUD)----
ProbeUiUtil.isolate_save(main, "smoke_ui_struct_probe_adv", true, false, true)
main.debug_overlay.seed_edit.text = "42" # 种子钉死(种子框默认为空=非首局随机,结构采样确定性禁依赖默认分支)
main.ui.modals.debug_overlay.seed_edit.text = "42" # 种子钉死(种子框默认为空=非首局随机,结构采样确定性禁依赖默认分支)
main._start_adventure_from_menu()
_settle(4)
await _audit("level_map", [main.level_screen])
await _audit("level_map", [main.ui.modals.level_screen])
var battle_id := _pick_battle_node(main)
if battle_id >= 0:
main.level_screen.route_chosen.emit(battle_id)
main.ui.modals.level_screen.route_chosen.emit(battle_id)
_settle(6)
_audit("battle_hud", [main.board_zone, main.info_panel, main.stage])
_audit("battle_hud", [main.ui.battle.board_zone, main.ui.battle.info_panel, main.ui.battle.stage])
_standeefit_contract(main)
# ---- 状态面板:组合根真实路径开层→结构断言→关闭。附只读性契约
#(R4——子树信号连接白名单巡检)与零动效契约(R5/P4 甲——零 AnimationPlayer/零 tween)。
@@ -133,74 +133,74 @@ func _ready() -> void:
# 一律红,须先入册审查);白名单={视图自身 _emit_closed, 组合根 _on_status_closed}。
main._open_status_panel()
_settle()
await _audit("status", [main.status_panel])
await _audit("status", [main.ui.modals.status_panel])
_status_readonly_contract(main)
_status_zero_motion_contract(main)
main._on_status_closed()
_settle()
if main.status_panel.visible:
if main.ui.modals.status_panel.visible:
problems.append("[status] 关闭后层未隐藏(模态栈单口失守)")
# ---- 图例层(旧模态、首过结构族):ap_bar legend_toggled
# 信号真路径开(board_zone 信号→组合根 _on_legend_toggled→_open_modal)→结构断言族→
# closed 信号真路径关(close()→组合根 _on_modal_closed)。
main.board_zone.legend_toggled.emit()
main.ui.battle.board_zone.legend_toggled.emit()
_settle()
if not main.legend_overlay.visible:
if not main.ui.modals.legend_overlay.visible:
problems.append("[legend] 图例层未打开(legend_toggled 路径中断)")
await _audit("legend", [main.legend_overlay])
main.legend_overlay.close()
await _audit("legend", [main.ui.modals.legend_overlay])
main.ui.modals.legend_overlay.close()
_settle()
if main.legend_overlay.visible:
if main.ui.modals.legend_overlay.visible:
problems.append("[legend] 关闭后层未隐藏(模态栈单口失守)")
else:
problems.append("[battle_hud] 候选中无战斗节点(驱动中断——候选=%s)" % str(main.level_screen._cand_ids))
problems.append("[battle_hud] 候选中无战斗节点(驱动中断——候选=%s)" % str(main.ui.modals.level_screen._cand_ids))
# ---- 兑付屏(真实 open 面 + 合成最小数据——结构断言只看矩形/宽度/可见性)----
main._end_overlay.open_victory("结构探针·胜利演算", "返回", Rect2(200, 200, 400, 300), {"gp_summary": "GP 0"})
main.ui.modals.end_overlay.open_victory("结构探针·胜利演算", "返回", Rect2(200, 200, 400, 300), {"gp_summary": "GP 0"})
_settle()
await _audit("battle_end", [main._end_overlay])
main._end_overlay.close()
await _audit("battle_end", [main.ui.modals.end_overlay])
main.ui.modals.end_overlay.close()
_settle()
# ---- 节点结算层(旧模态、首过结构族):rest 兑付真路径开
#(组合根 _open_modal 登记册+show_rest 合成喂入)→结构断言族→continue_pressed 信号真路径关
#(press_continue→组合根 _on_node_continue→_close_modal)。
main._open_modal(main.node_overlay)
main.node_overlay.show_rest(3, 15, 20)
main.ui.modals.flow.open(main.ui.modals.node_overlay)
main.ui.modals.node_overlay.show_rest(3, 15, 20)
_settle()
if not main.node_overlay.visible:
if not main.ui.modals.node_overlay.visible:
problems.append("[node] 节点结算层未打开(rest 兑付路径中断)")
await _audit("node_overlay", [main.node_overlay])
main.node_overlay.press_continue()
await _audit("node_overlay", [main.ui.modals.node_overlay])
main.ui.modals.node_overlay.press_continue()
_settle()
if main.node_overlay.visible:
if main.ui.modals.node_overlay.visible:
problems.append("[node] 关闭后层未隐藏(continue_pressed 路径中断)")
main.curio_overlay.open_pick("结构探针·三选一", [
main.ui.modals.curio_overlay.open_pick("结构探针·三选一", [
{"id": "probe_heal", "text": "回血\n恢复 3 点"},
{"id": "probe_magic", "text": "爆裂轰击\n下一击 +5"},
{"id": "probe_pierce", "text": "穿甲\n无视护甲"},
])
_settle()
await _audit("curio_pick", [main.curio_overlay])
main.curio_overlay.visible = false
await _audit("curio_pick", [main.ui.modals.curio_overlay])
main.ui.modals.curio_overlay.visible = false
_settle()
main.shop_overlay.open_shop([
main.ui.modals.shop_overlay.open_shop([
{"product_id": "probe_p1", "display_name": "探针商品甲", "attr": "atk", "flat_value": 1, "price": 10, "purchased": 0},
{"product_id": "probe_p2", "display_name": "探针商品乙", "attr": "hp", "flat_value": 2, "price": 20, "purchased": 0},
], 100)
_settle()
await _audit("shop", [main.shop_overlay])
await _audit("shop", [main.ui.modals.shop_overlay])
# ---- 术语传导:货架卡与三选一卡片的玩家面文案(物品名=专长获取、分类=专长凭证)
main.shop_overlay.open_shelf([
main.ui.modals.shop_overlay.open_shelf([
{"kind_id": "feat_ticket", "display_name": "专长获取", "value": 0, "price": 5},
{"kind_id": "heal", "display_name": "应急回复", "value": 6, "price": 5},
], 20)
_settle()
var ticket_row: Dictionary = main.shop_overlay._shelf_rows[0]
var ticket_row: Dictionary = main.ui.modals.shop_overlay._shelf_rows[0]
if String(main.db.run.shop.pool_row("feat_ticket").get("display_name", "")) != "专长获取":
problems.append("[shop_term] shop.tres 专长凭证件名未换代(现=%s)" % String(main.db.run.shop.pool_row("feat_ticket").get("display_name", "")))
if ticket_row.card.name_l.text != "专长获取":
@@ -211,7 +211,7 @@ func _ready() -> void:
problems.append("[shop_term] 专长凭证件描述未用规范流程句(现=%s)" % ticket_row.card.desc_l.text)
if ticket_row.card.foot_l.text != "专长凭证":
problems.append("[shop_term] 专长凭证件分类标注未用「专长凭证」(现=%s)" % ticket_row.card.foot_l.text)
var heal_row: Dictionary = main.shop_overlay._shelf_rows[1]
var heal_row: Dictionary = main.ui.modals.shop_overlay._shelf_rows[1]
if heal_row.card.desc_l.text != "回复 +6(本冒险)":
problems.append("[shop_term] 回复件描述漏了 heal 词表(现=%s)" % heal_row.card.desc_l.text)
if heal_row.card.foot_l.text != "回复":
@@ -223,7 +223,7 @@ func _ready() -> void:
problems.append("[curio_term] 专长凭证三选一卡未用物品名/规范流程句(现=%s)" % ticket_text)
if ticket_text.contains("门票") or ticket_text.contains("T5") or ticket_text.contains("持有集") or ticket_text.contains("奇物三选一"):
problems.append("[curio_term] 专长凭证三选一卡残留退役词/内部任务号(现=%s)" % ticket_text)
main.shop_overlay.visible = false
main.ui.modals.shop_overlay.visible = false
_settle()
# ---- ⑦resume 专项:续玩停点恢复(main.gd:717 报错回归闸)----
@@ -234,11 +234,11 @@ func _ready() -> void:
main.run_scope.runner = null # 全新启动等价态(真机=菜单直进续玩,无前置冒险——runner 从未赋值;探针此前推流会残留旧 runner)
main._resume_from_menu()
_settle(8)
if not main._end_overlay.visible:
if not main.ui.modals.end_overlay.visible:
problems.append("[resume] 续玩恢复后胜利总结面未开(三选一停点分支中断)")
else:
var found := {"ok": false}
_find_label_text(main._end_overlay, "合计 24", found)
_find_label_text(main.ui.modals.end_overlay, "合计 24", found)
if not found.ok:
problems.append("[resume] 胜利总结面 GP 行未见快照合计「合计 24」(runner 缺位守卫缺位——717 回归)")
var s: String = main._gp_summary_text({"gp_dropped": 0})
@@ -280,7 +280,7 @@ func _find_label_text(node: Node, needle: String, found: Dictionary) -> void:
func _pick_battle_node(main: Node) -> int:
# 入口/兑付停点走 level_screen.open_choices 直传(不写 _pending_candidates)——
# 候选从视图态取:_cand_ids × runner.nodes() 的 type(编号解析=node_id_of 单一出口)
var ls: Node = main.level_screen
var ls: Node = main.ui.modals.level_screen
if ls._map._runner == null:
return -1
for nd in ls._map._runner.nodes():
@@ -306,7 +306,7 @@ const _PAUSE_READONLY_SIGNALS: Array[String] = [
func _status_readonly_contract(main: Node) -> void:
var overlay: Control = main.status_panel
var overlay: Control = main.ui.modals.status_panel
var stack: Array = [overlay]
var conn_count := 0
while not stack.is_empty():
@@ -332,7 +332,7 @@ func _status_readonly_contract(main: Node) -> void:
# ⑨status 零动效契约(R5/P4 甲——零动效直开直关路径存在断言):
# 子树零 AnimationPlayer + 视图源码零 tween/动效包装调用(源码 token 扫描=ui_contrast 静态段同手法)
func _status_zero_motion_contract(main: Node) -> void:
var overlay: Control = main.status_panel
var overlay: Control = main.ui.modals.status_panel
var stack: Array = [overlay]
while not stack.is_empty():
var n: Node = stack.pop_back()
@@ -352,7 +352,7 @@ func _status_zero_motion_contract(main: Node) -> void:
# 清单外零连接。白名单={视图自身 _emit_closed〔返回钮〕, 组合根 _on_career_closed};页内任何
# 购买/导航/写入方向的新连接一律红,须先入册审查。
func _career_readonly_contract(main: Node) -> void:
var overlay: Control = main.career_overlay
var overlay: Control = main.ui.modals.career_overlay
var stack: Array = [overlay]
var conn_count := 0
while not stack.is_empty():
@@ -377,7 +377,7 @@ func _career_readonly_contract(main: Node) -> void:
# ⑪career 零动效契约(状态面板 ⑨ 同形制——P4 甲直开直关)
func _career_zero_motion_contract(main: Node) -> void:
var overlay: Control = main.career_overlay
var overlay: Control = main.ui.modals.career_overlay
var stack: Array = [overlay]
while not stack.is_empty():
var n: Node = stack.pop_back()
@@ -392,13 +392,13 @@ func _career_zero_motion_contract(main: Node) -> void:
# ⑫模态登记/树序全量合同(V1——career 专属登记序契约推广到全部模态+屏壳;
# 判据=main.LAYER_CONTRACT 单一事实源:登记册序==合同模态序、直接子层树序==合同序逐对相等。
# 判据=main.ui.LAYER_CONTRACT 单一事实源:登记册序==合同模态序、直接子层树序==合同序逐对相等。
# 两特例按合同数据表达:level_screen 宿住冒险屏壳(树序随宿主=全模态之下,遮挡语义归模态栈
# screen_state 登记)、camp_overlay 成员与 camp_screen 屏壳同槽(屏壳树序代言成员登记位)。
# _career_registry_contract 的断言(career=状态面板后/确认弹窗前、树序同步)由本全量合同覆盖)
# ⑭选档界面契约(卡③ sl1/sl2/sl3/sl4/sl9——呈现面全部来自喂入数据,视图零自判)
func _save_select_contract(main: Node, tpl: String) -> void:
var sso: Node = main.save_select_overlay
var sso: Node = main.ui.modals.save_select_overlay
# sl1 三槽呈现:槽卡计数==3+零滚动容器(禁滚动长列表形态——契约 1)
var rows: VBoxContainer = sso._rows_box
var live_rows := 0
@@ -477,13 +477,13 @@ func _collect_labels(node: Node, out: Array[String]) -> void:
func _modal_registry_contract(main: Node) -> void:
var list: Array = main._modals._list
var list: Array = main.ui.modals.flow.stack._list
# ① 登记册序==合同模态序(逐位点名——合同是登记序唯一事实源)
var contract_modals: Array = []
for entry: Dictionary in main.LAYER_CONTRACT:
for entry: Dictionary in main.ui.LAYER_CONTRACT:
if String(entry["kind"]) != "modal":
continue
var n: Node = main._layer_node(String(entry["key"]))
var n: Node = main.ui.node(String(entry["key"]))
if n == null:
problems.append("[registry] 合同层缺失: %s〔装配生命批 V1〕" % String(entry["key"]))
continue
@@ -498,10 +498,10 @@ func _modal_registry_contract(main: Node) -> void:
i, list[i].name, contract_modals[i].name])
# ② 直接子层树序==合同序逐对相等(屏壳/模态/全屏态/非视觉节点全链;宿住层随宿主不参与)
var prev: Node = null
for entry: Dictionary in main.LAYER_CONTRACT:
for entry: Dictionary in main.ui.LAYER_CONTRACT:
if entry.has("host"):
continue
var node: Node = main._layer_node(String(entry["shell"]) if entry.has("shell") else String(entry["key"]))
var node: Node = main.ui.node(String(entry["shell"]) if entry.has("shell") else String(entry["key"]))
if node == null:
problems.append("[registry] 合同层缺失: %s〔装配生命批 V1〕" % String(entry["key"]))
continue
@@ -510,23 +510,23 @@ func _modal_registry_contract(main: Node) -> void:
prev.name, node.name, node.get_index(), prev.get_index()])
prev = node
# ③ 宿住层特例:level_screen 宿主=冒险屏壳且在全直接子模态之下(遮挡语义归模态栈 screen_state)
var lv: Node = main.level_screen
if lv.get_parent() != main._adventure_screen:
var lv: Node = main.ui.modals.level_screen
if lv.get_parent() != main.ui.screens.adventure_screen:
problems.append("[registry] level_screen 宿主应=冒险屏壳(实测 %s)〔装配生命批 V1〕" % lv.get_parent().name)
elif lv.get_parent().get_index() >= main.legend_overlay.get_index():
elif lv.get_parent().get_index() >= main.ui.modals.legend_overlay.get_index():
problems.append("[registry] 冒险屏壳应在全模态之下(宿主 idx=%d legend idx=%d)〔装配生命批 V1〕" % [
lv.get_parent().get_index(), main.legend_overlay.get_index()])
lv.get_parent().get_index(), main.ui.modals.legend_overlay.get_index()])
# ④ 营地同槽特例:camp_screen 屏壳树序夹商店层与设置层之间(成员 camp_overlay 登记位代言)
var cs: Node = main._camp_screen
if cs.get_index() <= main.shop_overlay.get_index() or cs.get_index() >= main.settings_overlay.get_index():
var cs: Node = main.ui.screens.camp_screen
if cs.get_index() <= main.ui.modals.shop_overlay.get_index() or cs.get_index() >= main.ui.modals.settings_overlay.get_index():
problems.append("[registry] camp_screen 屏壳树序应夹商店与设置层之间(idx=%d shop=%d settings=%d)〔装配生命批 V1〕" % [
cs.get_index(), main.shop_overlay.get_index(), main.settings_overlay.get_index()])
cs.get_index(), main.ui.modals.shop_overlay.get_index(), main.ui.modals.settings_overlay.get_index()])
# ⑬career 零跳转契约(提纲 P4 甲——页内零「前往他处」入口:除「返回」外任何导航钮=红)
func _career_nojump_contract(main: Node) -> void:
for nav in ["营地", "商店", "设置", "冒险", "继续上局", "退出", "前往"]:
if ProbeUiUtil.find_button(main.career_overlay, nav, "contains") != null:
if ProbeUiUtil.find_button(main.ui.modals.career_overlay, nav, "contains") != null:
problems.append("[career][nojump] 页内出现导航入口「%s」(零跳转违约——生涯纯只读)" % nav)
@@ -534,7 +534,7 @@ func _career_nojump_contract(main: Node) -> void:
# (名行基线离盒底 1px 同型高危写法返修回归闸;
# 内容矩形=StandeeBody.content_rect(),最低绘制元素=底座下缘)
func _standeefit_contract(main: Node) -> void:
var st: Node = main.stage
var st: Node = main.ui.battle.stage
if st == null or st.hero_standee == null:
problems.append("[standee] 舞台/主角站桩缺失(断言中断)")
return
@@ -711,8 +711,8 @@ func _dump(c: Control, depth: int) -> void:
# ⑤start 专项:左列/右列矩形不相交(M2 双列契约——装配件命名 start_box/start_right 为探针锚点)
func _start_columns_contract(main: Node) -> void:
var box: Control = main._start_overlay.find_child("start_box", true, false)
var right: Control = main._start_overlay.find_child("start_right", true, false)
var box: Control = main.ui.screens.start_overlay.find_child("start_box", true, false)
var right: Control = main.ui.screens.start_overlay.find_child("start_right", true, false)
if box == null or right == null:
problems.append("[start][columns] 左列/右列节点缺失(start_box/start_right——装配命名失守)")
return