aboutsummaryrefslogtreecommitdiff
path: root/game/src/SaveLoadMenu
diff options
context:
space:
mode:
Diffstat (limited to 'game/src/SaveLoadMenu')
-rw-r--r--game/src/SaveLoadMenu/SaveLoadMenu.gd119
-rw-r--r--game/src/SaveLoadMenu/SaveLoadMenu.tscn109
-rw-r--r--game/src/SaveLoadMenu/SavePanelButton.gd41
-rw-r--r--game/src/SaveLoadMenu/SavePanelButton.tscn58
-rw-r--r--game/src/SaveLoadMenu/SaveResource.gd59
5 files changed, 386 insertions, 0 deletions
diff --git a/game/src/SaveLoadMenu/SaveLoadMenu.gd b/game/src/SaveLoadMenu/SaveLoadMenu.gd
new file mode 100644
index 0000000..abf1f8c
--- /dev/null
+++ b/game/src/SaveLoadMenu/SaveLoadMenu.gd
@@ -0,0 +1,119 @@
+extends Control
+
+@export var _save_scene : PackedScene
+
+@export_group("Nodes")
+@export var _label : Label
+@export var _scroll_list : BoxContainer
+@export var _save_line_edit : LineEdit
+@export var _save_load_button : Button
+@export var _tag_selection_tab : TabBar
+@export var _delete_dialog : ConfirmationDialog
+@export var _overwrite_dialog : ConfirmationDialog
+
+var is_save_menu : bool = true
+var _id_to_tag : Array[StringName] = []
+
+func filter_for_tag(tag : StringName) -> void:
+ for child in _scroll_list.get_children():
+ if tag == &"":
+ child.show()
+ else:
+ if tag == child.resource.session_tag:
+ child.show()
+ else:
+ child.hide()
+
+func show_for_load() -> void:
+ _label.text = "SAVELOADMENU_LOAD_TITLE"
+ _save_load_button.text = "SAVELOADMENU_LOAD_BUTTON"
+ _save_line_edit.editable = false
+ is_save_menu = false
+ show()
+
+func show_for_save() -> void:
+ _label.text = "SAVELOADMENU_SAVE_TITLE"
+ _save_load_button.text = "SAVELOADMENU_SAVE_BUTTON"
+ _save_line_edit.editable = true
+ is_save_menu = true
+ show()
+
+func _build_save_list() -> void:
+ _tag_selection_tab.add_tab("SAVELOADMENU_TABSELECTIONTABBAR_ALL")
+ for save_name in SaveManager._save_dictionary:
+ var save : SaveResource = SaveManager._save_dictionary[save_name]
+ var save_node := _create_save_node(save)
+ _scroll_list.add_child(save_node)
+ if not _id_to_tag.has(save.session_tag):
+ _id_to_tag.append(save.session_tag)
+ _tag_selection_tab.add_tab(save.session_tag)
+
+func _create_save_node(resource : SaveResource) -> Control:
+ var save_node = _save_scene.instantiate()
+ save_node.resource = resource
+ save_node.pressed.connect(_on_save_node_pressed.bind(save_node))
+ save_node.request_to_delete.connect(_on_save_node_delete_requested.bind(save_node))
+ return save_node
+
+func _queue_clear_scroll_list() -> void:
+ for child in _scroll_list.get_children():
+ child.queue_free()
+ _tag_selection_tab.clear_tabs()
+ _id_to_tag.clear()
+
+# REQUIREMENTS:
+# * UIFUN-84
+# * UIFUN-89
+func _on_close_button_pressed() -> void:
+ hide()
+
+func _on_delete_dialog_confirmed() -> void:
+ _requested_node_to_delete.resource.delete()
+ _requested_node_to_delete.queue_free()
+
+# REQUIREMENTS:
+# * UIFUNC-83
+func _on_overwrite_dialog_confirmed() -> void:
+ SaveManager.add_or_replace_save(SaveManager.make_new_save(_submitted_text))
+ _on_close_button_pressed()
+
+var _submitted_text : String = ""
+func _on_save_line_edit_text_submitted(new_text) -> void:
+ _submitted_text = new_text
+ if SaveManager.has_save(new_text):
+ _overwrite_dialog.dialog_text = tr("SAVELOADMENU_OVERWRITE_DIALOG_TEXT").format({ "file_name": _submitted_text })
+ _overwrite_dialog.title = tr("SAVELOADMENU_OVERWRITE_DIALOG_TITLE").format({ "file_name": _submitted_text })
+ _overwrite_dialog.popup_centered()
+ return
+ _on_overwrite_dialog_confirmed()
+
+func _on_save_load_button_pressed() -> void:
+ if is_save_menu:
+ _save_line_edit.text_submitted.emit(_save_line_edit.text)
+
+var _requested_node_to_delete : Control
+func _on_save_node_delete_requested(node : Control) -> void:
+ _requested_node_to_delete = node
+ _delete_dialog.dialog_text = tr("SAVELOADMENU_DELETE_DIALOG_TEXT").format({ "file_name": _requested_node_to_delete.resource.save_name })
+ _delete_dialog.title = tr("SAVELOADMENU_DELETE_DIALOG_TITLE").format({ "file_name": _requested_node_to_delete.resource.save_name })
+ _delete_dialog.popup_centered()
+
+# REQUIREMENTS:
+# * UIFUN-81
+# * UIFUN-86
+func _on_save_node_pressed(node : Control) -> void:
+ if is_save_menu:
+ _save_line_edit.text = node.resource.save_name
+
+func _on_tag_selection_tab_bar_tab_changed(tab) -> void:
+ if tab == 0:
+ filter_for_tag(&"")
+ else:
+ filter_for_tag(_id_to_tag[tab - 1])
+
+func _on_visibility_changed() -> void:
+ if visible:
+ _build_save_list()
+ else:
+ _queue_clear_scroll_list()
+ SaveManager.flush_save()
diff --git a/game/src/SaveLoadMenu/SaveLoadMenu.tscn b/game/src/SaveLoadMenu/SaveLoadMenu.tscn
new file mode 100644
index 0000000..e9f068e
--- /dev/null
+++ b/game/src/SaveLoadMenu/SaveLoadMenu.tscn
@@ -0,0 +1,109 @@
+[gd_scene load_steps=5 format=3 uid="uid://d3g6wbvwflmyk"]
+
+[ext_resource type="Script" path="res://src/SaveLoadMenu/SaveLoadMenu.gd" id="1_3jkds"]
+[ext_resource type="PackedScene" uid="uid://d2s7roinx2or7" path="res://src/SaveLoadMenu/SavePanelButton.tscn" id="2_fc6r3"]
+
+[sub_resource type="InputEventAction" id="InputEventAction_8vo2t"]
+action = &"ui_accept"
+pressed = true
+
+[sub_resource type="Shortcut" id="Shortcut_o1f2l"]
+events = [SubResource("InputEventAction_8vo2t")]
+
+[node name="SaveLoadMenu" type="MarginContainer" node_paths=PackedStringArray("_label", "_scroll_list", "_save_line_edit", "_save_load_button", "_tag_selection_tab", "_delete_dialog", "_overwrite_dialog")]
+editor_description = "UI-82, UI-89"
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 250
+theme_override_constants/margin_top = 100
+theme_override_constants/margin_right = 250
+theme_override_constants/margin_bottom = 100
+script = ExtResource("1_3jkds")
+_save_scene = ExtResource("2_fc6r3")
+_label = NodePath("SaveLoadPanel/SaveLoadList/TitleBarList/SaveLoadLabel")
+_scroll_list = NodePath("SaveLoadPanel/SaveLoadList/SaveLoadScroll/SaveLoadScrollList")
+_save_line_edit = NodePath("SaveLoadPanel/SaveLoadList/SaveLineEdit")
+_save_load_button = NodePath("SaveLoadPanel/SaveLoadList/SaveLoadButton")
+_tag_selection_tab = NodePath("SaveLoadPanel/SaveLoadList/TagSelectionList/TagSelectionTabBar")
+_delete_dialog = NodePath("DeleteDialog")
+_overwrite_dialog = NodePath("OverwriteDialog")
+
+[node name="SaveLoadPanel" type="PanelContainer" parent="."]
+layout_mode = 2
+
+[node name="SaveLoadList" type="VBoxContainer" parent="SaveLoadPanel"]
+layout_mode = 2
+
+[node name="TitleBarList" type="HBoxContainer" parent="SaveLoadPanel/SaveLoadList"]
+layout_mode = 2
+alignment = 2
+
+[node name="SaveLoadLabel" type="Label" parent="SaveLoadPanel/SaveLoadList/TitleBarList"]
+layout_mode = 2
+size_flags_horizontal = 6
+text = "SAVELOADMENU_SAVE_TITLE"
+
+[node name="CloseButton" type="Button" parent="SaveLoadPanel/SaveLoadList/TitleBarList"]
+editor_description = "UI-87, UI-94"
+layout_mode = 2
+text = "X"
+
+[node name="TagSelectionList" type="HBoxContainer" parent="SaveLoadPanel/SaveLoadList"]
+layout_mode = 2
+
+[node name="TagSelectionLabel" type="Label" parent="SaveLoadPanel/SaveLoadList/TagSelectionList"]
+layout_mode = 2
+text = "SAVELOADMENU_SESSION"
+
+[node name="TagSelectionTabBar" type="TabBar" parent="SaveLoadPanel/SaveLoadList/TagSelectionList"]
+layout_mode = 2
+size_flags_horizontal = 3
+tab_count = 1
+tab_0/title = "SAVELOADMENU_TABSELECTIONTABBAR_ALL"
+
+[node name="SaveLoadScroll" type="ScrollContainer" parent="SaveLoadPanel/SaveLoadList"]
+editor_description = "UI-83, UI-90"
+layout_mode = 2
+size_flags_vertical = 3
+
+[node name="SaveLoadScrollList" type="VBoxContainer" parent="SaveLoadPanel/SaveLoadList/SaveLoadScroll"]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="SaveLineEdit" type="LineEdit" parent="SaveLoadPanel/SaveLoadList"]
+editor_description = "UI-85, UI-92"
+layout_mode = 2
+
+[node name="SaveLoadButton" type="Button" parent="SaveLoadPanel/SaveLoadList"]
+editor_description = "UIFUN-82, UIFUN-87"
+layout_mode = 2
+size_flags_horizontal = 4
+shortcut = SubResource("Shortcut_o1f2l")
+shortcut_feedback = false
+text = "SAVELOADMENU_SAVE_BUTTON"
+
+[node name="DeleteDialog" type="ConfirmationDialog" parent="."]
+disable_3d = true
+title = "SAVELOADMENU_DELETE_DIALOG_TITLE"
+ok_button_text = "DIALOG_OK"
+dialog_text = "SAVELOADMENU_DELETE_DIALOG_TEXT"
+cancel_button_text = "DIALOG_CANCEL"
+
+[node name="OverwriteDialog" type="ConfirmationDialog" parent="."]
+disable_3d = true
+title = "SAVELOADMENU_OVERWRITE_DIALOG_TITLE"
+ok_button_text = "DIALOG_OK"
+dialog_text = "SAVELOADMENU_OVERWRITE_DIALOG_TEXT"
+cancel_button_text = "DIALOG_CANCEL"
+
+[connection signal="visibility_changed" from="." to="." method="_on_visibility_changed"]
+[connection signal="pressed" from="SaveLoadPanel/SaveLoadList/TitleBarList/CloseButton" to="." method="_on_close_button_pressed"]
+[connection signal="tab_changed" from="SaveLoadPanel/SaveLoadList/TagSelectionList/TagSelectionTabBar" to="." method="_on_tag_selection_tab_bar_tab_changed"]
+[connection signal="text_submitted" from="SaveLoadPanel/SaveLoadList/SaveLineEdit" to="." method="_on_save_line_edit_text_submitted"]
+[connection signal="pressed" from="SaveLoadPanel/SaveLoadList/SaveLoadButton" to="." method="_on_save_load_button_pressed"]
+[connection signal="confirmed" from="DeleteDialog" to="." method="_on_delete_dialog_confirmed"]
+[connection signal="confirmed" from="OverwriteDialog" to="." method="_on_overwrite_dialog_confirmed"]
diff --git a/game/src/SaveLoadMenu/SavePanelButton.gd b/game/src/SaveLoadMenu/SavePanelButton.gd
new file mode 100644
index 0000000..5fe4917
--- /dev/null
+++ b/game/src/SaveLoadMenu/SavePanelButton.gd
@@ -0,0 +1,41 @@
+@tool
+extends LobbyPanelButton
+
+signal request_to_delete
+
+@export_group("Nodes")
+@export var country_flag : TextureRect
+@export var date_label : Label
+@export var delete_button : BaseButton
+
+var resource : SaveResource:
+ get:
+ return resource
+ set(value):
+ if resource != null:
+ resource.changed.disconnect(_resource_changed)
+ resource = value
+ if resource != null:
+ resource.changed.connect(_resource_changed)
+ _resource_changed()
+
+func get_text() -> StringName:
+ return resource.save_name
+
+func set_text(value : StringName) -> void:
+ if resource != null:
+ resource.save_name = value
+
+func _ready():
+ _resource_changed()
+
+func _is_start_date() -> bool:
+ return false
+
+func _resource_changed() -> void:
+ if resource == null: return
+ name_label.text = resource.save_name
+ date_label.text = Time.get_datetime_string_from_unix_time(resource.get_save_file_time(), true)
+
+func _on_delete_button_pressed() -> void:
+ request_to_delete.emit()
diff --git a/game/src/SaveLoadMenu/SavePanelButton.tscn b/game/src/SaveLoadMenu/SavePanelButton.tscn
new file mode 100644
index 0000000..3a71a57
--- /dev/null
+++ b/game/src/SaveLoadMenu/SavePanelButton.tscn
@@ -0,0 +1,58 @@
+[gd_scene load_steps=2 format=3 uid="uid://d2s7roinx2or7"]
+
+[ext_resource type="Script" path="res://src/SaveLoadMenu/SavePanelButton.gd" id="1_rtuo6"]
+
+[node name="SavePanelButton" type="Container" node_paths=PackedStringArray("country_flag", "date_label", "delete_button", "background_button", "name_label")]
+editor_description = "UI-84, UI-91"
+offset_right = 276.0
+offset_bottom = 48.0
+script = ExtResource("1_rtuo6")
+country_flag = NodePath("SaveList/CountryFlag")
+date_label = NodePath("SaveList/DateLabel")
+delete_button = NodePath("SaveList/DeleteButton")
+background_button = NodePath("BackgroundButton")
+name_label = NodePath("SaveList/NameLabel")
+
+[node name="BackgroundButton" type="Button" parent="."]
+layout_mode = 2
+theme_type_variation = &"ButtonContainer"
+
+[node name="SaveList" type="HBoxContainer" parent="."]
+layout_mode = 2
+mouse_filter = 2
+
+[node name="CountryFlag" type="TextureRect" parent="SaveList"]
+layout_mode = 2
+size_flags_horizontal = 0
+size_flags_vertical = 4
+mouse_filter = 2
+
+[node name="NameLabel" type="Label" parent="SaveList"]
+layout_mode = 2
+size_flags_horizontal = 0
+size_flags_vertical = 1
+text = "PLACEHOLDER"
+vertical_alignment = 1
+
+[node name="DateLabel" type="Label" parent="SaveList"]
+layout_mode = 2
+size_flags_horizontal = 0
+size_flags_vertical = 1
+text = "00.00.0000"
+vertical_alignment = 1
+
+[node name="Separator" type="Control" parent="SaveList"]
+layout_mode = 2
+size_flags_horizontal = 3
+mouse_filter = 2
+
+[node name="DeleteButton" type="Button" parent="SaveList"]
+layout_mode = 2
+size_flags_horizontal = 8
+text = "x"
+
+[connection signal="button_down" from="BackgroundButton" to="." method="_on_background_button_button_down"]
+[connection signal="button_up" from="BackgroundButton" to="." method="_on_background_button_button_up"]
+[connection signal="pressed" from="BackgroundButton" to="." method="_on_background_button_pressed"]
+[connection signal="toggled" from="BackgroundButton" to="." method="_on_background_button_toggled"]
+[connection signal="pressed" from="SaveList/DeleteButton" to="." method="_on_delete_button_pressed"]
diff --git a/game/src/SaveLoadMenu/SaveResource.gd b/game/src/SaveLoadMenu/SaveResource.gd
new file mode 100644
index 0000000..5e7faa6
--- /dev/null
+++ b/game/src/SaveLoadMenu/SaveResource.gd
@@ -0,0 +1,59 @@
+extends Resource
+class_name SaveResource
+
+signal file_flushed(path : String)
+signal file_loaded
+signal file_moved_to_trash
+signal file_deleted
+signal trash_moved
+signal deleted
+
+var save_name : StringName:
+ get: return save_name
+ set(v):
+ save_name = v
+ file.set_value("Save", "name", save_name)
+ emit_changed()
+var session_tag : StringName:
+ get: return session_tag
+ set(v):
+ session_tag = v
+ file.set_value("Save", "session_tag", v)
+ emit_changed()
+var file_path : String:
+ get: return file_path
+ set(v):
+ file_path = v
+ emit_changed()
+var file : ConfigFile = ConfigFile.new()
+
+func set_file_path(name : StringName, path : String):
+ file_path = path
+ save_name = name
+
+func flush_save() -> Error:
+ file_flushed.emit(file_path)
+ var result := file.save(file_path)
+ file.clear()
+ return result
+
+func load_save(path : String = file_path) -> Error:
+ file_loaded.emit()
+ var result := file.load(path)
+ session_tag = file.get_value("Save", "session_tag", session_tag)
+ if path != file_path:
+ set_file_path(file.get_value("Save", "name", save_name), path)
+ return result
+
+func get_save_file_time() -> int:
+ return FileAccess.get_modified_time(file_path)
+
+func move_to_trash() -> Error:
+ trash_moved.emit()
+ file_moved_to_trash.emit()
+ return OS.move_to_trash(file_path)
+
+func delete() -> Error:
+ deleted.emit()
+ file_deleted.emit()
+ return DirAccess.remove_absolute(file_path)