Advertisement
Guest User

Untitled

a guest
Oct 18th, 2019
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.63 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement