feat: file-based config system + fix dashboard background rendering
This commit is contained in:
parent
c026c74af2
commit
c6bc1edda4
7 changed files with 97 additions and 20 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -15,6 +15,9 @@ godot_temp_*
|
||||||
*.swo
|
*.swo
|
||||||
*~
|
*~
|
||||||
|
|
||||||
|
# Config — user overrides, not committed
|
||||||
|
config/config.json
|
||||||
|
|
||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,77 @@ extends Node
|
||||||
|
|
||||||
signal config_changed(key: String, value: Variant)
|
signal config_changed(key: String, value: Variant)
|
||||||
|
|
||||||
var _settings: Dictionary = {
|
var _settings: Dictionary = {}
|
||||||
"refresh_interval": 1.0,
|
|
||||||
"show_cpu": true,
|
|
||||||
"show_memory": true,
|
func _ready() -> void:
|
||||||
"show_network": true,
|
_load_config()
|
||||||
"show_disk": true,
|
|
||||||
"theme": "default",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func get_setting(key: String, default_value: Variant = null) -> Variant:
|
func get_setting(key: String, default_value: Variant = null) -> Variant:
|
||||||
return _settings.get(key, default_value)
|
return _settings.get(key, default_value)
|
||||||
|
|
||||||
|
|
||||||
func set_setting(key: String, value: Variant) -> void:
|
func set_setting(key: String, value: Variant) -> void:
|
||||||
if _settings.has(key) and _settings[key] != value:
|
if _settings.has(key) and _settings[key] != value:
|
||||||
_settings[key] = value
|
_settings[key] = value
|
||||||
config_changed.emit(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)
|
||||||
|
|
|
||||||
9
config/default.json
Normal file
9
config/default.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"background_color": "0.08, 0.08, 0.12",
|
||||||
|
"refresh_interval": 1.0,
|
||||||
|
"show_cpu": true,
|
||||||
|
"show_memory": true,
|
||||||
|
"show_network": true,
|
||||||
|
"show_disk": true,
|
||||||
|
"theme": "default"
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
@tool
|
@tool
|
||||||
extends Control
|
extends PanelContainer
|
||||||
|
|
||||||
|
|
||||||
@onready var grid: DashboardGrid = %DashboardGrid
|
@onready var grid: DashboardGrid = %DashboardGrid
|
||||||
|
|
@ -8,16 +8,19 @@ var _modules: Array = []
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
if Engine.is_editor_hint():
|
|
||||||
_set_background()
|
|
||||||
return
|
|
||||||
_set_background()
|
_set_background()
|
||||||
_add_modules()
|
if not Engine.is_editor_hint():
|
||||||
|
_add_modules()
|
||||||
|
|
||||||
|
|
||||||
func _set_background() -> void:
|
func _set_background() -> void:
|
||||||
var bg := StyleBoxFlat.new()
|
var bg: StyleBoxFlat
|
||||||
bg.bg_color = Color(0.08, 0.08, 0.12, 1.0)
|
if ConfigManager.has_method("get_color"):
|
||||||
|
bg = StyleBoxFlat.new()
|
||||||
|
bg.bg_color = ConfigManager.get_color("background_color", Color(0.08, 0.08, 0.12))
|
||||||
|
else:
|
||||||
|
bg = StyleBoxFlat.new()
|
||||||
|
bg.bg_color = Color(0.08, 0.08, 0.12)
|
||||||
add_theme_stylebox_override("panel", bg)
|
add_theme_stylebox_override("panel", bg)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
[ext_resource type="Script" path="res://scripts/dashboard_grid.gd" id="2"]
|
[ext_resource type="Script" path="res://scripts/dashboard_grid.gd" id="2"]
|
||||||
[ext_resource type="Theme" path="res://themes/default_theme.tres" id="3"]
|
[ext_resource type="Theme" path="res://themes/default_theme.tres" id="3"]
|
||||||
|
|
||||||
[node name="Dashboard" type="Control"]
|
[node name="Dashboard" type="PanelContainer"]
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
extends Control
|
extends Control
|
||||||
|
|
||||||
|
|
||||||
|
@onready var bg: ColorRect = %Bg
|
||||||
@onready var v_label: Label = %VLabel
|
@onready var v_label: Label = %VLabel
|
||||||
@onready var panel_label: Label = %PanelLabel
|
@onready var panel_label: Label = %PanelLabel
|
||||||
@onready var transition_overlay: ColorRect = %TransitionOverlay
|
@onready var transition_overlay: ColorRect = %TransitionOverlay
|
||||||
|
|
@ -20,6 +21,10 @@ func _ready() -> void:
|
||||||
|
|
||||||
var screen_size: Vector2 = get_viewport_rect().size
|
var screen_size: Vector2 = get_viewport_rect().size
|
||||||
|
|
||||||
|
# Background color from config
|
||||||
|
if ConfigManager.has_method("get_color"):
|
||||||
|
bg.color = ConfigManager.get_color("background_color", Color(0.08, 0.08, 0.12))
|
||||||
|
|
||||||
# Compute end font sizes as a large fraction of screen height.
|
# Compute end font sizes as a large fraction of screen height.
|
||||||
# Use set() to go through the property system directly.
|
# Use set() to go through the property system directly.
|
||||||
_v_end = maxi(1, int(screen_size.y * 0.28))
|
_v_end = maxi(1, int(screen_size.y * 0.28))
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ theme = ExtResource("3")
|
||||||
script = ExtResource("1")
|
script = ExtResource("1")
|
||||||
|
|
||||||
[node name="Bg" type="ColorRect" parent="."]
|
[node name="Bg" type="ColorRect" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue