# VERTICAL SLICE - NOT FOR PRODUCTION # Date: 2026-09-13(四区布局诊断探针——"内容未满幅/棋盘底裁切"回归定位:打印窗口/视口/四区实际矩形 # 与最小尺寸、展开旗标,对照 battle.md §Layout 1280×800 基座规格) # 断言件(1280/1920 两档): # ①基座 1280×800(battle.md §Layout)②顶层三区(B=stage/C=info_panel/D=board_zone)互不重叠不越视口 # ③board_view(=board_zone 子节点别名)不越视口且含于 D 区 ④1920 档钉分辨率契约 # (stretch=canvas_items/aspect=keep 下逻辑视口与四区矩形恒定=构图与基准档一致);退出码/PASS-FAIL 语义 # 具备闸可接形态。原诊断打印面全保留。 # 运行:Godot_console.exe --headless --path . res://smoke/ui_layout_probe.tscn extends Node const ProbeUiUtil := preload("res://smoke/probe_ui_util.gd") # T6 收口:隔离样板单点 func _ready() -> void: await get_tree().process_frame # autoload 就绪 var main: Node = load("res://presentation/main.tscn").instantiate() add_child(main) await get_tree().process_frame # 存档隔离(迭代 8 卡①②——停点断点写盘随 main.save_manager;探针禁碰真实档,同族探针隔离纪律; # isolate_save 先删后建——上次运行的残留断点会触发互斥确认早退) ProbeUiUtil.isolate_save(main, "smoke_layout_probe_save", true, false, true) main.debug_overlay.seed_edit.text = "42" # 种子钉死(迭代 18 卡⑦审计🔴——种子框默认改空后空框=非首局随机,探针确定性禁依赖默认分支) main._start_adventure_from_menu() for i in range(3): await get_tree().process_frame var win := get_window() print("window.size=%s pos=%s mode=%s" % [win.size, win.position, win.mode]) print("viewport.visible_rect=%s" % get_viewport().get_visible_rect()) print("main.size=%s" % main.size) for c in main.get_children(): if c is Control: _dump_ctrl(c, 0) var zones := { "board_zone": main.board_zone, "board_view": main.board_view, "info_panel": main.info_panel, "stage": main.stage, } for k in zones: var ctl: Control = zones[k] if ctl == null: print("%s = null" % k) continue print("%-16s pos=%s size=%s min=%s hflag=%d vflag=%d" % [k, ctl.position, ctl.size, ctl.custom_minimum_size, ctl.size_flags_horizontal, ctl.size_flags_vertical]) var root_box: Control = main._adventure_screen.battle_root # 迭代 27 T1——屏壳化后战斗四区根迁冒险屏壳(序数寻址漂移改名寻址) print("four-zone root: anchors=(%s,%s)-(%s,%s) offsets=(%s,%s,%s,%s) size=%s" % [ root_box.anchor_left, root_box.anchor_top, root_box.anchor_right, root_box.anchor_bottom, root_box.offset_left, root_box.offset_top, root_box.offset_right, root_box.offset_bottom, root_box.size]) print("board_view cell_size=%s board=%s" % [main.board_view.get("cell_size"), main.board_view.board()]) # ── 最小布局断言(迭代 19 卡① T5——1280/1920 两档;语义见头注) ── var problems: PackedStringArray = [] var vr: Rect2 = get_viewport().get_visible_rect() if vr.size != Vector2(1280, 800): problems.append("基座视口 %s ≠ 1280x800(battle.md §Layout)" % vr.size) var azones := {"stage": main.stage, "info_panel": main.info_panel, "board_zone": main.board_zone} var arects := {} for k in azones: var actl: Control = azones[k] if actl == null: problems.append("%s=null" % k) continue var ar := Rect2(actl.global_position, actl.size) arects[k] = ar if ar.size.x <= 0.0 or ar.size.y <= 0.0: problems.append("%s 零尺寸 %s" % [k, ar.size]) elif not vr.encloses(ar): problems.append("%s 越视口 %s ⊄ %s" % [k, ar, vr]) var bvc: Control = main.board_view if bvc == null: problems.append("board_view=null") else: var br := Rect2(bvc.global_position, bvc.size) if not vr.encloses(br): problems.append("board_view 越视口 %s ⊄ %s" % [br, vr]) if arects.has("board_zone") and not arects["board_zone"].encloses(br): problems.append("board_view 越出 board_zone(%s ⊄ %s)" % [br, arects["board_zone"]]) var akeys := arects.keys() for i in range(akeys.size()): for j in range(i + 1, akeys.size()): if arects[akeys[i]].intersects(arects[akeys[j]]): problems.append("顶层区重叠 %s×%s(%s ∩ %s)" % [akeys[i], akeys[j], arects[akeys[i]], arects[akeys[j]]]) # 1920 档(Q4 注记对应面:单档 1280 闸+本两档断言钉 1920 构图恒等——分辨率维度不重复建闸) get_window().size = Vector2i(1920, 1080) for i in range(4): await get_tree().process_frame var vr2: Rect2 = get_viewport().get_visible_rect() if vr2 != vr: problems.append("1920 档逻辑视口漂移 %s ≠ %s(案甲:stretch 基座恒定)" % [vr2, vr]) for k in azones: var actl2: Control = azones[k] if actl2 == null: continue var ar2 := Rect2(actl2.global_position, actl2.size) if arects.has(k) and ar2 != arects[k]: problems.append("1920 档 %s 矩形漂移 %s ≠ %s(案甲:构图与基准档一致)" % [k, ar2, arects[k]]) if problems.is_empty(): print("[layout_probe] PASS — 1280/1920 两档全过(基座1280x800/顶层三区互斥不越界/board_view含于D区/案甲构图恒定)") get_tree().quit(0) else: for p in problems: print("[layout_probe] FAIL — " + p) print("[layout_probe] FAIL — %d 项断言未过" % problems.size()) get_tree().quit(1) func _dump_ctrl(c: Control, depth: int) -> void: var ind := " ".repeat(depth) print("%s%s pos=%s size=%s min=%s" % [ind, c.name, c.position, c.size, c.custom_minimum_size]) for ch in c.get_children(): if ch is Control: _dump_ctrl(ch, depth + 1)