From 5e6cec8353b0535af3a46bfd4c0114e88fc25ca8 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 06:31:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E7=A8=8B(=E7=9C=9F=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E5=8C=966/7=C2=B7ui=5Fstruct=5Fprobe):=204=E5=A4=84emit?= =?UTF-8?q?=E2=86=92=E7=9C=9F=E8=BE=93=E5=85=A5(=E9=94=BB=E7=82=89/?= =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=3D=E5=9C=BA=E6=99=AF=E5=91=BD?= =?UTF-8?q?=E4=B8=AD=E5=8C=BA=E7=9C=9F=E7=82=B9,forge=E5=85=B3=E7=AA=97=3D?= =?UTF-8?q?=E7=9C=9F=E7=82=B9=E8=BF=94=E5=9B=9E=E8=90=A5=E5=9C=B0=E9=92=AE?= =?UTF-8?q?,gate=3D=E6=8C=89=E4=B8=8B=E5=9C=A8=E5=91=BD=E4=B8=AD=E5=8C=BA+?= =?UTF-8?q?=E6=8A=AC=E6=9D=86=E7=A6=BB=E5=9C=BA=E9=98=B2=E8=AF=AF=E8=A7=A6?= =?UTF-8?q?=E7=A1=AE=E8=AE=A4=E2=80=94=E2=80=94=E5=9C=BA=E6=99=AF=E5=91=BD?= =?UTF-8?q?=E4=B8=AD=E6=B2=BF=3D=E6=8A=AC=E6=9D=86,=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E9=9A=8F=E6=8A=AC=E6=9D=86=E5=90=8C=E5=B8=A7=E5=BC=80,?= =?UTF-8?q?=E6=8A=AC=E6=9D=86=E8=90=BD=E5=8E=9F=E4=BD=8D=E7=BB=8F=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E4=BC=A0=E6=92=AD=E8=AF=AF=E8=A7=A6=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E9=92=AE=E5=AE=9E=E8=AF=81=E5=86=92=E9=99=A9=E8=AF=AF=E5=90=AF?= =?UTF-8?q?,=E6=8A=AC=E6=9D=86=E8=90=BD(2,2)=E4=B8=AD=E6=80=A7=E7=82=B9);?= =?UTF-8?q?=202=E5=A4=84=E4=BF=9D=E7=95=99emit+=E5=89=8D=E6=8F=90=E6=B3=A8?= =?UTF-8?q?=E8=AE=B0(route=E9=80=89=E8=B7=AF/=E5=9B=BE=E4=BE=8B=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E2=80=94=E2=80=94emit=E9=80=89=E8=B7=AF=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E4=B8=8Bbattle=5Froot=E6=9C=AA=E5=8F=8A=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E4=B8=94=E9=94=81=E5=9C=A8,=E7=9C=9F=E7=82=B9?= =?UTF-8?q?=E4=B8=8D=E5=8F=AF=E8=BE=BE);=20=E5=88=A4=E6=8D=AE=E5=87=BA?= =?UTF-8?q?=E5=A4=84=E6=B3=A8=E8=AE=B09=E6=9D=A1(camp.md:10/19/45+level-ma?= =?UTF-8?q?p:3+battle.md:154+HUD=E6=A1=86=E6=9E=B6:88+code-conventions:54/?= =?UTF-8?q?21=C3=972+=E5=AD=98=E6=A1=A3=E5=BA=8F=E5=88=97=E5=8C=96:61+arch?= =?UTF-8?q?itecture:168);=20=E6=9C=AC=E6=89=B9=E5=8F=91=E7=8E=B0=E8=AE=B0?= =?UTF-8?q?=E8=B4=A6:=20=E2=91=A0route=E4=BF=A1=E5=8F=B7=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E5=B1=8F=E5=B9=95=E5=88=87=E6=8D=A2=E6=97=B6=E5=BA=8F=E2=80=94?= =?UTF-8?q?=E2=80=94emit=E5=90=8Ebattle=5Froot=E6=8C=81=E7=BB=AD=E4=B8=8D?= =?UTF-8?q?=E6=98=BE=E7=A4=BA,battle=5Fhud=E5=AE=A1=E8=AE=A1=E9=95=BF?= =?UTF-8?q?=E6=9C=9F=E7=A9=BA=E8=BD=AC=E9=87=87=E6=A0=B7(=E5=81=87?= =?UTF-8?q?=E7=BB=BF=E9=9D=A2)=20=E2=91=A1=E7=9C=9F=E7=82=B9=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E9=87=87=E6=A0=B7=E5=8F=98=E5=AE=9E=E6=9A=B4=E9=9C=B2?= =?UTF-8?q?=E5=81=9C=E6=89=8B(64)/=E5=9B=BE=E4=BE=8B(56)=E5=90=8C=E5=AE=B9?= =?UTF-8?q?=E5=99=A8=E5=AE=BD=E5=BA=A6=E4=B8=8D=E7=AD=89(=E5=9C=A8?= =?UTF-8?q?=E5=86=8Cequal=5Fwidth=E7=BA=AA=E5=BE=8B=E5=BF=85=E7=BA=A2)=20?= =?UTF-8?q?=E2=91=A2=E5=9B=BE=E4=BE=8B=E5=BC=80=E5=90=AF=E7=9C=9F=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E6=89=BF=E8=BD=BD=E5=BE=85=E2=91=A0=E8=A3=81=E5=86=B3?= =?UTF-8?q?=E5=90=8E=E8=A1=A5=E2=80=94=E2=80=94=E4=B8=89=E9=A1=B9=E5=BE=85?= =?UTF-8?q?=E8=A3=81=E6=94=B6=E5=B0=BE=E5=91=88=E6=8A=A5;=20=E6=9C=AC?= =?UTF-8?q?=E6=AD=A5=E5=87=AD=E6=8D=AE:=20ui=5Fstruct=5Fprobe=20headless?= =?UTF-8?q?=E7=9B=B4=E8=B7=91PASS=20exit=3D0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/probe/ui_struct_probe.gd | 39 ++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/game/probe/ui_struct_probe.gd b/game/probe/ui_struct_probe.gd index e69662fb..d15fe3f5 100644 --- a/game/probe/ui_struct_probe.gd +++ b/game/probe/ui_struct_probe.gd @@ -68,7 +68,7 @@ func _ready() -> void: problems.append("[camp] 场景子节点序≠layout 表 z 序(逐层相等失守)〔营地图批 V1〕") if not rect_ok: problems.append("[camp] 层贴图矩形≠layout 表(逐值一致失守)〔营地图批 V1〕") - main.ui.modals.camp.scene.object_pressed.emit(&"forge") + ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"forge").get_center()) _settle() if not main.ui.modals.camp.forge.visible: problems.append("[camp] 点选锻炉→锻造子界面未开(场景点选路由中断)〔营地图批 V2〕") @@ -81,7 +81,7 @@ func _ready() -> void: scene_buttons += 1 if scene_buttons != 0: problems.append("[camp] 场景根态存在文字按钮(反参照纪律——禁文字按钮列表形态)〔营地图批 V9〕") - main.ui.modals.camp.forge.closed.emit() + ProbeUiUtil.push_click(main, ProbeUiUtil.find_button(main.ui.modals.camp.forge, "返回营地")) _settle() main._on_camp_closed() # 关层收闭(营地与选档层同收+开始层恢复——卡④ T3) _settle() @@ -89,10 +89,11 @@ func _ready() -> void: # ---- 生涯页:入口=帐篷旁笔记本(卡④ T3 改挂——场景点选信号真实路由→组合根 _open_career)→ # 结构断言族→只读巡检(契约 3)+零动效契约+零跳转契约(提纲 P4 甲)→组合根真实路径关闭。 #(登记序/树序契约统一在全模态 _modal_registry_contract——boot 段跑)---- + # oracle: design/gdd/ux/camp.md:19 帐篷旁笔记本→生涯记录;生涯页返回钮口径由结构校验兜底(生涯段) # 营地语境:开始层全程隐藏(笔记本入口在营地场景根——关生涯回营地不回开始层,卡④ T3 语境分支) main._camp_pres.open_camp() # 重开营地场景根(笔记本入口语境) _settle() - 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()) _settle() if not main.ui.modals.menu.career_overlay.visible or main.ui.screens.start_overlay.visible: problems.append("[career] 生涯页未打开或开始层未隐藏(笔记本改挂路径断裂)〔营地图批 V5〕") @@ -105,11 +106,26 @@ func _ready() -> void: if main.ui.modals.menu.career_overlay.visible or main.ui.screens.start_overlay.visible: problems.append("[career] 关闭后页未隐藏或开始层回弹(营地语境分支失守)〔营地图批 V5〕") # ---- Esc 浮窗结构段(卡⑤——三钮在位且仅三+零动效契约+登记序在册+debug_badge 不波及)---- + # oracle: design/gdd/ux/camp.md:45 ESC 优先序:有窗先关最上层窗、无窗才进浮窗;各窗自带关闭钮(Esc 段) main._camp_pres.open_camp() _settle() - main.ui.modals.camp.scene.object_pressed.emit(&"gate") + var gpos_gate: Vector2 = main.ui.modals.camp.scene.get_hotspot_rect(&"gate").get_center() + var gdown := InputEventMouseButton.new() + gdown.button_index = MOUSE_BUTTON_LEFT + gdown.pressed = true + gdown.position = gpos_gate + gdown.global_position = gpos_gate + main.get_viewport().push_input(gdown, true) # 按下在 gate 命中区 + await get_tree().process_frame + await get_tree().process_frame + var gup := InputEventMouseButton.new() + gup.button_index = MOUSE_BUTTON_LEFT + gup.pressed = false + gup.position = Vector2(2, 2) # 抬杆落点避开弹窗钮域——场景命中沿=抬杆,弹窗随抬杆同帧开;抬杆落原位会经事件传播误触确认钮(实证:冒险误启)。抬杆离场=不经历弹窗开关,段断言(Esc 路由)在净态成立 + gup.global_position = Vector2(2, 2) + main.get_viewport().push_input(gup, true) _settle() - main.ui.modals.menu.confirm_dialog.cancelled.emit() # 关大门弹窗(清场——浮窗段前提) + ProbeUiUtil.push_click(main, main.ui.modals.menu.confirm_dialog._cancel_btn) # 关大门弹窗(清场——浮窗段前提;无弹窗态=无害空点) _settle() var push_esc := func() -> void: var ev := InputEventKey.new() @@ -197,6 +213,7 @@ func _ready() -> void: _settle() # ---- 冒险簇(真流推进:开冒险→地图选路态→选战斗节点→战斗 HUD)---- + # oracle: design/gdd/ux/level-map.md:3 图上点击选路·候选按钮退役(冒险簇选路真点组) ProbeUiUtil.isolate_save(main, "smoke_ui_struct_probe_adv", true, false, true) main.ui.modals.menu.debug_overlay.seed_edit.text = "42" # 种子钉死(种子框默认为空=非首局随机,结构采样确定性禁依赖默认分支) main._start_adventure_from_menu() @@ -205,7 +222,7 @@ func _ready() -> void: var battle_id := _pick_battle_node(main) if battle_id >= 0: - main.ui.modals.run.level_screen.route_chosen.emit(battle_id) + main.ui.modals.run.level_screen.route_chosen.emit(battle_id) # 前提注入(保留 emit):本段被测面=战斗 HUD 结构审计,选路机制非其判据面——图上命中真入口由 ui_input_probe case⑫ 承载。附发现呈报:emit 路径下审计采样时 battle_root 尚未显示(审计长期空转采样);真点路径采样变实后暴露停手(64)/图例(56)同容器宽度不等——两项均待裁(收尾呈报) _settle(6) _audit("battle_hud", [main.ui.battle.board_zone, main.ui.battle.info_panel, main.ui.battle.stage]) _standeefit_contract(main) @@ -226,7 +243,8 @@ func _ready() -> void: # ---- 图例层(旧模态、首过结构族):ap_bar legend_toggled # 信号真路径开(board_zone 信号→组合根 _on_legend_toggled→_open_modal)→结构断言族→ # closed 信号真路径关(close()→组合根 _on_modal_closed)。 - main.ui.battle.board_zone.legend_toggled.emit() + # oracle: design/gdd/systems/表现与支撑/HUD框架.md:88 图例面板=模态族:统一登记序栈、入栈出栈、关闭逐层恢复(图例组) + main.ui.battle.board_zone.ap_bar._btn_legend.pressed.emit() # 前提注入(保留 emit):emit 选路路径下 battle_root 未及显示且输入锁在(实证在案),真点不可达——图例开启的真输入承载随「route 信号路径屏幕切换时序」发现一并呈报待裁 _settle() if not main.ui.modals.run.legend_overlay.visible: problems.append("[legend] 图例层未打开(legend_toggled 路径中断)") @@ -388,6 +406,7 @@ const _PAUSE_READONLY_SIGNALS: Array[String] = [ func _status_readonly_contract(main: Node) -> void: + # oracle: design/engineering/code-conventions.md:21 视图零核心写调用、依赖单向(status 只读巡检组) var overlay: Control = main.ui.modals.run.status_panel var stack: Array = [overlay] var conn_count := 0 @@ -434,6 +453,7 @@ func _status_zero_motion_contract(main: Node) -> void: # 清单外零连接。白名单={视图自身 _emit_closed〔返回钮〕, 组合根 _on_career_closed};页内任何 # 购买/导航/写入方向的新连接一律红,须先入册审查。 func _career_readonly_contract(main: Node) -> void: + # oracle: design/engineering/code-conventions.md:21 视图零核心写调用、依赖单向(career 只读巡检组) var overlay: Control = main.ui.modals.menu.career_overlay var stack: Array = [overlay] var conn_count := 0 @@ -480,6 +500,7 @@ func _career_zero_motion_contract(main: Node) -> void: # _career_registry_contract 的断言(career=状态面板后/确认弹窗前、树序同步)由本全量合同覆盖) # ⑭选档界面契约(卡③ sl1/sl2/sl3/sl4/sl9——呈现面全部来自喂入数据,视图零自判) func _save_select_contract(main: Node, tpl: String) -> void: + # oracle: design/gdd/systems/表现与支撑/存档序列化.md:61 三存档位独立文件、激活态由选档界面建立(选档契约组) var sso: Node = main.ui.modals.menu.save_select_overlay # sl1 三槽呈现:槽卡计数==3+零滚动容器(禁滚动长列表形态——契约 1) var rows: VBoxContainer = sso._rows_box @@ -559,6 +580,7 @@ func _collect_labels(node: Node, out: Array[String]) -> void: func _modal_registry_contract(main: Node) -> void: + # oracle: design/engineering/code-conventions.md:54 模态覆盖层层级规则——新增覆盖层必须登记 z 序位置(登记序契约组) var list: Array = main.ui.flow.stack._list # ① 登记册序==合同模态序(逐位点名——合同是登记序唯一事实源) var contract_modals: Array = [] @@ -626,6 +648,7 @@ func _modal_registry_contract(main: Node) -> void: # ⑬career 零跳转契约(提纲 P4 甲——页内零「前往他处」入口:除「返回」外任何导航钮=红) func _career_nojump_contract(main: Node) -> void: + # oracle: design/gdd/ux/camp.md:19 生涯记录入口与返回钮口径由结构校验兜底——页内零导航入口(零跳转契约组) for nav in ["营地", "商店", "设置", "冒险", "继续上局", "退出", "前往"]: if ProbeUiUtil.find_button(main.ui.modals.menu.career_overlay, nav, "contains") != null: problems.append("[career][nojump] 页内出现导航入口「%s」(零跳转违约——生涯纯只读)" % nav) @@ -635,6 +658,7 @@ func _career_nojump_contract(main: Node) -> void: # (名行基线离盒底 1px 同型高危写法返修回归闸; # 内容矩形=StandeeBody.content_rect(),最低绘制元素=底座下缘) func _standeefit_contract(main: Node) -> void: + # oracle: design/gdd/ux/battle.md:154 主角站桩立绘(无框立绘+落影)——站桩内容矩形⊆舞台(站桩适配组) var st: Node = main.ui.battle.stage if st == null or st.hero_standee == null: problems.append("[standee] 舞台/主角站桩缺失(断言中断)") @@ -719,6 +743,7 @@ func _in_scroll(c: Control) -> bool: func _audit(screen: String, roots: Array) -> void: + # oracle: design/engineering/architecture/architecture.md:168 组合根交接面与呈现装配——屏结构审计宿主面(结构审计组) for r in roots: if r != null and is_instance_valid(r): _force_layout(r)