diff --git a/ovr-utils/addons/settings-manager/Settings.tscn b/ovr-utils/addons/settings-manager/Settings.tscn new file mode 100644 index 0000000..5ad12ee --- /dev/null +++ b/ovr-utils/addons/settings-manager/Settings.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/settings-manager/settings.gd" type="Script" id=1] + +[node name="Settings" type="Node"] +script = ExtResource( 1 ) + +[node name="AutosaveTimer" type="Timer" parent="."] +wait_time = 300.0 +autostart = true + +[connection signal="timeout" from="AutosaveTimer" to="." method="_on_AutosaveTimer_timeout"] diff --git a/ovr-utils/addons/settings-manager/settings.gd b/ovr-utils/addons/settings-manager/settings.gd index be0316c..e1ca16b 100644 --- a/ovr-utils/addons/settings-manager/settings.gd +++ b/ovr-utils/addons/settings-manager/settings.gd @@ -1,10 +1,10 @@ extends Node -signal setting_changed # emitted with name, value +signal settings_saved signal settings_loaded # emitted when settings are loaded from file, needs to be connected in _init() -const DEBUG_SETTINGS = false -const SETTINGS_PATH = "user://settings.json" +var DEBUG_SETTINGS = true +var SETTINGS_PATH = "user://settings.json" const SETTINGS_DEF = { "example_1": { "name": "Example Toggle", @@ -16,66 +16,130 @@ const SETTINGS_DEF = { "example_2": { "name": "Example Number", "type": "number", - "default": 42, - "min": 1, # optional - "max": 100, # optional - "step": 4 # optional + "default": 42 }, "example_3": { - "name": "Example text", - "type": "string", - "default": "hello world" + "name": "Example section", + "type": "dict", + "definition": { + "example_4": { + "name": "Example text", + "type": "string", + "default": "hello world" + }, + "example_5": { + "name": "Example Vector3", + "type": "vector3", + "default": Vector3(1,2,3) + }, + "example_6": { + "name": "Example Quat", + "type": "quat", + "default": Quat() + } + } + }, + "example_7": { + "name": "Example array", + "type": "array", + "default": [1,23,4] + }, + "example_8": { + "name": "Example dict with varying size containing arrays", + "type": "dict", + "flags": ["resize"], + "definition": { + "type": "array", + "default": [99,45,1] + } + }, + "example_9": { + "name": "Example dict with varying size containing more dicts", + "type": "dict", + "flags": ["resize"], + "definition": { + "type": "dict", + "definition": { + "property1": { + "name": "Property 1", + "type": "number", + "default": 123 + }, + "property2": { + "name": "Property 2", + "type": "number", + "default": 345 + }, + } + } }, - "example_4": { - "name": "Example Vector3", - "type": "Vector3", - "default": [1, 2, 3] - } } -var _settings = {} +var s: Dictionary = {} func _ready() -> void: _init_settings() load_settings() - emit_signal("settings_loaded") save_settings() -func get_setting(key): - return _settings[key] - - -func set_setting(key, val): - if _settings[key] == val: - return - _settings[key] = val - - emit_signal("setting_changed", key, val) - save_settings() - - if DEBUG_SETTINGS: - print("Settings changed: ", key, " -> ", val) - - -func _init_settings(): +func _init_settings() -> void: for key in SETTINGS_DEF: - _settings[key] = SETTINGS_DEF[key].default + s[key] = _init_sub_setting(SETTINGS_DEF[key]) if DEBUG_SETTINGS: - print("Default settings: ", _settings) + print("Default settings: ", s) + + +func _init_sub_setting(def): + match def.type: + "dict": + if has_flag(def, "resize"): + return {} + var _s = {} + for key in def.definition: + _s[key] = _init_sub_setting(def.definition[key]) + return _s + _: + return def.default func save_settings(): var to_save = {} - for key in _settings: - if not (SETTINGS_DEF[key].has("flags") and "no_save" in SETTINGS_DEF[key].flags): - to_save[key] = _settings[key] + for key in s: + var val = _save_sub_setting(s[key], SETTINGS_DEF[key]) + if val != null: + to_save[key] = val var file = File.new() file.open(SETTINGS_PATH, File.WRITE) file.store_line(to_json(to_save)) file.close() + emit_signal("settings_saved") + + +func _save_sub_setting(val, def): + if has_flag(def, "no_save"): + return null + + match def.type: + "vector2": + return [val.x, val.y] + "vector3": + return [val.x, val.y, val.z] + "quat": + return [val.x, val.y, val.z, val.w] + "dict": + var resize = has_flag(def, "resize") + var _s = {} + for key in val: + var subdef = def.definition if resize else def.definition[key] + var v = _save_sub_setting(val[key], subdef) + if v != null: + _s[key] = v + return _s + _: + return val func load_settings() -> void: @@ -90,18 +154,43 @@ func load_settings() -> void: var new_settings = parse_json(file.get_as_text()) file.close() - # in case the settings format has changed, this is better than just clonging blindly for key in new_settings: - if _settings.has(key): - var value = new_settings[key] - match SETTINGS_DEF[key].type: - ["Vector2", "vector2"]: - _settings[key] = Vector2(value[0], value[1]) - ["Vector3", "vector3"]: - _settings[key] = Vector3(value[0], value[1], value[2]) - _: - _settings[key] = value + s[key] = _load_sub_setting(new_settings[key], SETTINGS_DEF[key]) + emit_signal("settings_loaded") if DEBUG_SETTINGS: print("Loaded settings from file") - print(_settings) + print(s) + + +func _load_sub_setting(val, def): + match def.type: + "vector2": + return Vector2(val[0], val[1]) + "vector3": + return Vector3(val[0], val[1], val[2]) + "quat": + return Quat(val[0], val[1], val[2], val[3]) + "dict": + var _s = {} + var resize = has_flag(def, "resize") + for key in val: + var subdef = def.definition if resize else def.definition[key] + _s[key] = _load_sub_setting(val[key], subdef) + return _s + _: + return val + + +func has_flag(def, flag): + return def.has("flags") and flag in def.flags + + +func _exit_tree() -> void: + # save on quit + save_settings() + + +func _on_AutosaveTimer_timeout() -> void: + # auto saves every 5 minutes, saving should also be done manually + save_settings() diff --git a/ovr-utils/addons/settings-manager/settings_manager.gd b/ovr-utils/addons/settings-manager/settings_manager.gd index a7c539f..9b2e63b 100644 --- a/ovr-utils/addons/settings-manager/settings_manager.gd +++ b/ovr-utils/addons/settings-manager/settings_manager.gd @@ -3,7 +3,7 @@ extends EditorPlugin func _enter_tree() -> void: - add_autoload_singleton("Settings", "res://addons/settings-manager/settings.gd") + add_autoload_singleton("Settings", "res://addons/settings-manager/Settings.tscn") func _exit_tree() -> void: diff --git a/ovr-utils/project.godot b/ovr-utils/project.godot index b2bec3c..f74899c 100644 --- a/ovr-utils/project.godot +++ b/ovr-utils/project.godot @@ -19,11 +19,11 @@ config/icon="res://icon.png" [autoload] OverlayInit="*res://addons/openvr_overlay/overlay_init.gd" -Settings="*res://addons/settings-manager/settings.gd" +Settings="*res://addons/settings-manager/Settings.tscn" [editor_plugins] -enabled=PoolStringArray( "res://addons/openvr_overlay/plugin.cfg", "res://addons/settings-manager/plugin.cfg" ) +enabled=PoolStringArray( "res://addons/godot-openvr/plugin.cfg", "res://addons/openvr_overlay/plugin.cfg", "res://addons/settings-manager/plugin.cfg" ) [gdnative]