Skip to content

Commit 9fce278

Browse files
committed
ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (ocornut#2711)
Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0).
1 parent 88bf056 commit 9fce278

File tree

3 files changed

+42
-32
lines changed

3 files changed

+42
-32
lines changed

docs/CHANGELOG.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ HOW TO UPDATE?
3434
-----------------------------------------------------------------------
3535

3636
Other Changes:
37+
- ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711)
38+
Note that some elements won't accurately fade down with the same intensity, and the color wheel
39+
when enabled will have small overlap glitches with (style.Alpha < 1.0).
3740
- Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count,
3841
would generally make the debug layer complain (Added in 1.72).
39-
- Backends: Vulkan: Added support for specifying multisample count.
40-
Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values
42+
- Backends: Vulkan: Added support for specifying multisample count.
43+
Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values
4144
to use, default is non-multisampled as before. (#2705, #2706) [@vilya]
4245

4346

imgui.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4439,7 +4439,7 @@ bool ImGui::IsMouseDoubleClicked(int button)
44394439
return g.IO.MouseDoubleClicked[button];
44404440
}
44414441

4442-
// [Internal] This doesn't test if the button is presed
4442+
// [Internal] This doesn't test if the button is pressed
44434443
bool ImGui::IsMouseDragPastThreshold(int button, float lock_threshold)
44444444
{
44454445
ImGuiContext& g = *GImGui;

imgui_widgets.cpp

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4402,17 +4402,19 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU
44024402
}
44034403

44044404
// Helper for ColorPicker4()
4405-
static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w)
4405+
static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha)
44064406
{
4407-
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32_BLACK);
4408-
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32_WHITE);
4409-
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32_BLACK);
4410-
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE);
4407+
ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha);
4408+
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32(0,0,0,alpha8));
4409+
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32(255,255,255,alpha8));
4410+
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32(0,0,0,alpha8));
4411+
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32(255,255,255,alpha8));
44114412
}
44124413

44134414
// Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
44144415
// (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.)
44154416
// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..)
4417+
// FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0)
44164418
bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
44174419
{
44184420
ImGuiContext& g = *GImGui;
@@ -4662,31 +4664,36 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
46624664
}
46634665
}
46644666

4665-
ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
4667+
const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha);
4668+
const ImU32 col_black = IM_COL32(0,0,0,style_alpha8);
4669+
const ImU32 col_white = IM_COL32(255,255,255,style_alpha8);
4670+
const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8);
4671+
const ImU32 col_hues[6 + 1] = { IM_COL32(255,0,0,style_alpha8), IM_COL32(255,255,0,style_alpha8), IM_COL32(0,255,0,style_alpha8), IM_COL32(0,255,255,style_alpha8), IM_COL32(0,0,255,style_alpha8), IM_COL32(255,0,255,style_alpha8), IM_COL32(255,0,0,style_alpha8) };
4672+
4673+
ImVec4 hue_color_f(1, 1, 1, style.Alpha); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
46664674
ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
4667-
ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, 1.0f));
4675+
ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha)); // Important: this is still including the main rendering/style alpha!!
46684676

4669-
const ImU32 hue_colors[6+1] = { IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255), IM_COL32(0,255,255,255), IM_COL32(0,0,255,255), IM_COL32(255,0,255,255), IM_COL32(255,0,0,255) };
46704677
ImVec2 sv_cursor_pos;
46714678

46724679
if (flags & ImGuiColorEditFlags_PickerHueWheel)
46734680
{
46744681
// Render Hue Wheel
4675-
const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
4682+
const float aeps = 0.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
46764683
const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);
46774684
for (int n = 0; n < 6; n++)
46784685
{
46794686
const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps;
46804687
const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
46814688
const int vert_start_idx = draw_list->VtxBuffer.Size;
46824689
draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
4683-
draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness);
4690+
draw_list->PathStroke(col_white, false, wheel_thickness);
46844691
const int vert_end_idx = draw_list->VtxBuffer.Size;
46854692

46864693
// Paint colors over existing vertices
46874694
ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner);
46884695
ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner);
4689-
ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]);
4696+
ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n+1]);
46904697
}
46914698

46924699
// Render Cursor + preview on Hue Wheel
@@ -4696,8 +4703,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
46964703
float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
46974704
int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
46984705
draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
4699-
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, IM_COL32(128,128,128,255), hue_cursor_segments);
4700-
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments);
4706+
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, col_midgrey, hue_cursor_segments);
4707+
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
47014708

47024709
// Render SV triangle (rotated according to hue)
47034710
ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
@@ -4707,46 +4714,46 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
47074714
draw_list->PrimReserve(6, 6);
47084715
draw_list->PrimVtx(tra, uv_white, hue_color32);
47094716
draw_list->PrimVtx(trb, uv_white, hue_color32);
4710-
draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE);
4711-
draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS);
4712-
draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK);
4713-
draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS);
4714-
draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f);
4717+
draw_list->PrimVtx(trc, uv_white, col_white);
4718+
draw_list->PrimVtx(tra, uv_white, 0);
4719+
draw_list->PrimVtx(trb, uv_white, col_white);
4720+
draw_list->PrimVtx(trc, uv_white, 0);
4721+
draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f);
47154722
sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
47164723
}
47174724
else if (flags & ImGuiColorEditFlags_PickerHueBar)
47184725
{
47194726
// Render SV Square
4720-
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE);
4721-
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK);
4722-
RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), 0.0f);
4727+
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white);
4728+
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black);
4729+
RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f);
47234730
sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much
47244731
sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);
47254732

47264733
// Render Hue Bar
47274734
for (int i = 0; i < 6; ++i)
4728-
draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]);
4735+
draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]);
47294736
float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f);
47304737
RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
4731-
RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);
4738+
RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
47324739
}
47334740

47344741
// Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
47354742
float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
4736-
draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12);
4737-
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, IM_COL32(128,128,128,255), 12);
4738-
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12);
4743+
draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12);
4744+
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, col_midgrey, 12);
4745+
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12);
47394746

47404747
// Render alpha bar
47414748
if (alpha_bar)
47424749
{
47434750
float alpha = ImSaturate(col[3]);
47444751
ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
4745-
RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
4746-
draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, col32_no_alpha, col32_no_alpha, col32_no_alpha & ~IM_COL32_A_MASK, col32_no_alpha & ~IM_COL32_A_MASK);
4752+
RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
4753+
draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK);
47474754
float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f);
47484755
RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
4749-
RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);
4756+
RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
47504757
}
47514758

47524759
EndGroup();

0 commit comments

Comments
 (0)