From 93d6868c5f065418c0cc8725f94c8b4aeacec161 Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Tue, 2 Jun 2026 01:03:34 -0700 Subject: [PATCH 1/5] init --- src/CSEditor/EditorWindow.cpp | 10 +- src/Features/CSEditor.cpp | 2 +- src/Features/PerformanceOverlay.cpp | 2 +- src/Menu.cpp | 2 +- src/Menu/FeatureListRenderer.cpp | 5 +- src/Utils/UI.cpp | 164 +++++++++++++++++++--------- src/Utils/UI.h | 10 +- 7 files changed, 130 insertions(+), 65 deletions(-) diff --git a/src/CSEditor/EditorWindow.cpp b/src/CSEditor/EditorWindow.cpp index 30077298f4..174e38e95a 100644 --- a/src/CSEditor/EditorWindow.cpp +++ b/src/CSEditor/EditorWindow.cpp @@ -90,16 +90,12 @@ bool IconButton(const char* label, bool filled, const char* iconType) bool result = ImGui::InvisibleButton(label, buttonSize); - bool hovered = ImGui::IsItemHovered(); - bool active = ImGui::IsItemActive(); - - ImU32 bgColor = active ? ImGui::GetColorU32(ImGuiCol_ButtonActive) : - hovered ? ImGui::GetColorU32(ImGuiCol_ButtonHovered) : - ImGui::GetColorU32(ImGuiCol_Button); ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_Text); auto* drawList = ImGui::GetWindowDrawList(); - drawList->AddRectFilled(cursorPos, ImVec2(cursorPos.x + buttonSize.x, cursorPos.y + buttonSize.y), bgColor, ImGui::GetStyle().FrameRounding); + const ImVec2 buttonMax(cursorPos.x + buttonSize.x, cursorPos.y + buttonSize.y); + drawList->AddRectFilled(cursorPos, buttonMax, ImGui::GetColorU32(ImGuiCol_Button), ImGui::GetStyle().FrameRounding); + Util::DrawCurrentItemRoundedButtonHighlight(drawList); ImVec2 center(cursorPos.x + buttonSize.x * 0.5f, cursorPos.y + buttonSize.y * 0.5f); float iconSize = buttonSize.x * 0.35f; diff --git a/src/Features/CSEditor.cpp b/src/Features/CSEditor.cpp index 7ff0c15f2f..c0f3ef6597 100644 --- a/src/Features/CSEditor.cpp +++ b/src/Features/CSEditor.cpp @@ -385,7 +385,7 @@ void CSEditor::RenderWeatherDetailsWindow(bool* open) } ImGui::SetNextWindowSize(ImVec2(600 * scale, 800 * scale), ImGuiCond_FirstUseEver); - if (ImGui::Begin("Weather Details##Popup", open, ImGuiWindowFlags_None)) { + if (Util::BeginWithRoundedClose("Weather Details##Popup", open, ImGuiWindowFlags_None)) { // Remember window position for next frame ImVec2 currentPos = ImGui::GetWindowPos(); if (currentPos.x != WeatherDetailsWindow.Position.x || currentPos.y != WeatherDetailsWindow.Position.y) { diff --git a/src/Features/PerformanceOverlay.cpp b/src/Features/PerformanceOverlay.cpp index 739e86d8d9..2ffe9f312f 100644 --- a/src/Features/PerformanceOverlay.cpp +++ b/src/Features/PerformanceOverlay.cpp @@ -357,7 +357,7 @@ void PerformanceOverlay::DrawOverlay() } // Create the window - ImGui::Begin("Performance Overlay", NULL, windowFlags); + Util::BeginWithRoundedClose("Performance Overlay", nullptr, windowFlags); // Remember window position for next frame if (ImGui::IsWindowAppearing()) { diff --git a/src/Menu.cpp b/src/Menu.cpp index cde6f6fc5d..7989f0f238 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -684,7 +684,7 @@ void Menu::DrawSettings() windowFlags |= ImGuiWindowFlags_NoTitleBar; } - ImGui::Begin(title.c_str(), &IsEnabled, windowFlags); + Util::BeginWithRoundedClose(title.c_str(), &IsEnabled, windowFlags); { // Update docking state tracking bool isDocked = ImGui::IsWindowDocked(); diff --git a/src/Menu/FeatureListRenderer.cpp b/src/Menu/FeatureListRenderer.cpp index 8764cc3af1..57f04e36c0 100644 --- a/src/Menu/FeatureListRenderer.cpp +++ b/src/Menu/FeatureListRenderer.cpp @@ -22,6 +22,7 @@ #include "SettingsOverrideManager.h" #include "State.h" #include "Util.h" +#include "Utils/UI.h" #include "WeatherVariableRegistry.h" namespace @@ -893,7 +894,7 @@ void FeatureListRenderer::DrawMenuVisitor::RenderReactiveConstraintWarningDialog ImVec2 center = ImGui::GetMainViewport()->GetCenter(); ImGui::SetNextWindowPos(center, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - if (ImGui::BeginPopupModal("Setting Change Warning", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + if (Util::BeginPopupModalWithRoundedClose("Setting Change Warning", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::TextWrapped("Some of your settings have been automatically adjusted due to feature incompatibilities."); ImGui::Spacing(); ImGui::Separator(); @@ -1010,4 +1011,4 @@ void FeatureListRenderer::DrawMenuVisitor::RenderReactiveConstraintWarningDialog g_reactiveWarningShow = false; g_reactiveWarningConstraints.clear(); } -} \ No newline at end of file +} diff --git a/src/Utils/UI.cpp b/src/Utils/UI.cpp index 045b55147c..b4a3c38979 100644 --- a/src/Utils/UI.cpp +++ b/src/Utils/UI.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -125,7 +126,7 @@ namespace Util // measurement frame, causing TextWrapped to wrap at 0px and produce an enormous height. // Setting an initial width gives TextWrapped a sensible wrap column on that frame. ImGui::SetNextWindowSize(ImVec2(400.0f * GetUIScale(), 0.0f), ImGuiCond_Appearing); - isOpen = ImGui::BeginPopupModal(name, p_open, flags | ImGuiWindowFlags_NoSavedSettings); + isOpen = BeginPopupModalWithRoundedClose(name, p_open, flags | ImGuiWindowFlags_NoSavedSettings); } CenteredPopupModal::~CenteredPopupModal() @@ -617,61 +618,99 @@ namespace Util return theme.UseMonochromeIcons ? theme.Palette.Text : ImVec4(1, 1, 1, 1); } + static float GetPillRounding(const ImVec2& min, const ImVec2& max) + { + IM_ASSERT(max.x >= min.x && max.y >= min.y); + return ImMin(max.x - min.x, max.y - min.y) * 0.5f; + } + + bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, ImDrawList* drawList) + { + return DrawRoundedButtonHighlight(min, max, hovered, active, GetPillRounding(min, max), drawList); + } + + bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, float rounding, ImDrawList* drawList) + { + if (!hovered && !active) + return false; + + IM_ASSERT(max.x >= min.x && max.y >= min.y); + IM_ASSERT(rounding >= 0.0f); + if (!drawList) + drawList = ImGui::GetWindowDrawList(); + + drawList->AddRectFilled(min, max, ImGui::GetColorU32(active ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered), rounding); + return true; + } + + bool DrawCurrentItemRoundedButtonHighlight(ImDrawList* drawList) + { + return DrawRoundedButtonHighlight(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), ImGui::IsItemHovered(), ImGui::IsItemActive(), drawList); + } + // Shared constants for title-bar button overlays - static constexpr float kButtonPad = 2.0f; // extra padding around hit/highlight area - static constexpr float kCrossDiag = 0.5f * 0.7071f; // half-size * 1/sqrt(2) for cross line endpoints - static constexpr float kCrossInset = 1.0f; // inward inset so cross doesn't touch edges + static constexpr float kTitleBarButtonPadding = 2.0f; + static constexpr float kCloseCrossDiagonalScale = 0.5f / std::numbers::sqrt2_v; + static constexpr float kCloseCrossInset = 1.0f; + static constexpr ImVec4 kTransparentButtonChrome(0, 0, 0, 0); - // Compute the bounding rect for a title-bar button of font-sized square + padding. - static ImRect ButtonBB(const ImVec2& origin, float fontSize) + static ImRect TitleBarButtonRect(const ImVec2& origin, float fontSize) { - const float full = fontSize + kButtonPad * 2.0f; + const float full = fontSize + kTitleBarButtonPadding * 2.0f; return ImRect(origin, ImVec2(origin.x + full, origin.y + full)); } - // Draws a rounded highlight overlay for a title bar button. - static void DrawRoundedButtonHighlight(ImGuiWindow* window, const ImRect& bb, float rounding) + static bool IsTitleBarButtonHovered(ImGuiWindow* window, const ImRect& bb) { ImGuiContext& g = *ImGui::GetCurrentContext(); - bool isTop = (g.HoveredWindow == window); - bool hovered = isTop && ImGui::IsMouseHoveringRect(bb.Min, bb.Max, false); - bool held = hovered && ImGui::IsMouseDown(ImGuiMouseButton_Left); - if (hovered || held) - window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered), rounding); + return g.HoveredWindow == window && ImGui::IsMouseHoveringRect(bb.Min, bb.Max, false); } + class NativeTitleBarButtonHighlightGuard + { + public: + NativeTitleBarButtonHighlightGuard() + { + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, kTransparentButtonChrome); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, kTransparentButtonChrome); + } + + ~NativeTitleBarButtonHighlightGuard() { ImGui::PopStyleColor(2); } + }; + // Draws a rounded close button overlay, matching native ImGui CloseButton position. - static void DrawRoundedCloseButton(ImGuiWindow* window, bool* p_open) + static void DrawRoundedCloseHighlight(ImGuiWindow* window) { + if (window->Flags & ImGuiWindowFlags_NoTitleBar) + return; + const auto& style = ImGui::GetStyle(); const float sz = ImGui::GetFontSize(); - const ImVec2 pos(window->Rect().Max.x - window->WindowBorderSize - style.FramePadding.x - sz - kButtonPad, - window->Rect().Min.y + style.FramePadding.y - kButtonPad); - const ImRect bb = ButtonBB(pos, sz); - const float rounding = (sz + kButtonPad * 2.0f) * 0.5f; - - ImGuiContext& g = *ImGui::GetCurrentContext(); - bool isTop = (g.HoveredWindow == window); - bool hovered = isTop && ImGui::IsMouseHoveringRect(bb.Min, bb.Max, false); + const ImVec2 pos(window->Rect().Max.x - window->WindowBorderSize - style.FramePadding.x - sz - kTitleBarButtonPadding, + window->Rect().Min.y + style.FramePadding.y - kTitleBarButtonPadding); + const ImRect bb = TitleBarButtonRect(pos, sz); + const bool hovered = IsTitleBarButtonHovered(window, bb); + const bool held = hovered && ImGui::IsMouseDown(ImGuiMouseButton_Left); window->DrawList->PushClipRect(window->Rect().Min, window->Rect().Max); - DrawRoundedButtonHighlight(window, bb, rounding); - - // Cross lines — matches ImGui's internal RenderCloseButton geometry - const ImVec2 c = bb.GetCenter(); - const float d = sz * kCrossDiag - kCrossInset; - const ImU32 col = ImGui::GetColorU32(ImGuiCol_Text); - window->DrawList->AddLine({ c.x - d, c.y - d }, { c.x + d, c.y + d }, col); - window->DrawList->AddLine({ c.x + d, c.y - d }, { c.x - d, c.y + d }, col); - window->DrawList->PopClipRect(); + const bool highlighted = DrawRoundedButtonHighlight(bb.Min, bb.Max, hovered, held, window->DrawList); - if (hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) - *p_open = false; + // Cross lines match ImGui's internal RenderCloseButton geometry. + if (highlighted) { + const ImVec2 c = bb.GetCenter(); + const float d = sz * kCloseCrossDiagonalScale - kCloseCrossInset; + const ImU32 col = ImGui::GetColorU32(ImGuiCol_Text); + window->DrawList->AddLine({ c.x - d, c.y - d }, { c.x + d, c.y + d }, col); + window->DrawList->AddLine({ c.x + d, c.y - d }, { c.x - d, c.y + d }, col); + } + window->DrawList->PopClipRect(); } // Draws a rounded highlight for the collapse/triangle button in the title bar. static void DrawRoundedCollapseHighlight(ImGuiWindow* window) { + if (window->Flags & ImGuiWindowFlags_NoTitleBar) + return; if (window->Flags & ImGuiWindowFlags_NoCollapse) return; if (ImGui::GetStyle().WindowMenuButtonPosition == ImGuiDir_None) @@ -679,34 +718,55 @@ namespace Util const auto& style = ImGui::GetStyle(); const float sz = ImGui::GetFontSize(); - const ImVec2 pos(window->Pos.x + window->WindowBorderSize + style.FramePadding.x - kButtonPad, - window->Pos.y + style.FramePadding.y - kButtonPad); - const ImRect bb = ButtonBB(pos, sz); - const float rounding = (sz + kButtonPad * 2.0f) * 0.5f; + const ImVec2 pos(window->Pos.x + window->WindowBorderSize + style.FramePadding.x - kTitleBarButtonPadding, + window->Pos.y + style.FramePadding.y - kTitleBarButtonPadding); + const ImRect bb = TitleBarButtonRect(pos, sz); + const bool hovered = IsTitleBarButtonHovered(window, bb); + const bool held = hovered && ImGui::IsMouseDown(ImGuiMouseButton_Left); window->DrawList->PushClipRect(window->Rect().Min, window->Rect().Max); - DrawRoundedButtonHighlight(window, bb, rounding); + const bool highlighted = DrawRoundedButtonHighlight(bb.Min, bb.Max, hovered, held, window->DrawList); - // Redraw the triangle arrow on top of the highlight so it stays visible - const ImVec2 arrowPos(pos.x + kButtonPad, pos.y + kButtonPad); - const ImGuiDir dir = window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down; - ImGui::RenderArrow(window->DrawList, arrowPos, ImGui::GetColorU32(ImGuiCol_Text), dir, 1.0f); + if (highlighted) { + const ImVec2 arrowPos(pos.x + kTitleBarButtonPadding, pos.y + kTitleBarButtonPadding); + const ImGuiDir dir = window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down; + ImGui::RenderArrow(window->DrawList, arrowPos, ImGui::GetColorU32(ImGuiCol_Text), dir, 1.0f); + } window->DrawList->PopClipRect(); } - bool BeginWithRoundedClose(const char* name, bool* p_open, ImGuiWindowFlags flags) + static void DrawRoundedTitleBarButtonHighlights(ImGuiWindow* window, bool hasCloseButton, bool hasCollapseButton) { - // Hide native sharp-cornered highlights; we draw rounded ones after Begin() - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0)); - bool visible = ImGui::Begin(name, p_open, flags); - ImGui::PopStyleColor(2); - if (auto* window = ImGui::GetCurrentWindowRead()) { + if (!window) + return; + + if (hasCollapseButton) DrawRoundedCollapseHighlight(window); - if (p_open) - DrawRoundedCloseButton(window, p_open); + if (hasCloseButton) + DrawRoundedCloseHighlight(window); + } + + bool BeginWithRoundedClose(const char* name, bool* p_open, ImGuiWindowFlags flags) + { + bool visible = false; + { + NativeTitleBarButtonHighlightGuard guard; + visible = ImGui::Begin(name, p_open, flags); + } + DrawRoundedTitleBarButtonHighlights(ImGui::GetCurrentWindowRead(), p_open != nullptr, true); + return visible; + } + + bool BeginPopupModalWithRoundedClose(const char* name, bool* p_open, ImGuiWindowFlags flags) + { + bool visible = false; + { + NativeTitleBarButtonHighlightGuard guard; + visible = ImGui::BeginPopupModal(name, p_open, flags); } + if (visible) + DrawRoundedTitleBarButtonHighlights(ImGui::GetCurrentWindowRead(), p_open != nullptr, false); return visible; } diff --git a/src/Utils/UI.h b/src/Utils/UI.h index 7a7aec368a..c48c21af3a 100644 --- a/src/Utils/UI.h +++ b/src/Utils/UI.h @@ -319,8 +319,16 @@ namespace Util /** Returns theme text color if monochrome icons enabled, otherwise white. */ ImVec4 GetIconTint(); - /// ImGui::Begin() wrapper that replaces the native close button with a rounded one. + /// Draws a pill-rounded hover/active fill over a button rect. + bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, ImDrawList* drawList = nullptr); + bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, float rounding, ImDrawList* drawList); + + /// Draws the rounded hover/active fill for the last submitted item. + bool DrawCurrentItemRoundedButtonHighlight(ImDrawList* drawList = nullptr); + + /// ImGui::Begin() wrappers that replace native title-bar button highlights with rounded ones. bool BeginWithRoundedClose(const char* name, bool* p_open, ImGuiWindowFlags flags = 0); + bool BeginPopupModalWithRoundedClose(const char* name, bool* p_open = nullptr, ImGuiWindowFlags flags = 0); /** * Button with simple flash feedback (matches action icon hover effect style) From bcb43cec6b3febef080751951e0c7f665b5938c3 Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Tue, 2 Jun 2026 03:06:56 -0700 Subject: [PATCH 2/5] AI comment --- src/Utils/UI.cpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/Utils/UI.cpp b/src/Utils/UI.cpp index b4a3c38979..dd95631b43 100644 --- a/src/Utils/UI.cpp +++ b/src/Utils/UI.cpp @@ -660,6 +660,25 @@ namespace Util return ImRect(origin, ImVec2(origin.x + full, origin.y + full)); } + static ImVec2 RightTitleBarButtonOrigin(ImGuiWindow* window, float fontSize, float offset = 0.0f) + { + const auto& style = ImGui::GetStyle(); + return ImVec2(window->Rect().Max.x - window->WindowBorderSize - style.FramePadding.x - fontSize - offset - kTitleBarButtonPadding, + window->Rect().Min.y + style.FramePadding.y - kTitleBarButtonPadding); + } + + static ImVec2 CollapseTitleBarButtonOrigin(ImGuiWindow* window, bool hasCloseButton, float fontSize) + { + const auto& style = ImGui::GetStyle(); + IM_ASSERT(style.WindowMenuButtonPosition == ImGuiDir_Left || style.WindowMenuButtonPosition == ImGuiDir_Right); + + if (style.WindowMenuButtonPosition == ImGuiDir_Right) + return RightTitleBarButtonOrigin(window, fontSize, hasCloseButton ? fontSize : 0.0f); + + return ImVec2(window->Pos.x + window->WindowBorderSize + style.FramePadding.x - kTitleBarButtonPadding, + window->Pos.y + style.FramePadding.y - kTitleBarButtonPadding); + } + static bool IsTitleBarButtonHovered(ImGuiWindow* window, const ImRect& bb) { ImGuiContext& g = *ImGui::GetCurrentContext(); @@ -684,10 +703,8 @@ namespace Util if (window->Flags & ImGuiWindowFlags_NoTitleBar) return; - const auto& style = ImGui::GetStyle(); const float sz = ImGui::GetFontSize(); - const ImVec2 pos(window->Rect().Max.x - window->WindowBorderSize - style.FramePadding.x - sz - kTitleBarButtonPadding, - window->Rect().Min.y + style.FramePadding.y - kTitleBarButtonPadding); + const ImVec2 pos = RightTitleBarButtonOrigin(window, sz); const ImRect bb = TitleBarButtonRect(pos, sz); const bool hovered = IsTitleBarButtonHovered(window, bb); const bool held = hovered && ImGui::IsMouseDown(ImGuiMouseButton_Left); @@ -707,7 +724,7 @@ namespace Util } // Draws a rounded highlight for the collapse/triangle button in the title bar. - static void DrawRoundedCollapseHighlight(ImGuiWindow* window) + static void DrawRoundedCollapseHighlight(ImGuiWindow* window, bool hasCloseButton) { if (window->Flags & ImGuiWindowFlags_NoTitleBar) return; @@ -716,10 +733,8 @@ namespace Util if (ImGui::GetStyle().WindowMenuButtonPosition == ImGuiDir_None) return; - const auto& style = ImGui::GetStyle(); const float sz = ImGui::GetFontSize(); - const ImVec2 pos(window->Pos.x + window->WindowBorderSize + style.FramePadding.x - kTitleBarButtonPadding, - window->Pos.y + style.FramePadding.y - kTitleBarButtonPadding); + const ImVec2 pos = CollapseTitleBarButtonOrigin(window, hasCloseButton, sz); const ImRect bb = TitleBarButtonRect(pos, sz); const bool hovered = IsTitleBarButtonHovered(window, bb); const bool held = hovered && ImGui::IsMouseDown(ImGuiMouseButton_Left); @@ -742,7 +757,7 @@ namespace Util return; if (hasCollapseButton) - DrawRoundedCollapseHighlight(window); + DrawRoundedCollapseHighlight(window, hasCloseButton); if (hasCloseButton) DrawRoundedCloseHighlight(window); } From 665e5a55760524ada9fdd38557cc8aa7e92ab0d3 Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Tue, 2 Jun 2026 03:42:02 -0700 Subject: [PATCH 3/5] Sync English translations --- package/SKSE/Plugins/CommunityShaders/Translations/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package/SKSE/Plugins/CommunityShaders/Translations/en.json b/package/SKSE/Plugins/CommunityShaders/Translations/en.json index b8dbab9f52..665ff94814 100644 --- a/package/SKSE/Plugins/CommunityShaders/Translations/en.json +++ b/package/SKSE/Plugins/CommunityShaders/Translations/en.json @@ -1729,6 +1729,7 @@ "menu.features.scene_specific_settings": "Scene Specific Settings", "menu.features.select_feature_left": "Please select a feature from the left.", "menu.features.select_item_left": "Please select an item on the left.", + "menu.features.setting_change_warning_title": "Setting Change Warning", "menu.features.settings_adjusted_warning": "Some of your settings have been automatically adjusted due to feature incompatibilities.", "menu.features.settings_hidden_disabled": "Feature settings are hidden because this feature is disabled at boot.", "menu.features.unloaded_features": "Unloaded Features", From 332ac852694aab8e26ce41e201866af96d198ee4 Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Tue, 2 Jun 2026 04:26:47 -0700 Subject: [PATCH 4/5] theme aware --- src/Menu/MenuHeaderRenderer.cpp | 13 ++++--------- src/Utils/UI.cpp | 9 ++++++++- src/Utils/UI.h | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Menu/MenuHeaderRenderer.cpp b/src/Menu/MenuHeaderRenderer.cpp index 5b48a79131..90ce3e1219 100644 --- a/src/Menu/MenuHeaderRenderer.cpp +++ b/src/Menu/MenuHeaderRenderer.cpp @@ -313,13 +313,11 @@ void MenuHeaderRenderer::RenderDockedIcons(const std::vector& action ImVec2 iconMax(iconX + iconSize - paddingReduction, iconY + iconSize - paddingReduction); // Use the full area for mouse interaction (including padding) - ImVec2 interactionMin(iconX, iconY); - ImVec2 interactionMax(iconX + iconSize, iconY + iconSize); + ImRect interactionRect({ iconX, iconY }, { iconX + iconSize, iconY + iconSize }); // Check mouse interaction against full area - ImVec2 mousePos = ImGui::GetMousePos(); - bool isHovered = mousePos.x >= interactionMin.x && mousePos.x <= interactionMax.x && - mousePos.y >= interactionMin.y && mousePos.y <= interactionMax.y; + const bool isHovered = ImGui::IsMouseHoveringRect(interactionRect.Min, interactionRect.Max, false); + Util::DrawRoundedButtonHighlight(interactionRect.Min, interactionRect.Max, isHovered, isHovered && ImGui::IsMouseDown(ImGuiMouseButton_Left), fgDrawList); // Only render if texture is valid if (it->texture) { @@ -341,9 +339,6 @@ void MenuHeaderRenderer::RenderDockedIcons(const std::vector& action // Handle interaction if (isHovered) { - // Draw subtle background for hovered icon using interaction area - fgDrawList->AddRectFilled(interactionMin, interactionMax, IM_COL32(255, 255, 255, 40)); - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { it->callback(); } @@ -446,4 +441,4 @@ void MenuHeaderRenderer::RenderWatermarkLogo(const Menu::UIIcons& uiIcons) } drawList->AddImage(uiIcons.logo.texture, logoMin, logoMax, ImVec2(0, 0), ImVec2(1, 1), watermarkColor); -} \ No newline at end of file +} diff --git a/src/Utils/UI.cpp b/src/Utils/UI.cpp index ad0d91b8c3..f0d5515ff8 100644 --- a/src/Utils/UI.cpp +++ b/src/Utils/UI.cpp @@ -626,9 +626,16 @@ namespace Util return ImMin(max.x - min.x, max.y - min.y) * 0.5f; } + static float GetThemedButtonHighlightRounding(const ImVec2& min, const ImVec2& max) + { + const float frameRounding = ImGui::GetStyle().FrameRounding; + IM_ASSERT(frameRounding >= 0.0f); + return ImMin(ImMax(frameRounding, 0.0f), GetPillRounding(min, max)); + } + bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, ImDrawList* drawList) { - return DrawRoundedButtonHighlight(min, max, hovered, active, GetPillRounding(min, max), drawList); + return DrawRoundedButtonHighlight(min, max, hovered, active, GetThemedButtonHighlightRounding(min, max), drawList); } bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, float rounding, ImDrawList* drawList) diff --git a/src/Utils/UI.h b/src/Utils/UI.h index 69a3ff940b..376bd962ac 100644 --- a/src/Utils/UI.h +++ b/src/Utils/UI.h @@ -319,7 +319,7 @@ namespace Util /** Returns theme text color if monochrome icons enabled, otherwise white. */ ImVec4 GetIconTint(); - /// Draws a pill-rounded hover/active fill over a button rect. + /// Draws a theme-rounded hover/active fill over a button rect. bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, ImDrawList* drawList = nullptr); bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, float rounding, ImDrawList* drawList); From bc54703072a7edfb42912091c5e8f8ca89d4a710 Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Tue, 2 Jun 2026 04:49:25 -0700 Subject: [PATCH 5/5] AI comment --- src/Menu/MenuHeaderRenderer.cpp | 2 +- src/Utils/UI.cpp | 11 ++++++++--- src/Utils/UI.h | 2 ++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Menu/MenuHeaderRenderer.cpp b/src/Menu/MenuHeaderRenderer.cpp index 90ce3e1219..c7fd4e32e7 100644 --- a/src/Menu/MenuHeaderRenderer.cpp +++ b/src/Menu/MenuHeaderRenderer.cpp @@ -317,7 +317,7 @@ void MenuHeaderRenderer::RenderDockedIcons(const std::vector& action // Check mouse interaction against full area const bool isHovered = ImGui::IsMouseHoveringRect(interactionRect.Min, interactionRect.Max, false); - Util::DrawRoundedButtonHighlight(interactionRect.Min, interactionRect.Max, isHovered, isHovered && ImGui::IsMouseDown(ImGuiMouseButton_Left), fgDrawList); + Util::DrawRoundedButtonHighlight(interactionRect, isHovered, isHovered && ImGui::IsMouseDown(ImGuiMouseButton_Left), fgDrawList); // Only render if texture is valid if (it->texture) { diff --git a/src/Utils/UI.cpp b/src/Utils/UI.cpp index f0d5515ff8..b60471bd8e 100644 --- a/src/Utils/UI.cpp +++ b/src/Utils/UI.cpp @@ -638,6 +638,11 @@ namespace Util return DrawRoundedButtonHighlight(min, max, hovered, active, GetThemedButtonHighlightRounding(min, max), drawList); } + bool DrawRoundedButtonHighlight(const ImRect& rect, bool hovered, bool active, ImDrawList* drawList) + { + return DrawRoundedButtonHighlight(rect.Min, rect.Max, hovered, active, drawList); + } + bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, float rounding, ImDrawList* drawList) { if (!hovered && !active) @@ -654,7 +659,7 @@ namespace Util bool DrawCurrentItemRoundedButtonHighlight(ImDrawList* drawList) { - return DrawRoundedButtonHighlight(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), ImGui::IsItemHovered(), ImGui::IsItemActive(), drawList); + return DrawRoundedButtonHighlight(ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()), ImGui::IsItemHovered(), ImGui::IsItemActive(), drawList); } // Shared constants for title-bar button overlays @@ -719,7 +724,7 @@ namespace Util const bool held = hovered && ImGui::IsMouseDown(ImGuiMouseButton_Left); window->DrawList->PushClipRect(window->Rect().Min, window->Rect().Max); - const bool highlighted = DrawRoundedButtonHighlight(bb.Min, bb.Max, hovered, held, window->DrawList); + const bool highlighted = DrawRoundedButtonHighlight(bb, hovered, held, window->DrawList); // Cross lines match ImGui's internal RenderCloseButton geometry. if (highlighted) { @@ -749,7 +754,7 @@ namespace Util const bool held = hovered && ImGui::IsMouseDown(ImGuiMouseButton_Left); window->DrawList->PushClipRect(window->Rect().Min, window->Rect().Max); - const bool highlighted = DrawRoundedButtonHighlight(bb.Min, bb.Max, hovered, held, window->DrawList); + const bool highlighted = DrawRoundedButtonHighlight(bb, hovered, held, window->DrawList); if (highlighted) { const ImVec2 arrowPos(pos.x + kTitleBarButtonPadding, pos.y + kTitleBarButtonPadding); diff --git a/src/Utils/UI.h b/src/Utils/UI.h index 376bd962ac..e81bad9c23 100644 --- a/src/Utils/UI.h +++ b/src/Utils/UI.h @@ -15,6 +15,7 @@ // Forward declarations struct ID3D11Device; struct ID3D11ShaderResourceView; +struct ImRect; struct ImVec2; class Menu; class Feature; @@ -320,6 +321,7 @@ namespace Util ImVec4 GetIconTint(); /// Draws a theme-rounded hover/active fill over a button rect. + bool DrawRoundedButtonHighlight(const ImRect& rect, bool hovered, bool active, ImDrawList* drawList = nullptr); bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, ImDrawList* drawList = nullptr); bool DrawRoundedButtonHighlight(const ImVec2& min, const ImVec2& max, bool hovered, bool active, float rounding, ImDrawList* drawList);