From ac6f9683b5419381bc7f4f02262464c095ee6ece Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jun 2026 11:41:24 +0200 Subject: [PATCH] Style: added MenuItemRounding, SelectableRounding, ImGuiStyleVar_MenuItemRounding, ImGuiStyleVar_SelectableRounding. (#7589, #9375, #9453) --- docs/CHANGELOG.txt | 4 ++++ imgui.cpp | 6 ++++++ imgui.h | 4 ++++ imgui_demo.cpp | 2 ++ imgui_widgets.cpp | 12 +++++++++--- 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ab70c87fd..736a2b67c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -93,6 +93,10 @@ Other Changes: - TreeNode: - Fixed nav cursor rendering with rounding even though tree nodes don't have it. (#7589) - Style: + - Added style.MenuItemRounding, ImGuiStyleVar_MenuItemRounding. (#7589, #9375, #9453) + - Added style.SelectableRounding, ImGuiStyleVar_SelectableRounding. (#7589, #9375, #9453) + The use of this is discouraged because it can easily create problems rendering e.g. + contiguous selection. - Scale the NavCursor border thickness when using large values with `ScallAllSizes()`. - DrawList: - Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091) diff --git a/imgui.cpp b/imgui.cpp index c9b23bc4f..f6fb61dcd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1533,6 +1533,8 @@ ImGuiStyle::ImGuiStyle() TreeLinesFlags = ImGuiTreeNodeFlags_DrawLinesNone; TreeLinesSize = 1.0f; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines. TreeLinesRounding = 0.0f; // Radius of lines connecting child nodes to the vertical line. + MenuItemRounding = 0.0f; // Radius of MenuItem, BeginMenu rounding. + SelectableRounding = 0.0f; // Radius of selectable rounding. MODIFYING THIS IS DISCOURAGED. CONTIGUOUS SELECTIONS WILL NOT LOOK RIGHT. (#7589) DragDropTargetRounding = 0.0f; // Radius of the drag and drop target frame. DragDropTargetBorderSize = 2.0f; // Thickness of the drag and drop target border. DragDropTargetPadding = 3.0f; // Size to expand the drag and drop target from actual target item size. @@ -1612,6 +1614,8 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor); TreeLinesSize = ImTrunc(TreeLinesSize * scale_factor); TreeLinesRounding = ImTrunc(TreeLinesRounding * scale_factor); + MenuItemRounding = ImTrunc(MenuItemRounding * scale_factor); + SelectableRounding = ImTrunc(SelectableRounding * scale_factor); DragDropTargetRounding = ImTrunc(DragDropTargetRounding * scale_factor); DragDropTargetBorderSize = ImTrunc(DragDropTargetBorderSize * scale_factor); DragDropTargetPadding = ImTrunc(DragDropTargetPadding * scale_factor); @@ -3685,6 +3689,8 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] = { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesSize)}, // ImGuiStyleVar_TreeLinesSize { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, MenuItemRounding)}, // ImGuiStyleVar_MenuItemRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableRounding)}, // ImGuiStyleVar_SelectableRounding { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, DragDropTargetRounding)}, // ImGuiStyleVar_DragDropTargetRounding { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign diff --git a/imgui.h b/imgui.h index 720e3c8cd..14c695b9f 100644 --- a/imgui.h +++ b/imgui.h @@ -1856,6 +1856,8 @@ enum ImGuiStyleVar_ ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding + ImGuiStyleVar_MenuItemRounding, // float MenuItemRounding + ImGuiStyleVar_SelectableRounding, // float SelectableRounding ImGuiStyleVar_DragDropTargetRounding, // float DragDropTargetRounding ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign @@ -2333,6 +2335,8 @@ struct ImGuiStyle ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes. float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines. float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line. + float MenuItemRounding; // Radius of MenuItem, BeginMenu rounding. + float SelectableRounding; // Radius of Selectable rounding. MODIFYING THIS IS DISCOURAGED. CONTIGUOUS SELECTIONS WILL NOT LOOK RIGHT. (#7589) float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding. float DragDropTargetBorderSize; // Thickness of the drag and drop target border. float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e0bbd9af6..1bd300666 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8556,6 +8556,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"); SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f"); SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f"); + SliderFloat("MenuItemRounding", &style.MenuItemRounding, 0.0f, 12.0f, "%.0f"); + // NB: SelectableRounding is intentionally NOT made visible here. We don't want to encourage people using that. SeparatorText("Scrollbar"); SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 045e8096d..cb9e97441 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7498,14 +7498,14 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl { // Between 1.91.0 and 1.91.4 we made selected Selectable use an arbitrary lerp between _Header and _HeaderHovered. Removed that now. (#8106) ImU32 col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(bb.Min, bb.Max, col, false, 0.0f); + RenderFrame(bb.Min, bb.Max, col, false, style.SelectableRounding); } if (g.NavId == id) { ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact; if (is_multi_select) nav_render_cursor_flags |= ImGuiNavRenderCursorFlags_AlwaysDraw; // Always show the nav rectangle - RenderNavCursor(bb, id, nav_render_cursor_flags, 0.0f); + RenderNavCursor(bb, id, nav_render_cursor_flags, style.SelectableRounding); } } @@ -9350,7 +9350,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) return false; ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; + ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None); @@ -9395,6 +9395,8 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) bool pressed; + const float backup_rounding = style.SelectableRounding; + style.SelectableRounding = style.MenuItemRounding; const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoAutoClosePopups | (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnClick; ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) @@ -9430,6 +9432,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) RenderArrow(window->DrawList, ImVec2(text_pos.x + offsets->OffsetMark + extra_w + g.FontSize * 0.30f, text_pos.y), GetColorU32(ImGuiCol_Text), ImGuiDir_Right); popup_pos = ImVec2(pos.x, text_pos.y - style.WindowPadding.y); } + style.SelectableRounding = backup_rounding; if (!enabled) EndDisabled(); @@ -9616,6 +9619,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut BeginDisabled(); // We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another. + const float backup_rounding = style.SelectableRounding; + style.SelectableRounding = style.MenuItemRounding; const ImGuiSelectableFlags selectable_flags = (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnRelease | (ImGuiSelectableFlags)ImGuiSelectableFlags_SetNavIdOnHover; ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) @@ -9659,6 +9664,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut RenderCheckMark(window->DrawList, text_pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); } } + style.SelectableRounding = backup_rounding; // Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394) // Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.