Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = GetCurrentWindow();
- ImDrawList* draw_list = window->DrawList;
- ImGuiStyle& style = g.Style;
- ImGuiIO& io = g.IO;
- PushID(label);
- BeginGroup();
- if (!(flags & ImGuiColorEditFlags_NoSidePreview))
- flags |= ImGuiColorEditFlags_NoSmallPreview;
- // Context menu: display and store options.
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- ColorPickerOptionsPopup(col, flags);
- // Read stored options
- if (!(flags & ImGuiColorEditFlags__PickerMask))
- flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__PickerMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__PickerMask;
- IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check that only 1 is selected
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
- // Setup
- bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha);
- ImVec2 picker_pos = window->DC.CursorPos;
- float square_sz = GetFrameHeight();
- float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars
- float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
- float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
- float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
- float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f);
- float wheel_thickness = sv_picker_size * 0.08f;
- float wheel_r_outer = sv_picker_size * 0.50f;
- float wheel_r_inner = wheel_r_outer - wheel_thickness;
- ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size*0.5f);
- // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.
- float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
- ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point.
- ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point.
- ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point.
- float H,S,V;
- ColorConvertRGBtoHSV(col[0], col[1], col[2], H, S, V);
- bool value_changed = false, value_changed_h = false, value_changed_sv = false;
- if (flags & ImGuiColorEditFlags_PickerHueWheel)
- {
- // Hue wheel + SV triangle logic
- InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
- if (IsItemActive())
- {
- ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
- ImVec2 current_off = g.IO.MousePos - wheel_center;
- float initial_dist2 = ImLengthSqr(initial_off);
- if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))
- {
- // Interactive with Hue wheel
- H = atan2f(current_off.y, current_off.x) / IM_PI*0.5f;
- if (H < 0.0f)
- H += 1.0f;
- value_changed = value_changed_h = true;
- }
- float cos_hue_angle = cosf(-H * 2.0f * IM_PI);
- float sin_hue_angle = sinf(-H * 2.0f * IM_PI);
- if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))
- {
- // Interacting with SV triangle
- ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle);
- if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated))
- current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
- float uu, vv, ww;
- ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww);
- V = ImClamp(1.0f - vv, 0.0001f, 1.0f);
- S = ImClamp(uu / V, 0.0001f, 1.0f);
- value_changed = value_changed_sv = true;
- }
- }
- if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))
- OpenPopup("context");
- }
- else if (flags & ImGuiColorEditFlags_PickerHueBar)
- {
- // SV rectangle logic
- InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
- if (IsItemActive())
- {
- S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1));
- V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
- value_changed = value_changed_sv = true;
- }
- if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))
- OpenPopup("context");
- // Hue bar logic
- SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
- InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
- if (IsItemActive())
- {
- H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
- value_changed = value_changed_h = true;
- }
- }
- // Alpha bar logic
- if (alpha_bar)
- {
- SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));
- InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
- if (IsItemActive())
- {
- col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
- value_changed = true;
- }
- }
- if (!(flags & ImGuiColorEditFlags_NoSidePreview))
- {
- SameLine(0, style.ItemInnerSpacing.x);
- BeginGroup();
- }
- if (!(flags & ImGuiColorEditFlags_NoLabel))
- {
- const char* label_display_end = FindRenderedTextEnd(label);
- if (label != label_display_end)
- {
- if ((flags & ImGuiColorEditFlags_NoSidePreview))
- SameLine(0, style.ItemInnerSpacing.x);
- TextUnformatted(label, label_display_end);
- }
- }
- if (!(flags & ImGuiColorEditFlags_NoSidePreview))
- {
- ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
- if ((flags & ImGuiColorEditFlags_NoLabel))
- Text("Current");
- ColorButton("##current", col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2));
- if (ref_col != NULL)
- {
- Text("Original");
- ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);
- if (ColorButton("##original", ref_col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2)))
- {
- memcpy(col, ref_col, ((flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4) * sizeof(float));
- value_changed = true;
- }
- }
- EndGroup();
- }
- // Convert back color to RGB
- if (value_changed_h || value_changed_sv)
- 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]);
- // R,G,B and H,S,V slider color editor
- if ((flags & ImGuiColorEditFlags_NoInputs) == 0)
- {
- PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);
- ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf;
- ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;
- if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags__DisplayMask) == 0)
- value_changed |= ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_RGB);
- if (flags & ImGuiColorEditFlags_DisplayHSV || (flags & ImGuiColorEditFlags__DisplayMask) == 0)
- value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_DisplayHSV);
- if (flags & ImGuiColorEditFlags_DisplayHex || (flags & ImGuiColorEditFlags__DisplayMask) == 0)
- value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_DisplayHex);
- PopItemWidth();
- }
- // Try to cancel hue wrap (after ColorEdit), if any
- if (value_changed)
- {
- float new_H, new_S, new_V;
- ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);
- if (new_H <= 0 && H > 0)
- {
- if (new_V <= 0 && V != new_V)
- ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);
- else if (new_S <= 0)
- ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);
- }
- }
- ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
- ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
- ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 1.0f));
- 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;
- if (flags & ImGuiColorEditFlags_PickerHueWheel)
- {
- // Render Hue Wheel
- const float aeps = 1.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);
- for (int n = 0; n < 6; n++)
- {
- const float a0 = (n) / 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;
- 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);
- const int vert_end_idx = draw_list->VtxBuffer.Size;
- // 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_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]);
- }
- // Render Cursor + preview on Hue Wheel
- float cos_hue_angle = cosf(H * 2.0f * IM_PI);
- float sin_hue_angle = sinf(H * 2.0f * IM_PI);
- ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f);
- 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);
- 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, IM_COL32_WHITE, hue_cursor_segments);
- // Render SV triangle (rotated according to hue)
- ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
- ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
- ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
- ImVec2 uv_white = GetFontTexUvWhitePixel();
- draw_list->PrimReserve(6, 6);
- draw_list->PrimVtx(tra, uv_white, hue_color32);
- draw_list->PrimVtx(trb, uv_white, hue_color32);
- draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE);
- draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS);
- draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK);
- draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS);
- draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f);
- sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
- }
- else if (flags & ImGuiColorEditFlags_PickerHueBar)
- {
- // 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), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK);
- 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.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
- 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]);
- 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);
- 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);
- }
- // 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;
- draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_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, IM_COL32_WHITE, 12);
- // Render alpha bar
- if (alpha_bar)
- {
- 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);
- RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,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);
- 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);
- 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);
- }
- EndGroup();
- PopID();
- return value_changed;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement