feat(ui): add in-game debug console with tilde toggle and command dispatch (#581)
- debug_console.gd: new ModalLayer Control — tilde key toggles bottom-40% panel, command history (up/down), SimBridge dispatch for all DebugCommandKind variants: ticks, contaminate, tp, activate, triangle, npc, triangles, pop, status, help - debug_console.tscn: minimal scene node; UI built programmatically in _ready() - input_mapper.gd: DEBUG_COMMAND action added to Action enum - sim_bridge.gd: DEBUG_COMMAND → "DebugCommand" wire mapping - protocol.gd: v18 debug_response decode (command, text, success fields) - game_state.gd: debug_response field + apply_snapshot one-shot handling - main.gd: @onready ref, router registration, _consume_debug_response(), settings signal - settings_dialog.gd: debug_console_toggled signal + CheckButton toggle row (+36px height), reads initial state from user://settings.cfg; CheckButton state loaded from PREFS_PATH - main.tscn: DebugConsole node on ModalLayer, load_steps 27→28 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=27 format=3 uid="uid://bswrmh7w8dbgm"]
|
||||
[gd_scene load_steps=28 format=3 uid="uid://bswrmh7w8dbgm"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/main.gd" id="1_main"]
|
||||
[ext_resource type="Script" path="res://scripts/rendering/world_renderer.gd" id="2_world"]
|
||||
@@ -26,6 +26,7 @@
|
||||
[ext_resource type="PackedScene" path="res://ui/examine_display.tscn" id="24_examine"]
|
||||
[ext_resource type="PackedScene" path="res://ui/journal_panel.tscn" id="25_journal"]
|
||||
[ext_resource type="PackedScene" path="res://ui/loading_screen.tscn" id="26_loading"]
|
||||
[ext_resource type="PackedScene" uid="uid://b2ndm9rvx8cqp" path="res://ui/debug_console.tscn" id="27_debug_console"]
|
||||
|
||||
[node name="Game" type="Node2D"]
|
||||
script = ExtResource("1_main")
|
||||
@@ -194,3 +195,6 @@ layer = 30
|
||||
|
||||
; #257: Loading screen — full-screen overlay during save/load round-trip
|
||||
[node name="LoadingScreen" parent="ModalLayer" instance=ExtResource("26_loading")]
|
||||
|
||||
; #581: Debug console — tilde key toggles, bottom 40% of screen
|
||||
[node name="DebugConsole" parent="ModalLayer" instance=ExtResource("27_debug_console")]
|
||||
|
||||
@@ -81,6 +81,11 @@ var rng_seed: Variant = null
|
||||
# One-shot: consumed by main.gd after display, then set back to null.
|
||||
var save_result: Variant = null
|
||||
|
||||
# v18 fields (#580): debug console response from server.
|
||||
# {command: String, text: String, success: bool} or null.
|
||||
# One-shot: consumed by main.gd and forwarded to DebugConsole, then set to null.
|
||||
var debug_response: Variant = null
|
||||
|
||||
# #257: Pending load path — set by main menu "Load Game" selection.
|
||||
# main.gd sends LOAD_GAME on startup if non-empty, then clears this field.
|
||||
# Format: user://saves/<game-id>/<filename>.sav or "" if no pending load.
|
||||
@@ -311,6 +316,12 @@ func apply_snapshot(snapshot: Dictionary) -> void:
|
||||
else:
|
||||
save_result = null
|
||||
|
||||
# v18: debug_response (#580) — debug console command result.
|
||||
if snapshot.has("debug_response") and snapshot.debug_response is Dictionary:
|
||||
debug_response = snapshot.debug_response
|
||||
else:
|
||||
debug_response = null
|
||||
|
||||
# v14: player_knowledge (#264, D-041) — partial KG dump for journal panel.
|
||||
# Only update when field is present (null means no change, server sends when KG changes).
|
||||
if snapshot.has("player_knowledge") and snapshot.player_knowledge is Dictionary:
|
||||
|
||||
@@ -24,6 +24,7 @@ enum Action {
|
||||
TELEPORT_HUB, # #501: Home key — Gauntlet dev teleport (not production fast-travel)
|
||||
SAVE_GAME, # #554: F5 quicksave — sends SaveGame to server with save path
|
||||
LOAD_GAME, # #554: F6 quickload — sends LoadGame to server with save path
|
||||
DEBUG_COMMAND, # #581: debug console command dispatch — sends DebugCommandKind to server
|
||||
}
|
||||
|
||||
var input_queue: Array[Dictionary] = []
|
||||
|
||||
@@ -416,6 +416,8 @@ static func action_enum_to_wire(action: int) -> String:
|
||||
return "SaveGame" # #554: F5 quicksave (D-085)
|
||||
InputMapper.Action.LOAD_GAME:
|
||||
return "LoadGame" # #554: F6 quickload (D-085)
|
||||
InputMapper.Action.DEBUG_COMMAND:
|
||||
return "DebugCommand" # #581: debug console command dispatch
|
||||
_:
|
||||
push_warning("SimBridge: unknown action enum %s" % action)
|
||||
return ""
|
||||
|
||||
@@ -22,6 +22,7 @@ extends Node2D
|
||||
@onready var bug_report_dialog = $ModalLayer/BugReportDialog # #495: F12 WRONG button
|
||||
@onready var settings_dialog = $ModalLayer/SettingsDialog # #528: audio settings (ESC/OPEN_MENU)
|
||||
@onready var loading_screen = $ModalLayer/LoadingScreen # #257: blocking overlay during load
|
||||
@onready var debug_console = $ModalLayer/DebugConsole # #581: tilde debug console
|
||||
|
||||
var _last_dialogue_npc_id: int = -1 # D-064: NPC entity_id for WalkAway input
|
||||
var _last_dialogue_npc_name: String = "" # #535: NPC name for dialogue_response attribution
|
||||
@@ -122,6 +123,11 @@ func _ready() -> void:
|
||||
_router.register("conversation_ended", _consume_conversation_ended)
|
||||
_router.register("dialogue_response", _consume_dialogue_response)
|
||||
_router.register("save_result", _consume_save_result)
|
||||
_router.register("debug_response", _consume_debug_response)
|
||||
|
||||
# #581: Wire settings_dialog debug console toggle → debug_console.set_enabled
|
||||
if settings_dialog and debug_console:
|
||||
settings_dialog.debug_console_toggled.connect(debug_console.set_enabled)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
@@ -382,6 +388,8 @@ func _consume_dialogue_response() -> void:
|
||||
if GameState.dialogue_response == null or not dialogue_box:
|
||||
return
|
||||
var dr: Dictionary = GameState.dialogue_response
|
||||
# v0.1: falls back to _last_dialogue_npc_id if wire omits speaker_entity_id.
|
||||
# Edge case: fast re-engagement with a different NPC could misattribute — low probability.
|
||||
var speaker_entity_id: int = dr.get("speaker_entity_id", _last_dialogue_npc_id)
|
||||
var speaker_color_index: int = dr.get("speaker_color_index", -1)
|
||||
var speaker_name: String = dr.get("speaker_name", _last_dialogue_npc_name)
|
||||
@@ -414,6 +422,14 @@ func _consume_save_result() -> void:
|
||||
monologue_display.show_notification(msg)
|
||||
|
||||
|
||||
# #581: Forward debug_response from server to the debug console.
|
||||
func _consume_debug_response() -> void:
|
||||
if GameState.debug_response == null or not debug_console:
|
||||
return
|
||||
debug_console.append_response(GameState.debug_response)
|
||||
GameState.debug_response = null
|
||||
|
||||
|
||||
# D-061: Handle dialogue option selection → send to server
|
||||
func _on_dialogue_option_selected(response_id: String, text: String) -> void:
|
||||
SimBridge.send_input({
|
||||
|
||||
@@ -244,6 +244,17 @@ static func decode_snapshot(bytes: PackedByteArray) -> Variant:
|
||||
"error": raw_save.get("error"),
|
||||
}
|
||||
|
||||
# v18: debug_response (#580) — debug console command result.
|
||||
# {command: String, text: String, success: bool}
|
||||
var debug_response: Variant = null
|
||||
var raw_debug: Variant = raw.get("debug_response")
|
||||
if raw_debug is Dictionary:
|
||||
debug_response = {
|
||||
"command": str(raw_debug.get("command", "")),
|
||||
"text": str(raw_debug.get("text", "")),
|
||||
"success": bool(raw_debug.get("success", false)),
|
||||
}
|
||||
|
||||
# TODO(server): Send stationary_ticks in ObserverSnapshot (D-071, D-020).
|
||||
# Server already tracks this in ListeningFocus component (server/src/simulation/listening.rs).
|
||||
# When server populates this field, client-side accumulation fallback in game_state.gd
|
||||
@@ -320,6 +331,7 @@ static func decode_snapshot(bytes: PackedByteArray) -> Variant:
|
||||
"examine_result": examine_result,
|
||||
"player_knowledge": player_knowledge,
|
||||
"save_result": save_result,
|
||||
"debug_response": debug_response,
|
||||
"stationary_ticks": stationary_ticks,
|
||||
"zone_id": zone_id,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
class_name DebugConsole
|
||||
extends Control
|
||||
|
||||
## In-game debug console (#581). Tilde key (`) toggles open/closed.
|
||||
## Semi-transparent panel anchored to bottom ~40% of screen.
|
||||
## Dispatches DebugCommandKind variants to server via SimBridge.
|
||||
## Settings-toggled; enabled state persisted in user://settings.cfg.
|
||||
|
||||
const PREFS_PATH := "user://settings.cfg"
|
||||
const PREFS_SECTION := "debug"
|
||||
const PREFS_KEY_ENABLED := "console_enabled"
|
||||
const MAX_LOG_LINES := 50
|
||||
|
||||
const BG_COLOR := Color(0.04, 0.04, 0.06, 0.92)
|
||||
const BORDER_COLOR := Color("#4a9ebb")
|
||||
const TEXT_COLOR := Color("#c8d0e0")
|
||||
const SUCCESS_COLOR := Color("#6bc9a6")
|
||||
const ERROR_COLOR := Color("#d45d5d")
|
||||
const INPUT_COLOR := Color("#e8c547")
|
||||
|
||||
var _enabled: bool = true
|
||||
var _open: bool = false
|
||||
var _log_lines: Array[String] = []
|
||||
var _panel: PanelContainer = null
|
||||
var _output_log: RichTextLabel = null
|
||||
var _input_line: LineEdit = null
|
||||
var _history: Array[String] = []
|
||||
var _history_idx: int = -1
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_load_prefs()
|
||||
visible = false
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
_build_ui()
|
||||
get_viewport().size_changed.connect(_update_panel_layout)
|
||||
|
||||
|
||||
func _build_ui() -> void:
|
||||
_panel = PanelContainer.new()
|
||||
_panel.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
_panel.anchor_left = 0.0
|
||||
_panel.anchor_top = 0.6
|
||||
_panel.anchor_right = 1.0
|
||||
_panel.anchor_bottom = 1.0
|
||||
_panel.offset_left = 0.0
|
||||
_panel.offset_top = 0.0
|
||||
_panel.offset_right = 0.0
|
||||
_panel.offset_bottom = 0.0
|
||||
|
||||
var bg_style := StyleBoxFlat.new()
|
||||
bg_style.bg_color = BG_COLOR
|
||||
bg_style.border_color = BORDER_COLOR
|
||||
bg_style.border_width_top = 1
|
||||
bg_style.content_margin_left = 8.0
|
||||
bg_style.content_margin_right = 8.0
|
||||
bg_style.content_margin_top = 6.0
|
||||
bg_style.content_margin_bottom = 6.0
|
||||
_panel.add_theme_stylebox_override("panel", bg_style)
|
||||
add_child(_panel)
|
||||
|
||||
var vbox := VBoxContainer.new()
|
||||
vbox.add_theme_constant_override("separation", 4)
|
||||
_panel.add_child(vbox)
|
||||
|
||||
_output_log = RichTextLabel.new()
|
||||
_output_log.bbcode_enabled = true
|
||||
_output_log.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
_output_log.scroll_following = true
|
||||
_output_log.selection_enabled = true
|
||||
_output_log.add_theme_color_override("default_color", TEXT_COLOR)
|
||||
_output_log.add_theme_font_size_override("normal_font_size", 13)
|
||||
vbox.add_child(_output_log)
|
||||
|
||||
var sep := HSeparator.new()
|
||||
vbox.add_child(sep)
|
||||
|
||||
_input_line = LineEdit.new()
|
||||
_input_line.placeholder_text = "enter command (help for list)"
|
||||
_input_line.clear_button_enabled = false
|
||||
_input_line.add_theme_font_size_override("font_size", 13)
|
||||
_input_line.add_theme_color_override("font_color", INPUT_COLOR)
|
||||
_input_line.text_submitted.connect(_on_input_submitted)
|
||||
_input_line.gui_input.connect(_on_input_key)
|
||||
vbox.add_child(_input_line)
|
||||
|
||||
|
||||
func _update_panel_layout() -> void:
|
||||
# Anchors handle resize automatically; no manual size calc needed.
|
||||
pass
|
||||
|
||||
|
||||
# -- Input handling --
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if not _enabled:
|
||||
return
|
||||
if not event is InputEventKey or not event.pressed or event.echo:
|
||||
return
|
||||
if event.keycode == KEY_QUOTELEFT:
|
||||
get_viewport().set_input_as_handled()
|
||||
_toggle()
|
||||
return
|
||||
if _open:
|
||||
# Consume all keyboard events — prevent movement/action leaking through
|
||||
get_viewport().set_input_as_handled()
|
||||
if event.keycode == KEY_ESCAPE:
|
||||
_close()
|
||||
|
||||
|
||||
func _on_input_key(event: InputEvent) -> void:
|
||||
if not event is InputEventKey or not event.pressed or event.echo:
|
||||
return
|
||||
if event.keycode == KEY_UP:
|
||||
_history_up()
|
||||
get_viewport().set_input_as_handled()
|
||||
elif event.keycode == KEY_DOWN:
|
||||
_history_down()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func _toggle() -> void:
|
||||
if _open:
|
||||
_close()
|
||||
else:
|
||||
_open_console()
|
||||
|
||||
|
||||
func _open_console() -> void:
|
||||
_open = true
|
||||
visible = true
|
||||
mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
_input_line.clear()
|
||||
_input_line.grab_focus()
|
||||
_history_idx = -1
|
||||
|
||||
|
||||
func _close() -> void:
|
||||
_open = false
|
||||
visible = false
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_input_line.release_focus()
|
||||
|
||||
|
||||
func is_open() -> bool:
|
||||
return _open
|
||||
|
||||
|
||||
# -- Command input --
|
||||
|
||||
func _on_input_submitted(text: String) -> void:
|
||||
var trimmed := text.strip_edges()
|
||||
_input_line.clear()
|
||||
_history_idx = -1
|
||||
if trimmed.is_empty():
|
||||
return
|
||||
if _history.is_empty() or _history[0] != trimmed:
|
||||
_history.push_front(trimmed)
|
||||
if _history.size() > 20:
|
||||
_history.pop_back()
|
||||
_append_text("> " + trimmed, TEXT_COLOR)
|
||||
_dispatch(trimmed)
|
||||
|
||||
|
||||
func _dispatch(line: String) -> void:
|
||||
var parts := line.split(" ", false)
|
||||
if parts.is_empty():
|
||||
return
|
||||
var cmd := parts[0].to_lower()
|
||||
match cmd:
|
||||
"help":
|
||||
_print_help()
|
||||
"ticks":
|
||||
if parts.size() < 2 or not parts[1].is_valid_int():
|
||||
_append_text("usage: ticks <n>", ERROR_COLOR)
|
||||
return
|
||||
var n := int(parts[1])
|
||||
if n <= 0:
|
||||
_append_text("ticks: n must be > 0", ERROR_COLOR)
|
||||
return
|
||||
_send_debug({"AdvanceTicks": n})
|
||||
"contaminate":
|
||||
_send_debug("SkipToContamination")
|
||||
"tp":
|
||||
if parts.size() < 2:
|
||||
_append_text("usage: tp <x> <y> [z] or tp <location_name>", ERROR_COLOR)
|
||||
return
|
||||
if parts.size() >= 3 and parts[1].is_valid_int() and parts[2].is_valid_int():
|
||||
var z := int(parts[3]) if parts.size() >= 4 and parts[3].is_valid_int() else 0
|
||||
_send_debug({"TeleportToPosition": {"x": int(parts[1]), "y": int(parts[2]), "z": z}})
|
||||
else:
|
||||
var loc := " ".join(PackedStringArray(parts.slice(1)))
|
||||
_send_debug({"TeleportToLocation": loc})
|
||||
"activate":
|
||||
_send_debug("ForceContaminationActivate")
|
||||
"triangle":
|
||||
if parts.size() < 2:
|
||||
_append_text("usage: triangle <id>", ERROR_COLOR)
|
||||
return
|
||||
_send_debug({"ForceTriangleActivation": parts[1]})
|
||||
"npc":
|
||||
if parts.size() < 2 or not parts[1].is_valid_int():
|
||||
_append_text("usage: npc <entity_id>", ERROR_COLOR)
|
||||
return
|
||||
_send_debug({"InspectNpc": int(parts[1])})
|
||||
"triangles":
|
||||
_send_debug("ListTriangles")
|
||||
"pop":
|
||||
_send_debug("ListPopulation")
|
||||
"status":
|
||||
_send_debug("GetContaminationStatus")
|
||||
_:
|
||||
_append_text("unknown command: '%s' (type 'help')" % cmd, ERROR_COLOR)
|
||||
|
||||
|
||||
func _send_debug(kind: Variant) -> void:
|
||||
var err := SimBridge.send_input({
|
||||
"action": InputMapper.Action.DEBUG_COMMAND,
|
||||
"action_data": kind,
|
||||
"timestamp_msec": Time.get_ticks_msec(),
|
||||
})
|
||||
if err != OK:
|
||||
_append_text("send error: %s" % error_string(err), ERROR_COLOR)
|
||||
|
||||
|
||||
# -- Response display --
|
||||
|
||||
## Append a server debug response to the output log. Auto-opens console if closed.
|
||||
func append_response(response: Dictionary) -> void:
|
||||
var success: bool = response.get("success", false)
|
||||
var text: String = response.get("text", "")
|
||||
var color := SUCCESS_COLOR if success else ERROR_COLOR
|
||||
_append_text(text, color)
|
||||
if not _open:
|
||||
_open_console()
|
||||
|
||||
|
||||
# -- Log rendering --
|
||||
|
||||
func _append_text(text: String, color: Color) -> void:
|
||||
var escaped := text.replace("[", "[lb]").replace("]", "[rb]")
|
||||
_log_lines.append("[color=%s]%s[/color]" % [color.to_html(false), escaped])
|
||||
if _log_lines.size() > MAX_LOG_LINES:
|
||||
_log_lines = _log_lines.slice(_log_lines.size() - MAX_LOG_LINES)
|
||||
if _output_log:
|
||||
_output_log.text = "\n".join(_log_lines)
|
||||
|
||||
|
||||
func _print_help() -> void:
|
||||
_append_text(
|
||||
"Commands:\n"
|
||||
+ " ticks <n> — fast-forward N ticks\n"
|
||||
+ " contaminate — skip to contamination phase\n"
|
||||
+ " tp <x> <y> [z] — teleport to tile position\n"
|
||||
+ " tp <location> — teleport to named location\n"
|
||||
+ " activate — force contamination activate\n"
|
||||
+ " triangle <id> — force triangle activation\n"
|
||||
+ " npc <entity_id> — inspect NPC state\n"
|
||||
+ " triangles — list all triangles\n"
|
||||
+ " pop — list active NPCs\n"
|
||||
+ " status — contamination status\n"
|
||||
+ " help — this list",
|
||||
TEXT_COLOR
|
||||
)
|
||||
|
||||
|
||||
# -- Command history --
|
||||
|
||||
func _history_up() -> void:
|
||||
if _history.is_empty():
|
||||
return
|
||||
_history_idx = mini(_history_idx + 1, _history.size() - 1)
|
||||
_input_line.text = _history[_history_idx]
|
||||
_input_line.caret_column = _input_line.text.length()
|
||||
|
||||
|
||||
func _history_down() -> void:
|
||||
if _history_idx <= 0:
|
||||
_history_idx = -1
|
||||
_input_line.clear()
|
||||
return
|
||||
_history_idx -= 1
|
||||
_input_line.text = _history[_history_idx]
|
||||
_input_line.caret_column = _input_line.text.length()
|
||||
|
||||
|
||||
# -- Settings --
|
||||
|
||||
func set_enabled(enabled: bool) -> void:
|
||||
_enabled = enabled
|
||||
if not _enabled and _open:
|
||||
_close()
|
||||
_save_prefs()
|
||||
|
||||
|
||||
func is_enabled() -> bool:
|
||||
return _enabled
|
||||
|
||||
|
||||
func _load_prefs() -> void:
|
||||
var cfg := ConfigFile.new()
|
||||
if cfg.load(PREFS_PATH) != OK:
|
||||
return
|
||||
_enabled = cfg.get_value(PREFS_SECTION, PREFS_KEY_ENABLED, true)
|
||||
|
||||
|
||||
func _save_prefs() -> void:
|
||||
var cfg := ConfigFile.new()
|
||||
cfg.load(PREFS_PATH) # load existing (may have other sections like "audio")
|
||||
cfg.set_value(PREFS_SECTION, PREFS_KEY_ENABLED, _enabled)
|
||||
var err := cfg.save(PREFS_PATH)
|
||||
if err != OK:
|
||||
push_warning("DebugConsole: failed to save prefs (%d)" % err)
|
||||
@@ -0,0 +1 @@
|
||||
uid://c8pvt3xr7kmd2
|
||||
@@ -0,0 +1,15 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://b2ndm9rvx8cqp"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://c8pvt3xr7kmd2" path="res://ui/debug_console.gd" id="1_debug_console"]
|
||||
|
||||
; #581: In-game debug console. Tilde key toggles. ModalLayer.
|
||||
; UI built programmatically in _ready() — scene contains only root node + script.
|
||||
[node name="DebugConsole" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 1
|
||||
script = ExtResource("1_debug_console")
|
||||
@@ -11,7 +11,7 @@ const TITLE_COLOR := Color("#4a9ebb")
|
||||
const FONT_SIZE := 14
|
||||
|
||||
const BOX_WIDTH := 460
|
||||
const BOX_HEIGHT := 340
|
||||
const BOX_HEIGHT := 376 # +36 for Debug Console row
|
||||
const PADDING := 20
|
||||
const ROW_HEIGHT := 36
|
||||
|
||||
@@ -28,6 +28,7 @@ var _active: bool = false
|
||||
var _container: VBoxContainer = null
|
||||
|
||||
signal closed
|
||||
signal debug_console_toggled(enabled: bool) # #581: debug console enabled/disabled
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -109,6 +110,29 @@ func _build_ui() -> void:
|
||||
db_label.text = _format_db(value)
|
||||
)
|
||||
|
||||
# #581: Debug Console toggle
|
||||
var debug_hbox := HBoxContainer.new()
|
||||
debug_hbox.custom_minimum_size = Vector2(0, ROW_HEIGHT)
|
||||
_container.add_child(debug_hbox)
|
||||
|
||||
var debug_label := Label.new()
|
||||
debug_label.text = "Debug Console"
|
||||
debug_label.custom_minimum_size = Vector2(150, 0)
|
||||
debug_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
debug_label.add_theme_font_size_override("font_size", FONT_SIZE)
|
||||
debug_label.add_theme_color_override("font_color", TEXT_COLOR)
|
||||
debug_hbox.add_child(debug_label)
|
||||
|
||||
var debug_check := CheckButton.new()
|
||||
var cfg := ConfigFile.new()
|
||||
debug_check.button_pressed = true # default: enabled
|
||||
if cfg.load(DebugConsole.PREFS_PATH) == OK:
|
||||
debug_check.button_pressed = cfg.get_value(DebugConsole.PREFS_SECTION, DebugConsole.PREFS_KEY_ENABLED, true)
|
||||
debug_check.toggled.connect(func(enabled: bool) -> void:
|
||||
debug_console_toggled.emit(enabled)
|
||||
)
|
||||
debug_hbox.add_child(debug_check)
|
||||
|
||||
# Spacer
|
||||
var spacer := Control.new()
|
||||
spacer.custom_minimum_size = Vector2(0, 8)
|
||||
|
||||
Reference in New Issue
Block a user