Browse Source

Merge pull request 'Save File Icon Creation' (#16) from game_save_icons into master

pull/17/head
Ryan Reed 1 month ago
parent
commit
3bced69ee4
15 changed files with 110 additions and 15 deletions
  1. +6
    -0
      autoloads/game_settings_manager.gd
  2. +1
    -0
      resources/game_settings/game_options_settings_resource.gd
  3. +48
    -5
      save_load/autoloads/save_game_manager.gd
  4. +3
    -0
      save_load/components/save_level_data_component.gd
  5. +3
    -1
      save_load/components/save_level_data_component.tscn
  6. +4
    -0
      save_load/resources/default_save_icon.tres
  7. +1
    -1
      save_load/resources/save_file_details_resource.gd
  8. +1
    -1
      save_load/ui/save_file.gd
  9. +2
    -2
      save_load/ui/save_file.tscn
  10. +2
    -3
      save_load/ui/save_files_list.gd
  11. +6
    -1
      save_load/ui/save_load_ui.gd
  12. +5
    -0
      scenes/root.tscn
  13. +6
    -0
      scenes/ui/menus/settings_menu.gd
  14. +18
    -1
      scenes/ui/menus/settings_menu.tscn
  15. +4
    -0
      scenes/ui/ui.gd

+ 6
- 0
autoloads/game_settings_manager.gd View File

@ -5,6 +5,7 @@ extends Node
signal game_options_block_highlight_changed(block_highlight_enabled: bool)
signal game_options_held_block_ui_changed(held_block_enabled: bool)
signal game_options_quickslots_ui_changed(quickslots_enabled: bool)
signal game_options_screenshot_saves_changed(screenshots_enabled: bool)
signal game_options_waila_changed(waila_enabled: bool)
#endregion
@ -36,6 +37,7 @@ func _init() -> void:
game_options_block_highlight_changed.connect(_on_game_options_block_highlight_changed)
game_options_held_block_ui_changed.connect(_on_game_options_held_block_ui_changed)
game_options_quickslots_ui_changed.connect(_on_game_options_quickslots_ui_changed)
game_options_screenshot_saves_changed.connect(_on_game_options_screenshot_saves_changed)
game_options_waila_changed.connect(_on_game_options_waila_changed)
graphics_fov_changed.connect(_on_graphics_fov_changed)
@ -61,6 +63,10 @@ func _on_game_options_quickslots_ui_changed(quickslots_enabled: bool) -> void:
settings.game_options.enable_quickslots_ui = quickslots_enabled
save_settings()
func _on_game_options_screenshot_saves_changed(screenshots_enabled: bool) -> void:
settings.game_options.enable_save_screenshots = screenshots_enabled
save_settings()
func _on_game_options_waila_changed(waila_enabled: bool) -> void:
settings.game_options.enable_waila = waila_enabled
save_settings()


+ 1
- 0
resources/game_settings/game_options_settings_resource.gd View File

@ -6,3 +6,4 @@ extends Resource
@export var enable_block_highlight: bool = true
@export var enable_quickslots_ui: bool = true
@export var enable_held_block: bool = true
@export var enable_save_screenshots: bool = true ## Take a screenshot during save to use as the save icon

+ 48
- 5
save_load/autoloads/save_game_manager.gd View File

@ -9,7 +9,6 @@ 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)
@ -18,9 +17,12 @@ signal quick_save
signal quick_load
signal open_save_list_ui
signal close_save_list_ui
signal toggle_save_icon_generation(toggled: bool) ## Enable/Disable the generation of a screenshot during save for the save icon.
var _enable_save_icon_generation: bool = true
var _game_data_resource: SaveGameDataResource = SaveGameDataResource.new()
var _save_icon_size: Vector2i = Vector2i(896, 504) ## If Vector2.ZERO, uses the user's resolution
var _save_level_data_component: SaveLevelDataComponent ## Contains the save paths and filenames
@ -28,8 +30,9 @@ 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)
load_save_file.connect(load_game_save)
delete_save_file.connect(_on_delete_save_file)
toggle_save_icon_generation.connect(_on_toggle_save_icon_generation)
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("quick_save"):
@ -71,14 +74,17 @@ func list_saves(include_quick_saves: bool = true, include_auto_saves: bool = tru
var _loaded_file: FileAccess = FileAccess.open(_save_path, FileAccess.READ)
_save_resource.filesize = _loaded_file.get_length()
if FileAccess.file_exists(save_game_data_path + _save_icon):
_save_resource.save_icon = _save_icon
_save_resource.save_icon_texture = _generate_save_icon_texture(save_game_data_path + _save_icon)
save_files.append(_save_resource)
save_files.sort_custom(_custom_save_file_sort)
return save_files
func load_game_save(resource_filename: String) -> void:
_load_game_resource(resource_filename)
game_loaded.emit()
func quick_save_game() -> void:
if not _load_save_level_data_component(): return
@ -90,7 +96,6 @@ 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()
@ -99,6 +104,22 @@ func quick_load_game() -> void:
func _custom_save_file_sort(a: SaveFileDetailsResource, b: SaveFileDetailsResource) -> bool:
return a.date_created > b.date_created
## Generate the texture for use in the save file listing
func _generate_save_icon_texture(save_icon: String) -> Texture2D:
var _icon_texture: Texture2D = ImageTexture.new()
if save_icon != null and !FileAccess.file_exists(save_icon):
_icon_texture = _save_level_data_component.default_save_icon_resource
elif save_icon == null:
_icon_texture = _save_level_data_component.default_save_icon_resource
else:
var _icon_image: Image = Image.new()
_icon_image.load(save_icon)
@warning_ignore("unsafe_method_access")
_icon_texture.set_image(_icon_image)
return _icon_texture
## 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")
@ -110,6 +131,7 @@ func _load_save_level_data_component() -> bool:
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)
@ -120,6 +142,8 @@ func _load_game_resource(resource_filename: String) -> void:
printerr("Failed to load save. Unknown format? ", save_game_file_path)
return
EntityManager.reset_world.emit()
var root_node: Window = get_tree().root
for resource: Resource in _game_data_resource.save_data_nodes:
if resource is Node3DDataResource:
@ -138,6 +162,8 @@ func _save_game_as_resource(resource_filename: String) -> void:
if result != OK:
printerr("Failed to save game (" , result, "): ", save_game_file_path)
_take_save_screenshot(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")
@ -151,6 +177,19 @@ func _save_node_data() -> void:
var save_final_resource: Node3DDataResource = save_data_resource.duplicate()
_game_data_resource.save_data_nodes.append(save_final_resource)
## Takes a screenshot and saves next to the save file[br]
## The icon utilizes the same filename as the save file, replacing `.tres` with `.png`
func _take_save_screenshot(save_game_file_path: String) -> void:
if !_enable_save_icon_generation: return
var _icon_filepath: String = save_game_file_path.replace(".tres", ".png")
var _icon: Image = get_viewport().get_texture().get_image()
if _save_icon_size != Vector2i.ZERO:
_icon.resize(_save_icon_size.x, _save_icon_size.y)
_icon.save_png(_icon_filepath)
func _on_save_game_as_resource(save_name: String) -> void:
if not _load_save_level_data_component(): return
@ -169,3 +208,7 @@ func _on_delete_save_file(filename: String) -> void:
var save_file_path: String = _save_level_data_component.settings.save_game_data_path + filename
DirAccess.remove_absolute(save_file_path)
DirAccess.remove_absolute(save_file_path.replace(".tres", ".png")) # Delete icon
func _on_toggle_save_icon_generation(toggled: bool) -> void:
_enable_save_icon_generation = toggled

+ 3
- 0
save_load/components/save_level_data_component.gd View File

@ -3,7 +3,10 @@
class_name SaveLevelDataComponent
extends Node
@export var default_save_icon_resource: CompressedTexture2D
@export var settings: SaveGameSettings ## The SaveGameSettings resource
@export var ui_node: CanvasLayer ## The UI to Show/Hide when taking screenshot (e.g. save icon generation)
func _ready() -> void:


+ 3
- 1
save_load/components/save_level_data_component.tscn View File

@ -1,8 +1,10 @@
[gd_scene load_steps=3 format=3 uid="uid://c3pqilb6yh5kc"]
[gd_scene load_steps=4 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="Texture2D" uid="uid://60ib8urc8xjo" path="res://save_load/resources/default_save_icon.tres" id="2_hd7aa"]
[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")
default_save_icon_resource = ExtResource("2_hd7aa")
settings = ExtResource("2_rkr1f")

+ 4
- 0
save_load/resources/default_save_icon.tres View File

@ -0,0 +1,4 @@
[gd_resource type="CompressedTexture2D" format=3 uid="uid://60ib8urc8xjo"]
[resource]
load_path = "res://.godot/imported/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.ctex"

+ 1
- 1
save_load/resources/save_file_details_resource.gd View File

@ -8,4 +8,4 @@ extends Node
@export var filename: String = ""
@export var date_created: String = ""
@export var filesize: int = 0
@export var save_icon: String = "res://assets/icon.svg"
@export var save_icon_texture: Texture2D

+ 1
- 1
save_load/ui/save_file.gd View File

@ -39,7 +39,7 @@ 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)
save_icon.texture = save_file_details.save_icon_texture
func set_save_name() -> void:
save_name_label.text = save_file_details.save_name


+ 2
- 2
save_load/ui/save_file.tscn View File

@ -1,6 +1,5 @@
[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"]
@ -8,6 +7,7 @@
[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://60ib8urc8xjo" path="res://save_load/resources/default_save_icon.tres" id="4_jgxci"]
[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"]
@ -46,7 +46,7 @@ size_flags_horizontal = 0
[node name="SaveFileIcon" type="TextureRect" parent="HBoxContainer"]
layout_mode = 2
texture = ExtResource("1_714lu")
texture = ExtResource("4_jgxci")
expand_mode = 3
[node name="NameDate" type="VBoxContainer" parent="HBoxContainer"]


+ 2
- 3
save_load/ui/save_files_list.gd View File

@ -5,8 +5,7 @@ extends VBoxContainer
func _ready() -> void:
SaveGameManager.refresh_saves_list.connect(_on_refresh_saves_list)
refresh_saves_list()
SaveGameManager.open_save_list_ui.connect(_on_open_save_list_ui)
## Clear the SaveFilesList node of all saves and load most recent saves
@ -25,5 +24,5 @@ func _clear_save_files_list() -> void:
for _panel: SaveFilePanel in get_children():
_panel.queue_free()
func _on_refresh_saves_list() -> void:
func _on_open_save_list_ui() -> void:
refresh_saves_list()

+ 6
- 1
save_load/ui/save_load_ui.gd View File

@ -22,8 +22,13 @@ func _on_create_save_button_pressed() -> void:
if save_name.strip_edges() == "":
save_name = Time.get_datetime_string_from_system().replace(":", "")
var _save_level_data_component: SaveLevelDataComponent = get_tree().get_first_node_in_group("save_level_data_component")
if _save_level_data_component.ui_node != null:
_save_level_data_component.ui_node.visible = false
await get_tree().create_timer(.150).timeout # A hack to allow time for UI to hide before taking screenshot
SaveGameManager.create_save_file.emit(save_name)
SaveGameManager.refresh_saves_list.emit()
if _save_level_data_component.ui_node != null:
_save_level_data_component.ui_node.visible = true
new_save_ui.hide()
SignalManager.resume_game.emit()


+ 5
- 0
scenes/root.tscn View File

@ -9,4 +9,9 @@ script = ExtResource("1_lrqlo")
[node name="World" parent="." instance=ExtResource("2_vvh5c")]
[node name="SaveLevelDataComponent" parent="World" index="3" node_paths=PackedStringArray("ui_node")]
ui_node = NodePath("../../UI")
[node name="UI" parent="." instance=ExtResource("3_vvh5c")]
[editable path="World"]

+ 6
- 0
scenes/ui/menus/settings_menu.gd View File

@ -6,6 +6,7 @@ extends Panel
@export var block_highlight_input: CheckButton
@export var held_block_ui_input: CheckButton
@export var quick_slots_ui_input: CheckButton
@export var screenshot_icon_input: CheckButton
@export var waila_input: CheckButton
@export_group("Graphics Settings Nodes")
@ -26,6 +27,7 @@ func apply_default_values() -> void:
block_highlight_input.set_pressed_no_signal(GameSettingsManager.settings.game_options.enable_block_highlight)
held_block_ui_input.set_pressed_no_signal(GameSettingsManager.settings.game_options.enable_held_block)
quick_slots_ui_input.set_pressed_no_signal(GameSettingsManager.settings.game_options.enable_quickslots_ui)
screenshot_icon_input.set_pressed_no_signal(GameSettingsManager.settings.game_options.enable_save_screenshots)
waila_input.set_pressed_no_signal(GameSettingsManager.settings.game_options.enable_waila)
#endregion
@ -52,6 +54,10 @@ func _on_quickslots_ui_toggled(toggled_on: bool) -> void:
func _on_enable_waila_toggled(toggled_on: bool) -> void:
GameSettingsManager.game_options_waila_changed.emit(toggled_on)
func _on_screenshot_icon_button_toggled(toggled_on: bool) -> void:
GameSettingsManager.game_options_screenshot_saves_changed.emit(toggled_on)
SaveGameManager.toggle_save_icon_generation.emit(toggled_on)
#endregion
#region Graphics Settings


+ 18
- 1
scenes/ui/menus/settings_menu.tscn View File

@ -14,7 +14,7 @@ corner_radius_top_right = 2
corner_radius_bottom_right = 2
corner_radius_bottom_left = 2
[node name="SettingsMenu" type="Panel" node_paths=PackedStringArray("block_highlight_input", "held_block_ui_input", "quick_slots_ui_input", "waila_input", "resolution_input", "fullscreen_input", "vsync_input", "fov_slider", "fov_value_label")]
[node name="SettingsMenu" type="Panel" node_paths=PackedStringArray("block_highlight_input", "held_block_ui_input", "quick_slots_ui_input", "screenshot_icon_input", "waila_input", "resolution_input", "fullscreen_input", "vsync_input", "fov_slider", "fov_value_label")]
process_mode = 3
anchors_preset = 15
anchor_right = 1.0
@ -25,6 +25,7 @@ script = ExtResource("1_qwcqe")
block_highlight_input = NodePath("Background/MarginContainer/VBoxContainer/TabContainer/Game/BlockHighlight/CheckButton")
held_block_ui_input = NodePath("Background/MarginContainer/VBoxContainer/TabContainer/Game/HeldBlockUI/CheckButton")
quick_slots_ui_input = NodePath("Background/MarginContainer/VBoxContainer/TabContainer/Game/QuickslotsUI/CheckButton")
screenshot_icon_input = NodePath("Background/MarginContainer/VBoxContainer/TabContainer/Game/ScreenshotIcon/CheckButton")
waila_input = NodePath("Background/MarginContainer/VBoxContainer/TabContainer/Game/Waila/CheckButton")
resolution_input = NodePath("Background/MarginContainer/VBoxContainer/TabContainer/Graphics/Resolution/OptionButton")
fullscreen_input = NodePath("Background/MarginContainer/VBoxContainer/TabContainer/Graphics/Fullscreen/CheckBox")
@ -126,6 +127,21 @@ text = "Enable Player Held Block"
layout_mode = 2
button_pressed = true
[node name="ScreenshotIcon" type="HBoxContainer" parent="Background/MarginContainer/VBoxContainer/TabContainer/Game"]
layout_mode = 2
[node name="Label" type="Label" parent="Background/MarginContainer/VBoxContainer/TabContainer/Game/ScreenshotIcon"]
layout_mode = 2
size_flags_horizontal = 3
tooltip_text = "Enable/Disable the taking of a screenshot to utilize as the save icon."
mouse_filter = 1
text = "Enable Save Screenshot"
[node name="CheckButton" type="CheckButton" parent="Background/MarginContainer/VBoxContainer/TabContainer/Game/ScreenshotIcon"]
layout_mode = 2
tooltip_text = "Enable/Disable the taking of a screenshot to utilize as the save icon."
button_pressed = true
[node name="Graphics" type="VBoxContainer" parent="Background/MarginContainer/VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
@ -244,6 +260,7 @@ text = "Close Settings"
[connection signal="toggled" from="Background/MarginContainer/VBoxContainer/TabContainer/Game/Waila/CheckButton" to="." method="_on_enable_waila_toggled"]
[connection signal="toggled" from="Background/MarginContainer/VBoxContainer/TabContainer/Game/QuickslotsUI/CheckButton" to="." method="_on_quickslots_ui_toggled"]
[connection signal="toggled" from="Background/MarginContainer/VBoxContainer/TabContainer/Game/HeldBlockUI/CheckButton" to="." method="_on_held_block_ui_toggled"]
[connection signal="toggled" from="Background/MarginContainer/VBoxContainer/TabContainer/Game/ScreenshotIcon/CheckButton" to="." method="_on_screenshot_icon_button_toggled"]
[connection signal="value_changed" from="Background/MarginContainer/VBoxContainer/TabContainer/Graphics/FOV/HSlider" to="." method="_on_fov_slider_changed"]
[connection signal="pressed" from="Background/MarginContainer/VBoxContainer/TabContainer/Graphics/CenterContainer/ApplyButton" to="." method="_on_graphics_apply_button_pressed"]
[connection signal="pressed" from="Background/BottomRow/CloseButton" to="." method="_on_close_button_pressed"]

+ 4
- 0
scenes/ui/ui.gd View File

@ -18,6 +18,7 @@ func _ready() -> void:
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)
SaveGameManager.game_loaded.connect(_on_game_loaded)
_on_resume_game()
@ -42,6 +43,9 @@ func _on_close_save_list_ui() -> void:
func _on_close_settings_menu() -> void:
SignalManager.resume_game.emit()
func _on_game_loaded() -> void:
_on_resume_game()
func _on_open_pause_menu() -> void:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE


Loading…
Cancel
Save