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
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Parse a "r, g, b" string from config into a Color with alpha 1.0.
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _load_config() -> void:
|
|
|
|
|
# Load defaults, then overlay user config.
|
|
|
|
|
var defaults := _read_json_file("res://config/default.json")
|
|
|
|
|
var user := _read_json_file("res://config/config.json")
|
|
|
|
|
|
|
|
|
|
_settings.clear()
|
|
|
|
|
if defaults != null and defaults is Dictionary:
|
|
|
|
|
_merge_dict(_settings, defaults as Dictionary)
|
|
|
|
|
if user != null and user is Dictionary:
|
|
|
|
|
_merge_dict(_settings, user as Dictionary)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static func _read_json_file(path: String) -> Variant:
|
|
|
|
|
var file := FileAccess.open(path, FileAccess.READ)
|
|
|
|
|
if file == null:
|
|
|
|
|
return null
|
|
|
|
|
var content: String = file.get_as_text()
|
|
|
|
|
var parsed: Variant = JSON.parse_string(content)
|
|
|
|
|
return parsed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static func _merge_dict(dst: Dictionary, src: Dictionary) -> void:
|
|
|
|
|
for key in src:
|
|
|
|
|
dst[key] = src[key]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _save_user_config() -> void:
|
|
|
|
|
# Only persists settings that differ from defaults.
|
|
|
|
|
var defaults := _read_json_file("res://config/default.json")
|
|
|
|
|
if not (defaults is Dictionary):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var diff: Dictionary = {}
|
|
|
|
|
for key in _settings:
|
|
|
|
|
if not defaults.has(key) or defaults[key] != _settings[key]:
|
|
|
|
|
diff[key] = _settings[key]
|
|
|
|
|
|
|
|
|
|
var path: String = "res://config/config.json"
|
|
|
|
|
var json_str: String = JSON.stringify(diff, "\t")
|
|
|
|
|
var file := FileAccess.open(path, FileAccess.WRITE)
|
|
|
|
|
if file != null:
|
|
|
|
|
file.store_string(json_str)
|