Add localization support and refactor menus

- Implemented LocalizationManager for handling multiple languages.
- Updated LoadGameMenu, MainMenu, PauseMenu, and SettingsMenu to support localization.
- Added InstanceSelectionMenu for selecting game instances.
- Refactored SaveManager to handle new SaveInstance structure.
- Created SaveDialog for saving games with user-defined names.
- Enhanced SaveData to manage multiple save instances.
- Added error handling and logging for save/load operations.
- Updated UI elements to reflect localized text.
This commit is contained in:
Björn Blomberg
2025-10-17 14:22:21 +02:00
parent b37fe0a858
commit 74062a37d6
32 changed files with 2304 additions and 46 deletions

View File

@@ -68,6 +68,7 @@ layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
process_mode = 3
script = ExtResource("2_a5qiy")
[node name="Background" type="ColorRect" parent="PauseMenu"]
@@ -105,6 +106,10 @@ text = "Resume"
layout_mode = 2
text = "Save Game"
[node name="SettingsButton" type="Button" parent="PauseMenu/MenuContainer"]
layout_mode = 2
text = "Settings"
[node name="MainMenuButton" type="Button" parent="PauseMenu/MenuContainer"]
layout_mode = 2
text = "Exit to Main Menu"
@@ -116,5 +121,6 @@ text = "Exit to Desktop"
[connection signal="pressed" from="UI/PauseButton" to="." method="_on_pause_button_pressed"]
[connection signal="pressed" from="PauseMenu/MenuContainer/ResumeButton" to="PauseMenu" method="_on_resume_button_pressed"]
[connection signal="pressed" from="PauseMenu/MenuContainer/SaveButton" to="PauseMenu" method="_on_save_button_pressed"]
[connection signal="pressed" from="PauseMenu/MenuContainer/SettingsButton" to="PauseMenu" method="_on_settings_button_pressed"]
[connection signal="pressed" from="PauseMenu/MenuContainer/MainMenuButton" to="PauseMenu" method="_on_main_menu_button_pressed"]
[connection signal="pressed" from="PauseMenu/MenuContainer/DesktopButton" to="PauseMenu" method="_on_desktop_button_pressed"]

View File

@@ -45,10 +45,15 @@ text = "Start Game"
layout_mode = 2
text = "Load Game"
[node name="SettingsButton" type="Button" parent="VBoxContainer"]
layout_mode = 2
text = "Settings"
[node name="ExitButton" type="Button" parent="VBoxContainer"]
layout_mode = 2
text = "Exit"
[connection signal="pressed" from="VBoxContainer/StartButton" to="." method="_on_start_button_pressed"]
[connection signal="pressed" from="VBoxContainer/LoadButton" to="." method="_on_load_button_pressed"]
[connection signal="pressed" from="VBoxContainer/SettingsButton" to="." method="_on_settings_button_pressed"]
[connection signal="pressed" from="VBoxContainer/ExitButton" to="." method="_on_exit_button_pressed"]

193
scenes/SettingsMenu.tscn Normal file
View File

