From accb0261b8fd4c1bd32f58b3ecc7a0b732d6006e Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Sat, 31 Aug 2019 18:44:20 +0300 Subject: [PATCH] ColorPicker / ColorEdit: restore Hue when zeroing Saturation. (#2722, #2770) Issue is fixed by storing last active color picker color and last hue value when active color picker takes rgb as input. Then if current color picker color matches last active color - hue value will be restored. IDs are not used because ColorEdit4() and ColorWidget4() may call each other in hard-to-predict ways and they both push their own IDs on to the stack. We need hue restoration to happen in entire stack of these widgets if topmost widget used hue restoration. Since these widgets operate on exact same color value - color was chosen as a factor deciding which widgets should restore hue. --- imgui_internal.h | 2 ++ imgui_widgets.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/imgui_internal.h b/imgui_internal.h index 47da60ab..8fc03a03 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1012,6 +1012,8 @@ struct ImGuiContext ImFont InputTextPasswordFont; ImGuiID TempInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets + float ColorEditLastHue; + float ColorEditLastActiveColor[3]; ImVec4 ColorPickerRef; bool DragCurrentAccumDirty; float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3adfc892..7466acff 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4200,7 +4200,12 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if ((flags & ImGuiColorEditFlags_InputHSV) && (flags & ImGuiColorEditFlags_DisplayRGB)) ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV)) + { ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); + // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. + if (f[1] == 0 && memcmp(g.ColorEditLastActiveColor, col, sizeof(float) * 3) == 0) + f[0] = g.ColorEditLastHue; + } int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; bool value_changed = false; @@ -4327,7 +4332,11 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag for (int n = 0; n < 4; n++) f[n] = i[n] / 255.0f; if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB)) + { + g.ColorEditLastHue = f[0]; ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); + memcpy(g.ColorEditLastActiveColor, f, sizeof(float) * 3); + } if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV)) ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); @@ -4504,7 +4513,12 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl float H = col[0], S = col[1], V = col[2]; float R = col[0], G = col[1], B = col[2]; if (flags & ImGuiColorEditFlags_InputRGB) + { ColorConvertRGBtoHSV(R, G, B, H, S, V); + // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. + if (S == 0 && memcmp(g.ColorEditLastActiveColor, col, sizeof(float) * 3) == 0) + H = g.ColorEditLastHue; + } else if (flags & ImGuiColorEditFlags_InputHSV) ColorConvertHSVtoRGB(H, S, V, R, G, B); @@ -4628,6 +4642,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl if (flags & ImGuiColorEditFlags_InputRGB) { ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); + g.ColorEditLastHue = H; + memcpy(g.ColorEditLastActiveColor, col, sizeof(float) * 3); } else if (flags & ImGuiColorEditFlags_InputHSV) { @@ -4680,7 +4696,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl R = col[0]; G = col[1]; B = col[2]; + float preserve_hue = H; ColorConvertRGBtoHSV(R, G, B, H, S, V); + H = preserve_hue; // Avoids picker losing hue value for 1 frame glitch. } else if (flags & ImGuiColorEditFlags_InputHSV) {