Debug menu F1 (use ctrl to lock cam). Design.md doc
This commit is contained in:
+192
@@ -0,0 +1,192 @@
|
||||
extends Node
|
||||
## Runtime debug panel. Toggle with F1.
|
||||
## Reads DP.get_all() to build controls — adding a param to DP is all that's needed to show it here.
|
||||
|
||||
var _panel: Control
|
||||
var _status_label: Label
|
||||
var _prev_mouse_mode: Input.MouseMode = Input.MOUSE_MODE_CAPTURED
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_build_ui()
|
||||
DP.any_changed.connect(_on_dp_changed)
|
||||
|
||||
|
||||
func _build_ui() -> void:
|
||||
var canvas := CanvasLayer.new()
|
||||
canvas.layer = 128
|
||||
add_child(canvas)
|
||||
|
||||
_panel = PanelContainer.new()
|
||||
_panel.anchor_left = 1.0
|
||||
_panel.anchor_right = 1.0
|
||||
_panel.anchor_top = 0.0
|
||||
_panel.anchor_bottom = 1.0
|
||||
_panel.offset_left = -390.0
|
||||
_panel.offset_right = 0.0
|
||||
_panel.offset_top = 0.0
|
||||
_panel.offset_bottom = 0.0
|
||||
_panel.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
_panel.visible = false
|
||||
|
||||
var bg := StyleBoxFlat.new()
|
||||
bg.bg_color = Color(0.08, 0.08, 0.10, 0.95)
|
||||
_panel.add_theme_stylebox_override("panel", bg)
|
||||
canvas.add_child(_panel)
|
||||
|
||||
var root_vbox := VBoxContainer.new()
|
||||
root_vbox.size_flags_horizontal = Control.SIZE_FILL
|
||||
_panel.add_child(root_vbox)
|
||||
|
||||
# ── Toolbar ───────────────────────────────────────────────────────────────
|
||||
var toolbar_margin := MarginContainer.new()
|
||||
toolbar_margin.add_theme_constant_override("margin_left", 8)
|
||||
toolbar_margin.add_theme_constant_override("margin_right", 8)
|
||||
toolbar_margin.add_theme_constant_override("margin_top", 6)
|
||||
toolbar_margin.add_theme_constant_override("margin_bottom", 4)
|
||||
root_vbox.add_child(toolbar_margin)
|
||||
|
||||
var toolbar := HBoxContainer.new()
|
||||
toolbar.add_theme_constant_override("separation", 6)
|
||||
toolbar_margin.add_child(toolbar)
|
||||
|
||||
var title := Label.new()
|
||||
title.text = "DEBUG [F1]"
|
||||
title.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
toolbar.add_child(title)
|
||||
|
||||
_status_label = Label.new()
|
||||
_status_label.modulate = Color(0.4, 1.0, 0.5)
|
||||
toolbar.add_child(_status_label)
|
||||
|
||||
var save_btn := Button.new()
|
||||
save_btn.text = "Save"
|
||||
save_btn.pressed.connect(_on_save)
|
||||
toolbar.add_child(save_btn)
|
||||
|
||||
var reset_btn := Button.new()
|
||||
reset_btn.text = "Reset All"
|
||||
reset_btn.pressed.connect(DP.reset_all)
|
||||
toolbar.add_child(reset_btn)
|
||||
|
||||
root_vbox.add_child(HSeparator.new())
|
||||
|
||||
# ── Scrollable content ────────────────────────────────────────────────────
|
||||
var scroll := ScrollContainer.new()
|
||||
scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
scroll.size_flags_horizontal = Control.SIZE_FILL
|
||||
root_vbox.add_child(scroll)
|
||||
|
||||
var content_margin := MarginContainer.new()
|
||||
content_margin.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
content_margin.add_theme_constant_override("margin_left", 8)
|
||||
content_margin.add_theme_constant_override("margin_right", 8)
|
||||
content_margin.add_theme_constant_override("margin_top", 4)
|
||||
content_margin.add_theme_constant_override("margin_bottom", 8)
|
||||
scroll.add_child(content_margin)
|
||||
|
||||
var content := VBoxContainer.new()
|
||||
content.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
content_margin.add_child(content)
|
||||
|
||||
_build_params(content)
|
||||
|
||||
|
||||
func _build_params(content: VBoxContainer) -> void:
|
||||
# Group keys by section preserving registration order
|
||||
var sections: Dictionary = {}
|
||||
for key: String in DP.get_all():
|
||||
var sec: String = DP.get_all()[key]["section"]
|
||||
if not sections.has(sec):
|
||||
sections[sec] = []
|
||||
sections[sec].append(key)
|
||||
|
||||
for section: String in sections:
|
||||
content.add_child(HSeparator.new())
|
||||
|
||||
var header := Label.new()
|
||||
header.text = section.to_upper()
|
||||
header.modulate = Color(0.75, 0.85, 1.0)
|
||||
content.add_child(header)
|
||||
|
||||
for key: String in sections[section]:
|
||||
_add_float_row(content, key, DP.get_all()[key])
|
||||
|
||||
|
||||
func _add_float_row(parent: VBoxContainer, key: String, meta: Dictionary) -> void:
|
||||
var row := HBoxContainer.new()
|
||||
row.size_flags_horizontal = Control.SIZE_FILL
|
||||
parent.add_child(row)
|
||||
|
||||
var lbl := Label.new()
|
||||
lbl.text = key.replace("_", " ")
|
||||
lbl.custom_minimum_size.x = 140
|
||||
lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
row.add_child(lbl)
|
||||
|
||||
var slider := HSlider.new()
|
||||
slider.min_value = meta["min"]
|
||||
slider.max_value = meta["max"]
|
||||
slider.step = meta["step"]
|
||||
slider.value = meta["value"]
|
||||
slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
slider.custom_minimum_size.x = 60
|
||||
row.add_child(slider)
|
||||
|
||||
var spin := SpinBox.new()
|
||||
spin.min_value = meta["min"]
|
||||
spin.max_value = meta["max"]
|
||||
spin.step = meta["step"]
|
||||
spin.value = meta["value"]
|
||||
spin.custom_minimum_size.x = 85
|
||||
row.add_child(spin)
|
||||
|
||||
# Slider → SpinBox + DP (use no_signal to avoid echo)
|
||||
slider.value_changed.connect(func(v: float) -> void:
|
||||
spin.set_value_no_signal(v)
|
||||
DP.set_value(key, v)
|
||||
)
|
||||
# SpinBox → Slider + DP
|
||||
spin.value_changed.connect(func(v: float) -> void:
|
||||
slider.set_value_no_signal(v)
|
||||
DP.set_value(key, v)
|
||||
)
|
||||
# External changes (reset, load) → sync both controls
|
||||
DP.any_changed.connect(func(changed_key: String, _val: Variant) -> void:
|
||||
if changed_key != key and changed_key != "__all__":
|
||||
return
|
||||
var v := DP.f(key)
|
||||
slider.set_value_no_signal(v)
|
||||
spin.set_value_no_signal(v)
|
||||
)
|
||||
|
||||
|
||||
func _on_save() -> void:
|
||||
DP.save()
|
||||
_status_label.text = "Saved!"
|
||||
get_tree().create_timer(1.5).timeout.connect(func() -> void:
|
||||
_status_label.text = ""
|
||||
)
|
||||
|
||||
|
||||
func _on_dp_changed(_key: String, _value: Variant) -> void:
|
||||
pass # individual rows handle their own updates via signal
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if _panel.visible and Input.is_key_pressed(KEY_CTRL) and event is InputEventMouseMotion:
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if not (event is InputEventKey and event.pressed and not event.echo):
|
||||
return
|
||||
if (event as InputEventKey).keycode != KEY_F1:
|
||||
return
|
||||
_panel.visible = not _panel.visible
|
||||
if _panel.visible:
|
||||
_prev_mouse_mode = Input.mouse_mode
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
else:
|
||||
Input.mouse_mode = _prev_mouse_mode
|
||||
get_viewport().set_input_as_handled()
|
||||
Reference in New Issue
Block a user