SHARE
TWEET

Untitled

a guest Oct 18th, 2019 81 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
  2. {
  3.     ImGuiContext& g = *GImGui;
  4.     ImGuiWindow* window = GetCurrentWindow();
  5.     ImDrawList* draw_list = window->DrawList;
  6.  
  7.     ImGuiStyle& style = g.Style;
  8.     ImGuiIO& io = g.IO;
  9.  
  10.     PushID(label);
  11.     BeginGroup();
  12.  
  13.     if (!(flags & ImGuiColorEditFlags_NoSidePreview))
  14.         flags |= ImGuiColorEditFlags_NoSmallPreview;
  15.  
  16.     // Context menu: display and store options.
  17.     if (!(flags & ImGuiColorEditFlags_NoOptions))
  18.         ColorPickerOptionsPopup(col, flags);
  19.  
  20.     // Read stored options
  21.     if (!(flags & ImGuiColorEditFlags__PickerMask))
  22.         flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__PickerMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__PickerMask;
  23.     IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check that only 1 is selected
  24.     if (!(flags & ImGuiColorEditFlags_NoOptions))
  25.         flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
  26.  
  27.     // Setup
  28.     bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha);
  29.     ImVec2 picker_pos = window->DC.CursorPos;
  30.     float square_sz = GetFrameHeight();
  31.     float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars
  32.     float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
  33.     float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
  34.     float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
  35.     float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f);
  36.  
  37.     float wheel_thickness = sv_picker_size * 0.08f;
  38.     float wheel_r_outer = sv_picker_size * 0.50f;
  39.     float wheel_r_inner = wheel_r_outer - wheel_thickness;
  40.     ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size*0.5f);
  41.    
  42.     // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.
  43.     float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
  44.     ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point.
  45.     ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point.
  46.     ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point.
  47.  
  48.     float H,S,V;
  49.     ColorConvertRGBtoHSV(col[0], col[1], col[2], H, S, V);
  50.  
  51.     bool value_changed = false, value_changed_h = false, value_changed_sv = false;
  52.  
  53.     if (flags & ImGuiColorEditFlags_PickerHueWheel)
  54.     {
  55.         // Hue wheel + SV triangle logic
  56.         InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
  57.         if (IsItemActive())
  58.         {
  59.             ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
  60.             ImVec2 current_off = g.IO.MousePos - wheel_center;
  61.             float initial_dist2 = ImLengthSqr(initial_off);
  62.             if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))
  63.             {
  64.                 // Interactive with Hue wheel
  65.                 H = atan2f(current_off.y, current_off.x) / IM_PI*0.5f;
  66.                 if (H < 0.0f)
  67.                     H += 1.0f;
  68.                 value_changed = value_changed_h = true;
  69.             }
  70.             float cos_hue_angle = cosf(-H * 2.0f * IM_PI);
  71.             float sin_hue_angle = sinf(-H * 2.0f * IM_PI);
  72.             if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))
  73.             {
  74.                 // Interacting with SV triangle
  75.                 ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle);
  76.                 if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated))
  77.                     current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
  78.                 float uu, vv, ww;
  79.                 ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww);
  80.                 V = ImClamp(1.0f - vv, 0.0001f, 1.0f);
  81.                 S = ImClamp(uu / V, 0.0001f, 1.0f);
  82.                 value_changed = value_changed_sv = true;
  83.             }
  84.         }
  85.         if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))
  86.             OpenPopup("context");
  87.     }
  88.     else if (flags & ImGuiColorEditFlags_PickerHueBar)
  89.     {
  90.         // SV rectangle logic
  91.         InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
  92.         if (IsItemActive())
  93.         {
  94.             S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1));
  95.             V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
  96.             value_changed = value_changed_sv = true;
  97.         }
  98.         if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))
  99.             OpenPopup("context");
  100.  
  101.         // Hue bar logic
  102.         SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
  103.         InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
  104.         if (IsItemActive())
  105.         {
  106.             H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
  107.             value_changed = value_changed_h = true;
  108.         }
  109.     }
  110.  
  111.     // Alpha bar logic
  112.     if (alpha_bar)
  113.     {
  114.         SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));
  115.         InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
  116.         if (IsItemActive())
  117.         {
  118.             col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
  119.             value_changed = true;
  120.         }
  121.     }
  122.  
  123.     if (!(flags & ImGuiColorEditFlags_NoSidePreview))
  124.     {
  125.         SameLine(0, style.ItemInnerSpacing.x);
  126.         BeginGroup();
  127.     }
  128.  
  129.     if (!(flags & ImGuiColorEditFlags_NoLabel))
  130.     {
  131.         const char* label_display_end = FindRenderedTextEnd(label);
  132.         if (label != label_display_end)
  133.         {
  134.             if ((flags & ImGuiColorEditFlags_NoSidePreview))
  135.                 SameLine(0, style.ItemInnerSpacing.x);
  136.             TextUnformatted(label, label_display_end);
  137.         }
  138.     }
  139.  
  140.     if (!(flags & ImGuiColorEditFlags_NoSidePreview))
  141.     {
  142.         ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
  143.         if ((flags & ImGuiColorEditFlags_NoLabel))
  144.             Text("Current");
  145.         ColorButton("##current", col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2));
  146.         if (ref_col != NULL)
  147.         {
  148.             Text("Original");
  149.             ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);
  150.             if (ColorButton("##original", ref_col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2)))
  151.             {
  152.                 memcpy(col, ref_col, ((flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4) * sizeof(float));
  153.                 value_changed = true;
  154.             }
  155.         }
  156.         EndGroup();
  157.     }
  158.  
  159.     // Convert back color to RGB
  160.     if (value_changed_h || value_changed_sv)
  161.         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]);
  162.  
  163.     // R,G,B and H,S,V slider color editor
  164.     if ((flags & ImGuiColorEditFlags_NoInputs) == 0)
  165.     {
  166.         PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);
  167.         ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf;
  168.         ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;
  169.         if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags__DisplayMask) == 0)
  170.             value_changed |= ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_RGB);
  171.          if (flags & ImGuiColorEditFlags_DisplayHSV || (flags & ImGuiColorEditFlags__DisplayMask) == 0)
  172.             value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_DisplayHSV);
  173.         if (flags & ImGuiColorEditFlags_DisplayHex || (flags & ImGuiColorEditFlags__DisplayMask) == 0)
  174.             value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_DisplayHex);
  175.         PopItemWidth();
  176.     }
  177.  
  178.     // Try to cancel hue wrap (after ColorEdit), if any
  179.     if (value_changed)
  180.     {
  181.         float new_H, new_S, new_V;
  182.         ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);
  183.         if (new_H <= 0 && H > 0)
  184.         {
  185.             if (new_V <= 0 && V != new_V)
  186.                 ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);
  187.             else if (new_S <= 0)
  188.                 ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);
  189.         }
  190.     }
  191.  
  192.     ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
  193.     ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
  194.     ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 1.0f));
  195.  
  196.     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) };
  197.     ImVec2 sv_cursor_pos;
  198.    
  199.     if (flags & ImGuiColorEditFlags_PickerHueWheel)
  200.     {
  201.         // Render Hue Wheel
  202.         const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
  203.         const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);
  204.         for (int n = 0; n < 6; n++)
  205.         {
  206.             const float a0 = (n) / 6.0f * 2.0f * IM_PI - aeps;
  207.             const float a1 = (n + 1.0f) / 6.0f * 2.0f * IM_PI + aeps;
  208.             const int vert_start_idx = draw_list->VtxBuffer.Size;
  209.             draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer) * 0.5f, a0, a1, segment_per_arc);
  210.             draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness);
  211.             const int vert_end_idx = draw_list->VtxBuffer.Size;
  212.  
  213.             // Paint colors over existing vertices
  214.             ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner);
  215.             ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner);
  216.             ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n + 1]);
  217.         }
  218.  
  219.         // Render Cursor + preview on Hue Wheel
  220.         float cos_hue_angle = cosf(H * 2.0f * IM_PI);
  221.         float sin_hue_angle = sinf(H * 2.0f * IM_PI);
  222.         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);
  223.         float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
  224.         int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
  225.         draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
  226.         draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, IM_COL32(128,128,128,255), hue_cursor_segments);
  227.         draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments);
  228.  
  229.         // Render SV triangle (rotated according to hue)
  230.         ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
  231.         ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
  232.         ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
  233.         ImVec2 uv_white = GetFontTexUvWhitePixel();
  234.         draw_list->PrimReserve(6, 6);
  235.         draw_list->PrimVtx(tra, uv_white, hue_color32);
  236.         draw_list->PrimVtx(trb, uv_white, hue_color32);
  237.         draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE);
  238.         draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS);
  239.         draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK);
  240.         draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS);
  241.         draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f);
  242.         sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
  243.     }
  244.     else if (flags & ImGuiColorEditFlags_PickerHueBar)
  245.     {
  246.         // Render SV Square
  247.         draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE);
  248.         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);
  249.         RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), 0.0f);
  250.         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
  251.         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);
  252.  
  253.         // Render Hue Bar
  254.         for (int i = 0; i < 6; ++i)
  255.             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]);
  256.         float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f);
  257.         RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
  258.         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);
  259.     }
  260.  
  261.     // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
  262.     float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
  263.     draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12);
  264.     draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, IM_COL32(128,128,128,255), 12);
  265.     draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12);
  266.  
  267.     // Render alpha bar
  268.     if (alpha_bar)
  269.     {
  270.         float alpha = ImSaturate(col[3]);
  271.         ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
  272.         RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
  273.         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);
  274.         float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f);
  275.         RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
  276.         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);
  277.     }
  278.  
  279.     EndGroup();
  280.     PopID();
  281.  
  282.     return value_changed;
  283. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top