audit: 全屏UI审计(用户令返工)——实机十二屏窗口化截图(ui_audit_probe真实信号驱动)×demo v2.1纯净模式浏览器现截九屏;逐屏并排对比图九组+差距报告(底栏重设计草案头号待裁/D1D2量级坐实/结算仪式感/背景全局差距/标题屏主操作语义/E5爆破带demo紫带证据);零代码修改
No files matched your search
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 487 KiB |
|
After Width: | Height: | Size: 516 KiB |
|
After Width: | Height: | Size: 374 KiB |
|
After Width: | Height: | Size: 457 KiB |
|
After Width: | Height: | Size: 415 KiB |
|
After Width: | Height: | Size: 375 KiB |
|
After Width: | Height: | Size: 372 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 510 KiB |
|
After Width: | Height: | Size: 538 KiB |
|
After Width: | Height: | Size: 394 KiB |
|
After Width: | Height: | Size: 479 KiB |
|
After Width: | Height: | Size: 433 KiB |
|
After Width: | Height: | Size: 392 KiB |
|
After Width: | Height: | Size: 390 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 952 KiB |
|
After Width: | Height: | Size: 448 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 763 KiB |
|
After Width: | Height: | Size: 579 KiB |
|
After Width: | Height: | Size: 623 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 303 KiB |
|
After Width: | Height: | Size: 288 KiB |
|
After Width: | Height: | Size: 256 KiB |
|
After Width: | Height: | Size: 829 KiB |
|
After Width: | Height: | Size: 420 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 802 KiB |
|
After Width: | Height: | Size: 361 KiB |
|
After Width: | Height: | Size: 199 KiB |
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 262 KiB |
|
After Width: | Height: | Size: 261 KiB |
|
After Width: | Height: | Size: 93 KiB |
@@ -0,0 +1,147 @@
|
||||
# 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
|
||||
|
||||
# 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 关卡地图(开始冒险→停点出图)
|
||||
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 商店(买前态)
|
||||
main.shop_overlay.open_shop([
|
||||
{"product_id": "attack", "display_name": "攻击强化", "attr": "atk", "flat_value": 1, "price": 12, "purchased": 0},
|
||||
{"product_id": "max_hp", "display_name": "生命强化", "attr": "hp", "flat_value": 3, "price": 12, "purchased": 0},
|
||||
{"product_id": "armor", "display_name": "护甲强化", "attr": "armor", "flat_value": 1, "price": 15, "purchased": 0},
|
||||
], 27)
|
||||
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()])
|
||||
@@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://smoke/ui_audit_probe.gd" id="1"]
|
||||
|
||||
[node name="UIAuditProbe" type="Node"]
|
||||
script = ExtResource("1")
|
||||