diff --git a/game/presentation/main.gd b/game/presentation/main.gd index bd941859..3c4887df 100644 --- a/game/presentation/main.gd +++ b/game/presentation/main.gd @@ -190,8 +190,8 @@ func _start_adventure_from_menu() -> void: # 主菜单「开始冒险」钮已随三入口化撤出(卡② mn6——主菜单侧断点互斥确认链同步摘除, # 弹窗本体与两分支逻辑归卡④大门承接)。本函数为探针直调中间态保留(mn10——冒险段探针 # 直调位点逐个登记实现报告「已知中间态」;卡④到位后由大门两分支换代)。无激活态写盘拒绝 - # 由卡① sv3 承接(结算不落盘)。 - ui.screens.start_overlay.visible = false + # 由卡① sv3 承接(结算不落盘)。开始层隐藏已收进 _start_adventure()(营地交互修复批契约 1 + # ——开局路径隐藏点唯一出口)。 _start_adventure() @@ -290,6 +290,7 @@ static func build_adventure_params(save_manager_ref: SaveManagerCore, meta_ref: # 冒险模式(三关连探——AdventureRunner 编排;转发信号签名与 runner 一致,接线照原样对接; # 信号连接只在组合根) func _start_adventure() -> void: + ui.screens.start_overlay.visible = false # 开局路径开始层隐藏唯一出口(营地交互修复批契约 1——三处调用方经此收口;失败分支开始层终态=隐藏,致命屏接管) ui.flow.close(ui.modals.menu.debug_overlay) # 开冒险路径显式关浮窗(调试浮窗默认开态下开局不带窗;对局中经角标再开) begin_session(true) _wire_adventure() diff --git a/game/presentation/views/camp_hud_band.gd b/game/presentation/views/camp_hud_band.gd index a228626a..530d735a 100644 --- a/game/presentation/views/camp_hud_band.gd +++ b/game/presentation/views/camp_hud_band.gd @@ -11,10 +11,15 @@ func _init() -> void: set_anchors_preset(Control.PRESET_TOP_WIDE) custom_minimum_size = Vector2(0, 48) # 高 48px 浮层覆盖、不挤压画面(camp.md §顶栏) mouse_filter = Control.MOUSE_FILTER_IGNORE # HUD 栏不挡场景命中区(浮层覆盖语义) + UiKit.camp_hud_band_surface(self) # 栏体色面——整件外观单一出口(色值与 α、铺满、不吃点击、挂载全在出口内);先入=绘制序底,徽章后入不被盖 _badge = UiKit.keystone_badge("钥石 0") - _badge.set_anchors_preset(Control.PRESET_CENTER_RIGHT) - _badge.position = Vector2(-160, 8) # 顶栏右位次(UiKit 现行件域内——代拍板 3) - add_child(_badge) + var dock := HBoxContainer.new() # 右对齐容器承载徽章(Q2 已裁乙——位数增宽自然向左展;摆位机制先例=confirm_dialog 钮行同款容器 alignment) + dock.set_anchors_preset(Control.PRESET_FULL_RECT) + dock.offset_right = -12.0 # 右缘内缩 12px(UiKit 钮间距同档——白名单 3) + dock.alignment = BoxContainer.ALIGNMENT_END + dock.mouse_filter = Control.MOUSE_FILTER_IGNORE # 容器自身默认 STOP——与出口内 IGNORE 是两个点,必须同批落(漏一处顶排物件点不动) + dock.add_child(_badge) + add_child(dock) ## 余额写入(格式串=既有消费面同款「钥石 %d」——badge 工厂约定单点,禁第二格式串) diff --git a/game/presentation/views/confirm_dialog.gd b/game/presentation/views/confirm_dialog.gd index 6ce39f15..8667c07b 100644 --- a/game/presentation/views/confirm_dialog.gd +++ b/game/presentation/views/confirm_dialog.gd @@ -30,13 +30,15 @@ func _init() -> void: box.add_child(btn_row) _cancel_btn = UiKit.button("取消") _cancel_btn.pressed.connect(_emit_cancelled) - btn_row.add_child(_cancel_btn) _secondary_btn = UiKit.button("次选项") _secondary_btn.pressed.connect(_emit_secondary) - btn_row.add_child(_secondary_btn) _confirm_btn = UiKit.button("确认") _confirm_btn.pressed.connect(_emit_confirmed) + # 位次定值(HUD框架.md:90 三条纪律·其三——推进钮在左、次推进居中、维持在右;四处消费方 + # 共用本件同一序。信号按按钮对象路由、不按位次——换序不改路由〔营地交互修复批契约 3〕) btn_row.add_child(_confirm_btn) + btn_row.add_child(_secondary_btn) + btn_row.add_child(_cancel_btn) visible = false diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index b8c615c8..57024b08 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -193,6 +193,7 @@ const TIP_BG := Color(0.16, 0.12, 0.09, 0.96) # tooltip 深底 const STAND_STONE := Color8(150, 130, 100) # 站桩石板地台·板身(standee_body 方向稿取色) const PLAZA_EDGE := Color8(76, 64, 56) # 小石台描边(art-bible §4.1 换色合并②合并目标——贴图已落此值,缺位回退同值) const CAMP_HEADER_BAND := Color8(110, 69, 38) # 营地柜台头带深棕 #6E4526(4-camp.png 方向稿取色;对齐 demo --wood-deep) +const CAMP_HUD_BAND := Color(CAMP_HEADER_BAND, 0.80) # 营地顶栏栏体=头带深棕×α0.80(camp.md §顶栏定值——派生收口单点,非色板新增;同文件 TOAST_BG/TIP_BG 带 α 先例) const CAMP_ROW_PLATE := Color8(240, 230, 206) # 营地行板暖米(同上) const CAMP_BADGE_PANEL := Color8(40, 32, 24) # 营地钥石徽暗底(同上) const HP_BAR_BACK := Color8(40, 34, 32) # 迷你血条深底 #282220(兼血数垫牌;站桩名字行素底同源——§6.1/§7.2 文字禁压地台) @@ -656,6 +657,19 @@ static func keystone_badge(text: String, icon_path := TEX_ICON_KEYSTONE, icon_px return KeystoneBadge.new(text, icon_path, icon_px) +## 营地顶栏栏体面(整件外观单一出口——营地交互修复批契约 4/5):色值与 α、铺满、不吃点击、 +## 挂上宿主五件事全写死在体内;形参只有 host——调用方没有可以忘记的形参。返回句柄供调用方 +## 读取与断言;徽章摆位不由本出口负责(归顶栏件内右对齐容器)。须在宿主入树前调用 +## (set_anchors_preset 是入树前动作——_modal_dim/overlay_bg 同形)。 +static func camp_hud_band_surface(host: Control) -> ColorRect: + var rect := ColorRect.new() + rect.color = CAMP_HUD_BAND + rect.set_anchors_preset(Control.PRESET_FULL_RECT) # 四边 offset 归零铺满宿主 + rect.mouse_filter = Control.MOUSE_FILTER_IGNORE # 栏体不吃点击(顶排物件命中区不受阻——契约 5) + host.add_child(rect) + return rect + + # 按钮皮·五态矩阵(逐实例 override 不动主题层) # 悬停:常态图+modulate 提亮(0.06 档与 primary_button 现行 lightened(0.06) 同纪律,零新素材); # 禁用:本族底+α0.45 幽灵化(与 font_disabled_color 同纪律); diff --git a/game/probe/ui_click_probe.gd b/game/probe/ui_click_probe.gd index 2b420b62..720f4e3d 100644 --- a/game/probe/ui_click_probe.gd +++ b/game/probe/ui_click_probe.gd @@ -744,10 +744,30 @@ func _ready() -> void: _problems.append("大门取消:未无变更退回营地(写口零调用/营地根 visible 失守)〔营地图批 V3〕") ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"gate").get_center()) await get_tree().process_frame - ProbeUiUtil.push_click(main, main.ui.modals.menu.confirm_dialog._confirm_btn) # 真点「确认」→开始新冒险 - await get_tree().process_frame + # R4 位次真点(营地交互修复批——位次与语义绑定钉):真点前消费方前置读(gate_new 在册)→ + # 按类型定位按钮行 child(0) 全局矩形中心真点——位次若错接,此点命中「否」,下方主证(翻转)即红。 + # oracle: design/gdd/systems/表现与支撑/HUD框架.md:90 确认弹窗位次定值:推进在左、维持居右(R4 位次真点) + if String(main._confirm_consumer) != "gate_new": + _problems.append("R4 前置:确认消费方非 gate_new(分派面漂移)〔营地交互批 V3〕") + var gate_row := _first_hbox(main.ui.modals.menu.confirm_dialog) + if gate_row == null or gate_row.get_child_count() != 3: + _problems.append("R4:按钮行缺失或子节点数≠3(位次判据面塌)〔营地交互批 V3〕") + else: + ProbeUiUtil.push_click_at(main, (gate_row.get_child(0) as Control).get_global_rect().get_center()) # 真点推进钮(左位) + for i in 3: + await get_tree().process_frame # 停点成形帧口径(先例 3 帧——screen_flow_probe 选路停点成形窗) if not main.run_scope.is_adventure or main.ui.modals.camp.scene.visible: _problems.append("大门确认:冒险未发起或营地场景屏未隐藏〔营地图批 V3〕〔营地图批 B1〕") + if String(main._confirm_consumer) != "": + _problems.append("R4 主证:确认后消费方未清零〔营地交互批 V3〕") + # 开局终态两钉(营地交互修复批——开始层隐藏收一处后的落点断言): + # oracle: design/gdd/systems/冒险循环/关卡节点地图.md:78 关卡开始 → 呈现节点图选路停点(开局终态两钉) + # R1=确认后开始层不可见(被测改动特有提交面——修复前该句恒红=「开局被开始层盖住」缺陷本体); + # R2=关卡画面(选路停点)在位(开局终态呈现面,与既有 is_adventure 断言同批缺一即红) + if main.ui.screens.start_overlay.visible: + _problems.append("大门无断点确认后:开始层滞留可见(开局被开始层盖住缺陷回潮)〔营地交互批 V1〕") + if not main.ui.modals.run.level_screen.visible: + _problems.append("大门无断点确认后:关卡画面(选路停点)未在位〔营地交互批 V2〕") # 有断点三出口(选路停点形注入——同开场行③ set_breakpoint 先例) main.save_manager.set_breakpoint({ "master_seed": 42, "rng_counter": 0, "hero_hp": 30, "gp": 10, "keystone": 0, @@ -1215,6 +1235,17 @@ func _stoptest_assert_hit() -> void: _problems.append("停手定型化段:停手钮真点零命中登记(驱动空转假绿)〔QA收口 V2〕") +func _first_hbox(node: Node) -> HBoxContainer: +# oracle: design/gdd/systems/表现与支撑/HUD框架.md:90 (位次真点定位——R4 判据面辅助) + if node is HBoxContainer: + return node + for ch in node.get_children(): + var found := _first_hbox(ch) + if found != null: + return found + return null + + func _report_stall(st: Dictionary) -> void: # oracle: design/engineering/test-conventions.md:30 (判定上报通道——验证函数组) var why := "" diff --git a/game/tests/run_all.gd b/game/tests/run_all.gd index 4fb4788e..02b76ac2 100644 --- a/game/tests/run_all.gd +++ b/game/tests/run_all.gd @@ -200,6 +200,7 @@ func _suites() -> Array: {"path": "res://tests/unit/presentation/tune_sim_batch_parity_test.gd", "expect": 0}, # 测速循环批双实现对拍(帧索引/运行态/进度串/stats/报告五面——信号步进 vs await 基线) {"path": "res://tests/unit/presentation/standee_present_values_test.gd", "expect": 0}, # 战斗一屏样张批 V5–V12(血条危险红/名字行素底不压地台与提档 FS_HINT/徽标/护甲 PNG 绑定/素材入包/地台色合并退役) {"path": "res://tests/unit/presentation/reward_overlay_test.gd", "expect": 0}, # 奖励节点 UI 直验(盲区补漏) + {"path": "res://tests/unit/presentation/confirm_dialog_test.gd", "expect": 0}, # 确认弹窗按钮位次与语义同钉(推进/次推/维持子节点序——营地交互修复批 R3) {"path": "res://tests/unit/presentation/level_map_info_fog_test.gd", "expect": 0}, # 信息迷雾——呈现显隐/Boss 豁免/详情零显示/大图拟合 {"path": "res://tests/unit/presentation/forge_workbench_test.gd", "expect": 0}, # 工作间两区六路线 UI 直验(V13 自动化前置面) {"path": "res://tests/unit/presentation/camp_scene_layout_test.gd", "expect": 0}, # 营地场景布局数据件校验(V14——fail-fast 判据+七命中区几何红线) diff --git a/game/tests/system_test.gd b/game/tests/system_test.gd index 9ccd6677..aaf53736 100644 --- a/game/tests/system_test.gd +++ b/game/tests/system_test.gd @@ -44,6 +44,7 @@ func _split_tail() -> void: await _smoke_run_lifecycle() await _smoke_sim_guards() await _smoke_lifecycle_matrix() + await _smoke_camp_hud_band() else: check(false, "V2/V3 前置:autoload 链未就绪(ConfigDB/SaveManager)") print("[system_test] 摘要:%d 项检查,%d 项失败" % [_checks, _failures]) @@ -603,4 +604,49 @@ func _smoke_lifecycle_matrix() -> void: for p in ["user://smoke_lifecycle.json", "user://smoke_lifecycle.json.tmp", "user://smoke_lifecycle_resume.json", "user://smoke_lifecycle_resume.json.tmp"]: if FileAccess.file_exists(p): - DirAccess.remove_absolute(p) \ No newline at end of file + DirAccess.remove_absolute(p) + + +func _smoke_camp_hud_band() -> void: +# oracle: design/gdd/ux/camp.md:41 (营地顶栏栏体定值与落座——几何/色值/吃点击五钉组) + print("--- 营地交互修复批 T3 顶栏栏体(R5:色值/铺满/不吃点击/首子件/徽章落座)---") + var main: Node = load("res://presentation/main.tscn").instantiate() + root.add_child(main) + await process_frame + await process_frame + main._camp_pres.open_camp() # 营地屏 boot 态为隐——先开营地(装配链 main_ui_build→camp_scene_view 落座) + for i in range(3): + await process_frame # 排版帧(容器重排在途读数不可信) + var band: Control = main.ui.modals.camp.scene.hud_band + check(band != null and band.is_inside_tree(), "R5 前置:顶栏件经装配链在树(camp_scene_view.hud_band 公开句柄)") + if band == null: + main.queue_free() + await process_frame + return + var badge_min: float = band.get_child(band.get_child_count() - 1).get_child(0).get_combined_minimum_size().y if band.get_child_count() > 0 else -1.0 + print("[system_test] 徽章 get_combined_minimum_size().y 实测 = %s(T3.0 前置读数——48=顶格落座前提)" % str(badge_min)) + check(band.get_child_count() >= 2 and band.get_child(0) is ColorRect, + "R5④ 栏体色面是顶栏件第一个子节点(子节点序=绘制序——色面先入不盖徽章)") + if band.get_child_count() >= 2 and band.get_child(0) is ColorRect: + var surface: ColorRect = band.get_child(0) + check(String(surface.color.to_html(true)) == "6e4526cc", + "R5① 栏体色=#6E4526×α0.80(to_html 字面编码——禁浮点分量直等)〔营地交互批 V4〕") + var band_rect: Rect2 = band.get_global_rect() + var surf_rect: Rect2 = surface.get_global_rect() + print("[system_test] 顶栏件实测 get_global_rect=%s、栏体=%s(R5② 承重=ui_registry FULL_RECT 注册)" % [band_rect, surf_rect]) + check(absf(surf_rect.size.x - band_rect.size.x) < 0.51 and absf(surf_rect.size.y - band_rect.size.y) < 0.51 + and absf(surf_rect.size.y - 48.0) < 0.51, + "R5② 栏体铺满宿主且高 48(全局矩形等值)〔营地交互批 V4〕") + check(surface.mouse_filter == Control.MOUSE_FILTER_IGNORE, + "R5③ 栏体不吃点击(MOUSE_FILTER_IGNORE——顶排物件命中区不受阻)〔营地交互批 V4〕") + var dock: Control = band.get_child(band.get_child_count() - 1) + var badge: Control = dock.get_child(0) if dock.get_child_count() > 0 else null + check(badge != null, + "R5⑤ 前置:徽章经右对齐容器在座(dock 尾子件)") + if badge != null: + var brect: Rect2 = badge.get_global_rect() + check(absf(brect.position.y - band_rect.position.y) < 0.51 + and absf(brect.end.x - (band_rect.end.x - 12.0)) < 0.51, + "R5⑤ 徽章顶格右位(y=栏顶格、end.x=栏右缘−12——全局矩形不与局部 position 混写)〔营地交互批 V4〕") + main.queue_free() + await process_frame \ No newline at end of file diff --git a/game/tests/unit/presentation/camp_scene_layout_test.gd b/game/tests/unit/presentation/camp_scene_layout_test.gd index a4a74b07..c3647bf5 100644 --- a/game/tests/unit/presentation/camp_scene_layout_test.gd +++ b/game/tests/unit/presentation/camp_scene_layout_test.gd @@ -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) diff --git a/game/tests/unit/presentation/confirm_dialog_test.gd b/game/tests/unit/presentation/confirm_dialog_test.gd new file mode 100644 index 00000000..ff7bbbfc --- /dev/null +++ b/game/tests/unit/presentation/confirm_dialog_test.gd @@ -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 — 双钮/三钮形态位次与语义同钉 全过")) diff --git a/reports/iter54-反哺点-2026-11-07.md b/reports/iter54-反哺点-2026-11-07.md index e072398a..13387792 100644 --- a/reports/iter54-反哺点-2026-11-07.md +++ b/reports/iter54-反哺点-2026-11-07.md @@ -6,6 +6,11 @@ 卡 1 §6 申报「无关联文档」——A2 为容错修复、B1/B2 为测试驱动面,零设计语义变化。核过面:`design/gdd/systems/排雷循环/排雷玩法.md`(停手语义句 :162/:167 与实装一致)、`design/engineering/test-conventions.md`(真输入管线条文 §2 与实装一致)——两处无需改句。 -## 卡 2|营地交互修复批——(随卡 2 推进补齐) +## 卡 2|营地交互修复批——两条 + +1. **`design/engineering/architecture/architecture.md` 呈现层模块表 CampHudBand 行(约 :175)**:现句「顶栏 48px 全宽窄条:钥石余额 badge 唯一呈现」已失真——本批落地后顶栏呈现物=栏体色面(`CAMP_HEADER_BAND`×α0.80 全宽)+钥石徽章(右位顶格)两件。建议改成:栏体与徽章两呈现物的实际形态描述;依据=实装读数(栏体 1280×48 全局矩形、徽章 end.x=栏右缘−12,system_test R5 五钉读数)。实现批禁写该文档,由文档批落文。 +2. **根 `体验验证清单.md` 增一行观测项**:营地顶栏观感(「成一条可辨窄带、徽章落在带内」)——需真人试玩下结论,已在实现报告目检总清单登记;由文档批落进清单正式在册。依据=卡 2 §6 同步面表行。 + +(未列项核对:camp.md §顶栏 与 art-bible §6.2 —— α0.80/栏高 48/色值零改值,按卡 2 §6「未改值不列」不列;HUD框架 §提示与弹层·其三「四处共用同一件同一序」——实装后句码一致,无发现不列;architecture.md :168 D1 HUD 视图单元接口——CampHudBand 仍为信号外发+setter 只读注入形态、新出口为 UiKit 工厂面(工厂单点先例在案),未失真不列。) ## 卡 3|精英专属池——(随卡 3 推进补齐) diff --git a/reports/iter54-实现报告-2026-11-07.md b/reports/iter54-实现报告-2026-11-07.md index 2af4b0df..e733570b 100644 --- a/reports/iter54-实现报告-2026-11-07.md +++ b/reports/iter54-实现报告-2026-11-07.md @@ -56,9 +56,50 @@ 6. **T2 断言①的登记件读取形态**:`_stoptest_assert_hit` 经 `_recorder._node_keys`/`_recorder._hits` 直读登记件命中表(登记件为探针共用面、卡 1 §13 申报零改动——不新增公开读口,探针面读私有沿现役惯例:ap_bar._btn_stop 同型先例)。 7. **卡 2 T4.4「等用户发令再走收口」与迭代单合并语义的冲突处置**:卡 2 写卡时为独立批(编入迭代 54 前),其末卡收口语义已被编排段换代为迭代级总收口(iter 技能第 5 步:一次合并、五步登记)。本批按迭代级收口执行,不逐卡等发令;此冲突为编排换代遗留,随本报告呈报。 -## 卡 2|营地交互修复批——状态:进行中 +## 卡 2|营地交互修复批——状态:已完成 -(随卡 2 任务卡推进补齐。) +### 各任务卡状态 + +| 任务卡 | 状态 | 摘要 | +|---|---|---| +| T1 开局路径隐藏点收一处 | 完成 | `_start_adventure()` 首句加开始层隐藏(开局唯一出口,契约 1)+删 `_start_adventure_from_menu()` 冗余句;探针大门无断点段追加 R1/R2〔提交 4d9687eb〕 | +| T2 确认弹窗按钮位次镜像 | 完成 | `add_child` 三句次序镜像(确认→次→取消,其余零动——契约 3);新单元套 confirm_dialog_test 入册;探针 R4 位次真点〔提交 46287043 区段〕 | +| T3 营地顶栏可见栏体 | 完成 | ui_kit 新增 CAMP_HUD_BAND+camp_hud_band_surface(host) 出口(契约 4/5);camp_hud_band 调出口+徽章右对齐容器落座;R5 五钉(系统测试)+R6 对比(单元套)〔提交 1958d329〕 | +| T4 产出物落位 | 完成 | 本报告卡 2 段+反哺点+gdstyle 基线修订(见下)+能力行名实核对 | + +### 实际对照表(R1–R8,补「结果」格) + +| 行 | 验收测试 | 结果 | +|---|---|---| +| R1 大门无断点按「是」后开始层不可见 | ui_click_probe 大门段〔营地交互批 V1〕 | 绿——探针直跑问题=0,断言在跑批中执行(修复前该句恒红判据零命中) | +| R2 开局落节点图选路停点 | ui_click_probe 大门段〔营地交互批 V2〕 | 绿——同批(3 帧口径下 level_screen.visible 断言过) | +| R3 两/三钮形态位次=推进→次→维持 | confirm_dialog_test 两函数 | 绿——直跑 exit=0 七断言全 PASS | +| R4 左位真点即推进 | ui_click_probe R4〔营地交互批 V3〕 | 绿——真点前 consumer=="gate_new" 前置读+child(0) 中心真点+真点后 is_adventure 翻转+consumer 清零,全部在跑批中执行 | +| R5 顶栏栏体几何与徽章落座 | system_test._smoke_camp_hud_band | 绿——76 检查 0 失败;T3.0 前置读数=徽章 min 高 48.0;五钉全过(色面 6e4526cc、铺满 1280×48、IGNORE、首子件、徽章顶格右位 end.x−12) | +| R6 栏体对落位带底色对比 ≥3:1 | camp_scene_layout_test._test_hud_band_contrast_over_bg | 绿——直跑 exit=0,规格侧算式实测 4.29:1(与卡面复核推算一致,顶带均色≈#DEEAE7) | +| R7 回归·件1 未动三条动线 | 既有大门两分支段+篝火段断言 | 绿——探针直跑问题=0(既有断言原样通过) | +| R8 回归·件2 路由与件数断言 | 探针次钮隐藏断言+system_test 三钮计数 | 绿——system_test 76/0(三钮计数断言在册);探针既有次钮断言原样通过 | + +### 卡 2 批末读数 + +- 静态扫描(S13)直跑:首跑出 `ui_kit.gd|quality/max-public-methods = 24(基线登记 23)` 恶化键——卡 2 §13 预申报的例外(用户 11-06 终裁「整件外观封公共件一个具名出口」的直接代价),按申报把 `tools/gdstyle_baseline.txt` 该行 23→24 修订后复跑绿(基线内 7 条、恶化 0)。基线修订的批准依据=卡 2 §13「本条即申报与请求」+U0 批卡。 +- 系统测试 76 检查 0 失败;单元侧 confirm_dialog_test/camp_scene_layout_test 直跑绿;探针直跑问题=0。卡 3 T3.8 的里程碑出口跑闸(--code 全档)覆盖本卡改动面的全档回归。 + +### 实机目检总清单(卡 2) + +| 目检项 | 登记处 | 义务口径 | +|---|---|---| +| 营地顶栏观感——成一条可辨窄带、徽章落在带内 | 本表(渲染闸七屏段营地截图随批产出可对照;卡 2 §1 真人目检项) | 真人检测只登记不阻塞——登记即完成义务 | + +### 遗留读数义务(卡 2) + +- 远端 CI 现查读数(合回后,按需现查)。 + +### 实现决定记录(卡 2 新增条目) + +8. **T2.3「前置重开」步重构为原位 R4**:卡面 T2.3 设计=既有确认真点后重开营地再测 R4;但该流程下 is_adventure 已为真、R4 主证「翻转」恒空转(且 `_on_confirm_declined` 同样清零 consumer,清零判据无判别力)。R4 对照表行的判据绑定面(主证=is_adventure 翻转)优先于任务卡步骤机制——改为真点前 is_adventure=false 的原位确认:既有确认成员点击替换为按钮行 child(0) 坐标真点,翻转成为真判据。既有断言(is_adventure+营地隐藏)原样保留。 +9. **T1.5 `--quick` 闸壳步以探针直跑代证**:改完即测铁规频率口径(轮内不跑闸壳全套含 --quick)下,T1.4 探针直跑即该件最窄确认(同一判据同源读数),未另起 --quick 闸壳跑批。 +10. **T3.0 读数实测 48.0**(卡面 L3 第 5 条警戒项未触发)——顶格落座前提成立,R5⑤ 判据照卡落装。 ## 卡 3|精英专属池——状态:待开工 diff --git a/tools/gdstyle_baseline.txt b/tools/gdstyle_baseline.txt index 84f9aaeb..66e4f3f5 100644 --- a/tools/gdstyle_baseline.txt +++ b/tools/gdstyle_baseline.txt @@ -9,6 +9,6 @@ game/core/adventure_runner.gd|quality/max-class-variables = 23 game/core/level_runner.gd|quality/max-class-variables = 30 game/core/level_runner.gd|quality/max-public-methods = 33 game/presentation/main.gd|quality/max-public-methods = 32 -game/presentation/views/ui_kit.gd|quality/max-public-methods = 23 +game/presentation/views/ui_kit.gd|quality/max-public-methods = 24 game/presentation/views/board_view.gd|quality/max-class-variables = 31 game/presentation/views/board_view.gd|quality/max-public-methods = 27