From 334f484892a1fa881d2a927c2aff222c15458b8f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 7 Sep 2026 19:43:18 +0200 Subject: [PATCH] ColorEdit4, ColorPicker4: added support for ImGuiItemFlags_MixedValue. (#5518, #5677, #6865) --- docs/CHANGELOG.txt | 5 +++-- imgui_demo.cpp | 6 ++++-- imgui_widgets.cpp | 22 ++++++++++++++++++---- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5008da1d3..a460b728d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -74,8 +74,9 @@ Other Changes: hasn't been owned by another items. This is more correct and also necessary to avoid Drags/Sliders cancelling also triggering a cancel menu. (#8564, #9534) - Misc: - - Added `ImGuiItemFlags_MixedValue` flag for representing mixed/indeterminate values - in Checkbox(), RadioButton(), DragXXX(), SliderXXX(), InputXXX(), Combo() functions. + - Added `ImGuiItemFlags_MixedValue` flag for representing mixed/indeterminate values. + Supported by: Checkbox(), RadioButton(), DragXXX(), SliderXXX(), InputXXX(), ColorXXX() + and Combo() functions. The scoped flag is designed for usage by advanced property editors. (#5518, #5677, #6865) - Fixed `GetBackgroundDrawList()`/`GetForegroundDrawList()` not being properly reset every frame when cumulated session time is very large (e.g. a few days). [@lailoken] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3c76b8d84..d75566170 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2085,9 +2085,9 @@ static void DemoWindowWidgetsMixedValues() ImGui::InputFloat("item 1", &items[1]); ImGui::InputFloat("item 2", &items[2]); - // Demonstrate Checkbox() - // (this is automatically used by e.g. CheckboxFlags()) + // Demonstrate Checkbox(), RadioButton(), Combo(), ColorEdit4() ImGui::SeparatorText("Others Widgets"); + ImGui::Text("(note: edits are not applied in this demo)"); // <-- Would need more state tracking. bool b_on = true, b_off = false; ImGui::Checkbox("Checkbox On", &b_on); ImGui::Checkbox("Checkbox Off", &b_off); @@ -2098,6 +2098,8 @@ static void DemoWindowWidgetsMixedValues() ImGui::RadioButton("RadioButton Mixed##2", true); // Showing 2 radio buttons makes the example more clear int combo_idx = 0; ImGui::Combo("Combo", &combo_idx, "One\0Two\0Three\0"); + ImVec4 color(0.5f, 0.5f, 0.5f, 0.5f); + ImGui::ColorEdit4("ColorEdit4", &color.x); ImGui::PopItemFlag(); ImGui::TreePop(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 591750e5d..706849773 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6058,7 +6058,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar; ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf; SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes? + PushItemFlag(ImGuiItemFlags_MixedValue, false); value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x); + PopItemFlag(); } EndPopup(); } @@ -6333,6 +6335,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl if (!(flags & ImGuiColorEditFlags_NoSidePreview)) { PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); + PushItemFlag(ImGuiItemFlags_MixedValue, false); ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); if ((flags & ImGuiColorEditFlags_NoLabel)) Text("Current"); @@ -6350,6 +6353,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl } } PopItemFlag(); + PopItemFlag(); EndGroup(); } @@ -6568,14 +6572,20 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl if (flags & ImGuiColorEditFlags_InputHSV) ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z); - ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f); - float grid_step = ImMin(size.x, size.y) / 2.99f; - float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f); + const ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f); + const float grid_step = ImMin(size.x, size.y) / 2.99f; + const float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f); + const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0; const float backup_alpha = g.Style.Alpha; if (g.DisabledStackSize > 0) g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches. - if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) + if (is_mixed) + { + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); + RenderTextClipped(ImVec2(bb.Min.x, bb.Min.y + g.Style.FramePadding.y), bb.Max, g.MixedValueLabel, NULL, NULL, ImVec2(0.5f, 0.0f)); + } + else if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) { float mid_x = IM_ROUND((bb.Min.x + bb.Max.x) * 0.5f); if ((flags & ImGuiColorEditFlags_AlphaNoBg) == 0) @@ -6612,7 +6622,9 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once); else SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once); + PushItemFlag(ImGuiItemFlags_MixedValue, false); ColorButton(desc_id, col, flags); + PopItemFlag(); SameLine(); TextEx("Color"); EndDragDropSource(); @@ -6656,7 +6668,9 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); ImGuiColorEditFlags flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_AlphaMask_; + PushItemFlag(ImGuiItemFlags_MixedValue, false); ColorButton("##preview", cf, (flags & flags_to_forward) | ImGuiColorEditFlags_NoTooltip, sz); + PopItemFlag(); SameLine(); if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_)) {