diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Core/Application.cpp | 11 | ||||
| -rw-r--r-- | src/Core/SettingsManager.cpp | 178 | ||||
| -rw-r--r-- | src/Core/SettingsManager.h | 70 | ||||
| -rw-r--r-- | src/States/ConfigState.cpp | 56 | ||||
| -rw-r--r-- | src/States/SimulationState.cpp | 56 |
5 files changed, 363 insertions, 8 deletions
diff --git a/src/Core/Application.cpp b/src/Core/Application.cpp index 302132a..b879535 100644 --- a/src/Core/Application.cpp +++ b/src/Core/Application.cpp @@ -1,6 +1,7 @@ #include "Application.h" #include "Rendering/Renderer.h" +#include "SettingsManager.h" #include "States/SimulationState.h" #include "States/ConfigState.h" @@ -98,7 +99,14 @@ namespace Donut { Logger::Init(); - RendererAPI::SetAPI(RendererAPI::API::OpenGL); + // Initialize settings manager first + SettingsManager::Initialize(); + + // Apply loaded settings + const auto& settings = SettingsManager::GetSettingsConst(); + RendererAPI::API api = (settings.graphics.renderAPI == "Vulkan") ? RendererAPI::API::Vulkan : RendererAPI::API::OpenGL; + RendererAPI::SetAPI(api); + Renderer::Init(); m_Window->InitImGui(); @@ -117,6 +125,7 @@ namespace Donut m_StateManager->Shutdown(); Renderer::Shutdown(); + SettingsManager::Shutdown(); Logger::Shutdown(); } diff --git a/src/Core/SettingsManager.cpp b/src/Core/SettingsManager.cpp new file mode 100644 index 0000000..f35a016 --- /dev/null +++ b/src/Core/SettingsManager.cpp @@ -0,0 +1,178 @@ +#include "SettingsManager.h" +#include "Log.h" +#include "ThemeManager.h" +#include "Rendering/Renderer.h" + +#include <fstream> +#include <filesystem> +#include <algorithm> + +namespace Donut +{ + Settings SettingsManager::s_Settings; + bool SettingsManager::s_Initialized = false; + + void SettingsManager::Initialize() + { + if (s_Initialized) + return; + + LoadSettings(); + s_Initialized = true; + DONUT_INFO("Settings Manager initialized"); + } + + void SettingsManager::Shutdown() + { + if (!s_Initialized) + return; + + SaveSettings(); + s_Initialized = false; + DONUT_INFO("Settings Manager shutdown"); + } + + void SettingsManager::LoadSettings() + { + std::string filePath = GetSettingsFilePath(); + + try + { + if (std::filesystem::exists(filePath)) + { + auto config = toml::parse(filePath); + + if (config.contains("simulation")) + { + auto sim = config["simulation"]; + s_Settings.simulation.targetFPS = toml::find_or(sim, "target_fps", 60); + s_Settings.simulation.computeHeight = toml::find_or(sim, "compute_height", 512); + s_Settings.simulation.maxStepsMoving = toml::find_or(sim, "max_steps_moving", 30000); + s_Settings.simulation.maxStepsStatic = toml::find_or(sim, "max_steps_static", 15000); + s_Settings.simulation.earlyExitDistance = toml::find_or(sim, "early_exit_distance", 5e12f); + s_Settings.simulation.gravityEnabled = toml::find_or(sim, "gravity_enabled", true); + + s_Settings.simulation.targetFPS = std::max(30, std::min(120, s_Settings.simulation.targetFPS)); + s_Settings.simulation.computeHeight = std::max(64, std::min(2048, s_Settings.simulation.computeHeight)); + s_Settings.simulation.maxStepsMoving = std::max(1000, std::min(60000, s_Settings.simulation.maxStepsMoving)); + s_Settings.simulation.maxStepsStatic = std::max(1000, std::min(30000, s_Settings.simulation.maxStepsStatic)); + s_Settings.simulation.earlyExitDistance = std::max(1e11f, std::min(1e13f, s_Settings.simulation.earlyExitDistance)); + } + + if (config.contains("graphics")) + { + auto gfx = config["graphics"]; + s_Settings.graphics.renderAPI = toml::find_or(gfx, "render_api", std::string("OpenGL")); + s_Settings.graphics.vSyncEnabled = toml::find_or(gfx, "vsync_enabled", true); + s_Settings.graphics.showFPS = toml::find_or(gfx, "show_fps", true); + s_Settings.graphics.showPerformanceMetrics = toml::find_or(gfx, "show_performance_metrics", true); + s_Settings.graphics.showDebugInfo = toml::find_or(gfx, "show_debug_info", false); + s_Settings.graphics.enableAntiAliasing = toml::find_or(gfx, "enable_anti_aliasing", true); + s_Settings.graphics.selectedTheme = toml::find_or(gfx, "selected_theme", std::string("Dark")); + + if (s_Settings.graphics.renderAPI != "OpenGL" && + s_Settings.graphics.renderAPI != "Vulkan") + s_Settings.graphics.renderAPI = "OpenGL"; + if (s_Settings.graphics.selectedTheme != "Dark" && + s_Settings.graphics.selectedTheme != "Light" && + s_Settings.graphics.selectedTheme != "Blue") + s_Settings.graphics.selectedTheme = "Dark"; + } + + DONUT_INFO("Settings loaded from {}", filePath); + } + else + { + LoadDefaultSettings(); + SaveSettings(); + DONUT_INFO("No settings file found, created default settings"); + } + } + catch (const std::exception& e) + { + DONUT_ERROR("Failed to load settings: {}", e.what()); + LoadDefaultSettings(); + } + } + + void SettingsManager::SaveSettings() + { + std::string filePath = GetSettingsFilePath(); + + try + { + std::filesystem::path path(filePath); + std::filesystem::create_directories(path.parent_path()); + + toml::value simulation = toml::table + { + {"target_fps", s_Settings.simulation.targetFPS }, + {"compute_height", s_Settings.simulation.computeHeight }, + {"max_steps_moving", s_Settings.simulation.maxStepsMoving }, + {"max_steps_static", s_Settings.simulation.maxStepsStatic }, + {"early_exit_distance", s_Settings.simulation.earlyExitDistance}, + {"gravity_enabled", s_Settings.simulation.gravityEnabled } + }; + + toml::value graphics = toml::table + { + {"render_api", s_Settings.graphics.renderAPI }, + {"vsync_enabled", s_Settings.graphics.vSyncEnabled }, + {"show_fps", s_Settings.graphics.showFPS }, + {"show_performance_metrics", s_Settings.graphics.showPerformanceMetrics}, + {"show_debug_info", s_Settings.graphics.showDebugInfo }, + {"enable_anti_aliasing", s_Settings.graphics.enableAntiAliasing }, + {"selected_theme", s_Settings.graphics.selectedTheme } + }; + + toml::value config = toml::table + { + {"simulation", simulation}, + {"graphics", graphics} + }; + + std::ofstream file(filePath); + file << config; + file.close(); + + DONUT_INFO("Settings saved to {}", filePath); + } + catch (const std::exception& e) + DONUT_ERROR("Failed to save settings: {}", e.what()); + } + + void SettingsManager::SetSimulationSettings(const SimulationSettings& settings) + { + s_Settings.simulation = settings; + SaveSettings(); + } + + void SettingsManager::SetGraphicsSettings(const GraphicsSettings& settings) + { + s_Settings.graphics = settings; + SaveSettings(); + } + + std::string SettingsManager::GetSettingsFilePath() + { + return "Config/settings.toml"; + } + + void SettingsManager::LoadDefaultSettings() + { + s_Settings.simulation.targetFPS = 60; + s_Settings.simulation.computeHeight = 512; + s_Settings.simulation.maxStepsMoving = 30000; + s_Settings.simulation.maxStepsStatic = 15000; + s_Settings.simulation.earlyExitDistance = 5e12f; + s_Settings.simulation.gravityEnabled = true; + + s_Settings.graphics.renderAPI = "OpenGL"; + s_Settings.graphics.vSyncEnabled = true; + s_Settings.graphics.showFPS = true; + s_Settings.graphics.showPerformanceMetrics = true; + s_Settings.graphics.showDebugInfo = false; + s_Settings.graphics.enableAntiAliasing = true; + s_Settings.graphics.selectedTheme = "Dark"; + } +} diff --git a/src/Core/SettingsManager.h b/src/Core/SettingsManager.h new file mode 100644 index 0000000..bea1162 --- /dev/null +++ b/src/Core/SettingsManager.h @@ -0,0 +1,70 @@ +#pragma once + +#include <string> +#include <toml.hpp> + +namespace Donut +{ + struct SimulationSettings + { + int targetFPS = 60; + int computeHeight = 512; + int maxStepsMoving = 30000; + int maxStepsStatic = 15000; + float earlyExitDistance = 5e12f; + bool gravityEnabled = true; + }; + + struct GraphicsSettings + { + std::string renderAPI = "OpenGL"; + bool vSyncEnabled = true; + bool showFPS = true; + bool showPerformanceMetrics = true; + bool showDebugInfo = false; + bool enableAntiAliasing = true; + std::string selectedTheme = "Dark"; + }; + + struct Settings + { + SimulationSettings simulation; + GraphicsSettings graphics; + }; + + class SettingsManager + { + public: + static void Initialize(); + static void Shutdown(); + + static void LoadSettings(); + static void SaveSettings(); + + static Settings& GetSettings() { return s_Settings; } + static const Settings& GetSettingsConst() { return s_Settings; } + + static void SetSimulationSettings(const SimulationSettings& settings); + static void SetGraphicsSettings(const GraphicsSettings& settings); + + static int GetTargetFPS() { return s_Settings.simulation.targetFPS; } + static int GetComputeHeight() { return s_Settings.simulation.computeHeight; } + static int GetMaxStepsMoving() { return s_Settings.simulation.maxStepsMoving; } + static int GetMaxStepsStatic() { return s_Settings.simulation.maxStepsStatic; } + static float GetEarlyExitDistance() { return s_Settings.simulation.earlyExitDistance; } + static bool GetGravityEnabled() { return s_Settings.simulation.gravityEnabled; } + static std::string GetRenderAPI() { return s_Settings.graphics.renderAPI; } + static bool GetVSyncEnabled() { return s_Settings.graphics.vSyncEnabled; } + static bool GetShowFPS() { return s_Settings.graphics.showFPS; } + static bool GetShowPerformanceMetrics() { return s_Settings.graphics.showPerformanceMetrics; } + static bool GetShowDebugInfo() { return s_Settings.graphics.showDebugInfo; } + static bool GetEnableAntiAliasing() { return s_Settings.graphics.enableAntiAliasing; } + static std::string GetSelectedTheme() { return s_Settings.graphics.selectedTheme; } + private: + static std::string GetSettingsFilePath(); + static void LoadDefaultSettings(); + private: + static Settings s_Settings; + static bool s_Initialized; + }; +} diff --git a/src/States/ConfigState.cpp b/src/States/ConfigState.cpp index 688c48a..1470c6d 100644 --- a/src/States/ConfigState.cpp +++ b/src/States/ConfigState.cpp @@ -2,6 +2,7 @@ #include "Rendering/Renderer.h" #include "Core/Application.h" #include "Core/ThemeManager.h" +#include "Core/SettingsManager.h" #include <imgui.h> #include <imgui_internal.h> @@ -13,8 +14,22 @@ namespace Donut { DONUT_INFO("Entering Config State"); - m_SelectedAPI = Renderer::GetAPI(); - m_SelectedTheme = static_cast<int>(ThemeManager::GetCurrentTheme()); + const auto& settings = SettingsManager::GetSettingsConst(); + + m_SelectedAPI = (settings.graphics.renderAPI == "Vulkan") ? RendererAPI::API::Vulkan : RendererAPI::API::OpenGL; + m_SelectedTheme = (settings.graphics.selectedTheme == "Light") ? 1 : + (settings.graphics.selectedTheme == "Blue") ? 2 : 0; + m_TargetFPS = settings.simulation.targetFPS; + m_ComputeHeight = settings.simulation.computeHeight; + m_MaxStepsMoving = settings.simulation.maxStepsMoving; + m_MaxStepsStatic = settings.simulation.maxStepsStatic; + m_EarlyExitDistance = settings.simulation.earlyExitDistance; + m_GravityEnabled = settings.simulation.gravityEnabled; + m_VSyncEnabled = settings.graphics.vSyncEnabled; + m_ShowFPS = settings.graphics.showFPS; + m_ShowPerformanceMetrics = settings.graphics.showPerformanceMetrics; + m_ShowDebugInfo = settings.graphics.showDebugInfo; + m_EnableAntiAliasing = settings.graphics.enableAntiAliasing; } void ConfigState::OnExit() @@ -60,7 +75,7 @@ namespace Donut ImGui::Columns(2, "ConfigColumns", true); - float availableHeight = ImGui::GetWindowHeight() - 140; // Reserve space for header, separator, buttons, and footer + float availableHeight = ImGui::GetWindowHeight() - 140; ImGui::BeginChild("GraphicsSettings", ImVec2(0, availableHeight), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Graphics Settings"); @@ -200,7 +215,7 @@ namespace Donut ImGui::Separator(); ImGui::Spacing(); - float buttonWidth = (ImGui::GetWindowWidth() - 80) / 4.0f; + float buttonWidth = (ImGui::GetWindowWidth() - 100) / 5.0f; if (ImGui::Button("Start Simulation", ImVec2(buttonWidth, 35))) { @@ -217,6 +232,13 @@ namespace Donut ApplySettings(); ImGui::SameLine(); + if (ImGui::Button("Save Settings", ImVec2(buttonWidth, 35))) + { + ApplySettings(); + DONUT_INFO("Settings saved manually"); + } + + ImGui::SameLine(); if (ImGui::Button("Exit", ImVec2(buttonWidth, 35))) Application::Get().Close(); @@ -237,8 +259,29 @@ namespace Donut void ConfigState::ApplySettings() { + SimulationSettings simSettings; + simSettings.targetFPS = m_TargetFPS; + simSettings.computeHeight = m_ComputeHeight; + simSettings.maxStepsMoving = m_MaxStepsMoving; + simSettings.maxStepsStatic = m_MaxStepsStatic; + simSettings.earlyExitDistance = m_EarlyExitDistance; + simSettings.gravityEnabled = m_GravityEnabled; + + GraphicsSettings gfxSettings; + gfxSettings.renderAPI = (m_SelectedAPI == RendererAPI::API::Vulkan) ? "Vulkan" : "OpenGL"; + gfxSettings.vSyncEnabled = m_VSyncEnabled; + gfxSettings.showFPS = m_ShowFPS; + gfxSettings.showPerformanceMetrics = m_ShowPerformanceMetrics; + gfxSettings.showDebugInfo = m_ShowDebugInfo; + gfxSettings.enableAntiAliasing = m_EnableAntiAliasing; + gfxSettings.selectedTheme = (m_SelectedTheme == 1) ? "Light" : + (m_SelectedTheme == 2) ? "Blue" : "Dark"; + + SettingsManager::SetSimulationSettings(simSettings); + SettingsManager::SetGraphicsSettings(gfxSettings); + RendererAPI::SetAPI(m_SelectedAPI); - DONUT_INFO("Settings applied"); + DONUT_INFO("Settings applied and saved"); } void ConfigState::ResetToDefaults() @@ -257,6 +300,7 @@ namespace Donut m_EnableAntiAliasing = true; m_SelectedTheme = 0; - DONUT_INFO("Settings reset to defaults"); + ApplySettings(); + DONUT_INFO("Settings reset to defaults and saved"); } }; diff --git a/src/States/SimulationState.cpp b/src/States/SimulationState.cpp index 87bf1ec..b4ed204 100644 --- a/src/States/SimulationState.cpp +++ b/src/States/SimulationState.cpp @@ -3,6 +3,7 @@ #include "Core/Application.h" #include "Core/Window.h" #include "Core/Event.h" +#include "Core/SettingsManager.h" #include <imgui.h> #include <GLFW/glfw3.h> @@ -12,6 +13,17 @@ namespace Donut void SimulationState::OnEnter() { DONUT_INFO("Entering Simulation State"); + + const auto& settings = SettingsManager::GetSettingsConst(); + + m_Engine.SetTargetFPS(settings.simulation.targetFPS); + m_Engine.SetComputeHeight(settings.simulation.computeHeight); + m_Engine.SetMaxStepsMoving(settings.simulation.maxStepsMoving); + m_Engine.SetMaxStepsStatic(settings.simulation.maxStepsStatic); + m_Engine.SetEarlyExitDistance(settings.simulation.earlyExitDistance); + m_Engine.GetGravity() = settings.simulation.gravityEnabled; + + m_Engine.UpdateComputeDimensions(); m_Initialized = true; } @@ -92,8 +104,22 @@ namespace Donut ImGui::Begin("Simulation Controls", nullptr, ImGuiWindowFlags_NoCollapse); ImGui::TextColored(ImVec4(0.8f, 0.8f, 1.0f, 1.0f), "Black Hole Simulation"); + ImGui::SameLine(); if (ImGui::Button("Back to Config")) Application::Get().GetStateManager().SwitchToState("Config"); + ImGui::SameLine(); + if (ImGui::Button("Save Settings")) + { + SimulationSettings settings = SettingsManager::GetSettingsConst().simulation; + settings.targetFPS = m_Engine.GetTargetFPS(); + settings.computeHeight = m_Engine.GetComputeHeight(); + settings.maxStepsMoving = m_Engine.GetMaxStepsMoving(); + settings.maxStepsStatic = m_Engine.GetMaxStepsStatic(); + settings.earlyExitDistance = m_Engine.GetEarlyExitDistance(); + settings.gravityEnabled = m_Engine.GetGravity(); + SettingsManager::SetSimulationSettings(settings); + DONUT_INFO("Simulation settings saved manually"); + } ImGui::Separator(); @@ -106,7 +132,12 @@ namespace Donut int targetFPS = m_Engine.GetTargetFPS(); if (ImGui::SliderInt("Target FPS", &targetFPS, 30, 120)) + { m_Engine.SetTargetFPS(targetFPS); + SimulationSettings settings = SettingsManager::GetSettingsConst().simulation; + settings.targetFPS = targetFPS; + SettingsManager::SetSimulationSettings(settings); + } ImGui::Spacing(); @@ -122,6 +153,9 @@ namespace Donut { m_Engine.SetComputeHeight(computeHeight); m_Engine.UpdateComputeDimensions(); + SimulationSettings settings = SettingsManager::GetSettingsConst().simulation; + settings.computeHeight = computeHeight; + SettingsManager::SetSimulationSettings(settings); } ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Compute Width: %d (auto-calculated)", m_Engine.GetComputeWidth()); @@ -133,13 +167,28 @@ namespace Donut int maxStepsMoving = m_Engine.GetMaxStepsMoving(); if (ImGui::SliderInt("Max Steps (Moving)", &maxStepsMoving, 1000, 60000)) + { m_Engine.SetMaxStepsMoving(maxStepsMoving); + SimulationSettings settings = SettingsManager::GetSettingsConst().simulation; + settings.maxStepsMoving = maxStepsMoving; + SettingsManager::SetSimulationSettings(settings); + } int maxStepsStatic = m_Engine.GetMaxStepsStatic(); if (ImGui::SliderInt("Max Steps (Static)", &maxStepsStatic, 1000, 30000)) + { m_Engine.SetMaxStepsStatic(maxStepsStatic); + SimulationSettings settings = SettingsManager::GetSettingsConst().simulation; + settings.maxStepsStatic = maxStepsStatic; + SettingsManager::SetSimulationSettings(settings); + } float earlyExitDistance = m_Engine.GetEarlyExitDistance(); if (ImGui::SliderFloat("Early Exit Distance", &earlyExitDistance, 1e11f, 1e13f, "%.2e")) + { m_Engine.SetEarlyExitDistance(earlyExitDistance); + SimulationSettings settings = SettingsManager::GetSettingsConst().simulation; + settings.earlyExitDistance = earlyExitDistance; + SettingsManager::SetSimulationSettings(settings); + } ImGui::Spacing(); @@ -147,7 +196,12 @@ namespace Donut ImGui::Separator(); bool& gravity = m_Engine.GetGravity(); - ImGui::Checkbox("Gravity Enabled", &gravity); + if (ImGui::Checkbox("Gravity Enabled", &gravity)) + { + SimulationSettings settings = SettingsManager::GetSettingsConst().simulation; + settings.gravityEnabled = gravity; + SettingsManager::SetSimulationSettings(settings); + } ImGui::Spacing(); |
