mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 21:21:06 +01:00 
			
		
		
		
	ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#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).
This commit is contained in:
		| @@ -34,6 +34,9 @@ HOW TO UPDATE? | |||||||
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------- | ||||||
|  |  | ||||||
| Other Changes: | Other Changes: | ||||||
|  | - ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#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). | ||||||
| - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, | - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, | ||||||
|   would generally make the debug layer complain (Added in 1.72). |   would generally make the debug layer complain (Added in 1.72). | ||||||
| - Backends: Vulkan: Added support for specifying multisample count. | - Backends: Vulkan: Added support for specifying multisample count. | ||||||
|   | |||||||
| @@ -4439,7 +4439,7 @@ bool ImGui::IsMouseDoubleClicked(int button) | |||||||
|     return g.IO.MouseDoubleClicked[button]; |     return g.IO.MouseDoubleClicked[button]; | ||||||
| } | } | ||||||
|  |  | ||||||
| // [Internal] This doesn't test if the button is presed | // [Internal] This doesn't test if the button is pressed | ||||||
| bool ImGui::IsMouseDragPastThreshold(int button, float lock_threshold) | bool ImGui::IsMouseDragPastThreshold(int button, float lock_threshold) | ||||||
| { | { | ||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|   | |||||||
| @@ -4402,17 +4402,19 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU | |||||||
| } | } | ||||||
|  |  | ||||||
| // Helper for ColorPicker4() | // Helper for ColorPicker4() | ||||||
| static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w) | static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha) | ||||||
| { | { | ||||||
|     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); |     ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha); | ||||||
|     ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x,             pos.y), half_sz,                              ImGuiDir_Right, IM_COL32_WHITE); |     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)); | ||||||
|     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); |     ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x,             pos.y), half_sz,                              ImGuiDir_Right, IM_COL32(255,255,255,alpha8)); | ||||||
|     ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x,     pos.y), half_sz,                              ImGuiDir_Left,  IM_COL32_WHITE); |     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)); | ||||||
|  |     ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x,     pos.y), half_sz,                              ImGuiDir_Left,  IM_COL32(255,255,255,alpha8)); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. | // Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. | ||||||
| // (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.) | // (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.) | ||||||
| // 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..) | // 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..) | ||||||
|  | // 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) | ||||||
| bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) | bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) | ||||||
| { | { | ||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
| @@ -4662,17 +4664,22 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z); |     const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha); | ||||||
|     ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f); |     const ImU32 col_black = IM_COL32(0,0,0,style_alpha8); | ||||||
|     ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, 1.0f)); |     const ImU32 col_white = IM_COL32(255,255,255,style_alpha8); | ||||||
|  |     const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8); | ||||||
|  |     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) }; | ||||||
|  |  | ||||||
|  |     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); | ||||||
|  |     ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f); | ||||||
|  |     ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha)); // Important: this is still including the main rendering/style alpha!! | ||||||
|  |  | ||||||
|     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) }; |  | ||||||
|     ImVec2 sv_cursor_pos; |     ImVec2 sv_cursor_pos; | ||||||
|  |  | ||||||
|     if (flags & ImGuiColorEditFlags_PickerHueWheel) |     if (flags & ImGuiColorEditFlags_PickerHueWheel) | ||||||
|     { |     { | ||||||
|         // Render Hue Wheel |         // Render Hue Wheel | ||||||
|         const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out). |         const float aeps = 0.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out). | ||||||
|         const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12); |         const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12); | ||||||
|         for (int n = 0; n < 6; n++) |         for (int n = 0; n < 6; n++) | ||||||
|         { |         { | ||||||
| @@ -4680,13 +4687,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | |||||||
|             const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps; |             const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps; | ||||||
|             const int vert_start_idx = draw_list->VtxBuffer.Size; |             const int vert_start_idx = draw_list->VtxBuffer.Size; | ||||||
|             draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc); |             draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc); | ||||||
|             draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness); |             draw_list->PathStroke(col_white, false, wheel_thickness); | ||||||
|             const int vert_end_idx = draw_list->VtxBuffer.Size; |             const int vert_end_idx = draw_list->VtxBuffer.Size; | ||||||
|  |  | ||||||
|             // Paint colors over existing vertices |             // Paint colors over existing vertices | ||||||
|             ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner); |             ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner); | ||||||
|             ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner); |             ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner); | ||||||
|             ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]); |             ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n+1]); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Render Cursor + preview on Hue Wheel |         // Render Cursor + preview on Hue Wheel | ||||||
| @@ -4696,8 +4703,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | |||||||
|         float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f; |         float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f; | ||||||
|         int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32); |         int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32); | ||||||
|         draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); |         draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); | ||||||
|         draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, IM_COL32(128,128,128,255), hue_cursor_segments); |         draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, col_midgrey, hue_cursor_segments); | ||||||
|         draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments); |         draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments); | ||||||
|  |  | ||||||
|         // Render SV triangle (rotated according to hue) |         // Render SV triangle (rotated according to hue) | ||||||
|         ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle); |         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 | |||||||
|         draw_list->PrimReserve(6, 6); |         draw_list->PrimReserve(6, 6); | ||||||
|         draw_list->PrimVtx(tra, uv_white, hue_color32); |         draw_list->PrimVtx(tra, uv_white, hue_color32); | ||||||
|         draw_list->PrimVtx(trb, uv_white, hue_color32); |         draw_list->PrimVtx(trb, uv_white, hue_color32); | ||||||
|         draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE); |         draw_list->PrimVtx(trc, uv_white, col_white); | ||||||
|         draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS); |         draw_list->PrimVtx(tra, uv_white, 0); | ||||||
|         draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK); |         draw_list->PrimVtx(trb, uv_white, col_white); | ||||||
|         draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS); |         draw_list->PrimVtx(trc, uv_white, 0); | ||||||
|         draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f); |         draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f); | ||||||
|         sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); |         sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); | ||||||
|     } |     } | ||||||
|     else if (flags & ImGuiColorEditFlags_PickerHueBar) |     else if (flags & ImGuiColorEditFlags_PickerHueBar) | ||||||
|     { |     { | ||||||
|         // Render SV Square |         // Render SV Square | ||||||
|         draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE); |         draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white); | ||||||
|         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); |         draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black); | ||||||
|         RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f); |         RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f); | ||||||
|         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 |         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 | ||||||
|         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); |         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); | ||||||
|  |  | ||||||
|         // Render Hue Bar |         // Render Hue Bar | ||||||
|         for (int i = 0; i < 6; ++i) |         for (int i = 0; i < 6; ++i) | ||||||
|             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]); |             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]); | ||||||
|         float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f); |         float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f); | ||||||
|         RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); |         RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); | ||||||
|         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); |         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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) |     // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) | ||||||
|     float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; |     float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; | ||||||
|     draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12); |     draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12); | ||||||
|     draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, IM_COL32(128,128,128,255), 12); |     draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, col_midgrey, 12); | ||||||
|     draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12); |     draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12); | ||||||
|  |  | ||||||
|     // Render alpha bar |     // Render alpha bar | ||||||
|     if (alpha_bar) |     if (alpha_bar) | ||||||
|     { |     { | ||||||
|         float alpha = ImSaturate(col[3]); |         float alpha = ImSaturate(col[3]); | ||||||
|         ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); |         ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); | ||||||
|         RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); |         RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); | ||||||
|         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); |         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); | ||||||
|         float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f); |         float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f); | ||||||
|         RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); |         RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); | ||||||
|         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); |         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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     EndGroup(); |     EndGroup(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user