From 9cbbd120e592ff017b438351e136ef89f9eaa702 Mon Sep 17 00:00:00 2001 From: David Kehoe Date: Wed, 10 Sep 2025 22:30:51 +1000 Subject: [PATCH 1/5] Update HomePageRenderer.cpp --- src/Menu/HomePageRenderer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Menu/HomePageRenderer.cpp b/src/Menu/HomePageRenderer.cpp index 803386ade1..778909228f 100644 --- a/src/Menu/HomePageRenderer.cpp +++ b/src/Menu/HomePageRenderer.cpp @@ -241,7 +241,9 @@ void HomePageRenderer::RenderFAQSection() ImGui::TextWrapped( "Yes! Community Shaders is completely open source and available on GitHub. You can view " "the source code, report issues, suggest features, and contribute to the project. " - "The project is licensed under GPL, ensuring it remains free and open for everyone."); + "The project is licensed under GPL, ensuring it remains free and open for everyone." + "Branding materials and assets (icons, nexus branding, typography, etc) are not covered by the GPL Licence." + "Any included assets may not be used without explicit permission."); } } From abd98323e2519bf5509adc2df5e2e7854ce2f316 Mon Sep 17 00:00:00 2001 From: davo0411 Date: Wed, 10 Sep 2025 22:44:51 +1000 Subject: [PATCH 2/5] Update src/Menu/HomePageRenderer.cpp Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/Menu/HomePageRenderer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Menu/HomePageRenderer.cpp b/src/Menu/HomePageRenderer.cpp index 778909228f..3ab5c239e5 100644 --- a/src/Menu/HomePageRenderer.cpp +++ b/src/Menu/HomePageRenderer.cpp @@ -242,9 +242,9 @@ void HomePageRenderer::RenderFAQSection() "Yes! Community Shaders is completely open source and available on GitHub. You can view " "the source code, report issues, suggest features, and contribute to the project. " "The project is licensed under GPL, ensuring it remains free and open for everyone." - "Branding materials and assets (icons, nexus branding, typography, etc) are not covered by the GPL Licence." - "Any included assets may not be used without explicit permission."); - } + "The project is licensed under GPL, ensuring it remains free and open for everyone." + " Branding materials and assets (icons, nexus branding, typography, etc) are not covered by the GPL Licence." + " Any included assets may not be used without explicit permission."); } void HomePageRenderer::RenderFirstTimeSetupDialog() From f48586d6de5df3ba8f12fc1f8bdfcb431bce489f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Sep 2025 12:45:10 +0000 Subject: [PATCH 3/5] =?UTF-8?q?style:=20=F0=9F=8E=A8=20apply=20pre-commit.?= =?UTF-8?q?ci=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automated formatting by clang-format, prettier, and other hooks. See https://pre-commit.ci for details. --- src/Menu/HomePageRenderer.cpp | 450 +++++++++++++++++----------------- 1 file changed, 225 insertions(+), 225 deletions(-) diff --git a/src/Menu/HomePageRenderer.cpp b/src/Menu/HomePageRenderer.cpp index 3ab5c239e5..6437d04b90 100644 --- a/src/Menu/HomePageRenderer.cpp +++ b/src/Menu/HomePageRenderer.cpp @@ -242,280 +242,280 @@ void HomePageRenderer::RenderFAQSection() "Yes! Community Shaders is completely open source and available on GitHub. You can view " "the source code, report issues, suggest features, and contribute to the project. " "The project is licensed under GPL, ensuring it remains free and open for everyone." - "The project is licensed under GPL, ensuring it remains free and open for everyone." - " Branding materials and assets (icons, nexus branding, typography, etc) are not covered by the GPL Licence." - " Any included assets may not be used without explicit permission."); -} - -void HomePageRenderer::RenderFirstTimeSetupDialog() -{ - // Block input to the game and make cursor visible - input blocking is handled by ShouldSwallowInput() - auto& io = ImGui::GetIO(); - io.WantCaptureMouse = true; - io.WantCaptureKeyboard = true; - io.MouseDrawCursor = true; // Show ImGui cursor - - // Center the window properly with rounded corners and thin border - ImVec2 center = ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f); - ImGui::SetNextWindowPos(center, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_Always); - - // Style for rounded window with thin border - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f); - ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); - - ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoTitleBar; // Prevent scrolling and remove title - - if (!ImGui::Begin("##FirstTimeSetup", nullptr, flags)) { - ImGui::PopStyleVar(2); - ImGui::End(); - return; + "The project is licensed under GPL, ensuring it remains free and open for everyone." + " Branding materials and assets (icons, nexus branding, typography, etc) are not covered by the GPL Licence." + " Any included assets may not be used without explicit permission."); } - auto menu = Menu::GetSingleton(); + void HomePageRenderer::RenderFirstTimeSetupDialog() + { + // Block input to the game and make cursor visible - input blocking is handled by ShouldSwallowInput() + auto& io = ImGui::GetIO(); + io.WantCaptureMouse = true; + io.WantCaptureKeyboard = true; + io.MouseDrawCursor = true; // Show ImGui cursor + + // Center the window properly with rounded corners and thin border + ImVec2 center = ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f); + ImGui::SetNextWindowPos(center, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); + ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_Always); + + // Style for rounded window with thin border + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); + + ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoTitleBar; // Prevent scrolling and remove title + + if (!ImGui::Begin("##FirstTimeSetup", nullptr, flags)) { + ImGui::PopStyleVar(2); + ImGui::End(); + return; + } - // Render CS logo as background watermark with proper aspect ratio - if (menu && menu->uiIcons.logo.texture) { - ImVec2 windowPos = ImGui::GetWindowPos(); - ImVec2 windowSize = ImGui::GetWindowSize(); + auto menu = Menu::GetSingleton(); - // Get the original texture size to maintain aspect ratio - ImVec2 textureSize = menu->uiIcons.logo.size; - float aspectRatio = textureSize.x / textureSize.y; + // Render CS logo as background watermark with proper aspect ratio + if (menu && menu->uiIcons.logo.texture) { + ImVec2 windowPos = ImGui::GetWindowPos(); + ImVec2 windowSize = ImGui::GetWindowSize(); - // Set desired height and calculate width to maintain aspect ratio - float logoHeight = LOGO_WATERMARK_HEIGHT; - float logoWidth = logoHeight * aspectRatio; + // Get the original texture size to maintain aspect ratio + ImVec2 textureSize = menu->uiIcons.logo.size; + float aspectRatio = textureSize.x / textureSize.y; - ImVec2 logoMin(windowPos.x + (windowSize.x - logoWidth) * 0.5f, - windowPos.y + (windowSize.y - logoHeight) * 0.5f); - ImVec2 logoMax(logoMin.x + logoWidth, logoMin.y + logoHeight); + // Set desired height and calculate width to maintain aspect ratio + float logoHeight = LOGO_WATERMARK_HEIGHT; + float logoWidth = logoHeight * aspectRatio; - // Render as subtle watermark background - ImU32 watermarkColor = IM_COL32(255, 255, 255, 60); - ImGui::GetWindowDrawList()->AddImage(menu->uiIcons.logo.texture, logoMin, logoMax, - ImVec2(0, 0), ImVec2(1, 1), watermarkColor); - } + ImVec2 logoMin(windowPos.x + (windowSize.x - logoWidth) * 0.5f, + windowPos.y + (windowSize.y - logoHeight) * 0.5f); + ImVec2 logoMax(logoMin.x + logoWidth, logoMin.y + logoHeight); - // Center all content - float windowWidth = ImGui::GetWindowWidth(); + // Render as subtle watermark background + ImU32 watermarkColor = IM_COL32(255, 255, 255, 60); + ImGui::GetWindowDrawList()->AddImage(menu->uiIcons.logo.texture, logoMin, logoMax, + ImVec2(0, 0), ImVec2(1, 1), watermarkColor); + } - // Welcome title - centered - const char* welcomeTitle = "Welcome to Community Shaders!"; - float welcomeTitleWidth = ImGui::CalcTextSize(welcomeTitle).x; - ImGui::SetCursorPosX((windowWidth - welcomeTitleWidth) * 0.5f); - ImGui::Text("%s", welcomeTitle); + // Center all content + float windowWidth = ImGui::GetWindowWidth(); - ImGui::Spacing(); + // Welcome title - centered + const char* welcomeTitle = "Welcome to Community Shaders!"; + float welcomeTitleWidth = ImGui::CalcTextSize(welcomeTitle).x; + ImGui::SetCursorPosX((windowWidth - welcomeTitleWidth) * 0.5f); + ImGui::Text("%s", welcomeTitle); - // Version text - wrapped and centered - const char* versionText = "This appears to be a new install, update, or reinstallation of Community Shaders."; - float textPadding = 40.0f; // Padding from window edges + ImGui::Spacing(); - // Use a centered region for wrapped text - ImGui::SetCursorPosX(textPadding); - ImGui::BeginGroup(); - ImGui::PushTextWrapPos(windowWidth - textPadding); + // Version text - wrapped and centered + const char* versionText = "This appears to be a new install, update, or reinstallation of Community Shaders."; + float textPadding = 40.0f; // Padding from window edges - // Calculate the wrapped text size to center it - ImVec2 textSize = ImGui::CalcTextSize(versionText, nullptr, true, windowWidth - textPadding * 2); - float centerOffset = (windowWidth - textPadding * 2 - textSize.x) * 0.5f; - if (centerOffset > 0) { - ImGui::SetCursorPosX(textPadding + centerOffset); - } + // Use a centered region for wrapped text + ImGui::SetCursorPosX(textPadding); + ImGui::BeginGroup(); + ImGui::PushTextWrapPos(windowWidth - textPadding); - ImGui::TextWrapped("%s", versionText); - ImGui::PopTextWrapPos(); - ImGui::EndGroup(); + // Calculate the wrapped text size to center it + ImVec2 textSize = ImGui::CalcTextSize(versionText, nullptr, true, windowWidth - textPadding * 2); + float centerOffset = (windowWidth - textPadding * 2 - textSize.x) * 0.5f; + if (centerOffset > 0) { + ImGui::SetCursorPosX(textPadding + centerOffset); + } - ImGui::Spacing(); + ImGui::TextWrapped("%s", versionText); + ImGui::PopTextWrapPos(); + ImGui::EndGroup(); - // Description - centered - const char* description = "Please select a hotkey to access the menu:"; - float descWidth = ImGui::CalcTextSize(description).x; - ImGui::SetCursorPosX((windowWidth - descWidth) * 0.5f); - ImGui::Text("%s", description); - - // Hotkey selection - clickable hotkey text - // Show current toggle key and allow user to change it by clicking on it - auto& themeSettings = menu->GetTheme(); - const char* currentKeyName = Util::Input::KeyIdToString(menu->GetSettings().ToggleKey); - - // Calculate text dimensions for centering and button area - float hotkeyWidth = ImGui::CalcTextSize(currentKeyName).x; - float centerX = (windowWidth - hotkeyWidth) * 0.5f; - ImGui::SetCursorPosX(centerX); - - // Create invisible button for hover detection and clicking - ImVec2 buttonPos = ImGui::GetCursorScreenPos(); - ImVec2 hotkeyTextSize = ImGui::CalcTextSize(currentKeyName); - bool hovered = false; - bool clicked = false; - - ImGui::PushID("HotkeyButton"); - if (ImGui::InvisibleButton("##HotkeyClick", hotkeyTextSize)) { - clicked = true; - } - hovered = ImGui::IsItemHovered(); - ImGui::PopID(); + ImGui::Spacing(); - // Set cursor position back for text rendering - ImGui::SetCursorScreenPos(buttonPos); + // Description - centered + const char* description = "Please select a hotkey to access the menu:"; + float descWidth = ImGui::CalcTextSize(description).x; + ImGui::SetCursorPosX((windowWidth - descWidth) * 0.5f); + ImGui::Text("%s", description); + + // Hotkey selection - clickable hotkey text + // Show current toggle key and allow user to change it by clicking on it + auto& themeSettings = menu->GetTheme(); + const char* currentKeyName = Util::Input::KeyIdToString(menu->GetSettings().ToggleKey); + + // Calculate text dimensions for centering and button area + float hotkeyWidth = ImGui::CalcTextSize(currentKeyName).x; + float centerX = (windowWidth - hotkeyWidth) * 0.5f; + ImGui::SetCursorPosX(centerX); + + // Create invisible button for hover detection and clicking + ImVec2 buttonPos = ImGui::GetCursorScreenPos(); + ImVec2 hotkeyTextSize = ImGui::CalcTextSize(currentKeyName); + bool hovered = false; + bool clicked = false; + + ImGui::PushID("HotkeyButton"); + if (ImGui::InvisibleButton("##HotkeyClick", hotkeyTextSize)) { + clicked = true; + } + hovered = ImGui::IsItemHovered(); + ImGui::PopID(); - // Choose color based on hover state - darken when hovered. - ImVec4 hotkeyColor = hovered ? - ImVec4(themeSettings.StatusPalette.CurrentHotkey.x * 0.7f, - themeSettings.StatusPalette.CurrentHotkey.y * 0.7f, - themeSettings.StatusPalette.CurrentHotkey.z * 0.7f, - themeSettings.StatusPalette.CurrentHotkey.w) : - themeSettings.StatusPalette.CurrentHotkey; + // Set cursor position back for text rendering + ImGui::SetCursorScreenPos(buttonPos); - ImGui::TextColored(hotkeyColor, "%s", currentKeyName); + // Choose color based on hover state - darken when hovered. + ImVec4 hotkeyColor = hovered ? + ImVec4(themeSettings.StatusPalette.CurrentHotkey.x * 0.7f, + themeSettings.StatusPalette.CurrentHotkey.y * 0.7f, + themeSettings.StatusPalette.CurrentHotkey.z * 0.7f, + themeSettings.StatusPalette.CurrentHotkey.w) : + themeSettings.StatusPalette.CurrentHotkey; - // Handle click to start hotkey capture - if (clicked) { - menu->settingToggleKey = true; - } + ImGui::TextColored(hotkeyColor, "%s", currentKeyName); - // Show hotkey capture message or hotkey text - if (menu->settingToggleKey) { - const char* pressKeyText = "Press any key to set as toggle key..."; - float pressKeyWidth = ImGui::CalcTextSize(pressKeyText).x; - ImGui::SetCursorPosX((windowWidth - pressKeyWidth) * 0.5f); - ImGui::Text("%s", pressKeyText); - } + // Handle click to start hotkey capture + if (clicked) { + menu->settingToggleKey = true; + } - ImGui::Spacing(); + // Show hotkey capture message or hotkey text + if (menu->settingToggleKey) { + const char* pressKeyText = "Press any key to set as toggle key..."; + float pressKeyWidth = ImGui::CalcTextSize(pressKeyText).x; + ImGui::SetCursorPosX((windowWidth - pressKeyWidth) * 0.5f); + ImGui::Text("%s", pressKeyText); + } - // "You can change this later" text - wrapped and centered - const char* laterText = "You can change this later in General > Keybindings."; - float laterWidth = ImGui::CalcTextSize(laterText).x; - if (laterWidth > windowWidth - 40.0f) { - // Text is too wide, use wrapped text with centering - float laterTextPadding = 40.0f; + ImGui::Spacing(); - ImGui::SetCursorPosX(laterTextPadding); - ImGui::BeginGroup(); - ImGui::PushTextWrapPos(windowWidth - laterTextPadding); + // "You can change this later" text - wrapped and centered + const char* laterText = "You can change this later in General > Keybindings."; + float laterWidth = ImGui::CalcTextSize(laterText).x; + if (laterWidth > windowWidth - 40.0f) { + // Text is too wide, use wrapped text with centering + float laterTextPadding = 40.0f; + + ImGui::SetCursorPosX(laterTextPadding); + ImGui::BeginGroup(); + ImGui::PushTextWrapPos(windowWidth - laterTextPadding); + + // Calculate the wrapped text size to center it + ImVec2 laterTextSize = ImGui::CalcTextSize(laterText, nullptr, true, windowWidth - laterTextPadding * 2); + float laterCenterOffset = (windowWidth - laterTextPadding * 2 - laterTextSize.x) * 0.5f; + if (laterCenterOffset > 0) { + ImGui::SetCursorPosX(laterTextPadding + laterCenterOffset); + } - // Calculate the wrapped text size to center it - ImVec2 laterTextSize = ImGui::CalcTextSize(laterText, nullptr, true, windowWidth - laterTextPadding * 2); - float laterCenterOffset = (windowWidth - laterTextPadding * 2 - laterTextSize.x) * 0.5f; - if (laterCenterOffset > 0) { - ImGui::SetCursorPosX(laterTextPadding + laterCenterOffset); + ImGui::TextWrapped("%s", laterText); + ImGui::PopTextWrapPos(); + ImGui::EndGroup(); + } else { + // Text fits, center it normally + ImGui::SetCursorPosX((windowWidth - laterWidth) * 0.5f); + ImGui::Text("%s", laterText); } - ImGui::TextWrapped("%s", laterText); - ImGui::PopTextWrapPos(); - ImGui::EndGroup(); - } else { - // Text fits, center it normally - ImGui::SetCursorPosX((windowWidth - laterWidth) * 0.5f); - ImGui::Text("%s", laterText); - } - - ImGui::Spacing(); - - // Center the continue button - float continueButtonWidth = 140.0f; - ImGui::SetCursorPosX((windowWidth - continueButtonWidth) * 0.5f); + ImGui::Spacing(); - // Check for Enter or Escape key first - bool shouldClose = ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape); + // Center the continue button + float continueButtonWidth = 140.0f; + ImGui::SetCursorPosX((windowWidth - continueButtonWidth) * 0.5f); - if (ImGui::Button("Continue", ImVec2(continueButtonWidth, 30)) || shouldClose) { - // No need to apply any hotkey - user has already set it or it defaults to VK_END - MarkFirstTimeSetupComplete(); - } + // Check for Enter or Escape key first + bool shouldClose = ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape); - // Center the help text - const char* helpText = "(Press Enter or Escape to continue)"; - float helpWidth = ImGui::CalcTextSize(helpText).x; - ImGui::SetCursorPosX((windowWidth - helpWidth) * 0.5f); - ImGui::TextDisabled("%s", helpText); + if (ImGui::Button("Continue", ImVec2(continueButtonWidth, 30)) || shouldClose) { + // No need to apply any hotkey - user has already set it or it defaults to VK_END + MarkFirstTimeSetupComplete(); + } - ImGui::PopStyleVar(2); // Pop WindowRounding and WindowBorderSize - ImGui::End(); -} + // Center the help text + const char* helpText = "(Press Enter or Escape to continue)"; + float helpWidth = ImGui::CalcTextSize(helpText).x; + ImGui::SetCursorPosX((windowWidth - helpWidth) * 0.5f); + ImGui::TextDisabled("%s", helpText); -bool HomePageRenderer::ShouldShowFirstTimeSetup() -{ - // Never show first-time setup in VR mode - if (REL::Module::IsVR()) { - return false; + ImGui::PopStyleVar(2); // Pop WindowRounding and WindowBorderSize + ImGui::End(); } - // Check if already completed this session - if (isFirstTimeSetupShown) { - return false; - } + bool HomePageRenderer::ShouldShowFirstTimeSetup() + { + // Never show first-time setup in VR mode + if (REL::Module::IsVR()) { + return false; + } - // Check if first-time setup has been completed by looking at UserSettings.json - std::filesystem::path userSettingsPath = Util::PathHelpers::GetUserSettingsPath(); + // Check if already completed this session + if (isFirstTimeSetupShown) { + return false; + } - // If UserSettings.json doesn't exist at all, this is definitely a first-time launch - if (!std::filesystem::exists(userSettingsPath)) { - return true; - } + // Check if first-time setup has been completed by looking at UserSettings.json + std::filesystem::path userSettingsPath = Util::PathHelpers::GetUserSettingsPath(); - // If UserSettings.json exists, check if FirstTimeSetupCompleted flag is set - try { - std::ifstream file(userSettingsPath); - if (!file.is_open()) { - return true; // If we can't read the file, assume first time + // If UserSettings.json doesn't exist at all, this is definitely a first-time launch + if (!std::filesystem::exists(userSettingsPath)) { + return true; } - nlohmann::json settings; - file >> settings; - file.close(); + // If UserSettings.json exists, check if FirstTimeSetupCompleted flag is set + try { + std::ifstream file(userSettingsPath); + if (!file.is_open()) { + return true; // If we can't read the file, assume first time + } - // Check if FirstTimeSetupCompleted exists and is true - if (settings.contains("FirstTimeSetupCompleted") && - settings["FirstTimeSetupCompleted"].is_boolean() && - settings["FirstTimeSetupCompleted"] == true) { - return false; // Setup already completed - } + nlohmann::json settings; + file >> settings; + file.close(); - return true; // Field doesn't exist or is false, show setup + // Check if FirstTimeSetupCompleted exists and is true + if (settings.contains("FirstTimeSetupCompleted") && + settings["FirstTimeSetupCompleted"].is_boolean() && + settings["FirstTimeSetupCompleted"] == true) { + return false; // Setup already completed + } + + return true; // Field doesn't exist or is false, show setup - } catch (const std::exception&) { - // If there's any error reading the file, assume first time - return true; + } catch (const std::exception&) { + // If there's any error reading the file, assume first time + return true; + } } -} -void HomePageRenderer::MarkFirstTimeSetupComplete() -{ - std::filesystem::path userSettingsPath = Util::PathHelpers::GetUserSettingsPath(); + void HomePageRenderer::MarkFirstTimeSetupComplete() + { + std::filesystem::path userSettingsPath = Util::PathHelpers::GetUserSettingsPath(); - try { - nlohmann::json settings; + try { + nlohmann::json settings; - // Read existing settings if file exists - if (std::filesystem::exists(userSettingsPath)) { - std::ifstream file(userSettingsPath); - if (file.is_open()) { - file >> settings; - file.close(); + // Read existing settings if file exists + if (std::filesystem::exists(userSettingsPath)) { + std::ifstream file(userSettingsPath); + if (file.is_open()) { + file >> settings; + file.close(); + } } - } - // Set the FirstTimeSetupCompleted flag - settings["FirstTimeSetupCompleted"] = true; + // Set the FirstTimeSetupCompleted flag + settings["FirstTimeSetupCompleted"] = true; - // Write back to file - std::filesystem::create_directories(userSettingsPath.parent_path()); - std::ofstream outFile(userSettingsPath); - if (outFile.is_open()) { - outFile << settings.dump(2); - outFile.close(); + // Write back to file + std::filesystem::create_directories(userSettingsPath.parent_path()); + std::ofstream outFile(userSettingsPath); + if (outFile.is_open()) { + outFile << settings.dump(2); + outFile.close(); + } + + } catch (const std::exception&) { + // If we can't write the file, just mark as shown this session to avoid repeated popups } - } catch (const std::exception&) { - // If we can't write the file, just mark as shown this session to avoid repeated popups + isFirstTimeSetupShown = true; // Mark as shown this session } - - isFirstTimeSetupShown = true; // Mark as shown this session -} From b070352a520d0788dbe36b2f47c0242f716536e0 Mon Sep 17 00:00:00 2001 From: David Kehoe Date: Mon, 15 Sep 2025 21:45:46 +1000 Subject: [PATCH 4/5] Update HomePageRenderer.cpp --- src/Menu/HomePageRenderer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Menu/HomePageRenderer.cpp b/src/Menu/HomePageRenderer.cpp index 6437d04b90..f3d56ed68f 100644 --- a/src/Menu/HomePageRenderer.cpp +++ b/src/Menu/HomePageRenderer.cpp @@ -246,8 +246,9 @@ void HomePageRenderer::RenderFAQSection() " Branding materials and assets (icons, nexus branding, typography, etc) are not covered by the GPL Licence." " Any included assets may not be used without explicit permission."); } +} - void HomePageRenderer::RenderFirstTimeSetupDialog() +void HomePageRenderer::RenderFirstTimeSetupDialog() { // Block input to the game and make cursor visible - input blocking is handled by ShouldSwallowInput() auto& io = ImGui::GetIO(); From a09cf1295dab9400b46f200a733d9f0cdd1c1c28 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 11:46:13 +0000 Subject: [PATCH 5/5] =?UTF-8?q?style:=20=F0=9F=8E=A8=20apply=20pre-commit.?= =?UTF-8?q?ci=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automated formatting by clang-format, prettier, and other hooks. See https://pre-commit.ci for details. --- src/Menu/HomePageRenderer.cpp | 442 +++++++++++++++++----------------- 1 file changed, 221 insertions(+), 221 deletions(-) diff --git a/src/Menu/HomePageRenderer.cpp b/src/Menu/HomePageRenderer.cpp index f3d56ed68f..8e1a4628b1 100644 --- a/src/Menu/HomePageRenderer.cpp +++ b/src/Menu/HomePageRenderer.cpp @@ -249,274 +249,274 @@ void HomePageRenderer::RenderFAQSection() } void HomePageRenderer::RenderFirstTimeSetupDialog() - { - // Block input to the game and make cursor visible - input blocking is handled by ShouldSwallowInput() - auto& io = ImGui::GetIO(); - io.WantCaptureMouse = true; - io.WantCaptureKeyboard = true; - io.MouseDrawCursor = true; // Show ImGui cursor - - // Center the window properly with rounded corners and thin border - ImVec2 center = ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f); - ImGui::SetNextWindowPos(center, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_Always); - - // Style for rounded window with thin border - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f); - ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); - - ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoTitleBar; // Prevent scrolling and remove title - - if (!ImGui::Begin("##FirstTimeSetup", nullptr, flags)) { - ImGui::PopStyleVar(2); - ImGui::End(); - return; - } +{ + // Block input to the game and make cursor visible - input blocking is handled by ShouldSwallowInput() + auto& io = ImGui::GetIO(); + io.WantCaptureMouse = true; + io.WantCaptureKeyboard = true; + io.MouseDrawCursor = true; // Show ImGui cursor + + // Center the window properly with rounded corners and thin border + ImVec2 center = ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f); + ImGui::SetNextWindowPos(center, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); + ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_Always); + + // Style for rounded window with thin border + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); + + ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoTitleBar; // Prevent scrolling and remove title + + if (!ImGui::Begin("##FirstTimeSetup", nullptr, flags)) { + ImGui::PopStyleVar(2); + ImGui::End(); + return; + } - auto menu = Menu::GetSingleton(); + auto menu = Menu::GetSingleton(); - // Render CS logo as background watermark with proper aspect ratio - if (menu && menu->uiIcons.logo.texture) { - ImVec2 windowPos = ImGui::GetWindowPos(); - ImVec2 windowSize = ImGui::GetWindowSize(); + // Render CS logo as background watermark with proper aspect ratio + if (menu && menu->uiIcons.logo.texture) { + ImVec2 windowPos = ImGui::GetWindowPos(); + ImVec2 windowSize = ImGui::GetWindowSize(); - // Get the original texture size to maintain aspect ratio - ImVec2 textureSize = menu->uiIcons.logo.size; - float aspectRatio = textureSize.x / textureSize.y; + // Get the original texture size to maintain aspect ratio + ImVec2 textureSize = menu->uiIcons.logo.size; + float aspectRatio = textureSize.x / textureSize.y; - // Set desired height and calculate width to maintain aspect ratio - float logoHeight = LOGO_WATERMARK_HEIGHT; - float logoWidth = logoHeight * aspectRatio; + // Set desired height and calculate width to maintain aspect ratio + float logoHeight = LOGO_WATERMARK_HEIGHT; + float logoWidth = logoHeight * aspectRatio; - ImVec2 logoMin(windowPos.x + (windowSize.x - logoWidth) * 0.5f, - windowPos.y + (windowSize.y - logoHeight) * 0.5f); - ImVec2 logoMax(logoMin.x + logoWidth, logoMin.y + logoHeight); + ImVec2 logoMin(windowPos.x + (windowSize.x - logoWidth) * 0.5f, + windowPos.y + (windowSize.y - logoHeight) * 0.5f); + ImVec2 logoMax(logoMin.x + logoWidth, logoMin.y + logoHeight); - // Render as subtle watermark background - ImU32 watermarkColor = IM_COL32(255, 255, 255, 60); - ImGui::GetWindowDrawList()->AddImage(menu->uiIcons.logo.texture, logoMin, logoMax, - ImVec2(0, 0), ImVec2(1, 1), watermarkColor); - } + // Render as subtle watermark background + ImU32 watermarkColor = IM_COL32(255, 255, 255, 60); + ImGui::GetWindowDrawList()->AddImage(menu->uiIcons.logo.texture, logoMin, logoMax, + ImVec2(0, 0), ImVec2(1, 1), watermarkColor); + } - // Center all content - float windowWidth = ImGui::GetWindowWidth(); + // Center all content + float windowWidth = ImGui::GetWindowWidth(); - // Welcome title - centered - const char* welcomeTitle = "Welcome to Community Shaders!"; - float welcomeTitleWidth = ImGui::CalcTextSize(welcomeTitle).x; - ImGui::SetCursorPosX((windowWidth - welcomeTitleWidth) * 0.5f); - ImGui::Text("%s", welcomeTitle); + // Welcome title - centered + const char* welcomeTitle = "Welcome to Community Shaders!"; + float welcomeTitleWidth = ImGui::CalcTextSize(welcomeTitle).x; + ImGui::SetCursorPosX((windowWidth - welcomeTitleWidth) * 0.5f); + ImGui::Text("%s", welcomeTitle); - ImGui::Spacing(); + ImGui::Spacing(); - // Version text - wrapped and centered - const char* versionText = "This appears to be a new install, update, or reinstallation of Community Shaders."; - float textPadding = 40.0f; // Padding from window edges + // Version text - wrapped and centered + const char* versionText = "This appears to be a new install, update, or reinstallation of Community Shaders."; + float textPadding = 40.0f; // Padding from window edges - // Use a centered region for wrapped text - ImGui::SetCursorPosX(textPadding); - ImGui::BeginGroup(); - ImGui::PushTextWrapPos(windowWidth - textPadding); + // Use a centered region for wrapped text + ImGui::SetCursorPosX(textPadding); + ImGui::BeginGroup(); + ImGui::PushTextWrapPos(windowWidth - textPadding); - // Calculate the wrapped text size to center it - ImVec2 textSize = ImGui::CalcTextSize(versionText, nullptr, true, windowWidth - textPadding * 2); - float centerOffset = (windowWidth - textPadding * 2 - textSize.x) * 0.5f; - if (centerOffset > 0) { - ImGui::SetCursorPosX(textPadding + centerOffset); - } + // Calculate the wrapped text size to center it + ImVec2 textSize = ImGui::CalcTextSize(versionText, nullptr, true, windowWidth - textPadding * 2); + float centerOffset = (windowWidth - textPadding * 2 - textSize.x) * 0.5f; + if (centerOffset > 0) { + ImGui::SetCursorPosX(textPadding + centerOffset); + } - ImGui::TextWrapped("%s", versionText); - ImGui::PopTextWrapPos(); - ImGui::EndGroup(); + ImGui::TextWrapped("%s", versionText); + ImGui::PopTextWrapPos(); + ImGui::EndGroup(); - ImGui::Spacing(); + ImGui::Spacing(); - // Description - centered - const char* description = "Please select a hotkey to access the menu:"; - float descWidth = ImGui::CalcTextSize(description).x; - ImGui::SetCursorPosX((windowWidth - descWidth) * 0.5f); - ImGui::Text("%s", description); - - // Hotkey selection - clickable hotkey text - // Show current toggle key and allow user to change it by clicking on it - auto& themeSettings = menu->GetTheme(); - const char* currentKeyName = Util::Input::KeyIdToString(menu->GetSettings().ToggleKey); - - // Calculate text dimensions for centering and button area - float hotkeyWidth = ImGui::CalcTextSize(currentKeyName).x; - float centerX = (windowWidth - hotkeyWidth) * 0.5f; - ImGui::SetCursorPosX(centerX); - - // Create invisible button for hover detection and clicking - ImVec2 buttonPos = ImGui::GetCursorScreenPos(); - ImVec2 hotkeyTextSize = ImGui::CalcTextSize(currentKeyName); - bool hovered = false; - bool clicked = false; - - ImGui::PushID("HotkeyButton"); - if (ImGui::InvisibleButton("##HotkeyClick", hotkeyTextSize)) { - clicked = true; - } - hovered = ImGui::IsItemHovered(); - ImGui::PopID(); + // Description - centered + const char* description = "Please select a hotkey to access the menu:"; + float descWidth = ImGui::CalcTextSize(description).x; + ImGui::SetCursorPosX((windowWidth - descWidth) * 0.5f); + ImGui::Text("%s", description); + + // Hotkey selection - clickable hotkey text + // Show current toggle key and allow user to change it by clicking on it + auto& themeSettings = menu->GetTheme(); + const char* currentKeyName = Util::Input::KeyIdToString(menu->GetSettings().ToggleKey); + + // Calculate text dimensions for centering and button area + float hotkeyWidth = ImGui::CalcTextSize(currentKeyName).x; + float centerX = (windowWidth - hotkeyWidth) * 0.5f; + ImGui::SetCursorPosX(centerX); + + // Create invisible button for hover detection and clicking + ImVec2 buttonPos = ImGui::GetCursorScreenPos(); + ImVec2 hotkeyTextSize = ImGui::CalcTextSize(currentKeyName); + bool hovered = false; + bool clicked = false; + + ImGui::PushID("HotkeyButton"); + if (ImGui::InvisibleButton("##HotkeyClick", hotkeyTextSize)) { + clicked = true; + } + hovered = ImGui::IsItemHovered(); + ImGui::PopID(); - // Set cursor position back for text rendering - ImGui::SetCursorScreenPos(buttonPos); + // Set cursor position back for text rendering + ImGui::SetCursorScreenPos(buttonPos); - // Choose color based on hover state - darken when hovered. - ImVec4 hotkeyColor = hovered ? - ImVec4(themeSettings.StatusPalette.CurrentHotkey.x * 0.7f, - themeSettings.StatusPalette.CurrentHotkey.y * 0.7f, - themeSettings.StatusPalette.CurrentHotkey.z * 0.7f, - themeSettings.StatusPalette.CurrentHotkey.w) : - themeSettings.StatusPalette.CurrentHotkey; + // Choose color based on hover state - darken when hovered. + ImVec4 hotkeyColor = hovered ? + ImVec4(themeSettings.StatusPalette.CurrentHotkey.x * 0.7f, + themeSettings.StatusPalette.CurrentHotkey.y * 0.7f, + themeSettings.StatusPalette.CurrentHotkey.z * 0.7f, + themeSettings.StatusPalette.CurrentHotkey.w) : + themeSettings.StatusPalette.CurrentHotkey; - ImGui::TextColored(hotkeyColor, "%s", currentKeyName); + ImGui::TextColored(hotkeyColor, "%s", currentKeyName); - // Handle click to start hotkey capture - if (clicked) { - menu->settingToggleKey = true; - } + // Handle click to start hotkey capture + if (clicked) { + menu->settingToggleKey = true; + } - // Show hotkey capture message or hotkey text - if (menu->settingToggleKey) { - const char* pressKeyText = "Press any key to set as toggle key..."; - float pressKeyWidth = ImGui::CalcTextSize(pressKeyText).x; - ImGui::SetCursorPosX((windowWidth - pressKeyWidth) * 0.5f); - ImGui::Text("%s", pressKeyText); - } + // Show hotkey capture message or hotkey text + if (menu->settingToggleKey) { + const char* pressKeyText = "Press any key to set as toggle key..."; + float pressKeyWidth = ImGui::CalcTextSize(pressKeyText).x; + ImGui::SetCursorPosX((windowWidth - pressKeyWidth) * 0.5f); + ImGui::Text("%s", pressKeyText); + } - ImGui::Spacing(); + ImGui::Spacing(); - // "You can change this later" text - wrapped and centered - const char* laterText = "You can change this later in General > Keybindings."; - float laterWidth = ImGui::CalcTextSize(laterText).x; - if (laterWidth > windowWidth - 40.0f) { - // Text is too wide, use wrapped text with centering - float laterTextPadding = 40.0f; - - ImGui::SetCursorPosX(laterTextPadding); - ImGui::BeginGroup(); - ImGui::PushTextWrapPos(windowWidth - laterTextPadding); - - // Calculate the wrapped text size to center it - ImVec2 laterTextSize = ImGui::CalcTextSize(laterText, nullptr, true, windowWidth - laterTextPadding * 2); - float laterCenterOffset = (windowWidth - laterTextPadding * 2 - laterTextSize.x) * 0.5f; - if (laterCenterOffset > 0) { - ImGui::SetCursorPosX(laterTextPadding + laterCenterOffset); - } + // "You can change this later" text - wrapped and centered + const char* laterText = "You can change this later in General > Keybindings."; + float laterWidth = ImGui::CalcTextSize(laterText).x; + if (laterWidth > windowWidth - 40.0f) { + // Text is too wide, use wrapped text with centering + float laterTextPadding = 40.0f; - ImGui::TextWrapped("%s", laterText); - ImGui::PopTextWrapPos(); - ImGui::EndGroup(); - } else { - // Text fits, center it normally - ImGui::SetCursorPosX((windowWidth - laterWidth) * 0.5f); - ImGui::Text("%s", laterText); - } + ImGui::SetCursorPosX(laterTextPadding); + ImGui::BeginGroup(); + ImGui::PushTextWrapPos(windowWidth - laterTextPadding); - ImGui::Spacing(); + // Calculate the wrapped text size to center it + ImVec2 laterTextSize = ImGui::CalcTextSize(laterText, nullptr, true, windowWidth - laterTextPadding * 2); + float laterCenterOffset = (windowWidth - laterTextPadding * 2 - laterTextSize.x) * 0.5f; + if (laterCenterOffset > 0) { + ImGui::SetCursorPosX(laterTextPadding + laterCenterOffset); + } - // Center the continue button - float continueButtonWidth = 140.0f; - ImGui::SetCursorPosX((windowWidth - continueButtonWidth) * 0.5f); + ImGui::TextWrapped("%s", laterText); + ImGui::PopTextWrapPos(); + ImGui::EndGroup(); + } else { + // Text fits, center it normally + ImGui::SetCursorPosX((windowWidth - laterWidth) * 0.5f); + ImGui::Text("%s", laterText); + } - // Check for Enter or Escape key first - bool shouldClose = ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape); + ImGui::Spacing(); - if (ImGui::Button("Continue", ImVec2(continueButtonWidth, 30)) || shouldClose) { - // No need to apply any hotkey - user has already set it or it defaults to VK_END - MarkFirstTimeSetupComplete(); - } + // Center the continue button + float continueButtonWidth = 140.0f; + ImGui::SetCursorPosX((windowWidth - continueButtonWidth) * 0.5f); - // Center the help text - const char* helpText = "(Press Enter or Escape to continue)"; - float helpWidth = ImGui::CalcTextSize(helpText).x; - ImGui::SetCursorPosX((windowWidth - helpWidth) * 0.5f); - ImGui::TextDisabled("%s", helpText); + // Check for Enter or Escape key first + bool shouldClose = ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape); - ImGui::PopStyleVar(2); // Pop WindowRounding and WindowBorderSize - ImGui::End(); + if (ImGui::Button("Continue", ImVec2(continueButtonWidth, 30)) || shouldClose) { + // No need to apply any hotkey - user has already set it or it defaults to VK_END + MarkFirstTimeSetupComplete(); } - bool HomePageRenderer::ShouldShowFirstTimeSetup() - { - // Never show first-time setup in VR mode - if (REL::Module::IsVR()) { - return false; - } + // Center the help text + const char* helpText = "(Press Enter or Escape to continue)"; + float helpWidth = ImGui::CalcTextSize(helpText).x; + ImGui::SetCursorPosX((windowWidth - helpWidth) * 0.5f); + ImGui::TextDisabled("%s", helpText); - // Check if already completed this session - if (isFirstTimeSetupShown) { - return false; - } + ImGui::PopStyleVar(2); // Pop WindowRounding and WindowBorderSize + ImGui::End(); +} - // Check if first-time setup has been completed by looking at UserSettings.json - std::filesystem::path userSettingsPath = Util::PathHelpers::GetUserSettingsPath(); +bool HomePageRenderer::ShouldShowFirstTimeSetup() +{ + // Never show first-time setup in VR mode + if (REL::Module::IsVR()) { + return false; + } - // If UserSettings.json doesn't exist at all, this is definitely a first-time launch - if (!std::filesystem::exists(userSettingsPath)) { - return true; - } + // Check if already completed this session + if (isFirstTimeSetupShown) { + return false; + } - // If UserSettings.json exists, check if FirstTimeSetupCompleted flag is set - try { - std::ifstream file(userSettingsPath); - if (!file.is_open()) { - return true; // If we can't read the file, assume first time - } + // Check if first-time setup has been completed by looking at UserSettings.json + std::filesystem::path userSettingsPath = Util::PathHelpers::GetUserSettingsPath(); - nlohmann::json settings; - file >> settings; - file.close(); + // If UserSettings.json doesn't exist at all, this is definitely a first-time launch + if (!std::filesystem::exists(userSettingsPath)) { + return true; + } - // Check if FirstTimeSetupCompleted exists and is true - if (settings.contains("FirstTimeSetupCompleted") && - settings["FirstTimeSetupCompleted"].is_boolean() && - settings["FirstTimeSetupCompleted"] == true) { - return false; // Setup already completed - } + // If UserSettings.json exists, check if FirstTimeSetupCompleted flag is set + try { + std::ifstream file(userSettingsPath); + if (!file.is_open()) { + return true; // If we can't read the file, assume first time + } - return true; // Field doesn't exist or is false, show setup + nlohmann::json settings; + file >> settings; + file.close(); - } catch (const std::exception&) { - // If there's any error reading the file, assume first time - return true; + // Check if FirstTimeSetupCompleted exists and is true + if (settings.contains("FirstTimeSetupCompleted") && + settings["FirstTimeSetupCompleted"].is_boolean() && + settings["FirstTimeSetupCompleted"] == true) { + return false; // Setup already completed } - } - void HomePageRenderer::MarkFirstTimeSetupComplete() - { - std::filesystem::path userSettingsPath = Util::PathHelpers::GetUserSettingsPath(); + return true; // Field doesn't exist or is false, show setup - try { - nlohmann::json settings; + } catch (const std::exception&) { + // If there's any error reading the file, assume first time + return true; + } +} - // Read existing settings if file exists - if (std::filesystem::exists(userSettingsPath)) { - std::ifstream file(userSettingsPath); - if (file.is_open()) { - file >> settings; - file.close(); - } - } +void HomePageRenderer::MarkFirstTimeSetupComplete() +{ + std::filesystem::path userSettingsPath = Util::PathHelpers::GetUserSettingsPath(); - // Set the FirstTimeSetupCompleted flag - settings["FirstTimeSetupCompleted"] = true; + try { + nlohmann::json settings; - // Write back to file - std::filesystem::create_directories(userSettingsPath.parent_path()); - std::ofstream outFile(userSettingsPath); - if (outFile.is_open()) { - outFile << settings.dump(2); - outFile.close(); + // Read existing settings if file exists + if (std::filesystem::exists(userSettingsPath)) { + std::ifstream file(userSettingsPath); + if (file.is_open()) { + file >> settings; + file.close(); } + } - } catch (const std::exception&) { - // If we can't write the file, just mark as shown this session to avoid repeated popups + // Set the FirstTimeSetupCompleted flag + settings["FirstTimeSetupCompleted"] = true; + + // Write back to file + std::filesystem::create_directories(userSettingsPath.parent_path()); + std::ofstream outFile(userSettingsPath); + if (outFile.is_open()) { + outFile << settings.dump(2); + outFile.close(); } - isFirstTimeSetupShown = true; // Mark as shown this session + } catch (const std::exception&) { + // If we can't write the file, just mark as shown this session to avoid repeated popups } + + isFirstTimeSetupShown = true; // Mark as shown this session +}