From 694fcfa064b4943e46d75ef0ea5722995c51113a Mon Sep 17 00:00:00 2001 From: xwalfie Date: Tue, 7 Jul 2026 23:34:30 +0200 Subject: [PATCH 1/5] feat: import nightly settings adds a new button that finds settings.json in nightly userfolder and maps the kv adds a new function to compute dB to percentage --- scripts/SoundManager.cs | 6 + scripts/database/settings/SettingsProfile.cs | 137 +++++++++++++++++-- scripts/ui/SettingsMenu.cs | 6 +- 3 files changed, 132 insertions(+), 17 deletions(-) diff --git a/scripts/SoundManager.cs b/scripts/SoundManager.cs index 9eb59133..e0fcea83 100644 --- a/scripts/SoundManager.cs +++ b/scripts/SoundManager.cs @@ -375,6 +375,12 @@ public static float ComputeVolumeDb(float volume, float master, float range) return (float)(-80 + range * Math.Pow(volume / 100, 0.1) * Math.Pow(master / 100, 0.1)); } + public static float ComputeVolumeFromDb(float db, float master, float range) + { + if (float.IsNegativeInfinity(db) || master <= 0) return 0; + return (float)Math.Clamp(100 * Math.Pow((db + 80) / (range * Math.Pow(master / 100, 0.1)), 10), 0, 100); + } + public static void UpdateVolume() { var settings = SettingsManager.Instance.Settings; diff --git a/scripts/database/settings/SettingsProfile.cs b/scripts/database/settings/SettingsProfile.cs index dd085036..c731b16f 100644 --- a/scripts/database/settings/SettingsProfile.cs +++ b/scripts/database/settings/SettingsProfile.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.Json; using Godot; public partial class SettingsProfile @@ -342,11 +343,11 @@ public partial class SettingsProfile /// public SettingsItem DisplayFPS { get; private set; } - // [Order] + [Order] /// /// Import settings from previous (nightly) version /// - // public SettingsItem RhythiaImport { get; private set; } + public SettingsItem RhythiaImport { get; private set; } [Order] /// @@ -1030,18 +1031,126 @@ public SettingsProfile() #region Other - // RhythiaImport = new(default) - // { - // Id = "RhythiaImport", - // Title = "Import Nightly Settings", - // Description = "Imports settings from the nightly client", - // Section = SettingsSection.Other, - // Buttons = - // [ - // new() { Title = "Import", Description = "", OnPressed = () => { } } - // ], - // SaveToDisk = false, - // }; + RhythiaImport = new(default) + { + Id = "RhythiaImport", + Title = "Import Nightly Settings", + Description = "Imports settings from the nightly client", + Section = SettingsSection.Other, + Buttons = + [ + new() { Title = "Import", Description = "", OnPressed = () => { + string nightlyDir = $"{Path.GetDirectoryName(Constants.USER_FOLDER)}/SoundSpacePlus"; + + if (Directory.Exists(nightlyDir)) { + string nightlySettingsPath = $"{nightlyDir}/settings.json"; + + string nightlySettings = File.Exists(nightlySettingsPath) ? File.ReadAllText(nightlySettingsPath) : null; + + if (nightlySettings == null) { + ToastNotification.Notify("Nightly settings not found, choose the settings file manually."); + }; + + using JsonDocument json = JsonDocument.Parse(nightlySettings); + JsonElement root = json.RootElement; + + T? getSetting(string key) where T : struct { + if (root.TryGetProperty(key, out JsonElement element)) { + return element.Deserialize(); + } + + return null; + } + + // needs a separate helper for strings due to the struct constraint in getSetting() + string? getStringSetting(string key) { + if (root.TryGetProperty(key, out JsonElement element)) { + return element.GetString(); + } + return null; + } + + double importVolume(string nightlyKey, double range) { + double? channelDb = getSetting(nightlyKey); + + if (channelDb == null) { + return 50; + } + + double masterDb = getSetting("master_volume") ?? 20 * Math.Log10(0.5); + double totalDb = Math.Clamp(masterDb + channelDb.Value, -80, 0); + + return SoundManager.ComputeVolumeFromDb((float)totalDb, 100, (float)range); + } + + SettingsProfile nightlyProfile = new SettingsProfile(); + + nightlyProfile.Sensitivity.Value = getSetting("sensitivity") * 2.16 * (70 / (getSetting("fov") ?? 70)) ?? nightlyProfile.Sensitivity.Value; + nightlyProfile.AbsoluteSensitivity.Value = getSetting("absolute_scale") ?? nightlyProfile.AbsoluteSensitivity.Value; + nightlyProfile.AbsoluteInput.Value = getSetting("absolute_mode") ?? nightlyProfile.AbsoluteInput.Value; + nightlyProfile.CursorDrift.Value = getSetting("enable_drift_cursor") ?? nightlyProfile.CursorDrift.Value; + nightlyProfile.ApproachRate.Value = getSetting("approach_rate") ?? nightlyProfile.ApproachRate.Value; + nightlyProfile.ApproachDistance.Value = getSetting("spawn_distance") ?? nightlyProfile.ApproachDistance.Value; + nightlyProfile.Pushback.Value = getSetting("do_note_pushback") ?? nightlyProfile.Pushback.Value; + nightlyProfile.CameraParallax.Value = getSetting("parallax") * 0.025 ?? nightlyProfile.CameraParallax.Value; + nightlyProfile.HUDParallax.Value = getSetting("ui_parallax") * 0.025 ?? nightlyProfile.HUDParallax.Value; + nightlyProfile.FoV.Value = getSetting("fov") ?? nightlyProfile.FoV.Value; + nightlyProfile.NoteColors.Value = getStringSetting("selected_colorset") ?? nightlyProfile.NoteColors.Value; + nightlyProfile.NoteMesh.Value = getStringSetting("selected_mesh") ?? nightlyProfile.NoteMesh.Value; + nightlyProfile.NoteSize.Value = getSetting("note_size") * 0.875 ?? nightlyProfile.NoteSize.Value; + nightlyProfile.NoteOpacity.Value = getSetting("note_opacity") ?? nightlyProfile.NoteOpacity.Value; + nightlyProfile.CursorScale.Value = getSetting("cursor_scale") ?? nightlyProfile.CursorScale.Value; + nightlyProfile.CursorRotation.Value = getSetting("cursor_spin") ?? nightlyProfile.CursorRotation.Value; + nightlyProfile.CursorTrail.Value = getSetting("cursor_trail") ?? nightlyProfile.CursorTrail.Value; + nightlyProfile.TrailTime.Value = getSetting("trail_time") ?? nightlyProfile.TrailTime.Value; + nightlyProfile.TrailDetail.Value = getSetting("trail_detail") ?? nightlyProfile.TrailDetail.Value; + nightlyProfile.SimpleHUD.Value = getSetting("simple_hud") ?? nightlyProfile.SimpleHUD.Value; + nightlyProfile.HitPopups.Value = getSetting("score_popup") ?? nightlyProfile.HitPopups.Value; + nightlyProfile.MissPopups.Value = getSetting("show_miss_effect") ?? nightlyProfile.MissPopups.Value; + nightlyProfile.Fullscreen.Value = getSetting("window_fullscreen") ?? nightlyProfile.Fullscreen.Value; + nightlyProfile.FPS.Value = getSetting("target_fps") ?? nightlyProfile.FPS.Value; + nightlyProfile.VolumeMaster.Value = 100; + nightlyProfile.VolumeMusic.Value = importVolume("music_volume", 70);; + nightlyProfile.VolumeHitSound.Value = importVolume("hit_volume", 80); + nightlyProfile.VolumeMissSound.Value = importVolume("miss_volume", 80); + nightlyProfile.VolumeSFX.Value = importVolume("fail_volume", 80); + nightlyProfile.EnableHitSound.Value = getSetting("play_hit_snd") ?? nightlyProfile.EnableHitSound.Value; + nightlyProfile.EnableMissSound.Value = getSetting("play_miss_snd") ?? nightlyProfile.EnableMissSound.Value; + nightlyProfile.EnableMenuMusic.Value = getSetting("play_menu_music") ?? nightlyProfile.EnableMenuMusic.Value; + nightlyProfile.AutoplayJukebox.Value = getSetting("auto_preview_song") ?? nightlyProfile.AutoplayJukebox.Value; + nightlyProfile.LocalOffset.Value = getSetting("music_offset") ?? nightlyProfile.LocalOffset.Value; + nightlyProfile.RecordReplays.Value = getSetting("record_replays") ?? nightlyProfile.RecordReplays.Value; + + // prevents overriding existing 'nightly' profile + string getProfileName(string baseName) { + string profilesDir = $"{Constants.USER_FOLDER}/profiles"; + Directory.CreateDirectory(profilesDir); + + string name = baseName; + int suffix = 0; + + while (File.Exists($"{profilesDir}/{name}.json")) { + suffix++; + name = $"{baseName}-{suffix}"; + } + + return name; + } + + string profileName = getProfileName("nightly"); + string profileJson = SettingsProfileConverter.Serialize(nightlyProfile); + File.WriteAllText($"{Constants.USER_FOLDER}/profiles/{profileName}.json", profileJson); + + SettingsManager.SetCurrentProfile(profileName); + SettingsManager.Load(); + SettingsMenu.Instance.UpdateProfileSelection(); + + ToastNotification.Notify($"Created profile '{profileName}'"); + } + } } + ], + SaveToDisk = false, + }; DisplayFPS = new(true) { diff --git a/scripts/ui/SettingsMenu.cs b/scripts/ui/SettingsMenu.cs index 1b89c2c5..af8998d5 100644 --- a/scripts/ui/SettingsMenu.cs +++ b/scripts/ui/SettingsMenu.cs @@ -53,7 +53,7 @@ public override void _Ready() SettingsManager.SetCurrentProfile(profile); SettingsManager.Reload(); - updateProfileSelection(); + UpdateProfileSelection(); }; profilesButton.ItemSelected += (index) => @@ -67,7 +67,7 @@ public override void _Ready() SettingsManager.Load(); }; - updateProfileSelection(); + UpdateProfileSelection(); Panel settingTemplate = categoryTemplate.GetNode("Container").GetNode("SettingTemplate"); CheckButton checkButtonTemplate = settingTemplate.GetNode("CheckButton"); @@ -248,7 +248,7 @@ public void SelectCategory(ScrollContainer category) sidebar.GetNode(new(selectedCategory.Name)).Color = Color.Color8(255, 255, 255, 8); } - private void updateProfileSelection() + public void UpdateProfileSelection() { // skip default for (int i = 1; i < profilesButton.ItemCount; i++) From 019bfbd6918396e2b5b3c953901dbd0cb955ca38 Mon Sep 17 00:00:00 2001 From: xwalfie Date: Wed, 8 Jul 2026 01:13:19 +0200 Subject: [PATCH 2/5] feat: added option to choose settings file manually --- scenes/main.tscn | 12 +- scripts/database/settings/SettingsProfile.cs | 239 +++++++++++-------- scripts/ui/SettingsMenu.cs | 3 + 3 files changed, 150 insertions(+), 104 deletions(-) diff --git a/scenes/main.tscn b/scenes/main.tscn index 4a9b0bfe..0796fbf3 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -130,7 +130,7 @@ handle_input_locally = false size = Vector2i(1280, 720) render_target_update_mode = 4 -[node name="Settings" type="ColorRect" parent="." unique_id=1393582030] +[node name="Settings" type="ColorRect" parent="." unique_id=1393582030 node_paths=PackedStringArray("ImportNightlyDialog")] visible = false z_index = 1 anchors_preset = 15 @@ -141,6 +141,7 @@ grow_vertical = 2 mouse_filter = 2 color = Color(0, 0, 0, 0.501961) script = ExtResource("2_o6xl0") +ImportNightlyDialog = NodePath("ImportNightlyDialog") [node name="Hide" type="Button" parent="Settings" unique_id=1153372742] self_modulate = Color(1, 1, 1, 0) @@ -333,6 +334,8 @@ layout_mode = 1 anchors_preset = -1 anchor_right = 1.0 offset_bottom = 50.0 +grow_horizontal = 2 +grow_vertical = 2 focus_mode = 0 mouse_default_cursor_shape = 2 theme = SubResource("Theme_jhjkh") @@ -429,6 +432,13 @@ grow_vertical = 2 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_popqt") +[node name="ImportNightlyDialog" type="FileDialog" parent="Settings" unique_id=1831752407] +title = "Open a File" +file_mode = 0 +access = 2 +filters = PackedStringArray("*.json") +use_native_dialog = true + [node name="Volume" type="Panel" parent="." unique_id=1219254705] modulate = Color(1, 1, 1, 0) z_index = 1 diff --git a/scripts/database/settings/SettingsProfile.cs b/scripts/database/settings/SettingsProfile.cs index c731b16f..cd83b2a5 100644 --- a/scripts/database/settings/SettingsProfile.cs +++ b/scripts/database/settings/SettingsProfile.cs @@ -349,6 +349,12 @@ public partial class SettingsProfile /// public SettingsItem RhythiaImport { get; private set; } + [Order] + /// + /// File dialog for the nightly import + /// + public SettingsItem ImportDialog { get; private set; } + [Order] /// /// Toggles recording for replays @@ -1043,115 +1049,27 @@ public SettingsProfile() string nightlyDir = $"{Path.GetDirectoryName(Constants.USER_FOLDER)}/SoundSpacePlus"; if (Directory.Exists(nightlyDir)) { - string nightlySettingsPath = $"{nightlyDir}/settings.json"; - - string nightlySettings = File.Exists(nightlySettingsPath) ? File.ReadAllText(nightlySettingsPath) : null; - - if (nightlySettings == null) { - ToastNotification.Notify("Nightly settings not found, choose the settings file manually."); - }; - - using JsonDocument json = JsonDocument.Parse(nightlySettings); - JsonElement root = json.RootElement; - - T? getSetting(string key) where T : struct { - if (root.TryGetProperty(key, out JsonElement element)) { - return element.Deserialize(); - } - - return null; - } - - // needs a separate helper for strings due to the struct constraint in getSetting() - string? getStringSetting(string key) { - if (root.TryGetProperty(key, out JsonElement element)) { - return element.GetString(); - } - return null; - } - - double importVolume(string nightlyKey, double range) { - double? channelDb = getSetting(nightlyKey); - - if (channelDb == null) { - return 50; - } - - double masterDb = getSetting("master_volume") ?? 20 * Math.Log10(0.5); - double totalDb = Math.Clamp(masterDb + channelDb.Value, -80, 0); - - return SoundManager.ComputeVolumeFromDb((float)totalDb, 100, (float)range); - } - - SettingsProfile nightlyProfile = new SettingsProfile(); - - nightlyProfile.Sensitivity.Value = getSetting("sensitivity") * 2.16 * (70 / (getSetting("fov") ?? 70)) ?? nightlyProfile.Sensitivity.Value; - nightlyProfile.AbsoluteSensitivity.Value = getSetting("absolute_scale") ?? nightlyProfile.AbsoluteSensitivity.Value; - nightlyProfile.AbsoluteInput.Value = getSetting("absolute_mode") ?? nightlyProfile.AbsoluteInput.Value; - nightlyProfile.CursorDrift.Value = getSetting("enable_drift_cursor") ?? nightlyProfile.CursorDrift.Value; - nightlyProfile.ApproachRate.Value = getSetting("approach_rate") ?? nightlyProfile.ApproachRate.Value; - nightlyProfile.ApproachDistance.Value = getSetting("spawn_distance") ?? nightlyProfile.ApproachDistance.Value; - nightlyProfile.Pushback.Value = getSetting("do_note_pushback") ?? nightlyProfile.Pushback.Value; - nightlyProfile.CameraParallax.Value = getSetting("parallax") * 0.025 ?? nightlyProfile.CameraParallax.Value; - nightlyProfile.HUDParallax.Value = getSetting("ui_parallax") * 0.025 ?? nightlyProfile.HUDParallax.Value; - nightlyProfile.FoV.Value = getSetting("fov") ?? nightlyProfile.FoV.Value; - nightlyProfile.NoteColors.Value = getStringSetting("selected_colorset") ?? nightlyProfile.NoteColors.Value; - nightlyProfile.NoteMesh.Value = getStringSetting("selected_mesh") ?? nightlyProfile.NoteMesh.Value; - nightlyProfile.NoteSize.Value = getSetting("note_size") * 0.875 ?? nightlyProfile.NoteSize.Value; - nightlyProfile.NoteOpacity.Value = getSetting("note_opacity") ?? nightlyProfile.NoteOpacity.Value; - nightlyProfile.CursorScale.Value = getSetting("cursor_scale") ?? nightlyProfile.CursorScale.Value; - nightlyProfile.CursorRotation.Value = getSetting("cursor_spin") ?? nightlyProfile.CursorRotation.Value; - nightlyProfile.CursorTrail.Value = getSetting("cursor_trail") ?? nightlyProfile.CursorTrail.Value; - nightlyProfile.TrailTime.Value = getSetting("trail_time") ?? nightlyProfile.TrailTime.Value; - nightlyProfile.TrailDetail.Value = getSetting("trail_detail") ?? nightlyProfile.TrailDetail.Value; - nightlyProfile.SimpleHUD.Value = getSetting("simple_hud") ?? nightlyProfile.SimpleHUD.Value; - nightlyProfile.HitPopups.Value = getSetting("score_popup") ?? nightlyProfile.HitPopups.Value; - nightlyProfile.MissPopups.Value = getSetting("show_miss_effect") ?? nightlyProfile.MissPopups.Value; - nightlyProfile.Fullscreen.Value = getSetting("window_fullscreen") ?? nightlyProfile.Fullscreen.Value; - nightlyProfile.FPS.Value = getSetting("target_fps") ?? nightlyProfile.FPS.Value; - nightlyProfile.VolumeMaster.Value = 100; - nightlyProfile.VolumeMusic.Value = importVolume("music_volume", 70);; - nightlyProfile.VolumeHitSound.Value = importVolume("hit_volume", 80); - nightlyProfile.VolumeMissSound.Value = importVolume("miss_volume", 80); - nightlyProfile.VolumeSFX.Value = importVolume("fail_volume", 80); - nightlyProfile.EnableHitSound.Value = getSetting("play_hit_snd") ?? nightlyProfile.EnableHitSound.Value; - nightlyProfile.EnableMissSound.Value = getSetting("play_miss_snd") ?? nightlyProfile.EnableMissSound.Value; - nightlyProfile.EnableMenuMusic.Value = getSetting("play_menu_music") ?? nightlyProfile.EnableMenuMusic.Value; - nightlyProfile.AutoplayJukebox.Value = getSetting("auto_preview_song") ?? nightlyProfile.AutoplayJukebox.Value; - nightlyProfile.LocalOffset.Value = getSetting("music_offset") ?? nightlyProfile.LocalOffset.Value; - nightlyProfile.RecordReplays.Value = getSetting("record_replays") ?? nightlyProfile.RecordReplays.Value; - - // prevents overriding existing 'nightly' profile - string getProfileName(string baseName) { - string profilesDir = $"{Constants.USER_FOLDER}/profiles"; - Directory.CreateDirectory(profilesDir); - - string name = baseName; - int suffix = 0; - - while (File.Exists($"{profilesDir}/{name}.json")) { - suffix++; - name = $"{baseName}-{suffix}"; - } - - return name; - } - - string profileName = getProfileName("nightly"); - string profileJson = SettingsProfileConverter.Serialize(nightlyProfile); - File.WriteAllText($"{Constants.USER_FOLDER}/profiles/{profileName}.json", profileJson); - - SettingsManager.SetCurrentProfile(profileName); - SettingsManager.Load(); - SettingsMenu.Instance.UpdateProfileSelection(); - - ToastNotification.Notify($"Created profile '{profileName}'"); + ImportFromNightlySettings($"{nightlyDir}/settings.json"); } } } ], SaveToDisk = false, }; + ImportDialog = new(default) + { + Id = "ImportDialog", + Title = "", + Description = "", + Section = SettingsSection.Other, + Buttons = + [ + new() { Title = "Choose file", Description = "", OnPressed = () => { + SettingsMenu.Instance.ImportNightlyDialog.PopupCentered(); + }} + ] + }; + DisplayFPS = new(true) { Id = "DisplayFPS", @@ -1257,4 +1175,119 @@ private static List getAvailableMeshes() return meshes; } + + public static void ImportFromNightlySettings(string settingsPath) + { + string nightlySettings = File.Exists(settingsPath) ? File.ReadAllText(settingsPath) : null; + + if (nightlySettings == null) + { + ToastNotification.Notify("Nightly settings not found, choose the settings file manually."); + return; + } + + using JsonDocument json = JsonDocument.Parse(nightlySettings); + JsonElement root = json.RootElement; + + T? getSetting(string key) where T : struct + { + if (root.TryGetProperty(key, out JsonElement element)) + { + return element.Deserialize(); + } + + return null; + } + + // needs a separate helper for strings due to the struct constraint in getSetting() + string? getStringSetting(string key) + { + if (root.TryGetProperty(key, out JsonElement element)) + { + return element.GetString(); + } + return null; + } + + double importVolume(string nightlyKey, double range) + { + double? channelDb = getSetting(nightlyKey); + + if (channelDb == null) + { + return 50; + } + + double masterDb = getSetting("master_volume") ?? 20 * Math.Log10(0.5); + double totalDb = Math.Clamp(masterDb + channelDb.Value, -80, 0); + + return SoundManager.ComputeVolumeFromDb((float)totalDb, 100, (float)range); + } + + SettingsProfile nightlyProfile = new SettingsProfile(); + + nightlyProfile.Sensitivity.Value = getSetting("sensitivity") * 2.16 * (70 / (getSetting("fov") ?? 70)) ?? nightlyProfile.Sensitivity.Value; + nightlyProfile.AbsoluteSensitivity.Value = getSetting("absolute_scale") ?? nightlyProfile.AbsoluteSensitivity.Value; + nightlyProfile.AbsoluteInput.Value = getSetting("absolute_mode") ?? nightlyProfile.AbsoluteInput.Value; + nightlyProfile.CursorDrift.Value = getSetting("enable_drift_cursor") ?? nightlyProfile.CursorDrift.Value; + nightlyProfile.ApproachRate.Value = getSetting("approach_rate") ?? nightlyProfile.ApproachRate.Value; + nightlyProfile.ApproachDistance.Value = getSetting("spawn_distance") ?? nightlyProfile.ApproachDistance.Value; + nightlyProfile.Pushback.Value = getSetting("do_note_pushback") ?? nightlyProfile.Pushback.Value; + nightlyProfile.CameraParallax.Value = getSetting("parallax") * 0.025 ?? nightlyProfile.CameraParallax.Value; + nightlyProfile.HUDParallax.Value = getSetting("ui_parallax") * 0.025 ?? nightlyProfile.HUDParallax.Value; + nightlyProfile.FoV.Value = getSetting("fov") ?? nightlyProfile.FoV.Value; + nightlyProfile.NoteColors.Value = getStringSetting("selected_colorset") ?? nightlyProfile.NoteColors.Value; + nightlyProfile.NoteMesh.Value = getStringSetting("selected_mesh") ?? nightlyProfile.NoteMesh.Value; + nightlyProfile.NoteSize.Value = getSetting("note_size") * 0.875 ?? nightlyProfile.NoteSize.Value; + nightlyProfile.NoteOpacity.Value = getSetting("note_opacity") ?? nightlyProfile.NoteOpacity.Value; + nightlyProfile.CursorScale.Value = getSetting("cursor_scale") ?? nightlyProfile.CursorScale.Value; + nightlyProfile.CursorRotation.Value = getSetting("cursor_spin") ?? nightlyProfile.CursorRotation.Value; + nightlyProfile.CursorTrail.Value = getSetting("cursor_trail") ?? nightlyProfile.CursorTrail.Value; + nightlyProfile.TrailTime.Value = getSetting("trail_time") ?? nightlyProfile.TrailTime.Value; + nightlyProfile.TrailDetail.Value = getSetting("trail_detail") ?? nightlyProfile.TrailDetail.Value; + nightlyProfile.SimpleHUD.Value = getSetting("simple_hud") ?? nightlyProfile.SimpleHUD.Value; + nightlyProfile.HitPopups.Value = getSetting("score_popup") ?? nightlyProfile.HitPopups.Value; + nightlyProfile.MissPopups.Value = getSetting("show_miss_effect") ?? nightlyProfile.MissPopups.Value; + nightlyProfile.Fullscreen.Value = getSetting("window_fullscreen") ?? nightlyProfile.Fullscreen.Value; + nightlyProfile.FPS.Value = getSetting("target_fps") ?? nightlyProfile.FPS.Value; + nightlyProfile.VolumeMaster.Value = 100; + nightlyProfile.VolumeMusic.Value = importVolume("music_volume", 70); ; + nightlyProfile.VolumeHitSound.Value = importVolume("hit_volume", 80); + nightlyProfile.VolumeMissSound.Value = importVolume("miss_volume", 80); + nightlyProfile.VolumeSFX.Value = importVolume("fail_volume", 80); + nightlyProfile.EnableHitSound.Value = getSetting("play_hit_snd") ?? nightlyProfile.EnableHitSound.Value; + nightlyProfile.EnableMissSound.Value = getSetting("play_miss_snd") ?? nightlyProfile.EnableMissSound.Value; + nightlyProfile.EnableMenuMusic.Value = getSetting("play_menu_music") ?? nightlyProfile.EnableMenuMusic.Value; + nightlyProfile.AutoplayJukebox.Value = getSetting("auto_preview_song") ?? nightlyProfile.AutoplayJukebox.Value; + nightlyProfile.LocalOffset.Value = getSetting("music_offset") ?? nightlyProfile.LocalOffset.Value; + nightlyProfile.RecordReplays.Value = getSetting("record_replays") ?? nightlyProfile.RecordReplays.Value; + + // prevents overriding existing 'nightly' profile + string getProfileName(string baseName) + { + string profilesDir = $"{Constants.USER_FOLDER}/profiles"; + Directory.CreateDirectory(profilesDir); + + string name = baseName; + int suffix = 0; + + while (File.Exists($"{profilesDir}/{name}.json")) + { + suffix++; + name = $"{baseName}-{suffix}"; + } + + return name; + } + + string profileName = getProfileName("nightly"); + string profileJson = SettingsProfileConverter.Serialize(nightlyProfile); + File.WriteAllText($"{Constants.USER_FOLDER}/profiles/{profileName}.json", profileJson); + + SettingsManager.SetCurrentProfile(profileName); + SettingsManager.Load(); + SettingsMenu.Instance.UpdateProfileSelection(); + + ToastNotification.Notify($"Created profile '{profileName}'"); + } } diff --git a/scripts/ui/SettingsMenu.cs b/scripts/ui/SettingsMenu.cs index af8998d5..bbb718e4 100644 --- a/scripts/ui/SettingsMenu.cs +++ b/scripts/ui/SettingsMenu.cs @@ -22,6 +22,8 @@ public partial class SettingsMenu : ColorRect private ScrollContainer selectedCategory; + [Export] public FileDialog ImportNightlyDialog; + public override void _Ready() { Instance = this; @@ -189,6 +191,7 @@ public override void _Ready() HideMenu(); hideButton.Pressed += HideMenu; + ImportNightlyDialog.FileSelected += SettingsProfile.ImportFromNightlySettings; } // Adding GetViewport().SetInputAsHandled() will prevent the Quit popup from appearing when clicking ESC in settings public override void _Input(InputEvent @event) From 0e0b51e8579b44aa3e764cb741cf26ca14fc6599 Mon Sep 17 00:00:00 2001 From: xwalfie Date: Wed, 8 Jul 2026 01:25:56 +0200 Subject: [PATCH 3/5] refactor: add comment and remove random thingy from scene --- scenes/main.tscn | 2 -- scripts/database/settings/SettingsProfile.cs | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/scenes/main.tscn b/scenes/main.tscn index 0796fbf3..317c889a 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -334,8 +334,6 @@ layout_mode = 1 anchors_preset = -1 anchor_right = 1.0 offset_bottom = 50.0 -grow_horizontal = 2 -grow_vertical = 2 focus_mode = 0 mouse_default_cursor_shape = 2 theme = SubResource("Theme_jhjkh") diff --git a/scripts/database/settings/SettingsProfile.cs b/scripts/database/settings/SettingsProfile.cs index cd83b2a5..98d2414d 100644 --- a/scripts/database/settings/SettingsProfile.cs +++ b/scripts/database/settings/SettingsProfile.cs @@ -1226,6 +1226,7 @@ double importVolume(string nightlyKey, double range) SettingsProfile nightlyProfile = new SettingsProfile(); + // sensitivity scales with fov but in nightly it doesnt nightlyProfile.Sensitivity.Value = getSetting("sensitivity") * 2.16 * (70 / (getSetting("fov") ?? 70)) ?? nightlyProfile.Sensitivity.Value; nightlyProfile.AbsoluteSensitivity.Value = getSetting("absolute_scale") ?? nightlyProfile.AbsoluteSensitivity.Value; nightlyProfile.AbsoluteInput.Value = getSetting("absolute_mode") ?? nightlyProfile.AbsoluteInput.Value; From f60df596d77c31aa257770ed9db32f57fd257b78 Mon Sep 17 00:00:00 2001 From: xwalfie Date: Thu, 9 Jul 2026 06:16:30 +0200 Subject: [PATCH 4/5] mmmm remove ; --- scripts/database/settings/SettingsProfile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/database/settings/SettingsProfile.cs b/scripts/database/settings/SettingsProfile.cs index 98d2414d..758587d9 100644 --- a/scripts/database/settings/SettingsProfile.cs +++ b/scripts/database/settings/SettingsProfile.cs @@ -1252,7 +1252,7 @@ double importVolume(string nightlyKey, double range) nightlyProfile.Fullscreen.Value = getSetting("window_fullscreen") ?? nightlyProfile.Fullscreen.Value; nightlyProfile.FPS.Value = getSetting("target_fps") ?? nightlyProfile.FPS.Value; nightlyProfile.VolumeMaster.Value = 100; - nightlyProfile.VolumeMusic.Value = importVolume("music_volume", 70); ; + nightlyProfile.VolumeMusic.Value = importVolume("music_volume", 70); nightlyProfile.VolumeHitSound.Value = importVolume("hit_volume", 80); nightlyProfile.VolumeMissSound.Value = importVolume("miss_volume", 80); nightlyProfile.VolumeSFX.Value = importVolume("fail_volume", 80); From b6fbcc6677eb31dc12fbc413db39c5dcf6c501d0 Mon Sep 17 00:00:00 2001 From: xwalfie Date: Thu, 9 Jul 2026 18:13:36 +0200 Subject: [PATCH 5/5] refactor: move nightly folder variable into a constant --- scripts/Constants.cs | 2 ++ scripts/database/settings/SettingsProfile.cs | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/Constants.cs b/scripts/Constants.cs index 580934f3..7f0a19f6 100644 --- a/scripts/Constants.cs +++ b/scripts/Constants.cs @@ -10,6 +10,8 @@ public partial class Constants : Node public static readonly string USER_FOLDER = OS.GetUserDataDir(); + public static readonly string NIGHTLY_FOLDER = $"{Path.GetDirectoryName(USER_FOLDER)}/SoundSpacePlus"; + public static readonly string DEFAULT_MAP_EXT = "phxm"; public static readonly bool TEMP_MAP_MODE = false;//OS.GetCmdlineArgs().Length > 0; diff --git a/scripts/database/settings/SettingsProfile.cs b/scripts/database/settings/SettingsProfile.cs index 758587d9..58659241 100644 --- a/scripts/database/settings/SettingsProfile.cs +++ b/scripts/database/settings/SettingsProfile.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection.Metadata; using System.Text.Json; using Godot; @@ -1046,10 +1047,9 @@ public SettingsProfile() Buttons = [ new() { Title = "Import", Description = "", OnPressed = () => { - string nightlyDir = $"{Path.GetDirectoryName(Constants.USER_FOLDER)}/SoundSpacePlus"; - if (Directory.Exists(nightlyDir)) { - ImportFromNightlySettings($"{nightlyDir}/settings.json"); + if (Directory.Exists(Constants.NIGHTLY_FOLDER)) { + ImportFromNightlySettings($"{Constants.NIGHTLY_FOLDER}/settings.json"); } } } ],