# VERTICAL SLICE - NOT FOR PRODUCTION # Date: 2026-10-04(迭代 14.5 调试整合批——主菜单三散件(随机种子/角色数值调整板/两层调试入口)收一张调试浮窗, # 原 views/tune_panel.gd 整体吸收退役) # 开发调试浮窗:入口 = 开始覆盖层右下角「调试」角标(DS_DEBUG=1 门控归组合根)——非主按钮组平级; # 仅开始菜单可开(浮于菜单之上的 Dialog 形态,不隐藏开始层——与确认弹窗同款;对局中不可达)。 # 列表页形态可扩展:后续调试项按区块往下追加,超高滚动。 # 纯视图边界(规范 1.3):数值应用/批量模拟/对局启动全部经信号外发由组合根承接 #(apply_requested / simulate_requested / debug_levels_requested / closed); # 模拟进度与报告经 setter 注入——零核心写、不拼报告文案(装配归 HudPresenter)。 # 探针接缝(ADR-0004"合成输入走真实翻译出口"口径):press_apply_for_probe 等三键 = 按钮真实信号路径。 class_name DebugOverlay extends Control signal apply_requested(atk_pct: int, hp_pct: int) # 应用并关闭——加成落表归组合根单一应用路径 signal simulate_requested(count: int) # 批量模拟编排归组合根(表基线复位 + 单路径施加) signal debug_levels_requested # 两层调试对局入口(编排归 debug_session.gd) signal closed var seed_edit: LineEdit # 组合根 _seed_value 唯一读取面(原开始覆盖层种子行迁入) var _db var _base_atk := 0 var _base_hp := 0 var _atk: HSlider var _hp: HSlider var _atk_val: Label var _hp_val: Label var _eff: Label var _sim_count: SpinBox var _sim_btn: Button var _sim_out: RichTextLabel func _init(db_ref, base_atk: int, base_hp: int) -> void: _db = db_ref _base_atk = base_atk _base_hp = base_hp _build() _sync_labels() visible = false # 显式初始化——不靠树序巧合(缺陷⑤家族纪律) # ---- 对外语义面(组合根/探针)---- func atk_pct() -> int: return int(_atk.value) func hp_pct() -> int: return int(_hp.value) func set_sliders(atk: int, hp: int) -> void: _atk.value = atk _hp.value = hp func reset_sliders() -> void: _atk.value = 0 _hp.value = 0 _sync_labels() func effect_text() -> String: return _eff.text func set_sim_count(n: int) -> void: _sim_count.value = n func is_running() -> bool: return _sim_btn.disabled func set_sim_running(running: bool) -> void: _sim_btn.disabled = running _sim_btn.text = "模拟中…" if running else "运行模拟" func set_sim_progress(text: String) -> void: _sim_out.text = text func set_sim_report(text: String) -> void: _sim_out.text = text func output_text() -> String: return _sim_out.get_parsed_text() # ---- 探针接缝(真实翻译出口——按钮 pressed 信号路径,非直调组合根)---- func press_apply_for_probe() -> void: _apply_btn_pressed() func press_reset_for_probe() -> void: _reset_btn_pressed() func press_simulate_for_probe() -> void: _sim_btn.pressed.emit() # ---- 内部(信号 → 外发)---- func _apply_btn_pressed() -> void: apply_requested.emit(atk_pct(), hp_pct()) func _reset_btn_pressed() -> void: reset_sliders() func effective_atk() -> int: return UiKit.scaled(_base_atk, atk_pct()) func effective_max_hp() -> int: return UiKit.scaled(_base_hp, hp_pct()) # ---- 内部构建(标题/关闭固定于浮窗骨架,可扩展列表区居中滚动)---- func _build() -> void: var shell: Dictionary = UiKit.modal_shell(self, UiKit.BG_OVERLAY, Vector2(640, 0), 8) var box: VBoxContainer = shell.box var title := UiKit.label("调试",UiKit.FS_TITLE, true, UiKit.WARM) box.add_child(title) var desc := UiKit.label( "开发调试专用——仅开始菜单可开(DS_DEBUG=1 时入口点亮)。\n百分比叠加基础值:攻击 %d / 生命 %d。影响所有模式(手动与模拟),不落盘。" % [_base_atk, _base_hp], 13, false, UiKit.WARM_SOFT) box.add_child(desc) box.add_child(HSeparator.new()) # 可扩展列表页(后续调试项按区块往下追加——超高滚动,滚轮下探) var scroll := ScrollContainer.new() scroll.custom_minimum_size = Vector2(0, 430) scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED box.add_child(scroll) var list := VBoxContainer.new() list.size_flags_horizontal = Control.SIZE_EXPAND_FILL list.add_theme_constant_override("separation", 8) scroll.add_child(list) # 区块⓪胜利演出风格(P-C5 两套并存——纹章拼合[默认]/尘金粒子;会话级不落盘) var fx_row := HBoxContainer.new() fx_row.add_theme_constant_override("separation", 10) list.add_child(fx_row) fx_row.add_child(UiKit.label("胜利演出",UiKit.FS_HINT, false, UiKit.WARM)) var fx_btn := UiKit.button("纹章拼合" if UiKit.victory_fx_style == "crest" else "尘金粒子") fx_btn.tooltip_text = "两套演出并存——点击切换(会话级,不落盘)" fx_btn.pressed.connect(func() -> void: UiKit.victory_fx_style = "dust" if UiKit.victory_fx_style == "crest" else "crest" fx_btn.text = "纹章拼合" if UiKit.victory_fx_style == "crest" else "尘金粒子") fx_row.add_child(fx_btn) # 区块①随机种子(原开始覆盖层种子行迁入——非法定值回退 42 的口径归组合根 _seed_value) var seed_row := HBoxContainer.new() list.add_child(seed_row) seed_row.add_child(UiKit.label("随机种子",UiKit.FS_BODY, false)) seed_edit = LineEdit.new() seed_edit.text = "42" seed_edit.custom_minimum_size = Vector2(120, 0) seed_row.add_child(seed_edit) list.add_child(HSeparator.new()) # 区块②角色数值调整板(原 TunePanel 内容原样吸收) var atk_row := _slider_row(list, "攻击加成") _atk = atk_row.slider _atk_val = atk_row.value_label var hp_row := _slider_row(list, "生命加成") _hp = hp_row.slider _hp_val = hp_row.value_label _eff = UiKit.label("",UiKit.FS_HINT, false) list.add_child(_eff) var btn_row := HBoxContainer.new() list.add_child(btn_row) var apply_btn := UiKit.button("应用并关闭") apply_btn.pressed.connect(_apply_btn_pressed) btn_row.add_child(apply_btn) var reset_btn := UiKit.button("重置为 0") reset_btn.pressed.connect(_reset_btn_pressed) btn_row.add_child(reset_btn) list.add_child(HSeparator.new()) # 区块③批量模拟(与 headless 扫描同口径——编排归 tune_sim_controller) var sim_row := HBoxContainer.new() list.add_child(sim_row) sim_row.add_child(UiKit.label("批量模拟第一关",UiKit.FS_BODY, false)) _sim_count = SpinBox.new() _sim_count.min_value = 10 _sim_count.max_value = 200 _sim_count.step = 10 _sim_count.value = 30 _sim_count.custom_minimum_size = Vector2(90, 0) sim_row.add_child(_sim_count) sim_row.add_child(UiKit.label("次(理性玩家策略,含面板当前加成)",UiKit.FS_HINT, false)) _sim_btn = UiKit.button("运行模拟") _sim_btn.pressed.connect(_emit_simulate_requested) sim_row.add_child(_sim_btn) _sim_out = RichTextLabel.new() _sim_out.bbcode_enabled = true _sim_out.custom_minimum_size = Vector2(0, 300) list.add_child(_sim_out) list.add_child(HSeparator.new()) # 区块④两层调试对局入口(原开始覆盖层调试按钮迁入——HP 关内延续) var dbg_btn := UiKit.button("调试 · 连续关卡两层(HP 关内延续)") dbg_btn.pressed.connect(_emit_debug_levels) list.add_child(dbg_btn) var close_btn := UiKit.button("关闭") close_btn.pressed.connect(_emit_closed) box.add_child(close_btn) func _slider_row(box: VBoxContainer, title: String) -> Dictionary: var row := HBoxContainer.new() box.add_child(row) row.add_child(UiKit.label(title,UiKit.FS_BODY, false)) var s := HSlider.new() s.min_value = 0 s.max_value = 300 s.step = 5 s.custom_minimum_size = Vector2(320, 24) row.add_child(s) var v := UiKit.label("+0%",UiKit.FS_BODY, true) v.custom_minimum_size = Vector2(70, 0) row.add_child(v) s.value_changed.connect(_on_slider_value_changed) return {"slider": s, "value_label": v} func _sync_labels() -> void: _atk_val.text = "+%d%%" % atk_pct() _hp_val.text = "+%d%%" % hp_pct() _eff.text = "生效值:攻击 %d → %d · 生命 %d → %d" % [ _base_atk, effective_atk(), _base_hp, effective_max_hp()] func _emit_simulate_requested() -> void: simulate_requested.emit(int(_sim_count.value)) func _emit_debug_levels() -> void: debug_levels_requested.emit() func _emit_closed() -> void: closed.emit() func _on_slider_value_changed(_value: float) -> void: _sync_labels()