Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ void Menu::ProcessInputEventQueue()
std::function<void()> action;
};
KeyAction keyActions[] = {
{ settings.ToggleKey, [this]() { IsEnabled = !IsEnabled; } },
{ settings.ToggleKey, [this]() { if (!HomePageRenderer::ShouldShowFirstTimeSetup()) IsEnabled = !IsEnabled; } },
{ settings.SkipCompilationKey, [shaderCache]() { shaderCache->backgroundCompilation = true; } },
{ settings.EffectToggleKey, [shaderCache]() { shaderCache->SetEnabled(!shaderCache->IsEnabled()); } },
{ settings.ShaderBlockPrevKey, [this, shaderCache]() { if (settings.EnableShaderBlocking) shaderCache->IterateShaderBlock(); } },
Expand Down
153 changes: 61 additions & 92 deletions src/Menu/HomePageRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ void HomePageRenderer::RenderFirstTimeSetupDialog()
io.WantCaptureKeyboard = true;
io.MouseDrawCursor = true; // Show ImGui cursor

// Draw semi-transparent dark overlay behind the dialog for depth
Util::DrawModalBackground();

Comment thread
Dlizzio marked this conversation as resolved.
// 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));
Expand Down Expand Up @@ -317,142 +320,108 @@ void HomePageRenderer::RenderFirstTimeSetupDialog()

// 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);

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

// 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);
}

ImGui::TextWrapped("%s", versionText);
ImGui::PopTextWrapPos();
ImGui::EndGroup();
auto centerText = [windowWidth](const char* text) {
ImGui::SetCursorPosX((windowWidth - ImGui::CalcTextSize(text).x) * 0.5f);
};
auto centerWidth = [windowWidth](float width) {
ImGui::SetCursorPosX((windowWidth - width) * 0.5f);
};

// Version text - two lines, both centered (reduced spacing between lines)
const char* versionLine1 = "This appears to be a new install, update, or";
const char* versionLine2 = "reinstallation of Community Shaders.";

centerText(versionLine1);
ImGui::Text("%s", versionLine1);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 4.0f);
centerText(versionLine2);
ImGui::Text("%s", versionLine2);

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);
const char* description = "Please choose a hotkey to access the menu:";
centerText(description);
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);
bool isCapturing = menu->settingToggleKey;

// Increase font size for hotkey text
ImGui::SetWindowFontScale(fontScale * HOTKEY_TEXT_SCALE_MULTIPLIER);
// Increase font size for hotkey text - bigger when capturing
ImGui::SetWindowFontScale(fontScale * (isCapturing ? HOTKEY_TEXT_SCALE_CAPTURING : HOTKEY_TEXT_SCALE));

// Calculate text dimensions for centering and button area
float hotkeyWidth = ImGui::CalcTextSize(currentKeyName).x;
float centerX = (windowWidth - hotkeyWidth) * 0.5f;
ImGui::SetCursorPosX(centerX);
// Format hotkey with brackets to make it look like a button
std::string hotkeyDisplay = isCapturing ? "[ ... ]" : std::string("[ ") + Util::Input::KeyIdToString(menu->GetSettings().ToggleKey) + " ]";
ImVec2 hotkeyTextSize = ImGui::CalcTextSize(hotkeyDisplay.c_str());

// Create invisible button for hover detection and clicking
centerWidth(hotkeyTextSize.x);
ImVec2 buttonPos = ImGui::GetCursorScreenPos();
ImVec2 hotkeyTextSize = ImGui::CalcTextSize(currentKeyName);
bool hovered = false;
bool clicked = false;

// Create invisible button for hover detection and clicking
ImGui::PushID("HotkeyButton");
if (ImGui::InvisibleButton("##HotkeyClick", hotkeyTextSize)) {
clicked = true;
}
hovered = ImGui::IsItemHovered();
bool clicked = ImGui::InvisibleButton("##HotkeyClick", hotkeyTextSize);
bool hovered = ImGui::IsItemHovered();
ImGui::PopID();

// 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 state
ImVec4 hotkeyColor;
if (isCapturing) {
// Pulsing effect using theme's hotkey color
hotkeyColor = Util::GetPulsingColor(themeSettings.StatusPalette.CurrentHotkey);
} else if (hovered) {
hotkeyColor = ImVec4(themeSettings.StatusPalette.CurrentHotkey.x * HOTKEY_HOVER_DIM_FACTOR,
themeSettings.StatusPalette.CurrentHotkey.y * HOTKEY_HOVER_DIM_FACTOR,
themeSettings.StatusPalette.CurrentHotkey.z * HOTKEY_HOVER_DIM_FACTOR,
themeSettings.StatusPalette.CurrentHotkey.w);
} else {
hotkeyColor = themeSettings.StatusPalette.CurrentHotkey;
}

ImGui::TextColored(hotkeyColor, "%s", currentKeyName);
ImGui::TextColored(hotkeyColor, "%s", hotkeyDisplay.c_str());

// Reset font scale
ImGui::SetWindowFontScale(fontScale);

// Handle click to start hotkey capture
if (clicked) {
if (clicked && !isCapturing) {
menu->settingToggleKey = true;
}

// Show hotkey capture message or hotkey text
if (menu->settingToggleKey) {
// Show hotkey capture message when in capture mode
if (isCapturing) {
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);
centerText(pressKeyText);
ImGui::TextDisabled("%s", pressKeyText);
}

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);
}

