#include "ConfigState.h" #include "Rendering/Renderer.h" #include "Core/Application.h" #include "Core/ThemeManager.h" #include "Core/SettingsManager.h" #include #include #include namespace Donut { void ConfigState::OnEnter() { DONUT_INFO("Entering Config State"); 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() { DONUT_INFO("Exiting Config State"); } void ConfigState::OnUpdate(float deltaTime) { if (m_ShowRestartMessage) { m_RestartMessageTimer += deltaTime; if (m_RestartMessageTimer > 3.0f) { m_ShowRestartMessage = false; m_RestartMessageTimer = 0.0f; } } } void ConfigState::OnRender() { Renderer::SetClearColor({ 0.1f, 0.1f, 0.1f, 1.0f }); Renderer::Clear(); } void ConfigState::OnEvent(Event& event) { } void ConfigState::OnImUIRender() { ImGui::SetNextWindowSize(ImVec2(900, 700), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x * 0.5f, ImGui::GetIO().DisplaySize.y * 0.5f), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); ImGui::Begin("Donut Configuration", nullptr, ImGuiWindowFlags_NoCollapse); ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]); ImGui::TextColored(ImVec4(0.8f, 0.8f, 1.0f, 1.0f), "Donut Configuration"); ImGui::PopFont(); ImGui::Separator(); ImGui::Columns(2, "ConfigColumns", true); 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"); ImGui::Separator(); ImGui::Text("Render API:"); ImGui::SameLine(); ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "(requires restart)"); const char* apiNames[] = { "OpenGL", "Vulkan" }; static int currentAPI = (int)m_SelectedAPI - 1; if (ImGui::BeginCombo("##RenderAPI", apiNames[currentAPI])) { for (int i = 0; i < IM_ARRAYSIZE(apiNames); i++) { const bool isSelected = (currentAPI == i); if (ImGui::Selectable(apiNames[i], isSelected)) { currentAPI = i; m_SelectedAPI = (RendererAPI::API)(i + 1); m_ShowRestartMessage = true; m_RestartMessageTimer = 0.0f; } if (isSelected) ImGui::SetItemDefaultFocus(); } ImGui::EndCombo(); } ImGui::Text("Current API: "); ImGui::SameLine(); const char* currentAPIName = (Renderer::GetAPI() == RendererAPI::API::OpenGL) ? "OpenGL" : "Vulkan"; ImGui::TextColored(ImVec4(0.3f, 0.8f, 0.3f, 1.0f), currentAPIName); ImGui::Spacing(); ImGui::Checkbox("Enable VSync", &m_VSyncEnabled); ImGui::SameLine(); ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "(recommended)"); ImGui::Spacing(); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Display"); ImGui::Separator(); ImGui::Text("Window Size: 1280x720"); ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Fullscreen: Not implemented yet"); ImGui::Spacing(); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "System Info"); ImGui::Separator(); ImGui::Text("OpenGL Version: %s", glGetString(GL_VERSION)); ImGui::Text("GPU: %s", glGetString(GL_RENDERER)); ImGui::Text("Vendor: %s", glGetString(GL_VENDOR)); ImGui::Spacing(); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Performance"); ImGui::Separator(); ImGui::SliderInt("Target FPS", &m_TargetFPS, 30, 120, "%d FPS"); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Target frame rate for the simulation"); ImGui::Checkbox("Show FPS Counter", &m_ShowFPS); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Display current FPS in the simulation"); ImGui::Checkbox("Show Performance Metrics", &m_ShowPerformanceMetrics); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Show detailed performance information"); ImGui::Checkbox("Show Debug Info", &m_ShowDebugInfo); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Display debug information and statistics"); ImGui::Checkbox("Enable Anti-Aliasing", &m_EnableAntiAliasing); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Enable anti-aliasing for smoother rendering"); ImGui::Spacing(); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Theme"); ImGui::Separator(); const char* themeNames[] = { "Dark", "Light", "Blue" }; if (ImGui::Combo("UI Theme", &m_SelectedTheme, themeNames, IM_ARRAYSIZE(themeNames))) ThemeManager::SetTheme(static_cast(m_SelectedTheme)); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Choose the application theme"); ImGui::EndChild(); ImGui::NextColumn(); ImGui::BeginChild("SimulationSettings", ImVec2(0, availableHeight), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Simulation Settings"); ImGui::Separator(); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Quality"); ImGui::Separator(); ImGui::SliderInt("Compute Height", &m_ComputeHeight, 64, 2048, "%d px"); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Resolution of the compute shader. Higher values give better quality but lower performance."); ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Higher = better quality, lower performance"); ImGui::SliderInt("Max Steps (Moving)", &m_MaxStepsMoving, 1000, 60000, "%d"); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Maximum ray marching steps when camera is moving"); ImGui::SliderInt("Max Steps (Static)", &m_MaxStepsStatic, 1000, 30000, "%d"); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Maximum ray marching steps when camera is stationary"); ImGui::SliderFloat("Early Exit Distance", &m_EarlyExitDistance, 1e11f, 1e13f, "%.2e"); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Distance at which ray marching stops to improve performance"); ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Distance at which ray marching stops"); ImGui::Spacing(); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Physics"); ImGui::Separator(); ImGui::Checkbox("Enable Gravity", &m_GravityEnabled); ImGui::EndChild(); ImGui::Columns(1); ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); float buttonWidth = (ImGui::GetWindowWidth() - 120) / 5.0f; if (ImGui::Button("World Builder", ImVec2(buttonWidth, 35))) { ApplySettings(); Application::Get().GetStateManager().SwitchToState("WorldBuilder"); } ImGui::SameLine(); if (ImGui::Button("Reset to Defaults", ImVec2(buttonWidth, 35))) ResetToDefaults(); ImGui::SameLine(); if (ImGui::Button("Apply Settings", ImVec2(buttonWidth, 35))) 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(); if (m_ShowRestartMessage) { ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.2f, 1.0f)); ImGui::TextWrapped("Warning: Render API changed! Please restart the application for changes to take effect."); ImGui::PopStyleColor(); } ImGui::Spacing(); ImGui::Separator(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Donut Engine v1.0.0 | Black Hole Simulation"); ImGui::End(); } 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 and saved"); } void ConfigState::ResetToDefaults() { m_SelectedAPI = RendererAPI::API::OpenGL; m_TargetFPS = 60; m_ComputeHeight = 512; m_MaxStepsMoving = 30000; m_MaxStepsStatic = 15000; m_EarlyExitDistance = 5e12f; m_GravityEnabled = true; m_VSyncEnabled = true; m_ShowFPS = true; m_ShowPerformanceMetrics = true; m_ShowDebugInfo = false; m_EnableAntiAliasing = true; m_SelectedTheme = 0; ApplySettings(); DONUT_INFO("Settings reset to defaults and saved"); } };