工程(真输入化5/7·screen_flow_probe): 14处emit→13处真输入——篝火/窗壳轮转/V6/V7/V8场景命中区push_click_at,二次确认真点_confirm_btn,选档返回/终局继续/生涯返回/清窗返回钮真点,esc返回主菜单真点_return_btn; V5b一处保留emit并注记(V5b被测面=窗开态遮罩挡场景点选,前提只能信号注入); 判据出处注记13条逐段挂(architecture:168互斥判据×2+test-conventions:49 boot组+camp.md:10/22/45×3+存档序列化:61选档+level-map:11/42+battle.md:57+settlement-summary:12); 本步凭据: screen_flow_probe headless直跑PASS exit=0(六步主流程+回退全绿)
This commit is contained in:
1 parent
e0b22f40fb
commit
4f48c40fd5
1 file changed
+27
-14
@@ -69,12 +69,14 @@ func _seals_text(f: Dictionary) -> String:
|
||||
|
||||
# ---- 流程状态位(与可见性是两回事,逐步单独判)----
|
||||
func _expect_adventure_seal(step: String, expect: bool) -> void:
|
||||
# oracle: design/engineering/architecture/architecture.md:168 三屏壳与呈现装配——屏级互斥与流程状态位判据宿主面(状态位判据组)
|
||||
var got: bool = main.run_scope != null and main.run_scope.is_adventure
|
||||
if got != expect:
|
||||
_problems.append("%s:流程状态位 is_adventure 应为 %s,实测 %s" % [step, str(expect), str(got)])
|
||||
|
||||
|
||||
func _expect_exclusive(step: String, expect: String) -> void:
|
||||
# oracle: design/engineering/architecture/architecture.md:168 屏壳切换与呈现装配(屏级互斥组)
|
||||
var f: Dictionary = _screen_seals()
|
||||
var pairs := [["菜单", "营地"], ["菜单", "冒险"], ["营地", "冒险"], ["终局", "营地"], ["终局", "菜单"]]
|
||||
for pair in pairs:
|
||||
@@ -101,6 +103,7 @@ func _frames(n: int = 2) -> void:
|
||||
|
||||
# ---- ① boot:菜单独占 ----
|
||||
func _step_boot_menu() -> void:
|
||||
# oracle: design/engineering/test-conventions.md:49 调试面发布态恒隐、无 UI 开启口(boot 组)
|
||||
_expect_exclusive("①boot", "菜单")
|
||||
_expect_adventure_seal("①boot", false)
|
||||
if main.ui.modals.menu.debug_overlay != null and main.ui.modals.menu.debug_overlay.visible:
|
||||
@@ -109,6 +112,7 @@ func _step_boot_menu() -> void:
|
||||
|
||||
# ---- ② 菜单 → 营地(真实按钮信号路径)----
|
||||
func _step_menu_to_camp() -> void:
|
||||
# oracle: design/gdd/ux/camp.md:10 营地=存档内局外枢纽,存档语境可达(菜单→营地组)
|
||||
# 营地经进档开层(卡② mn9 新路径——campbtn 已撤;槽模板注入隔离命名空间)
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_camp"):
|
||||
_problems.append("②菜单→营地:选档层新档钮缺失(新路径驱动中断)")
|
||||
@@ -119,14 +123,15 @@ func _step_menu_to_camp() -> void:
|
||||
|
||||
# ---- ③ 营地 → 菜单(回退路径:篝火二次确认动线——卡④ 营地唯一回菜单出口;选档层随关层收闭同收)----
|
||||
func _step_camp_back_to_menu() -> void:
|
||||
# oracle: design/gdd/ux/camp.md:22 篝火=离开营地回主菜单、必须二次确认(营地→菜单组)
|
||||
if main.ui.modals.camp.scene == null:
|
||||
_problems.append("③营地→菜单:营地场景根句柄缺失〔句柄子容器批 V1〕")
|
||||
return
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"campfire")
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"campfire").get_center())
|
||||
await _frames()
|
||||
if not main.ui.modals.menu.confirm_dialog.visible:
|
||||
_problems.append("③篝火:二次确认弹窗未现(camp.md v2.2 必须先确认)〔营地图批 V7〕")
|
||||
main.ui.modals.menu.confirm_dialog.confirmed.emit() # 二次确认离场(confirmed 先于关层——卡④ T4)
|
||||
ProbeUiUtil.push_click(main, main.ui.modals.menu.confirm_dialog._confirm_btn) # 二次确认离场(confirmed 先于关层——卡④ T4)
|
||||
await _frames()
|
||||
_expect_exclusive("③营地→菜单(回退)", "菜单")
|
||||
|
||||
@@ -135,6 +140,7 @@ func _step_camp_back_to_menu() -> void:
|
||||
# ---- 选档界面开合(卡③ sl10):函数直调开层(「进入存档」钮归卡② mn3)→屏级互斥采样→
|
||||
# 返回钮真实信号路径关闭→ESC 语境不响应(卡⑤ 契约 2 范围外——零实现即断言)。----
|
||||
func _step_save_select_open_back() -> void:
|
||||
# oracle: design/gdd/systems/表现与支撑/存档序列化.md:61 激活态由选档界面的「新档」或「进档」建立(选档开合组)
|
||||
ProbeUiUtil.isolate_save(main, "smoke_screen_flow_savesel", false, false, true)
|
||||
main.save_manager.slots.attach_slot_template("user://smoke_screen_flow_savesel_slot_%d.json")
|
||||
var esb: Button = ProbeUiUtil.find_button(main.ui.screens.start_overlay, "进入存档", "prefix")
|
||||
@@ -150,7 +156,7 @@ func _step_save_select_open_back() -> void:
|
||||
if back_btn == null:
|
||||
_problems.append("[savesel] sl10 返回钮缺失(页壳顶条)")
|
||||
else:
|
||||
back_btn.pressed.emit()
|
||||
ProbeUiUtil.push_click(main, back_btn)
|
||||
await get_tree().process_frame
|
||||
if main.ui.modals.menu.save_select_overlay.visible or not main.ui.screens.start_overlay.visible:
|
||||
_problems.append("[savesel] sl10 返回后选档未隐藏或开始层未恢复(关闭链失守)")
|
||||
@@ -181,6 +187,7 @@ func seals_check_single(f: Dictionary) -> bool:
|
||||
|
||||
|
||||
func _step_menu_to_adventure() -> void:
|
||||
# oracle: design/gdd/ux/level-map.md:11 入口停点候选数=入口个数(菜单→冒险组)
|
||||
# 开始冒险钮已随三入口化撤出——函数直调中间态(卡② mn10;卡④ 大门两分支换代)
|
||||
main._start_adventure_from_menu()
|
||||
await _frames(3)
|
||||
@@ -194,6 +201,7 @@ func _step_menu_to_adventure() -> void:
|
||||
|
||||
# ---- ⑤ 冒险内屏切换:关卡地图屏 ⇄ 战斗屏(屏内两态,屏级仍独占)----
|
||||
func _step_level_to_battle_and_back() -> void:
|
||||
# oracle: design/gdd/ux/battle.md:57 Entry & Exit Points——进出战斗屏(冒险内切换组)
|
||||
if not main.ui.modals.run.level_screen.visible:
|
||||
_problems.append("⑤冒险内切换:前置不在关卡地图屏")
|
||||
return
|
||||
@@ -213,6 +221,7 @@ func _step_level_to_battle_and_back() -> void:
|
||||
|
||||
# ---- ⑥ 放弃 → 终局(放弃路径=回退路径的非正常出口)----
|
||||
func _step_abandon_to_end() -> void:
|
||||
# oracle: design/gdd/ux/level-map.md:42 放弃冒险(任意选路停点)→ 冒险落幕(放弃→终局组)
|
||||
if main.run_scope == null or main.run_scope.adventure == null:
|
||||
_problems.append("⑥放弃→终局:前置无冒险实例")
|
||||
return
|
||||
@@ -225,10 +234,11 @@ func _step_abandon_to_end() -> void:
|
||||
|
||||
# ---- ⑦ 终局 → 菜单(终局出口返回开始界面)----
|
||||
func _step_end_back_to_menu() -> void:
|
||||
# oracle: design/gdd/ux/settlement-summary.md:12 冒险总结结算=冒险落幕时终局覆盖层(终局→菜单组)
|
||||
if main.ui.modals.run.end_overlay == null or not main.ui.modals.run.end_overlay.visible:
|
||||
_problems.append("⑦终局→菜单:前置不在终局")
|
||||
return
|
||||
main.ui.modals.run.end_overlay.continue_pressed.emit()
|
||||
ProbeUiUtil.push_click(main, main.ui.modals.run.end_overlay._btn) # 真点继续钮(_btn 唯一钮——ui_click_probe:543 同源)
|
||||
await _frames(3)
|
||||
_expect_exclusive("⑦终局→菜单", "菜单")
|
||||
if main.run_scope != null and main.run_scope.is_adventure:
|
||||
@@ -237,6 +247,7 @@ func _step_end_back_to_menu() -> void:
|
||||
|
||||
# ---- ③' 营地 Esc 浮窗+HUD(卡⑤——真实键盘合成路径 push_input;四态路由+三出口+语境分支+余额单口)----
|
||||
func _step_camp_esc_and_hud() -> void:
|
||||
# oracle: design/gdd/ux/camp.md:45 ESC 优先序:有功能窗口先关最上层窗,无窗才进 ESC 浮窗(Esc 段组)
|
||||
ProbeUiUtil.isolate_save(main, "smoke_screen_flow_esc", false, false, true)
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_esc"):
|
||||
_problems.append("[esc] 营地入口缺失(选档层新档钮驱动中断)〔ESC批 V1〕")
|
||||
@@ -254,7 +265,7 @@ func _step_camp_esc_and_hud() -> void:
|
||||
await _frames()
|
||||
if main.ui.modals.camp.esc_overlay.visible:
|
||||
_problems.append("[esc] echo 事件唤起浮窗(触发沿 pressed 且非 echo 失守)〔ESC批 V1〕")
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"dummy") # 子界面开态
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"dummy").get_center()) # 子界面开态
|
||||
await _frames()
|
||||
_push_esc()
|
||||
await _frames()
|
||||
@@ -285,7 +296,7 @@ func _step_camp_esc_and_hud() -> void:
|
||||
if not main.ui.modals.camp.esc_overlay.visible or main.ui.screens.start_overlay.visible:
|
||||
_problems.append("[esc] 关设置后未回浮窗或回弹主菜单(契约 3 语境分支失守)〔ESC批 V4〕〔ESC批 B3〕")
|
||||
# 返回主菜单动线(契约 4——浮窗自收+营地隐+选档收+菜单显)
|
||||
main.ui.modals.camp.esc_overlay.return_requested.emit()
|
||||
ProbeUiUtil.push_click(main, main.ui.modals.camp.esc_overlay._return_btn) # 真点返回主菜单钮(camp_esc_overlay 底栏钮)
|
||||
await _frames()
|
||||
if main.ui.modals.camp.esc_overlay.visible or main.ui.modals.camp.scene.visible or main.ui.modals.menu.save_select_overlay.visible or not main.ui.screens.start_overlay.visible:
|
||||
_problems.append("[esc] 返回主菜单动线失守(浮窗自收/营地隐/选档收/菜单显)〔ESC批 V3〕〔ESC批 B3〕")
|
||||
@@ -300,6 +311,7 @@ func _step_camp_esc_and_hud() -> void:
|
||||
# 判的是呈现形态换壳(近全屏面板→居中定尺寸窗壳 720×640):窗几何/场景根留底/遮罩 0.6/关闭钮/
|
||||
# 互斥单开/ESC 优先序/窗内滚动/生涯同壳——行为面(开合路由)零改,只钉窗壳可观测提交面。
|
||||
func _step_camp_window_shell() -> void:
|
||||
# oracle: design/gdd/ux/camp.md:45 五功能窗统一窗壳、五窗互斥单开、各窗自带关闭钮(窗壳 V1–V8 组)
|
||||
ProbeUiUtil.isolate_save(main, "smoke_screen_flow_winshell", false, false, true)
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_winshell"):
|
||||
_problems.append("[winshell] 营地入口缺失(选档层新档钮驱动中断)〔窗口化批 V1〕")
|
||||
@@ -323,11 +335,11 @@ func _step_camp_window_shell() -> void:
|
||||
if prev_back == null:
|
||||
_problems.append("[winshell] %s 底栏「返回营地」钮缺失〔窗口化批 V4〕" % String(opened.back()))
|
||||
else:
|
||||
prev_back.pressed.emit()
|
||||
ProbeUiUtil.push_click(main, prev_back)
|
||||
await _frames()
|
||||
if prev.visible or not main.ui.modals.camp.scene.visible:
|
||||
_problems.append("[winshell] %s 关闭钮按下未隐窗或场景根失守〔窗口化批 V4〕" % String(opened.back()))
|
||||
main.ui.modals.camp.scene.object_pressed.emit(k)
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(k).get_center())
|
||||
await _frames()
|
||||
opened.append(k)
|
||||
var view: Control = views[k]
|
||||
@@ -362,7 +374,7 @@ func _step_camp_window_shell() -> void:
|
||||
if vis_n != 1:
|
||||
_problems.append("[winshell] %s 开态五窗 visible 计数=%d 应=1(互斥单开失守)〔窗口化批 V5〕" % [String(k), vis_n])
|
||||
# 树窗点选遮挡(V5b——树窗开态向锻炉命中区推真实鼠标点:被遮罩挡=零新窗零响应)
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"dummy")
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"dummy") # 前提注入(保留 emit):V5b 被测面=窗开态遮罩挡场景点选——真点击会被遮罩吞掉,树窗开态只能信号注入建立
|
||||
await _frames()
|
||||
var tree_view: Control = views[&"dummy"]
|
||||
if not tree_view.visible:
|
||||
@@ -383,7 +395,7 @@ func _step_camp_window_shell() -> void:
|
||||
# 随栈 close 恢复语义逐层清账,V6/V8 从干净单窗态起步)
|
||||
await _close_all_windows(views)
|
||||
# V6 ESC 先关窗(生涯窗开态 Esc→关生涯窗、浮窗不唤起)
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"notebook")
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"notebook").get_center())
|
||||
await _frames()
|
||||
if not career.visible:
|
||||
_problems.append("[winshell] 生涯窗未开(V6 前置中断)〔窗口化批 V6〕")
|
||||
@@ -395,7 +407,7 @@ func _step_camp_window_shell() -> void:
|
||||
if main.ui.modals.camp.esc_overlay.visible:
|
||||
_problems.append("[winshell] 关窗同拍唤起浮窗(应无窗才进浮窗)〔窗口化批 V6〕")
|
||||
# V7 内容超高窗内滚动(树窗+真实投影喂加长行册)
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"dummy")
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"dummy").get_center())
|
||||
await _frames()
|
||||
if not tree_view.visible:
|
||||
_problems.append("[winshell] 树窗未开(V7 前置中断)〔窗口化批 V7〕")
|
||||
@@ -420,7 +432,7 @@ func _step_camp_window_shell() -> void:
|
||||
# 清窗经真实钮(同 V6 前置——干净单窗态起步)
|
||||
await _close_all_windows(views)
|
||||
# V8 生涯同壳(窗板同几何+返回钮在位+内容列滚动面在)
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"notebook")
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"notebook").get_center())
|
||||
await _frames()
|
||||
if not career.visible:
|
||||
_problems.append("[winshell] 生涯窗未开(V8 前置中断)〔窗口化批 V8〕")
|
||||
@@ -445,7 +457,7 @@ func _step_camp_window_shell() -> void:
|
||||
# 段尾收闭:生涯窗经真实「返回」钮关闭(on_camp_closed 关闭名单不含生涯窗——防残留泄段)
|
||||
var career_back: Button = ProbeUiUtil.find_button(career, "返回", "prefix")
|
||||
if career_back != null:
|
||||
career_back.pressed.emit()
|
||||
ProbeUiUtil.push_click(main, career_back)
|
||||
await _frames()
|
||||
if career.visible:
|
||||
_problems.append("[winshell] 生涯「返回」钮未隐窗〔窗口化批 V4〕")
|
||||
@@ -455,6 +467,7 @@ func _step_camp_window_shell() -> void:
|
||||
|
||||
# 清窗经真实钮(逐窗巡检 visible→钮 pressed——栈 close 恢复账随层清空)
|
||||
func _close_all_windows(views: Dictionary) -> void:
|
||||
# oracle: design/gdd/ux/camp.md:45 各窗自带关闭钮(清窗组)
|
||||
for k: StringName in [&"forge", &"chest", &"dummy", &"board"]:
|
||||
var w: Control = views[k]
|
||||
if not w.visible:
|
||||
@@ -463,7 +476,7 @@ func _close_all_windows(views: Dictionary) -> void:
|
||||
if back == null:
|
||||
_problems.append("[winshell] %s 底栏「返回营地」钮缺失〔窗口化批 V4〕" % String(k))
|
||||
continue
|
||||
back.pressed.emit()
|
||||
ProbeUiUtil.push_click(main, back)
|
||||
await _frames()
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user