iter54-卡2:营地交互修复批(开局隐藏点收一处 _start_adventure+确认弹窗按钮位次镜像确认→次→取消+营地顶栏可见栏体 camp_hud_band_surface 单参出口 CAMP_HUD_BAND×0.80)——对照表 R1-R8 全绿(探针 R1/R2/R4 落点断言/confirm_dialog_test 七断言/系统测试 R5 五钉 76 检查 0 失败/R6 WCAG 4.29:1),S13 ui_kit 基线 23→24 随卡预申报修订

This commit is contained in:
DKChan committed 2026-11-07 03:05:11 +08:00
1 parent 96123978c1
commit 4c424af358
12 files changed
+278 -17

No files matched your search

@@ -11,7 +11,14 @@ const _EXPECTED_KEYS: Array[StringName] = [&"gate", &"forge", &"dummy", &"chest"
func _initialize() -> void:
# oracle: design/gdd/ux/camp.md:29 (营地场景布局数据件——纵深与地平线组)
call_deferred("_test_layout_hotspot_geometry")
call_deferred("_run_all")
func _run_all() -> void:
# oracle: design/gdd/ux/camp.md:29 (套件统一收尾——双测试函数单进程单 quit)
await _test_layout_hotspot_geometry()
await _test_hud_band_contrast_over_bg()
quit(Kit.finish("camp_scene_layout_test", "PASS — 布局几何+顶栏栏体对比 全过"))
func _test_layout_hotspot_geometry() -> void:
@@ -19,7 +26,6 @@ func _test_layout_hotspot_geometry() -> void:
var table: CampSceneLayoutTable = load("res://data/tables/camp_scene_layout.tres")
Kit.check("V14 布局表加载且 schema 类在位〔营地图批 V14〕", table is CampSceneLayoutTable and table != null)
if table == null:
quit(Kit.finish("camp_scene_layout_test"))
return
var problems: Array[String] = table.validate()
Kit.check("V14 校验函数通过(问题清单空,实得 %s)〔营地图批 V14〕" % [problems], problems.is_empty())
@@ -88,4 +94,54 @@ func _test_layout_hotspot_geometry() -> void:
var load_ok: bool = db.load_tables("res://data/tables", true)
Kit.check("V14 ConfigDB 装载含营地布局表且校验过(is_ready=%s)〔营地图批 V14〕" % db.is_ready,
load_ok and db.is_ready and db.presentation.camp_scene_layout != null)
quit(Kit.finish("camp_scene_layout_test"))
# 顶栏栏体规格侧对比核验(R6——与 R5 分工:R5 核实装等值,本行核规格值本身达标):
# 按规格句在测试内写死 #6E4526 与 α0.80,与背景贴图顶带实测均色做 α 合成后算 WCAG 对比 ≥3.0。
# 禁把视图件的 color 直接当预期值喂进算式(oracle 镜像——test-conventions §8.7 判红)。
func _test_hud_band_contrast_over_bg() -> void:
# oracle: design/gdd/ux/camp.md:41 (顶栏栏体定值——对落位带底色对比 ≥3:1 组)
var table: CampSceneLayoutTable = load("res://data/tables/camp_scene_layout.tres")
var band_h := 48
if table != null:
band_h = int(table.hud_band_h) # 带高取数据出口(禁字面量)
var tex = load("res://assets/art/scene/scene_camp_bg.png")
var img: Image = null
if tex != null and tex.get_image() != null:
img = tex.get_image()
var scan_n := 0
var r_sum := 0.0
var g_sum := 0.0
var b_sum := 0.0
if img != null:
for y in range(0, mini(band_h, img.get_height())):
for x in range(img.get_width()): # 双层全像素扫描(非步长抽样——terrain_tile_sets_test 同款)
var c := img.get_pixel(x, y)
r_sum += c.r
g_sum += c.g
b_sum += c.b
scan_n += 1
Kit.check("R6 扫描面非空前置(顶带像素 %d > 0——贴图装载且带高在界)〔营地交互批 V5〕" % scan_n, scan_n > 0)
if scan_n == 0:
return
var bg := Color(r_sum / float(scan_n), g_sum / float(scan_n), b_sum / float(scan_n))
# 规格侧算式(camp.md:41 写死——#6E4526 × α0.80 对落位带背景合成)
var fg := Color(0x6e / 255.0, 0x45 / 255.0, 0x26 / 255.0, 0.80)
var mixed := Color(
fg.r * fg.a + bg.r * (1.0 - fg.a),
fg.g * fg.a + bg.g * (1.0 - fg.a),
fg.b * fg.a + bg.b * (1.0 - fg.a))
var lum_fg: float = _wcag_lum(mixed)
var lum_bg: float = _wcag_lum(bg)
var ratio: float = (maxf(lum_fg, lum_bg) + 0.05) / (minf(lum_fg, lum_bg) + 0.05)
print("[camp_scene_layout_test] 顶带均色=%s 合成后=%s WCAG 对比=%.2f:1(规格 ≥3:1)" % [bg, mixed, ratio])
Kit.check("R6 栏体合成色对落位带底色对比 ≥3.0(实测 %.2f)〔营地交互批 V5〕" % ratio, ratio >= 3.0)
## WCAG 相对亮度(sRGB 线性化——命名函数形态,避多行 lambda 嵌套三元解析坑)
func _wcag_lum(c: Color) -> float:
return 0.2126 * _srgb_lin(c.r) + 0.7152 * _srgb_lin(c.g) + 0.0722 * _srgb_lin(c.b)
func _srgb_lin(v: float) -> float:
return v / 12.92 if v <= 0.03928 else pow((v + 0.055) / 1.055, 2.4)
@@ -0,0 +1,59 @@
extends SceneTree
# 确认弹窗按钮位次与语义同钉单元套——
# 守 ConfirmDialog 公开入口 open()/open_three()(四处消费方实际用的两个公开方法)的按钮行子节点序:
# 推进钮恒 child(0)、次推进 child(1)、维持 child(2)(HUD框架.md:90 三条纪律·其三——营地交互修复批 R3)。
# 判据面=树的公开子节点序+Button 公开 text,零私有成员直读;次钮在 open() 里只置 visible=false
# 不从子节点表移除——双钮形态下子节点仍为 3,按下标断必取 child(2)。
# 运行:godot --headless --path game --script res://tests/unit/presentation/confirm_dialog_test.gd(expect 0)
const Kit := preload("res://tests/unit/test_kit.gd")
const ConfirmDialogScript := preload("res://presentation/views/confirm_dialog.gd")
func _initialize() -> void:
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:90 (确认弹窗按钮位次定值——位次与语义同钉组)
call_deferred("_run")
# 按类型向下定位第一个 HBoxContainer(该弹窗树内唯一横排——modal_shell 产 CenterContainer+
# PanelContainer+VBox 不产横排;HSeparator 与 UiKit.button 产件也不是 HBoxContainer)
func _find_btn_row(node: Node) -> HBoxContainer:
if node is HBoxContainer:
return node
for ch in node.get_children():
var found := _find_btn_row(ch)
if found != null:
return found
return null
func _test_two_button_row_order() -> void:
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:90 双钮形态位次=推进在左、维持在右(两钮同钉组)
var ov: Control = ConfirmDialogScript.new()
root.add_child(ov)
ov.open("t", "推进", "维持")
var row := _find_btn_row(ov)
Kit.check("双钮形态按钮行子节点数=3(次钮只隐藏不移除——非空前置)", row != null and row.get_child_count() == 3)
if row != null and row.get_child_count() == 3:
Kit.check("双钮形态位次 child(0)=推进", String((row.get_child(0) as Button).text) == "推进")
Kit.check("双钮形态位次 child(2)=维持(次钮占 child(1) 位——按下标断必取 child(2))", String((row.get_child(2) as Button).text) == "维持")
ov.queue_free()
func _test_three_button_row_order() -> void:
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:90 三钮形态位次=推进/次推/维持(三钮同钉组)
var ov: Control = ConfirmDialogScript.new()
root.add_child(ov)
ov.open_three("t", "推进", "次推", "维持")
var row := _find_btn_row(ov)
Kit.check("三钮形态按钮行子节点数=3(非空前置)", row != null and row.get_child_count() == 3)
if row != null and row.get_child_count() == 3:
Kit.check("三钮形态位次 child(0)=推进", String((row.get_child(0) as Button).text) == "推进")
Kit.check("三钮形态位次 child(1)=次推", String((row.get_child(1) as Button).text) == "次推")
Kit.check("三钮形态位次 child(2)=维持", String((row.get_child(2) as Button).text) == "维持")
ov.queue_free()
func _run() -> void:
_test_two_button_row_order()
_test_three_button_row_order()
quit(Kit.finish("confirm_dialog_test", "PASS — 双钮/三钮形态位次与语义同钉 全过"))