162 lines
6.4 KiB
GDScript
162 lines
6.4 KiB
GDScript
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||
# 全屏 UI 审计截图探针(2026-10-06 用户令——实机每一屏 vs demo v2.1 逐屏对比;shot_probe 十二屏扩展形)。
|
||
# 必须**窗口化**运行(真渲染面;headless 守卫同 shot_probe):
|
||
# Godot_console.exe --path . res://smoke/ui_audit_probe.tscn -- <输出目录>
|
||
# 覆盖 = demo 八映射屏(start/camp/settings/map/battle/bonus/shop/end 胜败两态)+ demo 无映射三屏
|
||
# (legend 图例/confirm 确认框/debug 调试浮窗)。真实信号路径驱动 + 合成面开窗(ui_struct_probe 同款
|
||
# 真实 open API+拟真数据);双帧 frame_post_draw 同步抓视口纹理。
|
||
extends Node
|
||
|
||
const ProbeUiUtil := preload("res://smoke/probe_ui_util.gd")
|
||
const Narrator := preload("res://presentation/battle_narrator.gd")
|
||
|
||
var main: Node
|
||
var out_dir := ""
|
||
var _problems: Array = []
|
||
|
||
|
||
func _ready() -> void:
|
||
if DisplayServer.get_name() == "headless":
|
||
print("[ui_audit] FAIL — 本探针必须窗口化运行(headless 无渲染面)")
|
||
get_tree().quit(1)
|
||
return
|
||
var args := OS.get_cmdline_user_args()
|
||
out_dir = args[0] if args.size() >= 1 and args[0] != "" else "user://ui-audit"
|
||
DirAccess.make_dir_recursive_absolute(out_dir)
|
||
await get_tree().process_frame
|
||
main = load("res://presentation/main.tscn").instantiate()
|
||
add_child(main)
|
||
await get_tree().process_frame
|
||
ProbeUiUtil.isolate_save(main, "smoke_ui_audit", true, true, false)
|
||
await get_tree().process_frame
|
||
# 断点种子(2026-10-06 判官 checkpoint——demo 标题屏=有档态「继续上局」主钮亮出;无种子=
|
||
# 续玩钮隐藏,主操作语义对齐⑤无从呈现。最小合法断点快照;后续「开始冒险」流程自然覆盖)
|
||
main.save_manager.set_breakpoint({
|
||
"master_seed": 42, "rng_counter": 0, "hero_hp": 20, "gp": 24, "keystone": 4,
|
||
"level_index": 1, "bonus": {}, "shop_purchased": {}, "relics": [],
|
||
"bonus_aux_carry": [], "keystone_drops": [], "bonus_taken": {},
|
||
})
|
||
main._refresh_resume_button()
|
||
await get_tree().process_frame
|
||
|
||
# 1 标题屏(启动态=有档态)
|
||
await _snap("1_start")
|
||
# 2 调试浮窗(P3 仅开始菜单可开——趁 _level_active=false 先截)
|
||
main._show_debug_overlay()
|
||
await _settle()
|
||
await _snap("9_debug")
|
||
main._close_debug_overlay()
|
||
await _settle()
|
||
# 3 设置
|
||
main._open_settings()
|
||
await _settle()
|
||
await _snap("3_settings")
|
||
main._on_settings_closed()
|
||
await _settle()
|
||
# 4 营地
|
||
var campbtn: Button = ProbeUiUtil.find_button(main._start_overlay, "营地", "contains")
|
||
if campbtn != null:
|
||
campbtn.pressed.emit()
|
||
await _settle()
|
||
await _snap("2_camp")
|
||
var close_btn: Button = ProbeUiUtil.find_button(main.camp_overlay, "关闭营地", "contains")
|
||
if close_btn != null:
|
||
close_btn.pressed.emit()
|
||
await _settle()
|
||
# 5 关卡地图(开始冒险→停点出图)
|
||
# 收种子断点(有断点时「开始冒险」=清档确认互斥弹窗——不收则断流,5_battle 截不上)
|
||
main.save_manager.clear_breakpoint()
|
||
main._refresh_resume_button()
|
||
await get_tree().process_frame
|
||
var lvbtn: Button = ProbeUiUtil.find_button(main._start_overlay, "开始冒险", "contains")
|
||
if lvbtn != null:
|
||
lvbtn.pressed.emit()
|
||
for i in 4:
|
||
await get_tree().process_frame
|
||
await _settle()
|
||
await _snap("4_map")
|
||
# 6 战斗(真实选路提交)
|
||
if main.level_screen != null and main.level_screen.visible:
|
||
main.level_screen.press_candidate(0)
|
||
for i in 10:
|
||
await get_tree().process_frame
|
||
await _settle()
|
||
await _snap("5_battle")
|
||
# 7 战斗结算·胜利(真实签名的拟真载荷——main.gd:697 同序)
|
||
main._end_overlay.open_victory(Narrator.battle_end_text("victory", true), "返回",
|
||
main.board_view.get_global_rect(), "战利品 GP +5 · 合计 24",
|
||
"钥石 · 累计 27", "本关加成:攻击 +1", 5, 24)
|
||
await _settle()
|
||
await _snap("8_end_victory")
|
||
main._end_overlay.close()
|
||
await _settle()
|
||
# 8 战斗结算·失败
|
||
main._end_overlay.open_defeat(Narrator.battle_end_text("defeat", false), "返回",
|
||
main.board_view.get_global_rect())
|
||
await _settle()
|
||
await _snap("8_end_defeat")
|
||
main._end_overlay.close()
|
||
await _settle()
|
||
# 9 三选一(拟真三卡)
|
||
main.curio_overlay.open_pick(Narrator.node_curio_header(), [
|
||
{"id": "heal_rare", "text": "回血\n恢复 3 点"},
|
||
{"id": "blast_rare", "text": "爆裂轰击\n下一击 +5"},
|
||
{"id": "pierce_rare", "text": "穿甲\n无视护甲"},
|
||
])
|
||
await _settle()
|
||
await _snap("6_bonus")
|
||
main.curio_overlay.visible = false
|
||
await _settle()
|
||
# 10 商店(买前态——pool 货架面=玩家正主形态,demo #v-shop 对比基线;T6 全屏页)
|
||
main.shop_overlay.open_shelf([
|
||
{"kind_id": "attack", "display_name": "攻击强化", "value": 1, "price": 12},
|
||
{"kind_id": "max_hp", "display_name": "生命强化", "value": 3, "price": 12},
|
||
{"kind_id": "armor", "display_name": "护甲片", "value": 1, "price": 15},
|
||
], 27)
|
||
main.shop_overlay.set_visit_info(0, 1.8) # 爬价规则行(T6——presenter 同款投喂)
|
||
await _settle()
|
||
await _snap("7_shop")
|
||
main.shop_overlay.visible = false
|
||
await _settle()
|
||
# 11 图例
|
||
main.legend_overlay.open()
|
||
await _settle()
|
||
await _snap("10_legend")
|
||
main.legend_overlay.close()
|
||
await _settle()
|
||
# 12 确认框(放弃二次确认实文案)
|
||
main.confirm_dialog.open("放弃冒险", "确认放弃本次冒险?已入账钥匙与 GP 将结算保留")
|
||
await _settle()
|
||
await _snap("11_confirm")
|
||
main.confirm_dialog.close()
|
||
await _settle()
|
||
|
||
for s in ["1_start", "9_debug", "3_settings", "2_camp", "4_map", "5_battle",
|
||
"8_end_victory", "8_end_defeat", "6_bonus", "7_shop", "10_legend", "11_confirm"]:
|
||
var p := out_dir.path_join("real_%s.png" % s)
|
||
if not FileAccess.file_exists(p):
|
||
_problems.append("截图缺失: %s" % s)
|
||
else:
|
||
var fa := FileAccess.open(p, FileAccess.READ)
|
||
if fa == null or fa.get_length() < 1000:
|
||
_problems.append("截图疑似空文件: %s" % s)
|
||
print("[ui_audit] 完成 out=%s 问题=%d %s" % [out_dir, _problems.size(), str(_problems)])
|
||
get_tree().quit(1 if _problems.size() > 0 else 0)
|
||
|
||
|
||
func _settle() -> void:
|
||
for i in 3:
|
||
await get_tree().process_frame
|
||
await RenderingServer.frame_post_draw
|
||
|
||
|
||
func _snap(key: String) -> void:
|
||
await RenderingServer.frame_post_draw
|
||
await RenderingServer.frame_post_draw
|
||
var img: Image = get_viewport().get_texture().get_image()
|
||
if img == null:
|
||
_problems.append("视口纹理为空: %s" % key)
|
||
return
|
||
img.save_png(out_dir.path_join("real_%s.png" % key))
|
||
print("[ui_audit] saved %s (%dx%d)" % [key, img.get_width(), img.get_height()])
|