# 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)