- CLAUDE.md 硬性红线新增「文件头零工作日志」;code-conventions.md 新增 §1.4.1(含反面案例) - 全仓 .gd 文件头注清偿:删除全部带日期条目、批次叙事段与迁移退役叙述,保留并改写为 现在时的职责、接口契约、GDD 锚内容(main.gd 头注 42→31 行、save_manager.gd 49→45 行) - 纯注释改动零行为变更,按用户令免测试免冒烟
114 lines
5.6 KiB
GDScript
114 lines
5.6 KiB
GDScript
# 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)
|