@@ -0,0 +1,193 @@
[gd_scene load_steps=2 format=3 uid="uid://b2k5vxrj8nq4h"]
[ext_resource type="Script" path="res://scripts/SettingsMenu.cs" id="1_settings"]
[node name="SettingsMenu" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
process_mode = 3
script = ExtResource("1_settings")
[node name="Background" type="ColorRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
color = Color(0.15, 0.15, 0.25, 1)
[node name="MainContainer" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -400.0
offset_top = -300.0
offset_right = 400.0
offset_bottom = 300.0
[node name="TitleLabel" type="Label" parent="MainContainer"]
layout_mode = 2
text = "SETTINGS"
horizontal_alignment = 1
[node name="HSeparator" type="HSeparator" parent="MainContainer"]
layout_mode = 2
[node name="TabContainer" type="TabContainer" parent="MainContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="General" type="Control" parent="MainContainer/TabContainer"]
layout_mode = 2
[node name="GeneralVBox" type="VBoxContainer" parent="MainContainer/TabContainer/General"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 20.0
offset_top = 20.0
offset_right = -20.0
offset_bottom = -20.0
[node name="LanguageContainer" type="HBoxContainer" parent="MainContainer/TabContainer/General/GeneralVBox"]
layout_mode = 2
[node name="LanguageLabel" type="Label" parent="MainContainer/TabContainer/General/GeneralVBox/LanguageContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Language:"
vertical_alignment = 1
[node name="LanguageOption" type="OptionButton" parent="MainContainer/TabContainer/General/GeneralVBox/LanguageContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Video" type="Control" parent="MainContainer/TabContainer"]
layout_mode = 2
[node name="VideoVBox" type="VBoxContainer" parent="MainContainer/TabContainer/Video"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 20.0
offset_top = 20.0
offset_right = -20.0
offset_bottom = -20.0
[node name="FullscreenContainer" type="HBoxContainer" parent="MainContainer/TabContainer/Video/VideoVBox"]
layout_mode = 2
[node name="FullscreenLabel" type="Label" parent="MainContainer/TabContainer/Video/VideoVBox/FullscreenContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Fullscreen:"
vertical_alignment = 1
[node name="FullscreenCheck" type="CheckBox" parent="MainContainer/TabContainer/Video/VideoVBox/FullscreenContainer"]
layout_mode = 2
[node name="Audio" type="Control" parent="MainContainer/TabContainer"]
layout_mode = 2
[node name="AudioVBox" type="VBoxContainer" parent="MainContainer/TabContainer/Audio"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 20.0
offset_top = 20.0
offset_right = -20.0
offset_bottom = -20.0
[node name="MasterContainer" type="VBoxContainer" parent="MainContainer/TabContainer/Audio/AudioVBox"]
layout_mode = 2
[node name="MasterLabel" type="Label" parent="MainContainer/TabContainer/Audio/AudioVBox/MasterContainer"]
layout_mode = 2
text = "Master Volume: 100"
[node name="MasterSlider" type="HSlider" parent="MainContainer/TabContainer/Audio/AudioVBox/MasterContainer"]
layout_mode = 2
min_value = 1.0
max_value = 100.0
step = 1.0
value = 100.0
[node name="BackgroundContainer" type="VBoxContainer" parent="MainContainer/TabContainer/Audio/AudioVBox"]
layout_mode = 2
[node name="BackgroundLabel" type="Label" parent="MainContainer/TabContainer/Audio/AudioVBox/BackgroundContainer"]
layout_mode = 2
text = "Background Volume: 100"
[node name="BackgroundSlider" type="HSlider" parent="MainContainer/TabContainer/Audio/AudioVBox/BackgroundContainer"]
layout_mode = 2
min_value = 1.0
max_value = 100.0
step = 1.0
value = 100.0
[node name="EffectsContainer" type="VBoxContainer" parent="MainContainer/TabContainer/Audio/AudioVBox"]
layout_mode = 2
[node name="EffectsLabel" type="Label" parent="MainContainer/TabContainer/Audio/AudioVBox/EffectsContainer"]
layout_mode = 2
text = "Effects Volume: 100"
[node name="EffectsSlider" type="HSlider" parent="MainContainer/TabContainer/Audio/AudioVBox/EffectsContainer"]
layout_mode = 2
min_value = 1.0
max_value = 100.0
step = 1.0
value = 100.0
[node name="RadioContainer" type="VBoxContainer" parent="MainContainer/TabContainer/Audio/AudioVBox"]
layout_mode = 2
[node name="RadioLabel" type="Label" parent="MainContainer/TabContainer/Audio/AudioVBox/RadioContainer"]
layout_mode = 2
text = "Radio Volume: 100"
[node name="RadioSlider" type="HSlider" parent="MainContainer/TabContainer/Audio/AudioVBox/RadioContainer"]
layout_mode = 2
min_value = 1.0
max_value = 100.0
step = 1.0
value = 100.0
[node name="HSeparator2" type="HSeparator" parent="MainContainer"]
layout_mode = 2
[node name="ButtonContainer" type="HBoxContainer" parent="MainContainer"]
layout_mode = 2
[node name="ApplyButton" type="Button" parent="MainContainer/ButtonContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Apply"
[node name="CancelButton" type="Button" parent="MainContainer/ButtonContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Cancel"
[node name="BackButton" type="Button" parent="MainContainer/ButtonContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Back"
[connection signal="item_selected" from="MainContainer/TabContainer/General/GeneralVBox/LanguageContainer/LanguageOption" to="." method="_on_language_option_item_selected"]
[connection signal="toggled" from="MainContainer/TabContainer/Video/VideoVBox/FullscreenContainer/FullscreenCheck" to="." method="_on_fullscreen_check_toggled"]
[connection signal="value_changed" from="MainContainer/TabContainer/Audio/AudioVBox/MasterContainer/MasterSlider" to="." method="_on_master_slider_value_changed"]
[connection signal="value_changed" from="MainContainer/TabContainer/Audio/AudioVBox/BackgroundContainer/BackgroundSlider" to="." method="_on_background_slider_value_changed"]
[connection signal="value_changed" from="MainContainer/TabContainer/Audio/AudioVBox/EffectsContainer/EffectsSlider" to="." method="_on_effects_slider_value_changed"]
[connection signal="value_changed" from="MainContainer/TabContainer/Audio/AudioVBox/RadioContainer/RadioSlider" to="." method="_on_radio_slider_value_changed"]
[connection signal="pressed" from="MainContainer/ButtonContainer/ApplyButton" to="." method="_on_apply_button_pressed"]
[connection signal="pressed" from="MainContainer/ButtonContainer/CancelButton" to="." method="_on_cancel_button_pressed"]
[connection signal="pressed" from="MainContainer/ButtonContainer/BackButton" to="." method="_on_back_button_pressed"]