diff --git a/README.md b/README.md index 5c5d36e..2800bc3 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ Building a Minecraft clone of sorts to learn Godot. -This was initially based on Sable Spirit Studio's YT series but has evolved to be quite a bit different. Very little of the original code exists (outside `DBItems`). - ![Skyblock Screenshot](assets/skyblock-screenshot.png) @@ -24,3 +22,9 @@ This was initially based on Sable Spirit Studio's YT series but has evolved to b | Quick Load | `F6` | | Quick Save | `F5` | | Sprint/Run | `Shift` | + + +## Acknowledgements + +* [Sable Spirit Studios](https://www.youtube.com/@SableSpiritStudio) for the inspiration and ideas +* [Tabler](https://tabler.io) for UI icons diff --git a/save_load/assets/folder-open-hover.png b/save_load/assets/folder-open-hover.png new file mode 100644 index 0000000..06ead5b Binary files /dev/null and b/save_load/assets/folder-open-hover.png differ diff --git a/save_load/assets/folder-open-hover.png.import b/save_load/assets/folder-open-hover.png.import new file mode 100644 index 0000000..f68715f --- /dev/null +++ b/save_load/assets/folder-open-hover.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://by4w5ll3le7g6" +path="res://.godot/imported/folder-open-hover.png-a1ef3a807e674ab8f8806dada553ab61.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/folder-open-hover.png" +dest_files=["res://.godot/imported/folder-open-hover.png-a1ef3a807e674ab8f8806dada553ab61.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/assets/folder-open-normal.png b/save_load/assets/folder-open-normal.png new file mode 100644 index 0000000..2a3f3a3 Binary files /dev/null and b/save_load/assets/folder-open-normal.png differ diff --git a/save_load/assets/folder-open-normal.png.import b/save_load/assets/folder-open-normal.png.import new file mode 100644 index 0000000..23f63a6 --- /dev/null +++ b/save_load/assets/folder-open-normal.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cmq51cgasug81" +path="res://.godot/imported/folder-open-normal.png-f7f228a37723c0515dbd7272838372e1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/folder-open-normal.png" +dest_files=["res://.godot/imported/folder-open-normal.png-f7f228a37723c0515dbd7272838372e1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/assets/folder-open-pressed.png b/save_load/assets/folder-open-pressed.png new file mode 100644 index 0000000..448ad27 Binary files /dev/null and b/save_load/assets/folder-open-pressed.png differ diff --git a/save_load/assets/folder-open-pressed.png.import b/save_load/assets/folder-open-pressed.png.import new file mode 100644 index 0000000..3e826ff --- /dev/null +++ b/save_load/assets/folder-open-pressed.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://blyryo60jydgi" +path="res://.godot/imported/folder-open-pressed.png-b69b4af3e2256bb46d3464e4d48a50c0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/folder-open-pressed.png" +dest_files=["res://.godot/imported/folder-open-pressed.png-b69b4af3e2256bb46d3464e4d48a50c0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/assets/save-hover.png b/save_load/assets/save-hover.png new file mode 100644 index 0000000..04fdbf9 Binary files /dev/null and b/save_load/assets/save-hover.png differ diff --git a/save_load/assets/save-hover.png.import b/save_load/assets/save-hover.png.import new file mode 100644 index 0000000..aa0c408 --- /dev/null +++ b/save_load/assets/save-hover.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://o3l0j53mgkan" +path="res://.godot/imported/save-hover.png-a059532ff43c1b9b7f190c464e6ac95e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/save-hover.png" +dest_files=["res://.godot/imported/save-hover.png-a059532ff43c1b9b7f190c464e6ac95e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/assets/save-normal.png b/save_load/assets/save-normal.png new file mode 100644 index 0000000..0cf93ed Binary files /dev/null and b/save_load/assets/save-normal.png differ diff --git a/save_load/assets/save-normal.png.import b/save_load/assets/save-normal.png.import new file mode 100644 index 0000000..cb6ff20 --- /dev/null +++ b/save_load/assets/save-normal.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ja8bc1h5x85o" +path="res://.godot/imported/save-normal.png-126e9be66da8efc0f0eb84b8cc03c6ff.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/save-normal.png" +dest_files=["res://.godot/imported/save-normal.png-126e9be66da8efc0f0eb84b8cc03c6ff.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/assets/save-pressed.png b/save_load/assets/save-pressed.png new file mode 100644 index 0000000..28f2cdd Binary files /dev/null and b/save_load/assets/save-pressed.png differ diff --git a/save_load/assets/save-pressed.png.import b/save_load/assets/save-pressed.png.import new file mode 100644 index 0000000..8583721 --- /dev/null +++ b/save_load/assets/save-pressed.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://crqgyft4gfilt" +path="res://.godot/imported/save-pressed.png-49f5851a0548d3847310651a4ef477c2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/save-pressed.png" +dest_files=["res://.godot/imported/save-pressed.png-49f5851a0548d3847310651a4ef477c2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/assets/trash-hover.png b/save_load/assets/trash-hover.png new file mode 100644 index 0000000..a75b5e7 Binary files /dev/null and b/save_load/assets/trash-hover.png differ diff --git a/save_load/assets/trash-hover.png.import b/save_load/assets/trash-hover.png.import new file mode 100644 index 0000000..0e256da --- /dev/null +++ b/save_load/assets/trash-hover.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cmrtuy0i5qc01" +path="res://.godot/imported/trash-hover.png-0c87af6ed9b10a21de0dd22a56db8a47.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/trash-hover.png" +dest_files=["res://.godot/imported/trash-hover.png-0c87af6ed9b10a21de0dd22a56db8a47.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/assets/trash-normal.png b/save_load/assets/trash-normal.png new file mode 100644 index 0000000..559fb5c Binary files /dev/null and b/save_load/assets/trash-normal.png differ diff --git a/save_load/assets/trash-normal.png.import b/save_load/assets/trash-normal.png.import new file mode 100644 index 0000000..37967e7 --- /dev/null +++ b/save_load/assets/trash-normal.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dvp5yeoqw36yt" +path="res://.godot/imported/trash-normal.png-9a70475e0bfa21e155c8f068d078dd58.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/trash-normal.png" +dest_files=["res://.godot/imported/trash-normal.png-9a70475e0bfa21e155c8f068d078dd58.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/assets/trash-pressed.png b/save_load/assets/trash-pressed.png new file mode 100644 index 0000000..3a8c56e Binary files /dev/null and b/save_load/assets/trash-pressed.png differ diff --git a/save_load/assets/trash-pressed.png.import b/save_load/assets/trash-pressed.png.import new file mode 100644 index 0000000..42246df --- /dev/null +++ b/save_load/assets/trash-pressed.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://brwa8yljyrlgy" +path="res://.godot/imported/trash-pressed.png-635c7d9409ea36b0244299e895c300c2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://save_load/assets/trash-pressed.png" +dest_files=["res://.godot/imported/trash-pressed.png-635c7d9409ea36b0244299e895c300c2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/save_load/autoloads/save_game_manager.gd b/save_load/autoloads/save_game_manager.gd index dae42bf..2558117 100644 --- a/save_load/autoloads/save_game_manager.gd +++ b/save_load/autoloads/save_game_manager.gd @@ -9,33 +9,163 @@ extends Node signal game_saved signal game_loaded +signal refresh_saves_list +signal create_auto_save_file +signal create_save_file(save_name: String) +signal delete_save_file(filename: String) +signal load_save_file(filename: String) +signal quick_save +signal quick_load +signal open_save_list_ui +signal close_save_list_ui +var _game_data_resource: SaveGameDataResource = SaveGameDataResource.new() +var _save_level_data_component: SaveLevelDataComponent ## Contains the save paths and filenames + + +func _ready() -> void: + quick_load.connect(quick_load_game) + quick_save.connect(quick_load_game) + create_save_file.connect(_on_save_game_as_resource) + load_save_file.connect(_load_game_resource) + delete_save_file.connect(_on_delete_save_file) + func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("quick_save"): - save_game() + quick_save_game() if event.is_action_pressed("quick_load"): - load_game() + quick_load_game() -func save_game() -> void: - var save_level_data_component: SaveLevelDataComponent = get_tree().get_first_node_in_group("save_level_data_component") +func list_saves(include_quick_saves: bool = true, include_auto_saves: bool = true) -> Array[SaveFileDetailsResource]: + var save_files: Array[SaveFileDetailsResource] = [] + if not _load_save_level_data_component(): + return save_files - if save_level_data_component == null: - push_error("Could not find SaveLevelDataComponent node in level") - return + var save_game_data_path: String = _save_level_data_component.settings.save_game_data_path + if !DirAccess.dir_exists_absolute(save_game_data_path): + return save_files + + for filename: String in ResourceLoader.list_directory(save_game_data_path): + # TODO: Rework so the settings determine the file_name prepends + if filename.begins_with("quicksave_") and not include_quick_saves: continue + elif filename.begins_with("autosave_") and not include_auto_saves: continue + elif !filename.begins_with("save_") and !filename.begins_with("quicksave_") and !filename.begins_with("autosave_"): continue + + var _save_path: String = save_game_data_path + filename + var _save_icon: String = filename.replace(".tres", ".png") + var _save_resource: SaveFileDetailsResource = SaveFileDetailsResource.new() + + # TODO: Reconsider loading the save to get the name + # This could be a large save making opening each one slow + # Should work out a better method for getting the save name (filename != save name) + var _save_file: SaveGameDataResource = ResourceLoader.load(_save_path) + _save_resource.save_name = _save_file.save_name + + _save_resource.filename = filename + _save_resource.date_created = Time.get_datetime_string_from_unix_time(FileAccess.get_modified_time(_save_path)) + + ## In 4.5, this can probably be replaced with FileAccess.get_size(_save_path) + ## This should reduce the need for opening the file here + var _loaded_file: FileAccess = FileAccess.open(_save_path, FileAccess.READ) + _save_resource.filesize = _loaded_file.get_length() - save_level_data_component.save_game() + if FileAccess.file_exists(save_game_data_path + _save_icon): + _save_resource.save_icon = _save_icon + + save_files.append(_save_resource) + + save_files.sort_custom(_custom_save_file_sort) + return save_files + +func quick_save_game() -> void: + if not _load_save_level_data_component(): return + + _game_data_resource.save_name = "Quick Save" + _save_game_as_resource(_save_level_data_component.settings.quicksave_file_name) game_saved.emit() -func load_game() -> void: +func quick_load_game() -> void: + if not _load_save_level_data_component(): return + + # TODO: Don't reset world if quicksave not found EntityManager.reset_world.emit() + _load_game_resource(_save_level_data_component.settings.quicksave_file_name) + game_loaded.emit() + - var save_level_data_component: SaveLevelDataComponent = get_tree().get_first_node_in_group("save_level_data_component") +## Sort the save files list by date created, descending +func _custom_save_file_sort(a: SaveFileDetailsResource, b: SaveFileDetailsResource) -> bool: + return a.date_created > b.date_created - if save_level_data_component == null: +## Find the SaveLevelDataComponent within the level which stores the save paths and filenames +func _load_save_level_data_component() -> bool: + _save_level_data_component = get_tree().get_first_node_in_group("save_level_data_component") + if _save_level_data_component == null: push_error("Could not find SaveLevelDataComponent node in level") + return false + + return true + +func _load_game_resource(resource_filename: String) -> void: + if not _load_save_level_data_component(): return + var save_game_file_path: String = _save_level_data_component.settings.save_game_data_path + resource_filename + if !FileAccess.file_exists(save_game_file_path): + printerr("Failed to load save. File does not exist: ", save_game_file_path) return - save_level_data_component.load_game() - game_loaded.emit() + _game_data_resource = ResourceLoader.load(save_game_file_path) + if _game_data_resource == null: + printerr("Failed to load save. Unknown format? ", save_game_file_path) + return + + var root_node: Window = get_tree().root + for resource: Resource in _game_data_resource.save_data_nodes: + if resource is Node3DDataResource: + (resource as Node3DDataResource)._load_data(root_node) + +func _save_game_as_resource(resource_filename: String) -> void: + if not _load_save_level_data_component(): return + + if !DirAccess.dir_exists_absolute(_save_level_data_component.settings.save_game_data_path): + DirAccess.make_dir_absolute(_save_level_data_component.settings.save_game_data_path) + + var save_game_file_path: String = _save_level_data_component.settings.save_game_data_path + resource_filename + _save_node_data() + + var result: int = ResourceSaver.save(_game_data_resource, save_game_file_path) + if result != OK: + printerr("Failed to save game (" , result, "): ", save_game_file_path) + +## Save the properties defined on the SaveDataComponents attached to various nodes (such as Block) +func _save_node_data() -> void: + var nodes: Array = get_tree().get_nodes_in_group("save_data_component") + + if nodes == null: return + + for node: Node in nodes: + if node is SaveDataComponent: + @warning_ignore("unsafe_method_access") + var save_data_resource: Node3DDataResource = node._save_data() + var save_final_resource: Node3DDataResource = save_data_resource.duplicate() + _game_data_resource.save_data_nodes.append(save_final_resource) + + +func _on_save_game_as_resource(save_name: String) -> void: + if not _load_save_level_data_component(): return + + var current_date: String = Time.get_datetime_string_from_system().replace(":", "") + var _filename: String = "save_" + current_date + ".tres" + + _game_data_resource.save_name = save_name + _save_game_as_resource(_filename) + game_saved.emit() + +func _on_delete_save_file(filename: String) -> void: + if filename.length() < 1: + printerr("_on_delete_save_file(): Empty filename provided") + return + + var save_file_path: String = _save_level_data_component.settings.save_game_data_path + filename + DirAccess.remove_absolute(save_file_path) diff --git a/save_load/components/save_level_data_component.gd b/save_load/components/save_level_data_component.gd index f7e8f5b..10ccc4b 100644 --- a/save_load/components/save_level_data_component.gd +++ b/save_load/components/save_level_data_component.gd @@ -1,90 +1,10 @@ -## Performs the actual saving and loading of data related to this level/scene -## Utilized by the SaveGameManager +## Provides an easy reference for save settings through an export rather than code +## Should be attached to the main world/level scene class_name SaveLevelDataComponent extends Node -## See documentation to where this path is: https://docs.godotengine.org/en/stable/tutorials/io/data_paths.html#accessing-persistent-user-data-user[br][br] -## Default Paths:[br] -## * Windows: %APPDATA%\Godot\app_userdata\[project_name][br] -## * macOS: ~/Library/Application Support/Godot/app_userdata/[project_name][br] -## * Linux: ~/.local/share/godot/app_userdata/[project_name][br] -@export var save_game_data_path: String = "user://game_data/" -@export var save_file_name: String = "save_%s_game_data.tres" - -var level_scene_name: String -var game_data_resource: SaveGameDataResource -var level_save_file_name: String -var save_game_file_path: String +@export var settings: SaveGameSettings ## The SaveGameSettings resource func _ready() -> void: add_to_group("save_level_data_component") - level_scene_name = get_parent().name - - level_save_file_name = save_file_name % level_scene_name - save_game_file_path = save_game_data_path + level_save_file_name - - -func save_node_data() -> void: - var nodes: Array = get_tree().get_nodes_in_group("save_data_component") - - if nodes == null: return - - game_data_resource = SaveGameDataResource.new() - for node: Node in nodes: - if node is SaveDataComponent: - @warning_ignore("unsafe_method_access") - var save_data_resource: Node3DDataResource = node._save_data() - var save_final_resource: Node3DDataResource = save_data_resource.duplicate() - game_data_resource.save_data_nodes.append(save_final_resource) - -func save_game() -> void: - if !DirAccess.dir_exists_absolute(save_game_data_path): - DirAccess.make_dir_absolute(save_game_data_path) - - save_node_data() - - var result: int = ResourceSaver.save(game_data_resource, save_game_file_path) - if result != OK: - printerr("Failed to save game: ", result) - -func load_game() -> void: - if !FileAccess.file_exists(save_game_file_path): - printerr("Failed to load save. File does not exist: ", save_game_file_path) - return - - game_data_resource = ResourceLoader.load(save_game_file_path) - if game_data_resource == null: - printerr("Failed to load save. Unknown format? ", save_game_file_path) - return - - var root_node: Window = get_tree().root - for resource: Resource in game_data_resource.save_data_nodes: - if resource is Node3DDataResource: - (resource as Node3DDataResource)._load_data(root_node) - - -func list_saves() -> Array[SaveFileDetailsResource]: # TODO: Update hints - var save_files: Array[SaveFileDetailsResource] = [] - if !DirAccess.dir_exists_absolute(save_game_data_path): - return save_files - - for filename: String in ResourceLoader.list_directory(save_game_data_path): - if !filename.begins_with("save_"): continue - if !filename.ends_with(".tres"): continue # Screenshots, etc - - var _save_path: String = save_game_data_path + filename - var _save_icon: String = filename.replace(".tres", ".png") - var _save_resource: SaveFileDetailsResource = SaveFileDetailsResource.new() - var _loaded_file: FileAccess = FileAccess.open(_save_path, FileAccess.READ) - - _save_resource.filename = filename - _save_resource.date_created = Time.get_datetime_string_from_unix_time(FileAccess.get_modified_time(_save_path)) - _save_resource.filesize = _loaded_file.get_length() - - if FileAccess.file_exists(save_game_data_path + _save_icon): - _save_resource.save_icon = _save_icon - - save_files.append(_save_resource) - - return save_files diff --git a/save_load/components/save_level_data_component.tscn b/save_load/components/save_level_data_component.tscn index ccdc1d0..570dc3a 100644 --- a/save_load/components/save_level_data_component.tscn +++ b/save_load/components/save_level_data_component.tscn @@ -1,6 +1,8 @@ -[gd_scene load_steps=2 format=3 uid="uid://c3pqilb6yh5kc"] +[gd_scene load_steps=3 format=3 uid="uid://c3pqilb6yh5kc"] [ext_resource type="Script" uid="uid://c7x2qvyu62230" path="res://save_load/components/save_level_data_component.gd" id="1_exguq"] +[ext_resource type="Resource" uid="uid://o32fooj1lxg7" path="res://save_load/resources/save_game_settings_resource.tres" id="2_rkr1f"] [node name="SaveLevelDataComponent" type="Node"] script = ExtResource("1_exguq") +settings = ExtResource("2_rkr1f") diff --git a/save_load/resources/save_file_details_resource.gd b/save_load/resources/save_file_details_resource.gd index e56bc20..dd90d45 100644 --- a/save_load/resources/save_file_details_resource.gd +++ b/save_load/resources/save_file_details_resource.gd @@ -4,6 +4,7 @@ class_name SaveFileDetailsResource extends Node +@export var save_name: String = "My Save" @export var filename: String = "" @export var date_created: String = "" @export var filesize: int = 0 diff --git a/save_load/resources/save_file_highlight_panel_theme.tres b/save_load/resources/save_file_highlight_panel_theme.tres new file mode 100644 index 0000000..083bbaa --- /dev/null +++ b/save_load/resources/save_file_highlight_panel_theme.tres @@ -0,0 +1,4 @@ +[gd_resource type="StyleBoxFlat" format=3 uid="uid://bwm315lqbbb87"] + +[resource] +bg_color = Color(0.728173, 0.579132, 0.164487, 1) diff --git a/save_load/resources/save_file_panel_theme.tres b/save_load/resources/save_file_panel_theme.tres new file mode 100644 index 0000000..7835864 --- /dev/null +++ b/save_load/resources/save_file_panel_theme.tres @@ -0,0 +1,8 @@ +[gd_resource type="StyleBoxFlat" format=3 uid="uid://biousyggn7iua"] + +[resource] +content_margin_left = 5.0 +content_margin_top = 5.0 +content_margin_right = 5.0 +content_margin_bottom = 5.0 +bg_color = Color(0, 0.65098, 0.886275, 0) diff --git a/save_load/resources/save_game_data_resource.gd b/save_load/resources/save_game_data_resource.gd index 6836bd1..44210ff 100644 --- a/save_load/resources/save_game_data_resource.gd +++ b/save_load/resources/save_game_data_resource.gd @@ -7,6 +7,4 @@ extends Resource @export var game_version: String = ProjectSettings.get_setting("application/config/version") @export var save_data_nodes: Array[Node3DDataResource] -## Path to the screenshot/icon[br] -## This should generally be in the following format: e.g. user://game_data/save_my_save_name_screenshot.png -@export var save_icon: String +@export var save_name: String diff --git a/save_load/resources/save_game_settings_resource.gd b/save_load/resources/save_game_settings_resource.gd new file mode 100644 index 0000000..4aca6b5 --- /dev/null +++ b/save_load/resources/save_game_settings_resource.gd @@ -0,0 +1,15 @@ +class_name SaveGameSettings +extends Resource + + +## See documentation to where this path is: https://docs.godotengine.org/en/stable/tutorials/io/data_paths.html#accessing-persistent-user-data-user[br][br] +## Default Paths:[br] +## * Windows: %APPDATA%\Godot\app_userdata\[project_name][br] +## * macOS: ~/Library/Application Support/Godot/app_userdata/[project_name][br] +## * Linux: ~/.local/share/godot/app_userdata/[project_name][br] +@export var save_game_data_path: String = "user://game_data/" +@export var max_auto_saves: int = 5 + +@export var save_file_name: String = "save_game_data.tres" +@export var quicksave_file_name: String = "quicksave_game_data.tres" +@export var autosave_file_name: String = "autosave_%s_game_data.tres" ## %s is the save number (probably 01) diff --git a/save_load/resources/save_game_settings_resource.gd.uid b/save_load/resources/save_game_settings_resource.gd.uid new file mode 100644 index 0000000..7d1ede0 --- /dev/null +++ b/save_load/resources/save_game_settings_resource.gd.uid @@ -0,0 +1 @@ +uid://d0iptf06t7f47 diff --git a/save_load/resources/save_game_settings_resource.tres b/save_load/resources/save_game_settings_resource.tres new file mode 100644 index 0000000..0e1f12d --- /dev/null +++ b/save_load/resources/save_game_settings_resource.tres @@ -0,0 +1,12 @@ +[gd_resource type="Resource" script_class="SaveGameSettings" load_steps=2 format=3 uid="uid://o32fooj1lxg7"] + +[ext_resource type="Script" uid="uid://d0iptf06t7f47" path="res://save_load/resources/save_game_settings_resource.gd" id="1_o1tpj"] + +[resource] +script = ExtResource("1_o1tpj") +save_game_data_path = "user://game_data/" +max_auto_saves = 5 +save_file_name = "save_%s_game_data.tres" +quicksave_file_name = "quicksave_game_data.tres" +autosave_file_name = "autosave_%s_game_data.tres" +metadata/_custom_type_script = "uid://d0iptf06t7f47" diff --git a/save_load/ui/save_file.gd b/save_load/ui/save_file.gd new file mode 100644 index 0000000..1c82756 --- /dev/null +++ b/save_load/ui/save_file.gd @@ -0,0 +1,67 @@ +class_name SaveFilePanel +extends Panel + + +@export var save_panel_highlight: StyleBoxFlat +@export var save_panel_normal: StyleBoxFlat + +@export_group("Node Exports") +@export var save_name_label: Label +@export var save_date_label: Label +@export var save_icon: TextureRect +@export var load_button: TextureButton +@export var delete_confirm_ui: Control +@export var delete_button: TextureButton +@export var delete_confirm_button: BaseButton +@export var delete_cancel_button: BaseButton + +var save_file_details: SaveFileDetailsResource + + +func _ready() -> void: + mouse_entered.connect(_on_mouse_entered) + mouse_exited.connect(_on_mouse_exited) + + delete_button.pressed.connect(_on_delete_button_pressed) + load_button.pressed.connect(_on_load_button_pressed) + + delete_confirm_button.pressed.connect(_on_delete_confirm_button_pressed) + delete_cancel_button.pressed.connect(_on_delete_cancel_button_pressed) + + +func initialize(_resource: SaveFileDetailsResource) -> void: + save_file_details = _resource + set_save_date() + set_save_icon() + set_save_name() + +func set_save_date() -> void: + save_date_label.text = save_file_details.date_created + +func set_save_icon() -> void: + save_icon.texture = load(save_file_details.save_icon) + +func set_save_name() -> void: + save_name_label.text = save_file_details.save_name + if save_file_details.save_name == null or save_file_details.save_name == "": + save_name_label.text = save_file_details.filename + + +func _on_delete_button_pressed() -> void: + delete_confirm_ui.show() + +func _on_delete_confirm_button_pressed() -> void: + SaveGameManager.delete_save_file.emit(save_file_details.filename) + queue_free() + +func _on_delete_cancel_button_pressed() -> void: + delete_confirm_ui.hide() + +func _on_load_button_pressed() -> void: + SaveGameManager.load_save_file.emit(save_file_details.filename) + +func _on_mouse_entered() -> void: + set("theme_override_styles/panel", save_panel_highlight) + +func _on_mouse_exited() -> void: + set("theme_override_styles/panel", save_panel_normal) diff --git a/save_load/ui/save_file.gd.uid b/save_load/ui/save_file.gd.uid new file mode 100644 index 0000000..276bc14 --- /dev/null +++ b/save_load/ui/save_file.gd.uid @@ -0,0 +1 @@ +uid://dcfdyua5gwpw4 diff --git a/save_load/ui/save_file.tscn b/save_load/ui/save_file.tscn new file mode 100644 index 0000000..9be91ae --- /dev/null +++ b/save_load/ui/save_file.tscn @@ -0,0 +1,127 @@ +[gd_scene load_steps=11 format=3 uid="uid://bb7poutsn4ex2"] + +[ext_resource type="Texture2D" uid="uid://dknv7amroftm8" path="res://assets/icon.svg" id="1_714lu"] +[ext_resource type="StyleBox" uid="uid://biousyggn7iua" path="res://save_load/resources/save_file_panel_theme.tres" id="1_cqw77"] +[ext_resource type="Texture2D" uid="uid://cmq51cgasug81" path="res://save_load/assets/folder-open-normal.png" id="1_k6haa"] +[ext_resource type="Script" uid="uid://dcfdyua5gwpw4" path="res://save_load/ui/save_file.gd" id="2_5g2eu"] +[ext_resource type="Texture2D" uid="uid://blyryo60jydgi" path="res://save_load/assets/folder-open-pressed.png" id="2_714lu"] +[ext_resource type="StyleBox" uid="uid://bwm315lqbbb87" path="res://save_load/resources/save_file_highlight_panel_theme.tres" id="3_om23c"] +[ext_resource type="Texture2D" uid="uid://by4w5ll3le7g6" path="res://save_load/assets/folder-open-hover.png" id="3_ubfnn"] +[ext_resource type="Texture2D" uid="uid://dvp5yeoqw36yt" path="res://save_load/assets/trash-normal.png" id="4_c2bnc"] +[ext_resource type="Texture2D" uid="uid://brwa8yljyrlgy" path="res://save_load/assets/trash-pressed.png" id="5_jgxci"] +[ext_resource type="Texture2D" uid="uid://cmrtuy0i5qc01" path="res://save_load/assets/trash-hover.png" id="6_cqw77"] + +[node name="SaveFilePanel" type="Panel" node_paths=PackedStringArray("save_name_label", "save_date_label", "save_icon", "load_button", "delete_confirm_ui", "delete_button", "delete_confirm_button", "delete_cancel_button")] +custom_minimum_size = Vector2(420, 60) +offset_right = 420.0 +offset_bottom = 60.0 +theme_override_styles/panel = ExtResource("1_cqw77") +script = ExtResource("2_5g2eu") +save_panel_highlight = ExtResource("3_om23c") +save_panel_normal = ExtResource("1_cqw77") +save_name_label = NodePath("HBoxContainer/NameDate/SaveName") +save_date_label = NodePath("HBoxContainer/NameDate/SaveDate") +save_icon = NodePath("HBoxContainer/SaveFileIcon") +load_button = NodePath("HBoxContainer/Actions/LoadButton") +delete_confirm_ui = NodePath("ConfirmDeletePanel") +delete_button = NodePath("HBoxContainer/Actions/DeleteButton") +delete_confirm_button = NodePath("ConfirmDeletePanel/VBoxContainer/HBoxContainer/ConfirmButton") +delete_cancel_button = NodePath("ConfirmDeletePanel/VBoxContainer/HBoxContainer/CancelButton") + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +custom_minimum_size = Vector2(400, 0) +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -200.0 +offset_top = -20.5 +offset_right = 200.0 +offset_bottom = 20.5 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 0 + +[node name="SaveFileIcon" type="TextureRect" parent="HBoxContainer"] +layout_mode = 2 +texture = ExtResource("1_714lu") +expand_mode = 3 + +[node name="NameDate" type="VBoxContainer" parent="HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 8 + +[node name="SaveName" type="Label" parent="HBoxContainer/NameDate"] +layout_mode = 2 +text = "Save name #1" + +[node name="SaveDate" type="Label" parent="HBoxContainer/NameDate"] +layout_mode = 2 +theme_override_font_sizes/font_size = 10 +text = "2025/03/20 13:43:12" + +[node name="Actions" type="HBoxContainer" parent="HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 10 + +[node name="LoadButton" type="TextureButton" parent="HBoxContainer/Actions"] +clip_contents = true +custom_minimum_size = Vector2(32, 32) +layout_mode = 2 +tooltip_text = "Load Save" +texture_normal = ExtResource("1_k6haa") +texture_pressed = ExtResource("2_714lu") +texture_hover = ExtResource("3_ubfnn") +ignore_texture_size = true +stretch_mode = 5 + +[node name="DeleteButton" type="TextureButton" parent="HBoxContainer/Actions"] +custom_minimum_size = Vector2(32, 32) +layout_mode = 2 +tooltip_text = "Delete Save" +texture_normal = ExtResource("4_c2bnc") +texture_pressed = ExtResource("5_jgxci") +texture_hover = ExtResource("6_cqw77") +ignore_texture_size = true +stretch_mode = 5 + +[node name="ConfirmDeletePanel" type="Panel" parent="."] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="ConfirmDeletePanel"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -61.5 +offset_top = -29.0 +offset_right = 61.5 +offset_bottom = 29.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Label" type="Label" parent="ConfirmDeletePanel/VBoxContainer"] +layout_mode = 2 +text = "Delete Save?" +horizontal_alignment = 1 + +[node name="HBoxContainer" type="HBoxContainer" parent="ConfirmDeletePanel/VBoxContainer"] +layout_mode = 2 + +[node name="ConfirmButton" type="Button" parent="ConfirmDeletePanel/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Confirm" + +[node name="CancelButton" type="Button" parent="ConfirmDeletePanel/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Cancel" diff --git a/save_load/ui/save_files_list.gd b/save_load/ui/save_files_list.gd new file mode 100644 index 0000000..d3f36de --- /dev/null +++ b/save_load/ui/save_files_list.gd @@ -0,0 +1,29 @@ +extends VBoxContainer + + +@export var save_file_scene: PackedScene + + +func _ready() -> void: + SaveGameManager.refresh_saves_list.connect(_on_refresh_saves_list) + refresh_saves_list() + + +## Clear the SaveFilesList node of all saves and load most recent saves +func refresh_saves_list() -> void: + _clear_save_files_list() + + var save_files: Array[SaveFileDetailsResource] = SaveGameManager.list_saves() + + for save_resource: SaveFileDetailsResource in save_files: + var _save_file: SaveFilePanel = save_file_scene.instantiate() + _save_file.initialize(save_resource) + add_child(_save_file) + + +func _clear_save_files_list() -> void: + for _panel: SaveFilePanel in get_children(): + _panel.queue_free() + +func _on_refresh_saves_list() -> void: + refresh_saves_list() diff --git a/save_load/ui/save_files_list.gd.uid b/save_load/ui/save_files_list.gd.uid new file mode 100644 index 0000000..ba9e57b --- /dev/null +++ b/save_load/ui/save_files_list.gd.uid @@ -0,0 +1 @@ +uid://cqabj86bq8whn diff --git a/save_load/ui/save_files_list.tscn b/save_load/ui/save_files_list.tscn new file mode 100644 index 0000000..136ebdf --- /dev/null +++ b/save_load/ui/save_files_list.tscn @@ -0,0 +1,10 @@ +[gd_scene load_steps=3 format=3 uid="uid://cyxieflejsggu"] + +[ext_resource type="Script" uid="uid://cqabj86bq8whn" path="res://save_load/ui/save_files_list.gd" id="1_sh1p7"] +[ext_resource type="PackedScene" uid="uid://bb7poutsn4ex2" path="res://save_load/ui/save_file.tscn" id="2_kb5u8"] + +[node name="SaveFilesList" type="VBoxContainer"] +clip_contents = true +size_flags_horizontal = 4 +script = ExtResource("1_sh1p7") +save_file_scene = ExtResource("2_kb5u8") diff --git a/save_load/ui/save_load_ui.gd b/save_load/ui/save_load_ui.gd new file mode 100644 index 0000000..11744cd --- /dev/null +++ b/save_load/ui/save_load_ui.gd @@ -0,0 +1,36 @@ +class_name SaveLoadUI +extends Control + + +@export var show_save_ui_button: BaseButton +@export var new_save_ui: Control +@export var save_name_input: LineEdit +@export var create_save_button: BaseButton +@export var create_save_cancel_button: BaseButton + + +func _ready() -> void: + show_save_ui_button.pressed.connect(_on_show_save_ui_button_pressed) + create_save_button.pressed.connect(_on_create_save_button_pressed) + create_save_cancel_button.pressed.connect(_on_create_save_cancel_button_pressed) + + new_save_ui.hide() + + +func _on_create_save_button_pressed() -> void: + var save_name: String = save_name_input.text + if save_name.strip_edges() == "": + save_name = Time.get_datetime_string_from_system().replace(":", "") + + SaveGameManager.create_save_file.emit(save_name) + SaveGameManager.refresh_saves_list.emit() + new_save_ui.hide() + SignalManager.resume_game.emit() + +func _on_create_save_cancel_button_pressed() -> void: + new_save_ui.hide() + +func _on_show_save_ui_button_pressed() -> void: + var current_date: String = Time.get_datetime_string_from_system() + save_name_input.text = current_date.replace(":", "") + new_save_ui.show() diff --git a/save_load/ui/save_load_ui.gd.uid b/save_load/ui/save_load_ui.gd.uid new file mode 100644 index 0000000..d3bf6a0 --- /dev/null +++ b/save_load/ui/save_load_ui.gd.uid @@ -0,0 +1 @@ +uid://b6831eygibii7 diff --git a/save_load/ui/save_load_ui.tscn b/save_load/ui/save_load_ui.tscn new file mode 100644 index 0000000..4c5f2f8 --- /dev/null +++ b/save_load/ui/save_load_ui.tscn @@ -0,0 +1,132 @@ +[gd_scene load_steps=7 format=3 uid="uid://dauchkhmnyk7n"] + +[ext_resource type="Script" uid="uid://b6831eygibii7" path="res://save_load/ui/save_load_ui.gd" id="1_lo08d"] +[ext_resource type="PackedScene" uid="uid://cyxieflejsggu" path="res://save_load/ui/save_files_list.tscn" id="1_tqtxm"] +[ext_resource type="PackedScene" uid="uid://bb7poutsn4ex2" path="res://save_load/ui/save_file.tscn" id="2_6uxbh"] +[ext_resource type="Texture2D" uid="uid://ja8bc1h5x85o" path="res://save_load/assets/save-normal.png" id="3_lo08d"] +[ext_resource type="Texture2D" uid="uid://crqgyft4gfilt" path="res://save_load/assets/save-pressed.png" id="4_md7la"] +[ext_resource type="Texture2D" uid="uid://o3l0j53mgkan" path="res://save_load/assets/save-hover.png" id="5_hmxxn"] + +[node name="SaveLoadUI" type="Control" node_paths=PackedStringArray("show_save_ui_button", "new_save_ui", "save_name_input", "create_save_button", "create_save_cancel_button")] +process_mode = 3 +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 6 +size_flags_vertical = 4 +script = ExtResource("1_lo08d") +show_save_ui_button = NodePath("Panel/MarginContainer/VBoxContainer/BottomRow/SaveButton") +new_save_ui = NodePath("Panel/NewSaveUI") +save_name_input = NodePath("Panel/NewSaveUI/MarginContainer/VBoxContainer/SaveNameInput") +create_save_button = NodePath("Panel/NewSaveUI/MarginContainer/VBoxContainer/SaveButton") +create_save_cancel_button = NodePath("Panel/NewSaveUI/MarginContainer/VBoxContainer/CancelButton") + +[node name="Panel" type="Panel" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="Panel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 20 +theme_override_constants/margin_top = 20 +theme_override_constants/margin_right = 20 +theme_override_constants/margin_bottom = 20 + +[node name="VBoxContainer" type="VBoxContainer" parent="Panel/MarginContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="Panel/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 40 +text = "Save/Load Game" +horizontal_alignment = 1 + +[node name="ScrollContainer" type="ScrollContainer" parent="Panel/MarginContainer/VBoxContainer"] +custom_minimum_size = Vector2(0, 500) +layout_mode = 2 +horizontal_scroll_mode = 0 + +[node name="SaveFilesList" parent="Panel/MarginContainer/VBoxContainer/ScrollContainer" instance=ExtResource("1_tqtxm")] +layout_mode = 2 +size_flags_horizontal = 6 + +[node name="SaveFilePanel" parent="Panel/MarginContainer/VBoxContainer/ScrollContainer/SaveFilesList" instance=ExtResource("2_6uxbh")] +layout_mode = 2 + +[node name="BottomRow" type="HBoxContainer" parent="Panel/MarginContainer/VBoxContainer"] +layout_mode = 2 +alignment = 1 + +[node name="SaveButton" type="TextureButton" parent="Panel/MarginContainer/VBoxContainer/BottomRow"] +clip_contents = true +custom_minimum_size = Vector2(32, 32) +layout_mode = 2 +tooltip_text = "New Save" +texture_normal = ExtResource("3_lo08d") +texture_pressed = ExtResource("4_md7la") +texture_hover = ExtResource("5_hmxxn") +ignore_texture_size = true +stretch_mode = 5 + +[node name="NewSaveUI" type="Panel" parent="Panel"] +visible = false +custom_minimum_size = Vector2(450, 100) +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="Panel/NewSaveUI"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -205.0 +offset_top = -29.5 +offset_right = 205.0 +offset_bottom = 29.5 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 5 + +[node name="VBoxContainer" type="VBoxContainer" parent="Panel/NewSaveUI/MarginContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 + +[node name="SaveNameLabel" type="Label" parent="Panel/NewSaveUI/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 20 +text = "Create New Save" + +[node name="SaveNameInput" type="LineEdit" parent="Panel/NewSaveUI/MarginContainer/VBoxContainer"] +custom_minimum_size = Vector2(400, 0) +layout_mode = 2 +placeholder_text = "New Save File Name" + +[node name="SaveButton" type="Button" parent="Panel/NewSaveUI/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Create Save" + +[node name="CancelButton" type="Button" parent="Panel/NewSaveUI/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Cancel" diff --git a/scenes/ui/menus/pause_menu.gd b/scenes/ui/menus/pause_menu.gd index 97a1dee..9be0c5a 100644 --- a/scenes/ui/menus/pause_menu.gd +++ b/scenes/ui/menus/pause_menu.gd @@ -23,13 +23,8 @@ func _on_exit_game_button_pressed() -> void: func _on_resume_button_pressed() -> void: hide_menu() -func _on_quick_load_pressed() -> void: - SaveGameManager.load_game() - hide_menu() - -func _on_quick_save_pressed() -> void: - SaveGameManager.save_game() - hide_menu() - func _on_settings_button_pressed() -> void: SignalManager.open_settings_menu.emit() + +func _on_saves_button_pressed() -> void: + SaveGameManager.open_save_list_ui.emit() diff --git a/scenes/ui/menus/pause_menu.tscn b/scenes/ui/menus/pause_menu.tscn index 4e357f3..9b7974f 100644 --- a/scenes/ui/menus/pause_menu.tscn +++ b/scenes/ui/menus/pause_menu.tscn @@ -36,45 +36,40 @@ theme_override_constants/margin_top = 10 theme_override_constants/margin_right = 10 theme_override_constants/margin_bottom = 10 -[node name="CenterContainer" type="VBoxContainer" parent="Background/MarginContainer"] +[node name="MenuContainer" type="VBoxContainer" parent="Background/MarginContainer"] layout_mode = 2 size_flags_horizontal = 4 theme_override_constants/separation = 20 -[node name="Title" type="Label" parent="Background/MarginContainer/CenterContainer"] +[node name="Title" type="Label" parent="Background/MarginContainer/MenuContainer"] layout_mode = 2 theme_override_font_sizes/font_size = 40 text = "Paused" horizontal_alignment = 1 vertical_alignment = 1 -[node name="ButtonsContainer" type="VBoxContainer" parent="Background/MarginContainer/CenterContainer"] +[node name="ButtonsContainer" type="VBoxContainer" parent="Background/MarginContainer/MenuContainer"] layout_mode = 2 size_flags_vertical = 6 theme_override_constants/separation = 20 -[node name="ResumeButton" type="Button" parent="Background/MarginContainer/CenterContainer/ButtonsContainer"] +[node name="ResumeButton" type="Button" parent="Background/MarginContainer/MenuContainer/ButtonsContainer"] layout_mode = 2 text = "Resume" -[node name="QuickSave" type="Button" parent="Background/MarginContainer/CenterContainer/ButtonsContainer"] +[node name="SavesButton" type="Button" parent="Background/MarginContainer/MenuContainer/ButtonsContainer"] layout_mode = 2 -text = "Quick Save" +text = "Saves" -[node name="QuickLoad" type="Button" parent="Background/MarginContainer/CenterContainer/ButtonsContainer"] -layout_mode = 2 -text = "Quick Load" - -[node name="SettingsButton" type="Button" parent="Background/MarginContainer/CenterContainer/ButtonsContainer"] +[node name="SettingsButton" type="Button" parent="Background/MarginContainer/MenuContainer/ButtonsContainer"] layout_mode = 2 text = "Settings" -[node name="ExitGameButton" type="Button" parent="Background/MarginContainer/CenterContainer/ButtonsContainer"] +[node name="ExitGameButton" type="Button" parent="Background/MarginContainer/MenuContainer/ButtonsContainer"] layout_mode = 2 text = "Exit Game" -[connection signal="pressed" from="Background/MarginContainer/CenterContainer/ButtonsContainer/ResumeButton" to="." method="_on_resume_button_pressed"] -[connection signal="pressed" from="Background/MarginContainer/CenterContainer/ButtonsContainer/QuickSave" to="." method="_on_quick_save_pressed"] -[connection signal="pressed" from="Background/MarginContainer/CenterContainer/ButtonsContainer/QuickLoad" to="." method="_on_quick_load_pressed"] -[connection signal="pressed" from="Background/MarginContainer/CenterContainer/ButtonsContainer/SettingsButton" to="." method="_on_settings_button_pressed"] -[connection signal="pressed" from="Background/MarginContainer/CenterContainer/ButtonsContainer/ExitGameButton" to="." method="_on_exit_game_button_pressed"] +[connection signal="pressed" from="Background/MarginContainer/MenuContainer/ButtonsContainer/ResumeButton" to="." method="_on_resume_button_pressed"] +[connection signal="pressed" from="Background/MarginContainer/MenuContainer/ButtonsContainer/SavesButton" to="." method="_on_saves_button_pressed"] +[connection signal="pressed" from="Background/MarginContainer/MenuContainer/ButtonsContainer/SettingsButton" to="." method="_on_settings_button_pressed"] +[connection signal="pressed" from="Background/MarginContainer/MenuContainer/ButtonsContainer/ExitGameButton" to="." method="_on_exit_game_button_pressed"] diff --git a/scenes/ui/ui.gd b/scenes/ui/ui.gd index 1f201a8..ea9b1db 100644 --- a/scenes/ui/ui.gd +++ b/scenes/ui/ui.gd @@ -3,9 +3,9 @@ extends CanvasLayer @onready var crosshair: CenterContainer = $Crosshair -@onready var inventory: Inventory = $Inventory @onready var quick_slots: MarginContainer = $QuickSlots @onready var pause_menu: PauseMenu = $PauseMenu +@onready var save_load_ui: Control = $SaveLoadUI @onready var settings_menu: SettingsMenu = $SettingsMenu @onready var waila: Waila = $Waila @@ -16,6 +16,8 @@ func _ready() -> void: SignalManager.close_settings_menu.connect(_on_close_settings_menu) SignalManager.open_settings_menu.connect(_on_open_settings_menu) SignalManager.resume_game.connect(_on_resume_game) + SaveGameManager.close_save_list_ui.connect(_on_close_save_list_ui) + SaveGameManager.open_save_list_ui.connect(_on_open_save_list_ui) _on_resume_game() @@ -23,7 +25,7 @@ func _ready() -> void: func hide_menus() -> void: pause_menu.visible = false settings_menu.visible = false - inventory.visible = false + save_load_ui.visible = false func hide_ui_elements() -> void: crosshair.visible = false @@ -34,6 +36,9 @@ func hide_ui_elements() -> void: func _on_close_pause_menu() -> void: SignalManager.resume_game.emit() +func _on_close_save_list_ui() -> void: + SignalManager.open_settings_menu.emit() + func _on_close_settings_menu() -> void: SignalManager.resume_game.emit() @@ -46,6 +51,15 @@ func _on_open_pause_menu() -> void: get_tree().paused = true +func _on_open_save_list_ui() -> void: + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + + hide_ui_elements() + hide_menus() + save_load_ui.visible = true + + get_tree().paused = true + func _on_open_settings_menu() -> void: Input.mouse_mode = Input.MOUSE_MODE_VISIBLE diff --git a/scenes/ui/ui.tscn b/scenes/ui/ui.tscn index c69a58d..36fb119 100644 --- a/scenes/ui/ui.tscn +++ b/scenes/ui/ui.tscn @@ -1,12 +1,11 @@ -[gd_scene load_steps=8 format=3 uid="uid://c7fj7wla8bd70"] +[gd_scene load_steps=7 format=3 uid="uid://c7fj7wla8bd70"] [ext_resource type="Script" uid="uid://bslimr2y4lnvq" path="res://scenes/ui/ui.gd" id="1_aac20"] [ext_resource type="PackedScene" uid="uid://dvogu3djluqsn" path="res://scenes/ui/waila.tscn" id="1_u7n8c"] [ext_resource type="PackedScene" uid="uid://cbiygbgpfk220" path="res://scenes/ui/quick_slots.tscn" id="4_g5kmx"] -[ext_resource type="PackedScene" uid="uid://dcr25y1lw4wjp" path="res://scenes/ui/inventory/inventory.tscn" id="5_0dwhk"] [ext_resource type="PackedScene" uid="uid://bopvfwcgnnawg" path="res://scenes/ui/menus/pause_menu.tscn" id="6_7vp6q"] -[ext_resource type="Resource" uid="uid://blfp6tiir282o" path="res://resources/inventory/player_inventory_testing.tres" id="6_pfayw"] [ext_resource type="PackedScene" uid="uid://4bdgwwx27m71" path="res://scenes/ui/menus/settings_menu.tscn" id="7_7vp6q"] +[ext_resource type="PackedScene" uid="uid://dauchkhmnyk7n" path="res://save_load/ui/save_load_ui.tscn" id="8_jcn1r"] [node name="UI" type="CanvasLayer"] script = ExtResource("1_aac20") @@ -32,12 +31,11 @@ mouse_filter = 2 [node name="QuickSlots" parent="." instance=ExtResource("4_g5kmx")] -[node name="Inventory" parent="." instance=ExtResource("5_0dwhk")] -visible = false -inventory_resource = ExtResource("6_pfayw") - [node name="PauseMenu" parent="." instance=ExtResource("6_7vp6q")] visible = false [node name="SettingsMenu" parent="." instance=ExtResource("7_7vp6q")] visible = false + +[node name="SaveLoadUI" parent="." instance=ExtResource("8_jcn1r")] +visible = false