ImGui::TextWrapped("%s", laterText);
ImGui::PopTextWrapPos();
ImGui::EndGroup();
} else {
// Text fits, center it normally
ImGui::SetCursorPosX((windowWidth - laterWidth) * 0.5f);
ImGui::Text("%s", laterText);
}
centerText(laterText);
ImGui::Text("%s", laterText);

ImGui::Spacing();

// Check for Enter or Escape key to close, but only if not capturing a hotkey
bool shouldClose = (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape)) && !menu->settingToggleKey;

if (shouldClose) {
if ((ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape)) && !isCapturing) {
MarkFirstTimeSetupComplete();
// Note: Settings are automatically saved to ensure welcome screen won't show again
}

// Center the help text
// Help text with breathing animation
const char* helpText = "Press Escape or Enter to continue";
float helpWidth = ImGui::CalcTextSize(helpText).x;
ImGui::SetCursorPosX((windowWidth - helpWidth) * 0.5f);
ImGui::TextDisabled("%s", helpText);

ImGui::SetWindowFontScale(fontScale * HELP_TEXT_SCALE);
centerText(helpText);
Util::DrawBreathingText(helpText);

// Reset font scale
ImGui::SetWindowFontScale(fontScale);
Comment thread
Dlizzio marked this conversation as resolved.

ImGui::End();
ImGui::PopStyleVar(2);
Expand Down
5 changes: 4 additions & 1 deletion src/Menu/HomePageRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ class HomePageRenderer
// Constants
static constexpr const char* DISCORD_URL = "https://discord.com/invite/nkrQybAsyy";
static constexpr float TITLE_FONT_SCALE = 2.0f;
static constexpr float HOTKEY_TEXT_SCALE_MULTIPLIER = 1.25f;
static constexpr float HOTKEY_TEXT_SCALE = 1.6f;
static constexpr float HOTKEY_TEXT_SCALE_CAPTURING = 2.0f;
static constexpr float HOTKEY_HOVER_DIM_FACTOR = 0.7f;
static constexpr float HELP_TEXT_SCALE = 1.35f;
static constexpr float QUICK_LINKS_BUTTON_WIDTH = 180.0f;
static constexpr float LOGO_WATERMARK_HEIGHT = 200.0f;

Expand Down
29 changes: 29 additions & 0 deletions src/Utils/UI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,35 @@ namespace Util
return lowerText.find(lowerQuery) != std::string::npos;
}

void DrawModalBackground(uint8_t alpha)
{
auto& io = ImGui::GetIO();
ImGui::GetBackgroundDrawList()->AddRectFilled(
ImVec2(0, 0),
io.DisplaySize,
IM_COL32(0, 0, 0, alpha));
}

void DrawBreathingText(const char* text, float speed, float minAlpha, float maxAlpha)
{
float alphaRange = maxAlpha - minAlpha;
float breathe = minAlpha + alphaRange * 0.5f * (1.0f + sinf((float)ImGui::GetTime() * speed));
auto& theme = globals::menu->GetTheme().Palette;
ImVec4 color = ImVec4(theme.Text.x, theme.Text.y, theme.Text.z, breathe);
ImGui::TextColored(color, "%s", text);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

ImVec4 GetPulsingColor(const ImVec4& baseColor, float speed, float minBrightness, float maxBrightness)
{
float brightnessRange = maxBrightness - minBrightness;
float pulse = minBrightness + brightnessRange * 0.5f * (1.0f + sinf((float)ImGui::GetTime() * speed));
return ImVec4(
baseColor.x * pulse,
baseColor.y * pulse,
baseColor.z * pulse,
baseColor.w);
}

void DrawSearchIcon(const ImVec2& position, float size, float alpha)
{
ImDrawList* drawList = ImGui::GetWindowDrawList();
Expand Down
25 changes: 25 additions & 0 deletions src/Utils/UI.h
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,31 @@ namespace Util
*/
void DrawSearchIcon(const ImVec2& position, float size = 20.0f, float alpha = 0.7f);

/**
* @brief Draws a semi-transparent dark overlay behind modal dialogs for depth.
* @param alpha The alpha value for the overlay (0-255, default: 160)
*/
void DrawModalBackground(uint8_t alpha = 160);

/**
* @brief Draws text with a breathing/pulsing alpha animation using theme text color.
* @param text The text to display
* @param speed Animation speed multiplier (default: 2.5f)
* @param minAlpha Minimum alpha value (default: 0.7f)
* @param maxAlpha Maximum alpha value (default: 1.0f)
*/
void DrawBreathingText(const char* text, float speed = 2.5f, float minAlpha = 0.7f, float maxAlpha = 1.0f);

/**
* @brief Returns a color with pulsing brightness animation applied.
* @param baseColor The base color to pulse
* @param speed Animation speed multiplier (default: 4.0f)
* @param minBrightness Minimum brightness multiplier (default: 0.7f)
* @param maxBrightness Maximum brightness multiplier (default: 1.0f)
* @return The color with pulsing brightness applied (alpha unchanged)
*/
ImVec4 GetPulsingColor(const ImVec4& baseColor, float speed = 4.0f, float minBrightness = 0.7f, float maxBrightness = 1.0f);

/**
* @brief Draws the feature search bar with magnifying glass icon.
* @param searchString Reference to the search string to modify
Expand Down