2026-05-20 12:41:00 -04:00
|
|
|
extends Node
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal config_changed(key: String, value: Variant)
|
|
|
|
|
|
2026-05-20 22:28:46 -04:00
|
|
|
var _settings: Dictionary = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ready() -> void:
|
|
|
|
|
_load_config()
|
2026-05-20 12:41:00 -04:00
|
|
|
|
|
|
|
|
|
2026-05-20 22:32:17 -04:00
|
|
|
## Read a flat setting by key (e.g. "background_color", "show_cpu").
|
2026-05-20 12:41:00 -04:00
|
|
|
func get_setting(key: String, default_value: Variant = null) -> Variant:
|
2026-05-20 22:28:46 -04:00
|
|
|
return _settings.get(key, default_value)
|
2026-05-20 12:41:00 -04:00
|
|
|
|
|
|
|
|
|
2026-05-20 22:32:17 -04:00
|
|
|
## Persist a setting and emit the change signal.
|
2026-05-20 12:41:00 -04:00
|
|
|
func set_setting(key: String, value: Variant) -> void:
|
2026-05-20 22:28:46 -04:00
|
|
|
if _settings.has(key) and _settings[key] != value:
|
|
|
|
|
_settings[key] = value
|
|
|
|
|
_save_user_config()
|
|
|
|
|
config_changed.emit(key, value)
|
|
|
|
|
|
|
|
|
|
|
2026-05-20 22:32:17 -04:00
|
|
|
## Parse a "r, g, b" string setting into a Color (alpha = 1.0).
|
2026-05-20 22:28:46 -04:00
|
|
|
func get_color(key: String, default_color: Color = Color.WHITE) -> Color:
|
|
|
|
|
var raw: Variant = _settings.get(key)
|
|
|
|
|
if raw == null or typeof(raw) != TYPE_STRING:
|
|
|
|
|
return default_color
|
|
|
|
|
var parts: PackedStringArray = (raw as String).split(",", false)
|
|
|
|
|
if parts.size() < 3:
|
|
|
|
|
return default_color
|
|
|
|
|
var r: float = parts[0].strip_edges().to_float()
|
|
|
|
|
var g: float = parts[1].strip_edges().to_float()
|
|
|
|
|
var b: float = parts[2].strip_edges().to_float()
|
|
|
|
|
return Color(r, g, b, 1.0)
|
|
|
|
|
|
|
|
|
|
|
2026-05-20 22:32:17 -04:00
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# INI loading via Godot's ConfigFile
|
|
|
|
|
# Keys are flattened as "{section}_{key}" for simple lookup.
|
|
|
|
|
# User config.cfg overrides default.cfg on a per-key basis.
|
|
|
|
|
# --------------------------------------------------------------------------
|
2026-05-20 22:28:46 -04:00
|
|
|
|
2026-05-20 22:32:17 -04:00
|
|
|
func _load_config() -> void:
|
2026-05-20 22:28:46 -04:00
|
|
|
_settings.clear()
|
2026-05-20 22:32:17 -04:00
|
|
|
_load_cfg("res://config/default.cfg")
|
|
|
|
|
_load_cfg("res://config/config.cfg") # silently ignored if absent
|
2026-05-20 22:28:46 -04:00
|
|
|
|
|
|
|
|
|
2026-05-20 22:32:17 -04:00
|
|
|
func _load_cfg(path: String) -> void:
|
|
|
|
|
var cfg := ConfigFile.new()
|
|
|
|
|
if cfg.load(path) != OK:
|
|
|
|
|
return
|
|
|
|
|
for section in cfg.get_sections():
|
|
|
|
|
for key in cfg.get_section_keys(section):
|
|
|
|
|
_settings[section + "_" + key] = cfg.get_value(section, key)
|
2026-05-20 22:28:46 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func _save_user_config() -> void:
|
2026-05-20 22:32:17 -04:00
|
|
|
# Load defaults to compare against.
|
|
|
|
|
var defaults := ConfigFile.new()
|
|
|
|
|
if defaults.load("res://config/default.cfg") != OK:
|
2026-05-20 22:28:46 -04:00
|
|
|
return
|
|
|
|
|
|
2026-05-20 22:32:17 -04:00
|
|
|
# Collect default keys for reference.
|
|
|
|
|
var default_keys: Dictionary = {}
|
|
|
|
|
for section in defaults.get_sections():
|
|
|
|
|
for key in defaults.get_section_keys(section):
|
|
|
|
|
default_keys[section + "_" + key] = { "section": section, "key": key }
|
|
|
|
|
|
|
|
|
|
var user_cfg := ConfigFile.new()
|
|
|
|
|
var has_diff: bool = false
|
|
|
|
|
|
|
|
|
|
for flat_key in _settings:
|
|
|
|
|
var entry: Variant = default_keys.get(flat_key)
|
|
|
|
|
var section: String
|
|
|
|
|
var cfg_key: String
|
|
|
|
|
if entry != null:
|
|
|
|
|
section = entry.section
|
|
|
|
|
cfg_key = entry.key
|
|
|
|
|
else:
|
|
|
|
|
# Not in defaults — derive section from flat key (before first "_").
|
|
|
|
|
var parts: PackedStringArray = flat_key.split("_", true, 1)
|
|
|
|
|
section = parts[0] if parts.size() > 1 else "general"
|
|
|
|
|
cfg_key = parts[-1]
|
|
|
|
|
|
|
|
|
|
var default_val: Variant = defaults.get_value(section, cfg_key, null)
|
|
|
|
|
if _settings[flat_key] != default_val:
|
|
|
|
|
user_cfg.set_value(section, cfg_key, _settings[flat_key])
|
|
|
|
|
has_diff = true
|
|
|
|
|
|
|
|
|
|
if has_diff:
|
|
|
|
|
user_cfg.save("res://config/config.cfg")
|