From 9c7fc660ccc5a649cc16013402a0a0d0527e9f4a Mon Sep 17 00:00:00 2001 From: lightyears Date: Fri, 2 Jun 2023 22:34:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=B8=B8=E6=88=8F=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Autoloads/GameSettings.cs | 110 +-------------------- Autoloads/GameSettingsNode.cs | 106 ++++++++++++++++++++ Components/Settings/AudioSettingsMenu.cs | 4 +- Components/Settings/SettingsMenu.cs | 4 +- Components/Settings/SettingsMenu.tscn | 9 +- Components/Settings/SettingsMenuPopup.cs | 2 +- Components/Settings/SettingsMenuPopup.tscn | 16 +-- Scenes/MainScene.cs | 2 +- Scenes/MainScene.tscn | 11 ++- project.godot | 2 +- 10 files changed, 141 insertions(+), 125 deletions(-) create mode 100644 Autoloads/GameSettingsNode.cs diff --git a/Autoloads/GameSettings.cs b/Autoloads/GameSettings.cs index 063ce93..dca3356 100644 --- a/Autoloads/GameSettings.cs +++ b/Autoloads/GameSettings.cs @@ -1,118 +1,16 @@ -using Newtonsoft.Json; - namespace CMSGame { - /// - /// 游戏设置持久化 - /// - public partial class GameSettings : Node - { - protected Dictionary CurrentSettings = new(); - - protected Dictionary OriginalSettings = new(); - - protected Dictionary SettingsPaths = new(); - - public BattleSettings BattleSettings => GetSettings(); - - public VideoSettings VideoSettings => GetSettings(); - - public AudioSettings AudioSettings => GetSettings(); - - public GameSettings() - { - RegisterAllSettings(); - } - - public override void _Ready() - { - MakeDirectories(); - LoadAllSettings(); - } - - protected void RegisterAllSettings() - { - RegisterSettings("BattleSettings.json"); - RegisterSettings("VideoSettings.json"); - RegisterSettings("AudioSettings.json"); - } - - protected void RegisterSettings(string filename) where TSettings : SettingsBase, new() - { - var defaultSettings = new TSettings(); - CurrentSettings.Add(typeof(TSettings), defaultSettings); - SettingsPaths.Add(typeof(TSettings), new GodotPath($"user://Settings/{filename}")); - } - - protected void LoadAllSettings() - { - foreach (var settingsType in SettingsPaths.Keys) - { - LoadSettings(settingsType); - } - } - - public override void _ExitTree() - { - foreach (var settingsType in SettingsPaths.Keys) - { - if (!OriginalSettings.ContainsKey(settingsType) || OriginalSettings[settingsType] != CurrentSettings[settingsType]) - { - SaveSettings(settingsType); - } - } - } - - private static void MakeDirectories() - { - DirAccess.MakeDirRecursiveAbsolute("user://Settings/"); - } - - private void LoadSettings(Type settingsType) - { - string settingsText = ReadFileAsString(SettingsPaths[settingsType]); - var settings = JsonConvert.DeserializeObject(settingsText, settingsType); - if (settings != null) - { - OriginalSettings[settingsType] = (SettingsBase)settings; - CurrentSettings[settingsType] = (SettingsBase)settings; - } - } - - public TSettings GetSettings() where TSettings : SettingsBase, new() - { - return (TSettings)CurrentSettings[typeof(TSettings)]; - } - - private static string ReadFileAsString(string path) - { - if (FileAccess.FileExists(path)) - { - using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read); - return file.GetAsText(); - } - return "null"; - } - - private void SaveSettings(Type settingsType) - { - string settingsText = JsonConvert.SerializeObject(CurrentSettings[settingsType]); - using var file = FileAccess.Open(SettingsPaths[settingsType], FileAccess.ModeFlags.Write); - file.StoreString(settingsText); - } - } - - public record class SettingsBase + public record class GameSettings { } - public record class BattleSettings : SettingsBase + public record class BattleSettings : GameSettings { } - public record class VideoSettings : SettingsBase + public record class VideoSettings : GameSettings { } - public record class AudioSettings : SettingsBase + public record class AudioSettings : GameSettings { /// /// 音乐音量 diff --git a/Autoloads/GameSettingsNode.cs b/Autoloads/GameSettingsNode.cs new file mode 100644 index 0000000..bc581e2 --- /dev/null +++ b/Autoloads/GameSettingsNode.cs @@ -0,0 +1,106 @@ +using Newtonsoft.Json; + +namespace CMSGame +{ + /// + /// 游戏设置持久化节点 + /// + /// 在游戏开始时载入用户设置,并在游戏关闭时保存用户设置。 + /// + public partial class GameSettingsNode : Node + { + protected Dictionary CurrentSettings = new(); + + protected Dictionary OriginalSettings = new(); + + protected Dictionary SettingsPaths = new(); + + public BattleSettings BattleSettings => GetSettings(); + + public VideoSettings VideoSettings => GetSettings(); + + public AudioSettings AudioSettings => GetSettings(); + + public GameSettingsNode() + { + RegisterAllSettings(); + } + + public override void _Ready() + { + MakeDirectories(); + LoadAllSettings(); + } + + protected void RegisterAllSettings() + { + RegisterSettings("BattleSettings.json"); + RegisterSettings("VideoSettings.json"); + RegisterSettings("AudioSettings.json"); + } + + protected void RegisterSettings(string filename) where TSettings : GameSettings, new() + { + var defaultSettings = new TSettings(); + CurrentSettings.Add(typeof(TSettings), defaultSettings); + SettingsPaths.Add(typeof(TSettings), new GodotPath($"user://Settings/{filename}")); + } + + protected void LoadAllSettings() + { + foreach (var settingsType in SettingsPaths.Keys) + { + LoadSettings(settingsType); + } + } + + public override void _ExitTree() + { + foreach (var settingsType in SettingsPaths.Keys) + { + if (!OriginalSettings.ContainsKey(settingsType) || OriginalSettings[settingsType] != CurrentSettings[settingsType]) + { + SaveSettings(settingsType); + } + } + } + + private static void MakeDirectories() + { + DirAccess.MakeDirRecursiveAbsolute("user://Settings/"); + } + + private void LoadSettings(Type settingsType) + { + string settingsText = ReadFileAsString(SettingsPaths[settingsType]); + var settings = JsonConvert.DeserializeObject(settingsText, settingsType); + if (settings != null) + { + OriginalSettings[settingsType] = (GameSettings)settings; + CurrentSettings[settingsType] = (GameSettings)settings; + } + } + + public TSettings GetSettings() where TSettings : GameSettings, new() + { + return (TSettings)CurrentSettings[typeof(TSettings)]; + } + + private static string ReadFileAsString(string path) + { + if (FileAccess.FileExists(path)) + { + using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read); + return file.GetAsText(); + } + return "null"; + } + + private void SaveSettings(Type settingsType) + { + string settingsText = JsonConvert.SerializeObject(CurrentSettings[settingsType]); + using var file = FileAccess.Open(SettingsPaths[settingsType], FileAccess.ModeFlags.Write); + file.StoreString(settingsText); + } + } +} diff --git a/Components/Settings/AudioSettingsMenu.cs b/Components/Settings/AudioSettingsMenu.cs index 2789ee9..661f292 100644 --- a/Components/Settings/AudioSettingsMenu.cs +++ b/Components/Settings/AudioSettingsMenu.cs @@ -2,7 +2,7 @@ namespace CMSGame { public partial class AudioSettingsMenu : VBoxContainer { - public GameSettings? GameSettings; + public GameSettingsNode? Settings; public HSlider? MasterVolumeSlider; @@ -12,7 +12,7 @@ namespace CMSGame public override void _Ready() { - this.GetAutoloadNode(ref GameSettings, nameof(GameSettings)); + this.GetAutoloadNode(ref Settings, nameof(GameSettingsNode)); MasterVolumeSlider = this.GetUniqueNode(nameof(MasterVolumeSlider)); MusicVolumeSlider = this.GetUniqueNode(nameof(MusicVolumeSlider)); diff --git a/Components/Settings/SettingsMenu.cs b/Components/Settings/SettingsMenu.cs index eb76b21..2421f55 100644 --- a/Components/Settings/SettingsMenu.cs +++ b/Components/Settings/SettingsMenu.cs @@ -2,11 +2,11 @@ namespace CMSGame { public partial class SettingsMenu : TabContainer { - public GameSettings? Settings; + public GameSettingsNode? Settings; public override void _Ready() { - this.GetAutoloadNode(ref Settings, nameof(GameSettings)); + this.GetAutoloadNode(ref Settings, nameof(GameSettingsNode)); } } } diff --git a/Components/Settings/SettingsMenu.tscn b/Components/Settings/SettingsMenu.tscn index 7532ad6..9ba9005 100644 --- a/Components/Settings/SettingsMenu.tscn +++ b/Components/Settings/SettingsMenu.tscn @@ -16,7 +16,6 @@ script = ExtResource("1_av57b") [node name="BattleSettingsMenu" type="VBoxContainer" parent="."] unique_name_in_owner = true -visible = false layout_mode = 2 script = ExtResource("2_xtjo5") @@ -28,6 +27,7 @@ script = ExtResource("3_68iki") [node name="AudioSettingsMenu" type="VBoxContainer" parent="."] unique_name_in_owner = true +visible = false layout_mode = 2 script = ExtResource("4_ciy5h") @@ -39,7 +39,8 @@ columns = 2 layout_mode = 2 text = "主音量" -[node name="MasterVolumnSlider" type="HSlider" parent="AudioSettingsMenu/GridContainer"] +[node name="MasterVolumeSlider" type="HSlider" parent="AudioSettingsMenu/GridContainer"] +unique_name_in_owner = true layout_mode = 2 max_value = 1.0 step = 0.01 @@ -49,7 +50,7 @@ value = 0.8 layout_mode = 2 text = "音乐音量" -[node name="MusicVolumnSlider" type="HSlider" parent="AudioSettingsMenu/GridContainer"] +[node name="MusicVolumeSlider" type="HSlider" parent="AudioSettingsMenu/GridContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(200, 0) layout_mode = 2 @@ -61,7 +62,7 @@ value = 0.8 layout_mode = 2 text = "音效音量" -[node name="SoundEffectVolumnSlider" type="HSlider" parent="AudioSettingsMenu/GridContainer"] +[node name="SoundEffectVolumeSlider" type="HSlider" parent="AudioSettingsMenu/GridContainer"] unique_name_in_owner = true layout_mode = 2 max_value = 1.0 diff --git a/Components/Settings/SettingsMenuPopup.cs b/Components/Settings/SettingsMenuPopup.cs index a383201..bff1404 100644 --- a/Components/Settings/SettingsMenuPopup.cs +++ b/Components/Settings/SettingsMenuPopup.cs @@ -2,7 +2,7 @@ namespace CMSGame { public partial class SettingsMenuPopup : Popup { - public void On_ConfirmButton_Pressed() + public void On_HidePopupButton_Pressed() { Hide(); } diff --git a/Components/Settings/SettingsMenuPopup.tscn b/Components/Settings/SettingsMenuPopup.tscn index a54444b..22e96ae 100644 --- a/Components/Settings/SettingsMenuPopup.tscn +++ b/Components/Settings/SettingsMenuPopup.tscn @@ -4,20 +4,24 @@ [ext_resource type="PackedScene" uid="uid://blk2uswpo2a7k" path="res://Components/Settings/SettingsMenu.tscn" id="2_qc1kk"] [node name="SettingsMenuPopup" type="Popup"] -size = Vector2i(172, 101) +size = Vector2i(800, 485) visible = true script = ExtResource("1_it4yp") [node name="VBoxContainer" type="VBoxContainer" parent="."] -offset_right = 40.0 -offset_bottom = 40.0 +offset_right = 800.0 +offset_bottom = 66.0 +alignment = 1 [node name="SettingsMenu" parent="VBoxContainer" instance=ExtResource("2_qc1kk")] +custom_minimum_size = Vector2(800, 450) layout_mode = 2 -[node name="ConfirmButton" type="Button" parent="VBoxContainer"] +[node name="HidePopupButton" type="Button" parent="VBoxContainer"] unique_name_in_owner = true +custom_minimum_size = Vector2(200, 0) layout_mode = 2 -text = "保存并退出" +size_flags_horizontal = 4 +text = "关闭" -[connection signal="pressed" from="VBoxContainer/ConfirmButton" to="." method="On_ConfirmButton_Pressed"] +[connection signal="pressed" from="VBoxContainer/HidePopupButton" to="." method="On_HidePopupButton_Pressed"] diff --git a/Scenes/MainScene.cs b/Scenes/MainScene.cs index 7548423..e8fcbf1 100644 --- a/Scenes/MainScene.cs +++ b/Scenes/MainScene.cs @@ -4,7 +4,7 @@ namespace CMSGame { public void On_SettingsPopupButton_Pressed() { - GetNode("%SettingsPopup").PopupCentered(); + GetNode("%SettingsMenuPopup").PopupCentered(); } public void On_QuitButton_Pressed() diff --git a/Scenes/MainScene.tscn b/Scenes/MainScene.tscn index b5fe19a..a6528c8 100644 --- a/Scenes/MainScene.tscn +++ b/Scenes/MainScene.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=3 format=3 uid="uid://c3ovsoq6o7y3t"] +[gd_scene load_steps=4 format=3 uid="uid://c3ovsoq6o7y3t"] [ext_resource type="Script" path="res://Scenes/MainScene.cs" id="1_kso8c"] [ext_resource type="Theme" uid="uid://cn55cr5w4yy3n" path="res://Themes/UI.tres" id="1_y72s3"] +[ext_resource type="PackedScene" uid="uid://cslqihnfw0me2" path="res://Components/Settings/SettingsMenuPopup.tscn" id="3_1d7q7"] [node name="MainScene" type="Control"] layout_mode = 3 @@ -10,7 +11,6 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -theme = ExtResource("1_y72s3") script = ExtResource("1_kso8c") [node name="BackgroundImage" type="Label" parent="."] @@ -34,6 +34,7 @@ offset_top = -65.5 offset_right = 287.0 offset_bottom = 65.5 grow_vertical = 2 +theme = ExtResource("1_y72s3") theme_override_constants/separation = 16 [node name="StartButton" type="Button" parent="StartMenu"] @@ -48,6 +49,12 @@ text = "设置" layout_mode = 2 text = "退出" +[node name="SettingsMenuPopup" parent="." instance=ExtResource("3_1d7q7")] +unique_name_in_owner = true +title = "游戏设置" +visible = false +borderless = false + [connection signal="pressed" from="StartMenu/StartButton" to="." method="On_BattleDemo1Button_Pressed"] [connection signal="pressed" from="StartMenu/SettingsButton" to="." method="On_SettingsPopupButton_Pressed"] [connection signal="pressed" from="StartMenu/QuitButton" to="." method="On_QuitButton_Pressed"] diff --git a/project.godot b/project.godot index 0988869..25c2758 100644 --- a/project.godot +++ b/project.godot @@ -22,7 +22,7 @@ config/icon="res://icon.svg" [autoload] -GameSettings="*res://Autoloads/GameSettings.cs" +GameSettingsNode="*res://Autoloads/GameSettingsNode.cs" BackgroundMusicPlayer="*res://Autoloads/BackgroundMusicPlayer.tscn" [display]