diff --git a/.gitignore b/.gitignore index eb650cf..9d0944a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ # Godot-specific ignores .import/ export.cfg -export_presets.cfg # Imported translations (automatically generated from CSV files) *.translation diff --git a/_exports/.gitignore b/_exports/.gitignore new file mode 100644 index 0000000..687a16d --- /dev/null +++ b/_exports/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!*.md + diff --git a/_exports/readme.md b/_exports/readme.md new file mode 100644 index 0000000..3f298d4 --- /dev/null +++ b/_exports/readme.md @@ -0,0 +1,7 @@ +# _builds + +This folder is used to builds export. + +The `export_path` of `/export_presets.cfg` will export any build here + +Never commit any change to the `/export_presets.cfg` diff --git a/default_data/settings.cfg b/default_data/settings.cfg new file mode 100644 index 0000000..7338331 --- /dev/null +++ b/default_data/settings.cfg @@ -0,0 +1,31 @@ +[user] +fps_overlay=false +sensitivity=1.0 +sensitivity_game=0 +sensitivity_game_value=0.022 + +[crosshair] +color=Color(0, 255, 0, 1) +outline_color=Color(0, 0, 0, 1) +enable_outline=false +dot_enable=false +dot_size=2.0 +outline_width=1.0 +thickness=1.0 +length=10.0 +gap=5.0 + +[world] +world_texture="checkerboard.png" +world_color=Color(0.361, 0.616, 1, 1) +target_color=Color(1, 0.749, 0, 1) + +[video] +fov=80 +window_mode="fullscreen" +resolution=1.0 +fps_limit=120 + +[audio] +volume=1.0 +hit_sound="beep" diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..531fe19 --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,62 @@ +[preset.0] + +name="Windows Desktop" +platform="Windows Desktop" +runnable=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="*.cfg" +exclude_filter="" +export_path="_exports/LibreAim.exe" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_wrapper=1 +binary_format/embed_pck=true +texture_format/bptc=true +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +binary_format/architecture="x86_64" +codesign/enable=false +codesign/timestamp=true +codesign/timestamp_server_url="" +codesign/digest_algorithm=1 +codesign/description="" +codesign/custom_options=PackedStringArray() +application/modify_resources=true +application/icon="res://icon.svg" +application/console_wrapper_icon="" +application/icon_interpolation=4 +application/file_version="" +application/product_version="" +application/company_name="" +application/product_name="" +application/file_description="" +application/copyright="" +application/trademarks="" +application/export_angle=0 +ssh_remote_deploy/enabled=false +ssh_remote_deploy/host="user@host_ip" +ssh_remote_deploy/port="22" +ssh_remote_deploy/extra_args_ssh="" +ssh_remote_deploy/extra_args_scp="" +ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}' +$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}' +$trigger = New-ScheduledTaskTrigger -Once -At 00:00 +$settings = New-ScheduledTaskSettingsSet +$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings +Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true +Start-ScheduledTask -TaskName godot_remote_debug +while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 } +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue" +ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue +Remove-Item -Recurse -Force '{temp_dir}'" diff --git a/scenes/autoload/data_manager.gd b/scenes/autoload/data_manager.gd index 5847e88..9cffaef 100644 --- a/scenes/autoload/data_manager.gd +++ b/scenes/autoload/data_manager.gd @@ -1,86 +1,113 @@ extends Node -const FILE_NAME: String = "settings.json" -const FILE_PATH: String = "user://" + FILE_NAME -## JSON file is divided in categories in order to keep things organized. -const CATEGORIES_ROUTES: Dictionary = { - categories.SETTINGS: "settings", - categories.CROSSHAIR: "crosshair", - categories.HIGH_SCORE: "high_score" -} +const USER_PATH: String = "user://data/" +const FORMAT: String = "cfg" +const DEFAULT_PATH :String = "res://default_data/" -enum categories { SETTINGS, CROSSHAIR, HIGH_SCORE } +const SETTINGS_FILE_PATH := "settings" +const HIGHSCORE_FILE_PATH := "highscores" +const HIGHSCORE_SECTION := "user" +const LOAD_ON_READY_PATHS := [SETTINGS_FILE_PATH, HIGHSCORE_FILE_PATH] -var game_data: Dictionary = {} +var default_data :Dictionary = {} +var file_data: Dictionary = {} +var pending_file_changes :Dictionary = {} + +## save changes to disk at the end of current update frame +var auto_apply_changes := true func _ready() -> void: - load_all_data() + for file_path in LOAD_ON_READY_PATHS: + _get_config(file_path) -func save_data(key, value, category: categories, file_directory = FILE_PATH) -> void: - var category_key = CATEGORIES_ROUTES[category] - if !game_data.has(category_key): - game_data[category_key] = {} - game_data[category_key][key] = value - var json = JSON.stringify(game_data, "\t") - var file = FileAccess.open(file_directory, FileAccess.WRITE) - file.store_line(json) - file.close() +func get_wrapper(file_path: String, section: String) -> SectionWrapper: + var wrapper := SectionWrapper.new() + wrapper.file_path = file_path + wrapper.section = section + return wrapper + +func get_data(file_path: String, section: String, key :String, default :Variant = null) -> Variant: + var config := _get_config(file_path) + return config.get_value(section, key, default) + +func set_data(file_path: String, section: String, key: String, value: Variant): + var config := _get_config(file_path) + config.set_value(section, key, value) + pending_file_changes[file_path] = true + if auto_apply_changes and not get_tree().process_frame.is_connected(_save_pending): + get_tree().process_frame.connect(_save_pending, CONNECT_ONE_SHOT) func save_high_score(key: String, value) -> void: if is_high_score(key, value): - DataManager.save_data(key, value, DataManager.categories.HIGH_SCORE) + set_data(HIGHSCORE_FILE_PATH, HIGHSCORE_SECTION, key, value) func is_high_score(key: String, value) -> bool: - var category_key = CATEGORIES_ROUTES[DataManager.categories.HIGH_SCORE] - if game_data.has(category_key) \ - and game_data[category_key].has(key): - return value > game_data[category_key][key] - else: - return true + return value > get_high_score(key) func get_high_score(key: String) -> int: - var category_key = CATEGORIES_ROUTES[DataManager.categories.HIGH_SCORE] - if game_data.has(category_key) \ - and game_data[category_key].has(key): - return game_data[category_key][key] - return 0 + return get_data(HIGHSCORE_FILE_PATH, HIGHSCORE_SECTION, key, 0) -func save_all_data(file_directory: String = FILE_PATH) -> void: - var json = JSON.stringify(game_data, "\t") - var file = FileAccess.open(file_directory, FileAccess.WRITE) - file.store_line(json) - file.close() +func _get_config(file_path: String) -> ConfigFile: + if not file_data.has(file_path): + file_data[file_path] = _load_file(file_path) + return file_data[file_path] -func get_data(category: categories, key: String): - var result = null - if game_data != null \ - and game_data.has(CATEGORIES_ROUTES[category]) \ - and game_data.get(CATEGORIES_ROUTES[category]).has(key): - result = game_data.get(CATEGORIES_ROUTES[category]).get(key) - return result +# there's no reason to use this, but it's good to have it for completeness +func save_all_data() -> void: + for file_path in file_data: + _save_file(file_path) + pending_file_changes.clear() -func load_all_data(file_directory: String = FILE_PATH) -> void: - var json = JSON.new() - var result = {} - var file = FileAccess.open(file_directory, FileAccess.READ) - if file: - json.parse(file.get_as_text()) - file.close() - else: - print("File not found.") +func _save_pending(): + for file_path in pending_file_changes: + _save_file(file_path) + pending_file_changes.clear() - if json.data != null: - result = json.data - game_data = result +func _cancel_pending(): + for file_path in pending_file_changes: + _load_file(file_path) + pending_file_changes.clear() -func set_parameter_if_exists(category: categories, parameter, key: String): - var new_value = DataManager.get_data(category, key) - if new_value != null: - return new_value - return parameter +func _save_file(file_path:String): + if not file_data.has(file_path): + push_error("Data file does not exist: %s"%file_path) + return + var config := _get_config(file_path) + var full_path := USER_PATH + file_path + "."+FORMAT + DirAccess.make_dir_recursive_absolute(full_path.get_base_dir()) + var res := config.save(full_path) + assert(res == OK, "Error saving data: %s path: %s"%[res, full_path]) -func set_color_if_exists(category: categories, parameter: Color, key: String) -> Color: - var new_color = set_parameter_if_exists(category, parameter, key) - if new_color != null and new_color is String: - new_color = Global.string_to_color(new_color) - return new_color +func _load_file(file_path: String) -> ConfigFile: + var config := ConfigFile.new() + config.load(USER_PATH + file_path + "."+FORMAT) + + var default_config := _load_default_file(file_path) + if default_config != null: + _merge_config(config, default_config) + + return config + +func _load_default_file(file_path :String) -> ConfigFile: + var default_path := DEFAULT_PATH + file_path + ".cfg" + var config_file = ConfigFile.new() + config_file.load(default_path) + return config_file + +func _merge_config(config: ConfigFile, to_merge: ConfigFile): + for section in to_merge.get_sections(): + for key in to_merge.get_section_keys(section): + if config.has_section_key(section, key): + continue + var val = to_merge.get_value(section, key) + config.set_value(section, key, val) + +class SectionWrapper: + var file_path:String + var section:String + func set_data(key: String, value: Variant): + DataManager.set_data(file_path, section, key, value) + func get_data(key: String, default: Variant = null) -> Variant: + return DataManager.get_data(file_path, section, key, default) + func get_keys() -> PackedStringArray: + return DataManager.get_config(file_path).get_section_keys(section) diff --git a/scenes/autoload/display_manager.gd b/scenes/autoload/display_manager.gd index 10b4b64..877e69d 100644 --- a/scenes/autoload/display_manager.gd +++ b/scenes/autoload/display_manager.gd @@ -2,15 +2,14 @@ extends Node signal window_mode_updated(window_mode: DisplayServer.WindowMode) +var data_wrapper:DataManager.SectionWrapper: + get: + return DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "video") + func _ready() -> void: - var category = DataManager.categories.SETTINGS - if DataManager.get_data(category, "window_mode"): - var selected = DataManager.get_data(category, "window_mode") - set_window_mode(get_window_mode_from_string(selected)) - var fps_limit = 120 - if DataManager.get_data(category, "fps_limit"): - fps_limit = int(DataManager.get_data(category, "fps_limit")) - set_max_fps(fps_limit) + var selected = data_wrapper.get_data("window_mode") + set_window_mode(get_window_mode_from_string(selected)) + set_max_fps( data_wrapper.get_data("fps_limit") ) func _input(event) -> void: if event.is_action_pressed("fullscreen"): @@ -42,9 +41,9 @@ func set_window_mode(window_mode: DisplayServer.WindowMode) -> void: window_mode_updated.emit(window_mode) DisplayServer.window_set_mode(window_mode) if window_mode == DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN: - DataManager.save_data("window_mode", "fullscreen", DataManager.categories.SETTINGS) + data_wrapper.set_data("window_mode", "fullscreen") elif window_mode == DisplayServer.WINDOW_MODE_MAXIMIZED: - DataManager.save_data("window_mode", "windowed", DataManager.categories.SETTINGS) + data_wrapper.set_data("window_mode", "windowed") func set_max_fps(value) -> void: Engine.set_max_fps(value) diff --git a/scenes/autoload/global.gd b/scenes/autoload/global.gd index 238c03a..6570678 100644 --- a/scenes/autoload/global.gd +++ b/scenes/autoload/global.gd @@ -55,27 +55,12 @@ func get_world_textures() -> Array: return textures func get_current_world_texture() -> Texture2D: - const CATEGORY = DataManager.categories.SETTINGS - var current_texture = DataManager.get_data(CATEGORY, "world_texture") - if !current_texture: - current_texture = "checkerboard.png" + var current_texture = DataManager.get_data(DataManager.SETTINGS_FILE_PATH, "world", "world_texture") return load(get_world_textures_path() + current_texture) func get_world_textures_path() -> String: return "res://assets/images/world/" -func string_to_vector3d(string_vector: String) -> Vector3: - var components_str = string_vector.substr(1, string_vector.length() - 2) - var components = components_str.split(",") - - # Convert each component from string to float - var x = components[0].to_float() - var y = components[1].to_float() - var z = components[2].to_float() - - # Create the Vector3D object - return Vector3(x, y, z) - func string_to_color(string_vector: String) -> Color: var components_str = string_vector.substr(1, string_vector.length() - 2) var components = components_str.split(",") diff --git a/scenes/autoload/overlay_ui_label.gd b/scenes/autoload/overlay_ui_label.gd index 6b889e2..5d03e90 100644 --- a/scenes/autoload/overlay_ui_label.gd +++ b/scenes/autoload/overlay_ui_label.gd @@ -1,7 +1,7 @@ extends Label func _process(_delta: float) -> void: - if DataManager.get_data(DataManager.categories.SETTINGS, "fps_overlay"): + if DataManager.get_data(DataManager.SETTINGS_FILE_PATH, "user", "fps_overlay"): set_text("FPS " + str(Engine.get_frames_per_second())) else: set_text("") diff --git a/scenes/enemies/target.gd b/scenes/enemies/target.gd index d8e7a40..2245796 100644 --- a/scenes/enemies/target.gd +++ b/scenes/enemies/target.gd @@ -45,9 +45,8 @@ func _set_health_slider() -> void: $HealthSlider.enable() func _set_target_material() -> void: - var category = DataManager.categories.SETTINGS - if DataManager.get_data(category, "target_color") != null: - var material_override = _mesh_instance.get_mesh().get_material() - material_override.set_albedo(Global.string_to_color(DataManager.get_data(category, "target_color"))) - material_override.set_emission(Global.string_to_color(DataManager.get_data(category, "target_color"))) - _mesh_instance.material_override = material_override + var material_override = _mesh_instance.get_mesh().get_material() + var col = DataManager.get_data(DataManager.SETTINGS_FILE_PATH, "world", "target_color") + material_override.set_albedo(col) + material_override.set_emission(col) + _mesh_instance.material_override = material_override diff --git a/scenes/game_world/crosshair.gd b/scenes/game_world/crosshair.gd index ccdeb83..24265bb 100644 --- a/scenes/game_world/crosshair.gd +++ b/scenes/game_world/crosshair.gd @@ -1,17 +1,17 @@ extends Control ## Renders the user crosshair -var _color := Color(0, 255, 255, 1) -var _outline_color := Color(0,0,0) +var _color :Color +var _outline_color :Color -var _enable_outline := true -var _dot_enable := false +var _enable_outline :bool +var _dot_enable :bool -var _dot_size: float = 6.0 -var _outline_width: float = 1.0 -var _thickness: float = 2.0 -var _length: float = 12.0 -var _gap: float = 5.0 +var _dot_size: float +var _outline_width: float +var _thickness: float +var _length: float +var _gap: float var current_crosshair: Dictionary = { "top": [], @@ -36,16 +36,16 @@ func _on_options_refresh_crosshair() -> void: queue_redraw() func _load_save() -> void: - var category = DataManager.categories.CROSSHAIR - _dot_enable = DataManager.set_parameter_if_exists(category, _dot_enable, "dot") - _dot_size = DataManager.set_parameter_if_exists(category, _dot_size, "dot_size") - _length = DataManager.set_parameter_if_exists(category, _length, "length") - _thickness = DataManager.set_parameter_if_exists(category, _thickness, "thickness") - _gap = DataManager.set_parameter_if_exists(category, _gap, "gap") - _enable_outline = DataManager.set_parameter_if_exists(category, _enable_outline, "outline_enable") - _outline_width = DataManager.set_parameter_if_exists(category, _outline_width, "outline_width") - _color = DataManager.set_color_if_exists(category, _color, "color") - _outline_color = DataManager.set_color_if_exists(category, _outline_color, "outline_color") + var wrapper := DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "crosshair") + _dot_enable = wrapper.get_data("dot_enable") + _dot_size = wrapper.get_data("dot_size") + _length = wrapper.get_data("length") + _thickness = wrapper.get_data("thickness") + _gap = wrapper.get_data("gap") + _enable_outline = wrapper.get_data("enable_outline") + _outline_width = wrapper.get_data("outline_width") + _color = wrapper.get_data("color") + _outline_color = wrapper.get_data("outline_color") func _load_crosshair() -> void: current_crosshair["dot"] = [ diff --git a/scenes/game_world/destroyed_sound.gd b/scenes/game_world/destroyed_sound.gd index 5c29c59..beb6264 100644 --- a/scenes/game_world/destroyed_sound.gd +++ b/scenes/game_world/destroyed_sound.gd @@ -7,13 +7,15 @@ func _ready() -> void: func _on_volume_updated(_value: float) -> void: update_hit_sound() +var data_wrapper:DataManager.SectionWrapper: + get: + return DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "audio") + func update_hit_sound() -> void: - var volume = DataManager.get_data(DataManager.categories.SETTINGS, "volume") + var volume = data_wrapper.get_data("volume") if volume != null: var this_bus := AudioServer.get_bus_index("Master") AudioServer.set_bus_volume_db(this_bus, lerpf(-20, 0, volume)) AudioServer.set_bus_mute(this_bus, volume == 0) - var category := DataManager.categories.SETTINGS - if DataManager.get_data(category, "hit_sound") != null: - var selected = DataManager.get_data(category, "hit_sound") - stream = load(Audio.hit_sounds[selected]) + var selected = data_wrapper.get_data("hit_sound") + stream = load(Audio.hit_sounds[selected]) diff --git a/scenes/game_world/game_world.gd b/scenes/game_world/game_world.gd index 5dacf2b..1795343 100644 --- a/scenes/game_world/game_world.gd +++ b/scenes/game_world/game_world.gd @@ -89,6 +89,5 @@ func _spawn_initial_targets(): func _update_world_appareance() -> void: var world_material: StandardMaterial3D = preload("res://assets/material_default.tres") world_material.albedo_texture = Global.get_current_world_texture() - const CATEGORY = DataManager.categories.SETTINGS - $DirectionalLight3D.light_color = DataManager.set_color_if_exists(CATEGORY, \ - $DirectionalLight3D.light_color, "world_color") + var wrapper = DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "world") + $DirectionalLight3D.light_color = wrapper.get_data("world_color") diff --git a/scenes/game_world/player/player_manager.gd b/scenes/game_world/player/player_manager.gd index cf02565..c086a1d 100644 --- a/scenes/game_world/player/player_manager.gd +++ b/scenes/game_world/player/player_manager.gd @@ -20,8 +20,7 @@ var current_shoot_cooldown: float @onready var bullet_hole = preload("res://scenes/game_world/bullet_hole.tscn") func _ready() -> void: - const CATEGORY := DataManager.categories.SETTINGS - camera.fov = DataManager.set_parameter_if_exists(CATEGORY, camera.fov, "camera_fov") + camera.fov = DataManager.get_data("settings", "video", "fov") mouse_sensitivity = _get_mouse_sensitivity() func _input(event: InputEvent) -> void: @@ -61,11 +60,8 @@ func _physics_process(delta: float) -> void: move_and_slide() func _get_mouse_sensitivity() -> float: - const CATEGORY := DataManager.categories.SETTINGS - var user_sensitivity: float = 1 - var conversion_sensitivity: float = 0.022 - conversion_sensitivity = DataManager.set_parameter_if_exists(CATEGORY, conversion_sensitivity, "sensitivity_game_value") - user_sensitivity = DataManager.set_parameter_if_exists(CATEGORY, user_sensitivity, "sensitivity") + var user_sensitivity: float = DataManager.get_data("settings", "user", "sensitivity") + var conversion_sensitivity: float = DataManager.get_data("settings", "user", "sensitivity_game_value") return user_sensitivity * conversion_sensitivity func _handle_joypad_rotation(delta: float) -> void: diff --git a/scenes/main_menu/settings/settings_audio.gd b/scenes/main_menu/settings/settings_audio.gd index ab60fb1..d6ab381 100644 --- a/scenes/main_menu/settings/settings_audio.gd +++ b/scenes/main_menu/settings/settings_audio.gd @@ -8,33 +8,32 @@ const hit_sounds: Dictionary = { "kalimba": "res://scenes/enemies/kalimba.ogg", } -var category := DataManager.categories.SETTINGS +var data_wrapper:DataManager.SectionWrapper: + get: + return DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "audio") func _ready() -> void: - category = DataManager.categories.SETTINGS - if DataManager.get_data(category, "volume") != null: - _set_volume_label() + _set_volume_label() var option_button := $OptionButton for sound in hit_sounds: option_button.add_item(sound) - if DataManager.get_data(category, "hit_sound") != null: - var selected = DataManager.get_data(category, "hit_sound") - for i in range(option_button.item_count): - if selected == option_button.get_item_text(i): - option_button.select(i) + var selected = data_wrapper.get_data("hit_sound") + for i in range(option_button.item_count): + if selected == option_button.get_item_text(i): + option_button.select(i) func _on_volume_slider_value_changed(value) -> void: - DataManager.save_data("volume", value, category) + data_wrapper.set_data("volume", value) _set_volume_label() func _set_volume_label() -> void: var volume_label := $VolumeLabel - volume_label.text = "Volume " + str(DataManager.get_data(category, "volume")) + volume_label.text = "Volume " + str(data_wrapper.get_data("volume")) var volume_slider := $VolumeSlider - volume_slider.value = DataManager.get_data(category, "volume") + volume_slider.value = data_wrapper.get_data("volume") func _on_option_button_item_selected(index: int) -> void: - DataManager.save_data("hit_sound", hit_sounds.keys()[index], category) + data_wrapper.set_data("hit_sound", hit_sounds.keys()[index]) $Preview/AudioStreamPlayer.update_hit_sound() func _on_preview_pressed() -> void: diff --git a/scenes/main_menu/settings/settings_controls.gd b/scenes/main_menu/settings/settings_controls.gd index 7609aaa..955818a 100644 --- a/scenes/main_menu/settings/settings_controls.gd +++ b/scenes/main_menu/settings/settings_controls.gd @@ -11,25 +11,22 @@ const games_sensitivities: Dictionary = { @onready var game = $Game @onready var sensitivity = $Sensitivity + +var data_wrapper:DataManager.SectionWrapper: + get: + return DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "user") + func _ready() -> void: for sens in games_sensitivities: game.add_item(sens) - var category = DataManager.categories.SETTINGS - if DataManager.get_data(category, "sensitivity"): - sensitivity.value = DataManager.get_data(category, "sensitivity") - if DataManager.get_data(category, "sensitivity_game"): - game.selected = DataManager.get_data(category, "sensitivity_game") + sensitivity.value = data_wrapper.get_data("sensitivity") + game.selected = data_wrapper.get_data("sensitivity_game") func _on_sensitivity_change_value(value) -> void: - DataManager.save_data("sensitivity_game", game.get_selected_id(), \ - DataManager.categories.SETTINGS) - DataManager.save_data("sensitivity_game_value", games_sensitivities.get(game.get_item_text(game.get_selected_id())), \ - DataManager.categories.SETTINGS) - DataManager.save_data("sensitivity", float(value), \ - DataManager.categories.SETTINGS) + data_wrapper.set_data("sensitivity_game", game.get_selected_id(), ) + data_wrapper.set_data("sensitivity_game_value", games_sensitivities.get(game.get_item_text(game.get_selected_id())) ) + data_wrapper.set_data("sensitivity", float(value)) func _on_game_item_selected(index: int) -> void: - DataManager.save_data("sensitivity_game", index, \ - DataManager.categories.SETTINGS) - DataManager.save_data("sensitivity_game_value", games_sensitivities.get(game.get_item_text(index)), \ - DataManager.categories.SETTINGS) + data_wrapper.set_data("sensitivity_game", index) + data_wrapper.set_data("sensitivity_game_value", games_sensitivities.get(game.get_item_text(index)) ) diff --git a/scenes/main_menu/settings/settings_crosshair.gd b/scenes/main_menu/settings/settings_crosshair.gd index b4f8e3b..f9995fd 100644 --- a/scenes/main_menu/settings/settings_crosshair.gd +++ b/scenes/main_menu/settings/settings_crosshair.gd @@ -3,6 +3,7 @@ extends Control signal refresh_crosshair + @onready var crosshair := $CrosshairSettings/Preview/Crosshair @onready var file_export := $ExportFileDialog @onready var file_import := $ImportFileDialog @@ -21,19 +22,29 @@ func _on_import_pressed() -> void: file_import.visible = true func _on_export_file_dialog_file_selected(path: String) -> void: - DataManager.save_all_data(path) + var cfg := ConfigFile.new() + var wrapper := DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "crosshair") + for key in wrapper.get_keys(): + cfg.set_value(wrapper.section, key, wrapper.get_data(key)) + cfg.save(path) func _on_import_file_dialog_file_selected(path: String) -> void: - DataManager.load_all_data(path) - DataManager.save_all_data() - emit_signal("refresh_crosshair") + var cfg := ConfigFile.new() + var err := cfg.load(path) + if err != OK: + push_warning("Could not import crosshair %s"%path) + return + var wrapper := DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "crosshair") + for key in cfg.get_section_keys(wrapper.section): + wrapper.set_data(key, cfg.get_value(wrapper.section, key)) load_saved() + queue_refresh_crosshair() func _on_dot_change_value(value: float) -> void: change_value("dot_size", float(value)) func _on_dot_toggle_checkbox(value: bool) -> void: - change_value("dot", value) + change_value("dot_enable", value) func _on_length_change_value(value: float) -> void: change_value("length", float(value)) @@ -42,7 +53,7 @@ func _on_thickness_change_value(value: float) -> void: change_value("thickness", float(value)) func _on_outline_toggle_checkbox(value: bool) -> void: - change_value("outline_enable", value) + change_value("enable_outline", value) func _on_outline_change_value(value: float) -> void: change_value("outline_width", float(value)) @@ -51,31 +62,26 @@ func _on_gap_change_value(value: float) -> void: change_value("gap", float(value)) func _on_crosshair_color_color_changed(color: Color) -> void: - change_value("color", str(color)) + change_value("color", color) func _on_outline_color_color_changed(color: Color) -> void: - change_value("outline_color", str(color)) - + change_value("outline_color", color) + func change_value(key: String, value) -> void: - DataManager.save_data(key, value, DataManager.categories.CROSSHAIR) - emit_signal("refresh_crosshair") + DataManager.set_data(DataManager.SETTINGS_FILE_PATH, "crosshair", key, value) + queue_refresh_crosshair() + +func queue_refresh_crosshair(): + # delay changes so we do not spam this event in load_saved() + if not get_tree().process_frame.is_connected(emit_signal.bind("refresh_crosshair")): + get_tree().process_frame.connect(emit_signal.bind("refresh_crosshair"), CONNECT_ONE_SHOT) func load_saved() -> void: - const CATEGORY := DataManager.categories.CROSSHAIR - var container := $CrosshairSettings - var dot := container.get_node("Dot") - dot.checkbox_value = DataManager.set_parameter_if_exists(CATEGORY, dot.checkbox_value, "dot") - dot.value = DataManager.set_parameter_if_exists(CATEGORY, dot.value, "dot_size") - var length := container.get_node("Length") - length.value = DataManager.set_parameter_if_exists(CATEGORY, length.value, "length") - var thickness := container.get_node("Thickness") - thickness.value = DataManager.set_parameter_if_exists(CATEGORY, thickness.value, "thickness") - var gap := container.get_node("Gap") - gap.value = DataManager.set_parameter_if_exists(CATEGORY, gap.value, "gap") - var outline := container.get_node("Outline") - outline.checkbox_value = DataManager.set_parameter_if_exists(CATEGORY, outline.checkbox_value, "outline_enable") - outline.value = DataManager.set_parameter_if_exists(CATEGORY, outline.value, "outline_width") - var crosshair_color := container.get_node("Color/CrosshairColor") - crosshair_color.color = DataManager.set_color_if_exists(CATEGORY, crosshair_color.color, "color") - var outline_color := container.get_node("OutlineColor/OutlineColor") - outline_color.color = DataManager.set_color_if_exists(CATEGORY, outline_color.color, "outline_color") + crosshair._load_save() + const plainValueChanges := ["dot_size", "length", "thickness", "gap", "outline_width"] + for param in plainValueChanges: + get_node("%"+param).value = crosshair.get("_"+param) + %dot_size.checkbox_value = crosshair._dot_enable + %outline_width.checkbox_value = crosshair._enable_outline + %crosshair_color.color = crosshair._color + %outline_color.color = crosshair._outline_color diff --git a/scenes/main_menu/settings/settings_crosshair.tscn b/scenes/main_menu/settings/settings_crosshair.tscn index a845ecb..2371f91 100644 --- a/scenes/main_menu/settings/settings_crosshair.tscn +++ b/scenes/main_menu/settings/settings_crosshair.tscn @@ -101,34 +101,39 @@ size_flags_horizontal = 4 size_flags_vertical = 4 script = ExtResource("3_uw2kl") -[node name="Dot" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +[node name="dot_size" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +unique_name_in_owner = true layout_mode = 2 label_text = "Dot" max_value = 10.0 value = 10.0 -[node name="Length" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +[node name="length" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +unique_name_in_owner = true layout_mode = 2 label_text = "Length" max_value = 50.0 value = 20.0 has_checkbox = false -[node name="Thickness" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +[node name="thickness" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +unique_name_in_owner = true layout_mode = 2 label_text = "Thickness" max_value = 10.0 value = 10.0 has_checkbox = false -[node name="Gap" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +[node name="gap" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +unique_name_in_owner = true layout_mode = 2 label_text = "Gap" max_value = 25.0 value = 25.0 has_checkbox = false -[node name="Outline" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +[node name="outline_width" parent="CrosshairSettings" instance=ExtResource("4_2iwqj")] +unique_name_in_owner = true layout_mode = 2 label_text = "Outline" max_value = 10.0 @@ -142,7 +147,8 @@ layout_mode = 2 size_flags_horizontal = 3 text = "Color" -[node name="CrosshairColor" type="ColorPickerButton" parent="CrosshairSettings/Color" groups=["Persist", "PutLabel"]] +[node name="crosshair_color" type="ColorPickerButton" parent="CrosshairSettings/Color" groups=["Persist", "PutLabel"]] +unique_name_in_owner = true custom_minimum_size = Vector2(220, 0) layout_mode = 2 color = Color(0, 1, 1, 1) @@ -155,7 +161,8 @@ layout_mode = 2 size_flags_horizontal = 3 text = "Outline color" -[node name="OutlineColor" type="ColorPickerButton" parent="CrosshairSettings/OutlineColor" groups=["Persist", "PutLabel"]] +[node name="outline_color" type="ColorPickerButton" parent="CrosshairSettings/OutlineColor" groups=["Persist", "PutLabel"]] +unique_name_in_owner = true custom_minimum_size = Vector2(220, 0) layout_mode = 2 @@ -189,15 +196,15 @@ access = 2 use_native_dialog = true [connection signal="refresh_crosshair" from="." to="CrosshairSettings/Preview/Crosshair" method="_on_options_refresh_crosshair"] -[connection signal="change_value" from="CrosshairSettings/Dot" to="." method="_on_dot_change_value"] -[connection signal="toggle_checkbox" from="CrosshairSettings/Dot" to="." method="_on_dot_toggle_checkbox"] -[connection signal="change_value" from="CrosshairSettings/Length" to="." method="_on_length_change_value"] -[connection signal="change_value" from="CrosshairSettings/Thickness" to="." method="_on_thickness_change_value"] -[connection signal="change_value" from="CrosshairSettings/Gap" to="." method="_on_gap_change_value"] -[connection signal="change_value" from="CrosshairSettings/Outline" to="." method="_on_outline_change_value"] -[connection signal="toggle_checkbox" from="CrosshairSettings/Outline" to="." method="_on_outline_toggle_checkbox"] -[connection signal="color_changed" from="CrosshairSettings/Color/CrosshairColor" to="." method="_on_crosshair_color_color_changed"] -[connection signal="color_changed" from="CrosshairSettings/OutlineColor/OutlineColor" to="." method="_on_outline_color_color_changed"] +[connection signal="change_value" from="CrosshairSettings/dot_size" to="." method="_on_dot_change_value"] +[connection signal="toggle_checkbox" from="CrosshairSettings/dot_size" to="." method="_on_dot_toggle_checkbox"] +[connection signal="change_value" from="CrosshairSettings/length" to="." method="_on_length_change_value"] +[connection signal="change_value" from="CrosshairSettings/thickness" to="." method="_on_thickness_change_value"] +[connection signal="change_value" from="CrosshairSettings/gap" to="." method="_on_gap_change_value"] +[connection signal="change_value" from="CrosshairSettings/outline_width" to="." method="_on_outline_change_value"] +[connection signal="toggle_checkbox" from="CrosshairSettings/outline_width" to="." method="_on_outline_toggle_checkbox"] +[connection signal="color_changed" from="CrosshairSettings/Color/crosshair_color" to="." method="_on_crosshair_color_color_changed"] +[connection signal="color_changed" from="CrosshairSettings/OutlineColor/outline_color" to="." method="_on_outline_color_color_changed"] [connection signal="pressed" from="Export" to="." method="_on_export_pressed"] [connection signal="file_selected" from="ExportFileDialog" to="." method="_on_export_file_dialog_file_selected"] [connection signal="pressed" from="Import" to="." method="_on_import_pressed"] diff --git a/scenes/main_menu/settings/settings_fps_limit.gd b/scenes/main_menu/settings/settings_fps_limit.gd index be19843..199d2f2 100644 --- a/scenes/main_menu/settings/settings_fps_limit.gd +++ b/scenes/main_menu/settings/settings_fps_limit.gd @@ -4,16 +4,17 @@ extends VBoxContainer @onready var fps_limit_slider = $FPSLimitSlider @onready var fps_limit_label = $FPSLimitLabel +var data_wrapper:DataManager.SectionWrapper: + get: + return DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "video") + func _on_fps_limit_slider_value_changed(value): - DataManager.save_data("fps_limit", value, DataManager.categories.SETTINGS) + data_wrapper.set_data("fps_limit", value) DisplayManager.set_max_fps(value) update_label() func _ready(): - var category = DataManager.categories.SETTINGS - - if DataManager.get_data(category, "fps_limit"): - fps_limit_slider.value = DataManager.get_data(category, "fps_limit") + fps_limit_slider.value = data_wrapper.get_data("fps_limit") update_label() diff --git a/scenes/main_menu/settings/settings_fps_overlay.gd b/scenes/main_menu/settings/settings_fps_overlay.gd index 51bacba..0848b37 100644 --- a/scenes/main_menu/settings/settings_fps_overlay.gd +++ b/scenes/main_menu/settings/settings_fps_overlay.gd @@ -3,11 +3,12 @@ extends HBoxContainer @onready var fps_overlay_checkbox = $FPSOverlayCheckBox +var data_wrapper:DataManager.SectionWrapper: + get: + return DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "user") + func _on_fps_overlay_check_box_toggled(value: bool) -> void: - DataManager.save_data("fps_overlay", value, DataManager.categories.SETTINGS) + data_wrapper.set_data("fps_overlay", value) func _ready() -> void: - var category = DataManager.categories.SETTINGS - - if DataManager.get_data(category, "fps_overlay"): - fps_overlay_checkbox.button_pressed = DataManager.get_data(category, "fps_overlay") + fps_overlay_checkbox.set_pressed_no_signal(data_wrapper.get_data("fps_overlay")) diff --git a/scenes/main_menu/settings/settings_video.gd b/scenes/main_menu/settings/settings_video.gd index a42ea16..4c5e6d7 100644 --- a/scenes/main_menu/settings/settings_video.gd +++ b/scenes/main_menu/settings/settings_video.gd @@ -6,36 +6,36 @@ extends Control @onready var fov_slider = $FovSlider @onready var window_mode_options = $WindowModeOptions +var data_wrapper:DataManager.SectionWrapper: + get: + return DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "video") + func _ready() -> void: DisplayManager.window_mode_updated.connect(_on_display_manager_window_mode_updated) _update_fov_label() _update_resolution_label() get_viewport().size_changed.connect(self._update_resolution_label) - var category = DataManager.categories.SETTINGS - if DataManager.get_data(category, "resolution"): - resolution_slider.value = DataManager.get_data(category, "resolution") - if DataManager.get_data(category, "camera_fov"): - fov_slider.value = DataManager.get_data(category, "camera_fov") - if DataManager.get_data(category, "window_mode"): - var selected = DataManager.get_data(category, "window_mode") - for i in range(window_mode_options.item_count): - if selected == window_mode_options.get_item_text(i): - window_mode_options.select(i) + resolution_slider.value = data_wrapper.get_data("resolution") + fov_slider.value = data_wrapper.get_data("fov") + var selected = data_wrapper.get_data("window_mode") + for i in range(window_mode_options.item_count): + if selected == window_mode_options.get_item_text(i): + window_mode_options.select(i) func _on_resolution_slider_value_changed(value: float) -> void: get_viewport().scaling_3d_scale = value _update_resolution_label() - DataManager.save_data("resolution", value, DataManager.categories.SETTINGS) + data_wrapper.set_data("resolution", value) func _on_fov_slider_value_changed(value: float) -> void: _update_fov_label() - DataManager.save_data("camera_fov", value, DataManager.categories.SETTINGS) + data_wrapper.set_data("fov", value) func _on_window_mode_options_item_selected(index: int) -> void: var option = window_mode_options.get_item_text(index) DisplayManager.set_window_mode_from_string(option) - DataManager.save_data("window_mode", option, DataManager.categories.SETTINGS) + data_wrapper.set_data("window_mode", option) func _on_display_manager_window_mode_updated(window_mode): var selected = DisplayManager.get_string_from_window_mode(window_mode) diff --git a/scenes/main_menu/settings/settings_world_appareance.gd b/scenes/main_menu/settings/settings_world_appareance.gd index ef8fdc6..cc688c6 100644 --- a/scenes/main_menu/settings/settings_world_appareance.gd +++ b/scenes/main_menu/settings/settings_world_appareance.gd @@ -1,24 +1,26 @@ extends VBoxContainer ## World appareance settings -const CATEGORY = DataManager.categories.SETTINGS - @onready var world_color = $WorldColor/Color @onready var world_texture = $WorldTexture @onready var target_color = $TargetColor/TargetColor @onready var preview = $Preview @onready var target_preview = $Preview/TargetPreview +var data_wrapper:DataManager.SectionWrapper: + get: + return DataManager.get_wrapper(DataManager.SETTINGS_FILE_PATH, "world") + func _on_color_color_changed(color: Color) -> void: - DataManager.save_data("world_color", str(color), CATEGORY) + data_wrapper.set_data("world_color", color) update_preview() func _on_target_color_color_changed(color: Color) -> void: - DataManager.save_data("target_color", str(color), CATEGORY) + data_wrapper.set_data("target_color", color) update_preview() func _on_world_texture_item_selected(index) -> void: - DataManager.save_data("world_texture", world_texture.get_item_text(index), CATEGORY) + data_wrapper.set_data("world_texture", world_texture.get_item_text(index)) update_preview() func _ready() -> void: @@ -26,20 +28,19 @@ func _ready() -> void: for texture in Global.get_world_textures(): world_texture.add_icon_item(load(Global.get_world_textures_path() + texture), texture, i) i+=1 - world_color.color = DataManager.set_color_if_exists(CATEGORY, world_color.color, "world_color") - target_color.color = DataManager.set_color_if_exists(CATEGORY, target_color.color, "target_color") + world_color.color = data_wrapper.get_data("world_color") + target_color.color = data_wrapper.get_data("target_color") get_selected_texture_index() update_preview() func get_selected_texture_index() -> void: - if DataManager.get_data(CATEGORY, "world_texture"): - var selected = DataManager.get_data(CATEGORY, "world_texture") - for i in range(world_texture.item_count): - if selected == world_texture.get_item_text(i): - world_texture.select(i) + var selected = data_wrapper.get_data("world_texture") + for i in range(world_texture.item_count): + if selected == world_texture.get_item_text(i): + world_texture.select(i) update_preview() func update_preview() -> void: preview.texture = Global.get_current_world_texture() - preview.self_modulate = DataManager.set_color_if_exists(CATEGORY, preview.self_modulate, "world_color") - target_preview.color = DataManager.set_color_if_exists(CATEGORY, target_preview.color, "target_color") + preview.self_modulate = data_wrapper.get_data("world_color") + target_preview.color = data_wrapper.get_data("target_color")