修复: 卡①T1——渲染闸 tools/render_gate.sh 落码+shot_probe 扩屏七屏(设置面/生涯页/暂停层真实信号路径入屏,商店房考证不可达注记留 B 批)+board_shot_probe 取证三件套(headless 护栏/空纹理 fail/board_meta.json 取样坐标落盘)+golden_board_crop/golden_baseline_refresh 两辅助件;隔离档即时 apply 修正(真实档 fullscreen 态污染抓帧尺寸 2304x1440≠1280 基准档——探针侧环境修正零运行时 diff);取证段失败语义=闸红(Q7)

This commit is contained in:
DKChan committed 2026-10-08 19:19:22 +08:00
1 parent 4c171fc509
commit 3d04432f7a
6 files changed
+349 -6

No files matched your search

+20
View File
@@ -4,12 +4,22 @@
# Godot_console.exe --path . res://smoke/board_shot_probe.tscn -- <输出目录>
# 流程:L1/L2/L3 各起一板(真实 LevelRunner+settle_batch 驱动 ~18 步 novice——自然揭示数字/旗),
# BoardView 真渲染,frame_post_draw 同步后抓视口 PNG。零存档触碰(无 save_manager 引用)。
# 迭代 19 卡① T1/T2(2026-10-08):①headless fail-fast 护栏(shot_probe 同款);
# ②空纹理取证 fail(Q7——取证段失败=闸红,零字节/空纹理不允许静默落盘);
# ③board_meta.json 取样坐标落盘(棋盘视图全局矩形——golden 前置裁剪坐标源,禁硬编码像素)。
extends Node
const AutoPlayer := preload("res://smoke/auto_player.gd")
var _meta := {} # 棋盘视图实测几何(全局 rect——tools/golden_board_crop.py 取样坐标源)
func _ready() -> void:
# 运行前提=窗口化真渲染面(shot_probe 同款护栏——headless 下 frame_post_draw 永不触发+视口纹理恒空)
if DisplayServer.get_name() == "headless":
print("[board_shot] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空);正主=tools/render_gate.sh 取证段")
get_tree().quit(1)
return
var args := OS.get_cmdline_user_args()
var out := args[0] if args.size() >= 1 and args[0] != "" else "user://board-shots"
DirAccess.make_dir_recursive_absolute(out)
@@ -53,10 +63,20 @@ func _ready() -> void:
await get_tree().process_frame
await RenderingServer.frame_post_draw
var img := get_viewport().get_texture().get_image()
if img == null or img.is_empty():
push_error("[board_shot] FAIL — 抓帧空纹理: %s(Q7 取证语义=闸红)" % tag)
get_tree().quit(1)
return
var path := "%s/board_%s.png" % [out, tag]
img.save_png(path)
_meta[tag] = {"x": view.global_position.x, "y": view.global_position.y,
"w": view.size.x, "h": view.size.y}
print("[board_shot] saved %s (%dx%d)" % [path, img.get_width(), img.get_height()])
view.queue_free()
await get_tree().process_frame
var mf := FileAccess.open(out.path_join("board_meta.json"), FileAccess.WRITE)
if mf != null:
mf.store_string(JSON.stringify(_meta))
mf.close()
print("[board_shot] done")
get_tree().quit(0)
+2
View File
@@ -29,6 +29,8 @@ func _ready() -> void:
add_child(main)
await get_tree().process_frame
ProbeUiUtil.isolate_save(main, "fx_shot_probe", false, true, false)
# 隔离档即时应用(迭代 19 卡① T1——真实档 fullscreen 态会污染抓帧尺寸〔shot_probe 同款修正〕)
main.settings_store.apply()
for i in 8:
await get_tree().process_frame # UI 装配完成等足帧(canvas_item 空引用窗口)
var lvbtn: Button = ProbeUiUtil.find_button(main._start_overlay, "开始冒险", "contains")
+77 -6
View File
@@ -1,12 +1,17 @@
# VERTICAL SLICE - NOT FOR PRODUCTION
# 整屏截图探针(迭代 9 卡⑰a 2026-09-30——呈现层测试分级 B 档基建:四屏视口截图程序化产出)。
# 整屏截图探针(迭代 9 卡⑰a 2026-09-30——呈现层测试分级 B 档基建:视口截图程序化产出;
# 迭代 19 卡① T1 2026-10-08 扩屏四屏→七屏——新纳 设置面/生涯页/暂停层,正主=tools/render_gate.sh)。
# 必须**窗口化**运行(真渲染设备——headless 无渲染面,get_image 得到空纹理):
# Godot_console.exe --path . res://smoke/shot_probe.tscn -- <输出目录>
# 流程 = 真实按钮信号路径驱动(ui_click_probe 同款;存档/设置/元进度三面换注隔离档——禁碰真实档,
# 坑册「断点写盘随 save_manager 引用走」教训同款覆盖):菜单(启动态)→ 营地(campbtn)→
# 关卡画面(lvbtn→停点出图)→ 战斗(level_screen.press_candidate(0) 真实选路提交)。
# 坑册「断点写盘随 save_manager 引用走」教训同款覆盖):菜单(启动态)→ 设置面(settingsbtn
# 真实信号路径)→ 生涯页(careerbtn 同款)→ 营地(campbtn)→ 关卡画面(lvbtn→停点出图)→
# 战斗(level_screen.press_candidate(0) 真实选路提交)→ 暂停层(地图屏暂停角标真实信号路径)。
# 每屏双帧 + frame_post_draw 同步后抓 get_viewport().get_texture(),PNG 落输出目录;
# 最小自检 = 四件存在且非零字节(像素方差断言归 tools/shot_checker.py——B 档骨架分工)。
# 最小自检 = 七件存在且非零字节(像素方差断言归 tools/shot_checker.py——B 档骨架分工)。
# 商店房注记(迭代 19 卡① T1 考证结论,代拍板白名单授权):真实路径必经 L1 打穿→L2 商店节点
# 选路(ui_click_probe 实证商店层在 L2 Boss 前必经位)——探针现行驱动只进首战节点,低代价确定性
# 到达不成立;合成投喂(ui_struct_probe 同款)破坏本探针真实路径口径 → 不纳屏,注记留 B 批。
extends Node
const ProbeUiUtil := preload("res://smoke/probe_ui_util.gd") # T6 收口:树寻址/隔离样板单点
@@ -32,12 +37,57 @@ func _ready() -> void:
await get_tree().process_frame
# ── 存档/元进度/设置三面隔离(ui_click_probe 同款——真档零污染;历史语义 = contains 寻址) ──
ProbeUiUtil.isolate_save(main, "smoke_shot_probe", false, true, false)
# 隔离档即时应用(迭代 19 卡① T1——main 装配已按真实设置恢复过窗口态〔本机实测:真实档
# fullscreen=true 时窗口进全屏,视口纹理 2304x1440≠1280 基准档,checker 尺寸/取样全盘失真〕;
# apply 隔离档出厂默认=窗口化 1280x800,恢复本探针设计前提。探针侧环境修正,零运行时改动)
main.settings_store.apply()
await get_tree().process_frame
# ① 菜单(启动态)
_meta["menu_sub"] = ProbeUiUtil.label_rect(main._start_overlay, "改造批")
_meta["menu_help"] = ProbeUiUtil.label_rect(main._start_overlay, "玩法:")
_meta["menu_title"] = ProbeUiUtil.label_rect(main._start_overlay, "Dungeon Sweeper")
await _snap("menu")
# ①b 设置面(迭代 19 卡① T1 扩屏——settingsbtn 真实信号路径,开合同款真实钮)
var setbtn: Button = ProbeUiUtil.find_button(main._start_overlay, "设置", "prefix")
if setbtn == null:
_problems.append("设置入口缺失(开始层 settingsbtn)")
else:
setbtn.pressed.emit()
for i in 3:
await get_tree().process_frame
if not main.settings_overlay.visible:
_problems.append("设置面未打开(settingsbtn 路径)")
else:
_meta["settings_title"] = ProbeUiUtil.label_rect(main.settings_overlay, "设置")
await _snap("settings")
var set_close: Button = ProbeUiUtil.find_button(main.settings_overlay, "返回", "prefix")
if set_close == null:
_problems.append("设置面返回钮缺失")
else:
set_close.pressed.emit()
await get_tree().process_frame
# ①c 生涯页(迭代 19 卡① T1 扩屏——careerbtn 真实信号路径,ui_struct_probe 同款入口链)
var careerbtn: Button = ProbeUiUtil.find_button(main._start_overlay, "生涯", "prefix")
if careerbtn == null:
_problems.append("生涯入口缺失(开始层 careerbtn)")
else:
careerbtn.pressed.emit()
for i in 3:
await get_tree().process_frame
if not main.career_overlay.visible or main._start_overlay.visible:
_problems.append("生涯页未打开或开始层未隐藏(careerbtn 路径)")
else:
_meta["career_title"] = ProbeUiUtil.label_rect(main.career_overlay, "生 涯")
await _snap("career")
var career_close: Button = ProbeUiUtil.find_button(main.career_overlay, "返回", "prefix")
if career_close == null:
_problems.append("生涯页返回钮缺失")
else:
career_close.pressed.emit()
for i in 3:
await get_tree().process_frame
if main.career_overlay.visible or not main._start_overlay.visible:
_problems.append("生涯页关闭后页未隐藏或开始层未恢复")
# ② 营地
var campbtn: Button = ProbeUiUtil.find_button(main._start_overlay, "营地", "contains")
if campbtn == null:
@@ -84,6 +134,27 @@ func _ready() -> void:
var dc := int(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME))
_meta["battle_draw_calls"] = dc
print("[shot_probe] battle draw_calls=%d(基线 270/目标 <200)" % dc)
# ⑤ 暂停层(迭代 19 卡① T1 扩屏——战斗屏暂停角标真实信号路径;层在战斗屏之上开合)
var pb: Button = main.board_zone.pause_badge
if pb == null or not pb.visible or pb.disabled:
_problems.append("暂停入口角标缺失/置灰(战斗屏 board_zone)")
else:
pb.pressed.emit()
for i in 3:
await get_tree().process_frame
if not main.pause_overlay.visible:
_problems.append("暂停层未打开(角标路径)")
else:
_meta["pause_title"] = ProbeUiUtil.label_rect(main.pause_overlay, "暂停")
await _snap("pause")
var pause_close: Button = ProbeUiUtil.find_button(main.pause_overlay, "继续", "prefix")
if pause_close == null:
_problems.append("暂停层继续钮缺失")
else:
pause_close.pressed.emit()
await get_tree().process_frame
if main.pause_overlay.visible:
_problems.append("暂停层关闭后未隐藏(继续钮路径)")
else:
_problems.append("关卡画面未出现(lvbtn 路径)")
# ── 几何元数据落盘(shot_checker 取样坐标源) ──
@@ -91,8 +162,8 @@ func _ready() -> void:
if mf != null:
mf.store_string(JSON.stringify(_meta))
mf.close()
# ── 最小自检:四件存在且非零字节 ──
for s in ["menu", "camp", "level", "battle"]:
# ── 最小自检:七件存在且非零字节(迭代 19 卡① T1 扩屏后口径) ──
for s in ["menu", "settings", "career", "camp", "level", "battle", "pause"]:
var p := out_dir.path_join("shot_%s.png" % s)
if not FileAccess.file_exists(p):
_problems.append("截图缺失: %s" % p)