godot-plateformer/__settings/SettingModel.gd

109 lines
3.2 KiB
GDScript3
Raw Normal View History

2026-01-15 17:43:58 +08:00
# scripts/settings/SettingsModel.gd
extends Node
class_name SettingsModel
## ===============================
## Dependencies
## ===============================
const SettingsSchema = preload("res://__settings/SettingSchema.gd")
const SettingsStorage = preload("res://__settings/SettingStorage.gd")
## ===============================
## Signals
## ===============================
signal setting_changed(section: String, key: String, value)
signal settings_applied
signal settings_reverted
## ===============================
## Internal State
## ===============================
var _data_committed : Dictionary = {} # 已生效 / 已保存
var _data_working : Dictionary = {} # UI 正在修改
var _storage := SettingsStorage.new()
## ===============================
## Lifecycle
## ===============================
func _ready() -> void:
_load()
## ===============================
## Public API (Read)
## ===============================
func get_setting(section: String, key: String) -> Variant:
return _data_working.get(section, {}).get(key)
func get_section(section: String) -> Dictionary:
return _data_working.get(section, {}).duplicate(true)
## ===============================
## Public API (Write - Working Only)
## ===============================
func set_setting(section: String, key: String, value: Variant) -> void:
if not _data_working.has(section):
_data_working[section] = {}
_data_working[section][key] = value
emit_signal("setting_changed", section, key, value)
## ===============================
## Typed Getters
## ===============================
func get_bool(section: String, key: String) -> bool:
var value = get_setting(section, key)
return value if typeof(value) == TYPE_BOOL else false
func get_int(section: String, key: String) -> int:
var value = get_setting(section, key)
return value if typeof(value) == TYPE_INT else 0
func get_float(section: String, key: String) -> float:
var value = get_setting(section, key)
if typeof(value) == TYPE_FLOAT or typeof(value) == TYPE_INT:
return float(value)
return 0.0
func get_string(section: String, key: String) -> String:
var value = get_setting(section, key)
return value if typeof(value) == TYPE_STRING else ""
## ===============================
## Transaction Control
## ===============================
func apply() -> void:
_data_committed = _data_working.duplicate(true)
for section in _data_committed.keys():
for key in _data_committed[section].keys():
_storage.set_value(section, key, _data_committed[section][key])
_storage.save()
emit_signal("settings_applied")
func revert() -> void:
_data_working = _data_committed.duplicate(true)
emit_signal("settings_reverted")
func has_unsaved_changes() -> bool:
return _data_working != _data_committed
## ===============================
## Internal
## ===============================
func _load() -> void:
_storage.load()
# 1. Load defaults
_data_committed = SettingsSchema.defaults().duplicate(true)
# 2. Override with saved values
for section in _data_committed.keys():
for key in _data_committed[section].keys():
var default_value = _data_committed[section][key]
var value = _storage.get_value(section, key, default_value)
_data_committed[section][key] = value
# 3. Init working copy
_data_working = _data_committed.duplicate(true)