Blender V4.3
interface_region_color_picker.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstdarg>
12#include <cstdlib>
13#include <cstring>
14
15#include "MEM_guardedalloc.h"
16
17#include "DNA_userdef_types.h"
18
19#include "BLI_listbase.h"
20#include "BLI_string.h"
21#include "BLI_utildefines.h"
22
23#include "WM_types.hh"
24
25#include "RNA_access.hh"
26
27#include "UI_interface.hh"
28
29#include "BLT_translation.hh"
30
32
33#include "interface_intern.hh"
34
39
40/* -------------------------------------------------------------------- */
44static void ui_color_picker_rgb_round(float rgb[3])
45{
46 /* Handle small rounding errors in color space conversions. Doing these for
47 * all color space conversions would be expensive, but for the color picker
48 * we can do the extra work. */
49 for (int i = 0; i < 3; i++) {
50 if (fabsf(rgb[i]) < 5e-5f) {
51 rgb[i] = 0.0f;
52 }
53 else if (fabsf(1.0f - rgb[i]) < 5e-5f) {
54 rgb[i] = 1.0f;
55 }
56 }
57}
58
59void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3])
60{
61 /* Convert RGB to HSV, remaining as compatible as possible with the existing
62 * r_hsv value (for example when value goes to zero, preserve the hue). */
63 switch (U.color_picker_type) {
65 rgb_to_hsl_compat_v(rgb, r_cp);
66 break;
67 default:
68 rgb_to_hsv_compat_v(rgb, r_cp);
69 break;
70 }
71}
72
73void ui_color_picker_rgb_to_hsv(const float rgb[3], float r_cp[3])
74{
75 switch (U.color_picker_type) {
77 rgb_to_hsl_v(rgb, r_cp);
78 break;
79 default:
80 rgb_to_hsv_v(rgb, r_cp);
81 break;
82 }
83}
84
85void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3])
86{
87 switch (U.color_picker_type) {
89 hsl_to_rgb_v(r_cp, rgb);
90 break;
91 default:
92 hsv_to_rgb_v(r_cp, rgb);
93 break;
94 }
95}
96
98{
99 if (but->rnaprop) {
101 return true;
102 }
103 }
104
105 return but->block->is_color_gamma_picker;
106}
107
109{
110 if (but->rnaprop) {
111 const PropertySubType prop_subtype = RNA_property_subtype(but->rnaprop);
112 if (ELEM(prop_subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
113 const int color_components_count = RNA_property_array_length(&but->rnapoin, but->rnaprop);
114 if (color_components_count == 4) {
115 return true;
116 }
117 }
118 }
119
120 return false;
121}
122
124{
125 /* Map to color picking space for HSV values and HSV cube/circle,
126 * assuming it is more perceptually linear than the scene linear
127 * space for intuitive color picking. */
128 if (!ui_but_is_color_gamma(but)) {
131 }
132}
133
141
144/* -------------------------------------------------------------------- */
149 uiBut *from_but,
150 const float rgb_scene_linear[3])
151{
152 /* Convert from RGB to HSV in scene linear space color for number editing. */
153 if (cpicker->is_init == false) {
154 ui_color_picker_rgb_to_hsv(rgb_scene_linear, cpicker->hsv_scene_linear);
155 }
156 else {
157 ui_color_picker_rgb_to_hsv_compat(rgb_scene_linear, cpicker->hsv_scene_linear);
158 }
159
160 /* Convert from RGB to HSV in perceptually linear space for picker widgets. */
161 float rgb_perceptual[3];
162 copy_v3_v3(rgb_perceptual, rgb_scene_linear);
163 if (from_but) {
164 ui_scene_linear_to_perceptual_space(from_but, rgb_perceptual);
165 }
166
167 if (cpicker->is_init == false) {
168 ui_color_picker_rgb_to_hsv(rgb_perceptual, cpicker->hsv_perceptual);
170 }
171 else {
172 ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, cpicker->hsv_perceptual);
173 }
174
175 cpicker->is_init = true;
176}
177
179{
180 float rgb_perceptual[3];
181 ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
182 float *hsv_perceptual = cpicker->hsv_perceptual;
183
184 ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_perceptual);
185
186 ui_but_v3_set(but, rgb_perceptual);
187}
188
189/* Updates all buttons who share the same color picker as the one passed. */
191 uiBlock *block,
192 ColorPicker *cpicker,
193 const float rgba_scene_linear[4])
194{
195 ui_color_picker_update_hsv(cpicker, from_but, rgba_scene_linear);
196
197 LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
198 if (bt->custom_data != cpicker) {
199 continue;
200 }
201
202 if (bt->rnaprop) {
203 ui_but_v4_set(bt, rgba_scene_linear);
204 /* original button that created the color picker already does undo
205 * push, so disable it on RNA buttons in the color picker block */
207 }
208 else if (bt->type == UI_BTYPE_TEXT) {
209 /* Hex text input field. */
210 float rgba_hex[4];
211 uchar rgba_hex_uchar[4];
212 char col[16];
213
214 /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc...). */
215 copy_v4_v4(rgba_hex, rgba_scene_linear);
216 if (from_but && !ui_but_is_color_gamma(from_but)) {
219 }
220
221 rgba_float_to_uchar(rgba_hex_uchar, rgba_hex);
222
223 int col_len;
224 if (cpicker->has_alpha) {
225 col_len = SNPRINTF_RLEN(col, "#%02X%02X%02X%02X", UNPACK4_EX((uint), rgba_hex_uchar, ));
226 }
227 else {
228 col_len = SNPRINTF_RLEN(col, "#%02X%02X%02X", UNPACK3_EX((uint), rgba_hex_uchar, ));
229 }
230 memcpy(bt->poin, col, col_len + 1); /* +1 offset for the # symbol. */
231 }
232
233 ui_but_update(bt);
234 }
235}
236
237static void ui_colorpicker_rgba_update_cb(bContext * /*C*/, void *bt1, void * /*arg*/)
238{
239 uiBut *but = static_cast<uiBut *>(bt1);
240 uiPopupBlockHandle *popup = but->block->handle;
241 ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
242 PointerRNA ptr = but->rnapoin;
243 PropertyRNA *prop = but->rnaprop;
244 float rgba_scene_linear[4];
245
246 if (prop) {
247 zero_v4(rgba_scene_linear);
248 RNA_property_float_get_array(&ptr, prop, rgba_scene_linear);
249 ui_update_color_picker_buts_rgba(but, but->block, cpicker, rgba_scene_linear);
250 }
251
252 if (popup) {
254 }
255}
256
257static void ui_colorpicker_hsv_update_cb(bContext * /*C*/, void *bt1, void *bt2)
258{
259 uiBut *but = static_cast<uiBut *>(bt1);
260 uiPopupBlockHandle *popup = but->block->handle;
261 ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
262
263 /* Get RNA ptr/prop from the original color datablock button (bt2) since the HSV buttons (bt1)
264 * do not directly point to it. */
265 uiBut *color_but = static_cast<uiBut *>(bt2);
266 PointerRNA color_ptr = color_but->rnapoin;
267 PropertyRNA *color_prop = color_but->rnaprop;
268 float rgba_scene_linear[4];
269
270 if (color_prop) {
271 zero_v4(rgba_scene_linear);
272 /* Get the current RGBA color for its (optional) Alpha component,
273 * then update RGB components from the current HSV values. */
274 RNA_property_float_get_array(&color_ptr, color_prop, rgba_scene_linear);
275 ui_color_picker_hsv_to_rgb(cpicker->hsv_scene_linear, rgba_scene_linear);
276 ui_update_color_picker_buts_rgba(but, but->block, cpicker, rgba_scene_linear);
277 }
278
279 if (popup) {
281 }
282}
283
284static void ui_colorpicker_hex_rna_cb(bContext * /*C*/, void *bt1, void *bt2)
285{
286 uiBut *but = static_cast<uiBut *>(bt1);
287 uiPopupBlockHandle *popup = but->block->handle;
288 ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
289 char hexcol[128];
290 ui_but_string_get(but, hexcol, ARRAY_SIZE(hexcol));
291
292 /* In case the current color contains an Alpha component but the Hex string does not, get the
293 * current color to preserve the Alpha component.
294 * Like #ui_colorpicker_hsv_update_cb, the original color datablock button (bt2) is used since
295 * Hex Text Field button (bt1) doesn't directly point to it. */
296 uiBut *color_but = static_cast<uiBut *>(bt2);
297 PointerRNA color_ptr = color_but->rnapoin;
298 PropertyRNA *color_prop = color_but->rnaprop;
299
300 float rgba[4];
301 if (color_prop) {
302 zero_v4(rgba);
303 RNA_property_float_get_array(&color_ptr, color_prop, rgba);
304 }
305 /* Override current color with parsed the Hex string to preserve the original Alpha if the
306 * hex string doesn't contain it. */
307 hex_to_rgba(hexcol, rgba, rgba + 1, rgba + 2, rgba + 3);
308
309 /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc...). */
310 if (!ui_but_is_color_gamma(but)) {
313 }
314
315 ui_update_color_picker_buts_rgba(but, but->block, cpicker, rgba);
316
317 if (popup) {
319 }
320}
321
322static void ui_popup_close_cb(bContext * /*C*/, void *bt1, void * /*arg*/)
323{
324 uiBut *but = (uiBut *)bt1;
325 uiPopupBlockHandle *popup = but->block->handle;
326
327 if (popup) {
328 ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
329 BLI_assert(cpicker->is_init);
330 popup->menuretval = (equals_v3v3(cpicker->hsv_perceptual, cpicker->hsv_perceptual_init) ?
333 }
334}
335
336static void ui_colorpicker_hide_reveal(uiBlock *block, ePickerType colormode)
337{
338 /* tag buttons */
339 LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
340 if ((bt->func == ui_colorpicker_rgba_update_cb) && (bt->type == UI_BTYPE_NUM_SLIDER) &&
341 (bt->rnaindex != 3))
342 {
343 /* RGB sliders (color circle and alpha are always shown) */
344 SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_RGB), UI_HIDDEN);
345 }
346 else if (bt->func == ui_colorpicker_hsv_update_cb) {
347 /* HSV sliders */
348 SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HSV), UI_HIDDEN);
349 }
350 }
351}
352
353static void ui_colorpicker_create_mode_cb(bContext * /*C*/, void *bt1, void * /*arg*/)
354{
355 uiBut *bt = static_cast<uiBut *>(bt1);
356 const short colormode = ui_but_value_get(bt);
358}
359
360#define PICKER_TOTAL_W (180.0f * UI_SCALE_FAC)
361#define PICKER_BAR ((8.0f * UI_SCALE_FAC) + (6 * U.pixelsize))
362#define PICKER_SPACE (8.0f * UI_SCALE_FAC)
363#define PICKER_W (PICKER_TOTAL_W - PICKER_BAR - PICKER_SPACE)
364#define PICKER_H PICKER_W
365
368 PropertyRNA *prop,
369 ColorPicker *cpicker)
370{
371 uiBut *bt;
372 uiButHSVCube *hsv_but;
373
374 /* HS circle */
375 bt = uiDefButR_prop(block,
377 0,
378 "",
379 0,
380 0,
381 PICKER_H,
382 PICKER_W,
383 ptr,
384 prop,
385 -1,
386 0.0,
387 0.0,
388 TIP_("Color"));
390 bt->custom_data = cpicker;
391
392 /* value */
393 if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
394 hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
396 0,
397 "",
399 0,
401 PICKER_H,
402 ptr,
403 prop,
404 -1,
405 0.0,
406 0.0,
407 "Lightness");
408 hsv_but->gradient_type = UI_GRAD_L_ALT;
409 UI_but_func_set(hsv_but, ui_colorpicker_rgba_update_cb, hsv_but, nullptr);
410 }
411 else {
412 hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
414 0,
415 "",
417 0,
419 PICKER_H,
420 ptr,
421 prop,
422 -1,
423 0.0,
424 0.0,
426 hsv_but->gradient_type = UI_GRAD_V_ALT;
427 UI_but_func_set(hsv_but, ui_colorpicker_rgba_update_cb, hsv_but, nullptr);
428 }
429 hsv_but->custom_data = cpicker;
430}
431
434 PropertyRNA *prop,
435 eButGradientType type,
436 ColorPicker *cpicker)
437{
438 uiButHSVCube *hsv_but;
439
440 BLI_assert(type <= UI_GRAD_HS);
441
442 /* HS square */
443 hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
445 0,
446 "",
447 0,
450 PICKER_H,
451 ptr,
452 prop,
453 -1,
454 0.0,
455 0.0,
456 TIP_("Color"));
457 hsv_but->gradient_type = type;
458 UI_but_func_set(hsv_but, ui_colorpicker_rgba_update_cb, hsv_but, nullptr);
459 hsv_but->custom_data = cpicker;
460
461 /* value */
462 hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
464 0,
465 "",
466 0,
467 0,
470 ptr,
471 prop,
472 -1,
473 0.0,
474 0.0,
476 hsv_but->gradient_type = (eButGradientType)(type + 3);
477 UI_but_func_set(hsv_but, ui_colorpicker_rgba_update_cb, hsv_but, nullptr);
478 hsv_but->custom_data = cpicker;
479}
480
481/* a HS circle, V slider, rgb/hsv/hex sliders */
482static void ui_block_colorpicker(uiBlock *block,
483 uiBut *from_but,
484 float rgba_scene_linear[4],
485 bool show_picker)
486{
487 /* ePickerType */
488 static char colormode = 1;
489 uiBut *bt;
490 int picker_width;
491 static char hexcol[128];
492 float softmin, softmax, hardmin, hardmax, step, precision;
493 int yco;
495 PointerRNA *ptr = &from_but->rnapoin;
496 PropertyRNA *prop = from_but->rnaprop;
497
498 picker_width = PICKER_TOTAL_W;
499
500 RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
501 RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
502 RNA_property_float_get_array(ptr, prop, rgba_scene_linear);
503
504 ui_color_picker_update_hsv(cpicker, from_but, rgba_scene_linear);
505 cpicker->has_alpha = ui_but_color_has_alpha(from_but);
506
507 /* when the softmax isn't defined in the RNA,
508 * using very large numbers causes sRGB/linear round trip to fail. */
509 if (softmax == FLT_MAX) {
510 softmax = 1.0f;
511 }
512
513 switch (U.color_picker_type) {
515 ui_colorpicker_square(block, ptr, prop, UI_GRAD_SV, cpicker);
516 break;
518 ui_colorpicker_square(block, ptr, prop, UI_GRAD_HS, cpicker);
519 break;
521 ui_colorpicker_square(block, ptr, prop, UI_GRAD_HV, cpicker);
522 break;
523
524 /* user default */
527 default:
528 ui_colorpicker_circle(block, ptr, prop, cpicker);
529 break;
530 }
531
532 /* mode */
533 yco = -1.5f * UI_UNIT_Y;
535 bt = uiDefButC(block,
537 0,
538 IFACE_("RGB"),
539 0,
540 yco,
541 picker_width / 2,
542 UI_UNIT_Y,
543 &colormode,
544 0.0,
545 float(PICKER_TYPE_RGB),
546 TIP_("Red, Green, Blue"));
550 bt->custom_data = cpicker;
551 bt = uiDefButC(block,
553 0,
554 IFACE_((U.color_picker_type == USER_CP_CIRCLE_HSL) ? "HSL" : "HSV"),
555 picker_width / 2,
556 yco,
557 picker_width / 2,
558 UI_UNIT_Y,
559 &colormode,
560 0.0,
561 float(PICKER_TYPE_HSV),
562 (U.color_picker_type == USER_CP_CIRCLE_HSL) ? TIP_("Hue, Saturation, Lightness") :
563 TIP_("Hue, Saturation, Value"));
567 bt->custom_data = cpicker;
568 UI_block_align_end(block);
569
570 yco = -3.0f * UI_UNIT_Y;
571
572 /* NOTE: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */
573
574 /* RGB values */
576 bt = uiDefButR_prop(block,
578 0,
579 IFACE_("Red:"),
580 0,
581 yco,
582 picker_width,
583 UI_UNIT_Y,
584 ptr,
585 prop,
586 0,
587 0.0,
588 0.0,
589 TIP_("Red"));
593 bt->custom_data = cpicker;
594 bt = uiDefButR_prop(block,
596 0,
597 IFACE_("Green:"),
598 0,
599 yco -= UI_UNIT_Y,
600 picker_width,
601 UI_UNIT_Y,
602 ptr,
603 prop,
604 1,
605 0.0,
606 0.0,
607 TIP_("Green"));
611 bt->custom_data = cpicker;
612 bt = uiDefButR_prop(block,
614 0,
615 IFACE_("Blue:"),
616 0,
617 yco -= UI_UNIT_Y,
618 picker_width,
619 UI_UNIT_Y,
620 ptr,
621 prop,
622 2,
623 0.0,
624 0.0,
625 TIP_("Blue"));
629 bt->custom_data = cpicker;
630
631 /* Could use:
632 * uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND | UI_ITEM_R_SLIDER, "", ICON_NONE);
633 * but need to use UI_but_func_set for updating other fake buttons */
634
635 /* HSV values */
636 yco = -3.0f * UI_UNIT_Y;
637 bt = uiDefButF(block,
639 0,
640 IFACE_("Hue:"),
641 0,
642 yco,
643 picker_width,
644 UI_UNIT_Y,
645 cpicker->hsv_scene_linear,
646 0.0,
647 1.0,
648 TIP_("Hue"));
653 bt->custom_data = cpicker;
654 bt = uiDefButF(block,
656 0,
657 IFACE_("Saturation:"),
658 0,
659 yco -= UI_UNIT_Y,
660 picker_width,
661 UI_UNIT_Y,
662 cpicker->hsv_scene_linear + 1,
663 0.0,
664 1.0,
665 TIP_("Saturation"));
670 bt->custom_data = cpicker;
671 if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
672 bt = uiDefButF(block,
674 0,
675 IFACE_("Lightness:"),
676 0,
677 yco -= UI_UNIT_Y,
678 picker_width,
679 UI_UNIT_Y,
680 cpicker->hsv_scene_linear + 2,
681 0.0,
682 1.0,
683 TIP_("Lightness"));
686 }
687 else {
688 bt = uiDefButF(block,
690 0,
692 0,
693 yco -= UI_UNIT_Y,
694 picker_width,
695 UI_UNIT_Y,
696 cpicker->hsv_scene_linear + 2,
697 0.0,
698 softmax,
700 }
704
705 bt->hardmax = hardmax; /* Not common but RGB may be over 1.0. */
707 bt->custom_data = cpicker;
708
709 if (cpicker->has_alpha) {
710 bt = uiDefButR_prop(block,
712 0,
713 IFACE_("Alpha:"),
714 0,
715 yco -= UI_UNIT_Y,
716 picker_width,
717 UI_UNIT_Y,
718 ptr,
719 prop,
720 3,
721 0.0,
722 0.0,
723 TIP_("Alpha"));
727 bt->custom_data = cpicker;
728 }
729 else {
730 rgba_scene_linear[3] = 1.0f;
731 }
732
733 UI_block_align_end(block);
734
735 /* Hex color is in sRGB space. */
736 float rgba_hex[4];
737 uchar rgba_hex_uchar[4];
738
739 copy_v4_v4(rgba_hex, rgba_scene_linear);
740
741 if (!ui_but_is_color_gamma(from_but)) {
744 }
745
746 rgba_float_to_uchar(rgba_hex_uchar, rgba_hex);
747
748 if (cpicker->has_alpha) {
749 SNPRINTF(hexcol, "#%02X%02X%02X%02X", UNPACK4_EX((uint), rgba_hex_uchar, ));
750 }
751 else {
752 SNPRINTF(hexcol, "#%02X%02X%02X", UNPACK3_EX((uint), rgba_hex_uchar, ));
753 }
754
755 yco -= UI_UNIT_Y * 1.5f;
756
757 const int label_width = picker_width * 0.15f;
758 const int eyedropper_offset = show_picker ? UI_UNIT_X * 1.25f : 0;
759 const int text_width = picker_width - label_width - eyedropper_offset;
760
761 uiDefBut(block,
763 0,
764 IFACE_("Hex"),
765 0,
766 yco,
767 label_width,
768 UI_UNIT_Y,
769 nullptr,
770 0.0,
771 0.0,
772 nullptr);
773
774 bt = uiDefBut(block,
776 0,
777 IFACE_(""),
778 label_width,
779 yco,
780 text_width,
781 UI_UNIT_Y,
782 hexcol,
783 0,
784 cpicker->has_alpha ? 10 : 8,
785 nullptr);
786 const auto bt_tooltip_func = [](bContext & /*C*/, uiTooltipData &tip, void *has_alpha_ptr) {
787 const bool *has_alpha = static_cast<bool *>(has_alpha_ptr);
788 if (*has_alpha) {
790 "Hex triplet for color with alpha (#RRGGBBAA).",
791 {},
794 false);
795 }
796 else {
798 "Hex triplet for color (#RRGGBB).",
799 {},
802 false);
803 }
805 tip, "Gamma corrected", {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL, false);
806 };
808 bt, bt_tooltip_func, static_cast<void *>(&cpicker->has_alpha), nullptr);
811 bt->custom_data = cpicker;
812
813 if (show_picker) {
814 bt = uiDefIconButO(block,
816 "UI_OT_eyedropper_color",
818 ICON_EYEDROPPER,
819 picker_width - UI_UNIT_X,
820 yco,
821 UI_UNIT_X,
822 UI_UNIT_Y,
823 nullptr);
826 UI_but_func_set(bt, ui_popup_close_cb, bt, nullptr);
827 bt->custom_data = cpicker;
828 }
829
830 ui_colorpicker_hide_reveal(block, (ePickerType)colormode);
831}
832
833static int ui_colorpicker_wheel_cb(const bContext * /*C*/, uiBlock *block, const wmEvent *event)
834{
835 /* Increase/Decrease the Color HSV Value component using the mouse wheel. */
836 float add = 0.0f;
837
838 if (event->type == WHEELUPMOUSE) {
839 add = 0.05f;
840 }
841 else if (event->type == WHEELDOWNMOUSE) {
842 add = -0.05f;
843 }
844
845 if (add != 0.0f) {
846 LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
847 if (but->type == UI_BTYPE_HSVCUBE && but->active == nullptr) {
848 uiPopupBlockHandle *popup = block->handle;
849 ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
850 float *hsv_perceptual = cpicker->hsv_perceptual;
851
852 /* Get the RGBA Color. */
853 float rgba_perceptual[4];
854 ui_but_v4_get(but, rgba_perceptual);
855 ui_scene_linear_to_perceptual_space(but, rgba_perceptual);
856
857 /* Convert it to HSV. */
858 ui_color_picker_rgb_to_hsv_compat(rgba_perceptual, hsv_perceptual);
859
860 /* Increment/Decrement its value from mouse wheel input. */
861 hsv_perceptual[2] = clamp_f(hsv_perceptual[2] + add, 0.0f, 1.0f);
862
863 /* Convert it to linear space RGBA, and apply it back to the button. */
864 float rgba_scene_linear[4];
865 rgba_scene_linear[3] = rgba_perceptual[3]; /* Transfer Alpha component. */
866 ui_color_picker_hsv_to_rgb(hsv_perceptual, rgba_scene_linear);
867 ui_perceptual_to_scene_linear_space(but, rgba_scene_linear);
868 ui_but_v4_set(but, rgba_scene_linear);
869
870 /* Update all other Color Picker buttons to reflect the color change. */
871 ui_update_color_picker_buts_rgba(but, block, cpicker, rgba_scene_linear);
872 if (popup) {
874 }
875
876 return 1;
877 }
878 }
879 }
880 return 0;
881}
882
884{
885 uiBut *but = static_cast<uiBut *>(arg_but);
886 uiBlock *block;
887
888 block = UI_block_begin(C, handle->region, __func__, UI_EMBOSS);
889
890 if (ui_but_is_color_gamma(but)) {
891 block->is_color_gamma_picker = true;
892 }
893
894 copy_v3_v3(handle->retvec, but->editvec);
895
896 ui_block_colorpicker(block, but, handle->retvec, true);
897
901
903 block->direction = UI_DIR_UP;
904
905 return block;
906}
907
909{
910 ColorPicker *cpicker = MEM_cnew<ColorPicker>(__func__);
911 BLI_addhead(&block->color_pickers.list, cpicker);
912
913 return cpicker;
914}
915
#define BLI_assert(a)
Definition BLI_assert.h:50
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
MINLINE float clamp_f(float value, float min, float max)
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition math_color.cc:57
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3])
void hex_to_rgba(const char *hexcol, float *r_r, float *r_g, float *r_b, float *r_a)
void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
Definition math_color.cc:62
void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
void rgb_to_hsl_compat_v(const float rgb[3], float r_hsl[3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v4(float r[4])
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
#define SNPRINTF_RLEN(dst, format,...)
Definition BLI_string.h:598
unsigned char uchar
unsigned int uint
#define UNPACK3_EX(pre, a, post)
#define ARRAY_SIZE(arr)
#define UNPACK4_EX(pre, a, post)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define TIP_(msgid)
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
#define CTX_TIP_(context, msgid)
#define BLT_I18NCONTEXT_COLOR
@ USER_CP_SQUARE_SV
@ USER_CP_CIRCLE_HSL
@ USER_CP_SQUARE_HS
@ USER_CP_SQUARE_HV
@ USER_CP_CIRCLE_HSV
BLI_INLINE void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
void IMB_colormanagement_color_picking_to_scene_linear_v3(float scene_linear[3], const float color_picking[3])
void IMB_colormanagement_scene_linear_to_color_picking_v3(float color_picking[3], const float scene_linear[3])
BLI_INLINE void IMB_colormanagement_scene_linear_to_srgb_v3(float srgb[3], const float scene_linear[3])
Read Guarded memory(de)allocation.
PropertySubType
Definition RNA_types.hh:135
@ PROP_COLOR
Definition RNA_types.hh:163
@ PROP_COLOR_GAMMA
Definition RNA_types.hh:175
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
void UI_but_flag_disable(uiBut *but, int flag)
@ UI_RETURN_UPDATE
@ UI_RETURN_CANCEL
@ UI_RETURN_OK
#define UI_UNIT_Y
@ UI_EMBOSS
void UI_block_theme_style_set(uiBlock *block, char theme_style)
void UI_but_func_tooltip_custom_set(uiBut *but, uiButToolTipCustomFunc func, void *arg, uiFreeArgFunc free_arg)
@ UI_BLOCK_LOOP
@ UI_BLOCK_MOVEMOUSE_QUIT
@ UI_BLOCK_KEEP_OPEN
@ UI_BLOCK_OUT_1
uiBut * uiDefButC(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, char *poin, float min, float max, const char *tip)
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, const char *tip)
void UI_block_bounds_set_normal(uiBlock *block, int addval)
Definition interface.cc:574
void UI_tooltip_text_field_add(uiTooltipData &data, std::string text, std::string suffix, const uiTooltipStyle style, const uiTooltipColorID color_id, const bool is_pad=false)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss)
void UI_but_number_slider_precision_set(uiBut *but, float precision)
uiBut * uiDefIconButO(uiBlock *block, int type, const char *opname, wmOperatorCallContext opcontext, int icon, int x, int y, short width, short height, const char *tip)
uiBut * uiDefButF(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, float *poin, float min, float max, const char *tip)
@ UI_DIR_UP
@ UI_TIP_STYLE_NORMAL
@ UI_TIP_STYLE_HEADER
void UI_but_number_slider_step_size_set(uiBut *but, float step_size)
void UI_but_drawflag_disable(uiBut *but, int flag)
void UI_block_align_begin(uiBlock *block)
@ UI_BLOCK_THEME_STYLE_POPUP
eButGradientType
@ UI_GRAD_L_ALT
@ UI_GRAD_SV
@ UI_GRAD_V_ALT
@ UI_GRAD_HV
@ UI_GRAD_HS
@ UI_TIP_LC_NORMAL
uiBut * uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, const char *tip)
#define UI_UNIT_X
@ UI_BTYPE_BUT
@ UI_BTYPE_NUM_SLIDER
@ UI_BTYPE_HSVCIRCLE
@ UI_BTYPE_TEXT
@ UI_BTYPE_HSVCUBE
@ UI_BTYPE_LABEL
@ UI_BTYPE_ROW
@ UI_BUT_ICON_LEFT
@ UI_BUT_TEXT_LEFT
@ UI_BUT_UNDO
void UI_block_align_end(uiBlock *block)
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:218
unsigned int U
Definition btGjkEpa3.h:78
#define fabsf(x)
uint col
void ui_but_v4_get(uiBut *but, float vec[4])
void ui_but_v4_set(uiBut *but, const float vec[4])
void ui_but_update(uiBut *but)
double ui_but_value_get(uiBut *but)
void ui_but_string_get(uiBut *but, char *str, const size_t str_maxncpy)
void ui_but_v3_set(uiBut *but, const float vec[3])
@ UI_HIDDEN
static void ui_color_picker_rgb_round(float rgb[3])
static void ui_colorpicker_hide_reveal(uiBlock *block, ePickerType colormode)
static void ui_colorpicker_square(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, eButGradientType type, ColorPicker *cpicker)
ColorPicker * ui_block_colorpicker_create(uiBlock *block)
void ui_perceptual_to_scene_linear_space(uiBut *but, float rgb[3])
static void ui_colorpicker_rgba_update_cb(bContext *, void *bt1, void *)
void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3])
static void ui_colorpicker_hex_rna_cb(bContext *, void *bt1, void *bt2)
static void ui_colorpicker_circle(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, ColorPicker *cpicker)
void ui_color_picker_rgb_to_hsv(const float rgb[3], float r_cp[3])
void ui_scene_linear_to_perceptual_space(uiBut *but, float rgb[3])
static void ui_color_picker_update_hsv(ColorPicker *cpicker, uiBut *from_but, const float rgb_scene_linear[3])
void ui_but_hsv_set(uiBut *but)
static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba_scene_linear[4], bool show_picker)
static void ui_colorpicker_create_mode_cb(bContext *, void *bt1, void *)
uiBlock * ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3])
bool ui_but_color_has_alpha(uiBut *but)
static void ui_colorpicker_hsv_update_cb(bContext *, void *bt1, void *bt2)
bool ui_but_is_color_gamma(uiBut *but)
static int ui_colorpicker_wheel_cb(const bContext *, uiBlock *block, const wmEvent *event)
static void ui_popup_close_cb(bContext *, void *bt1, void *)
static void ui_update_color_picker_buts_rgba(uiBut *from_but, uiBlock *block, ColorPicker *cpicker, const float rgba_scene_linear[4])
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
#define FLT_MAX
Definition stdcycles.h:14
float hsv_perceptual_init[3]
float hsv_scene_linear[3]
float hsv_perceptual[3]
bool is_color_gamma_picker
ColorPickerData color_pickers
uiPopupBlockHandle * handle
ListBase buttons
int(* block_event_func)(const bContext *C, uiBlock *, const wmEvent *)
eButGradientType gradient_type
void * custom_data
float * editvec
PropertyRNA * rnaprop
uiBlock * block
PointerRNA rnapoin
short type
Definition WM_types.hh:722
@ WHEELUPMOUSE
@ WHEELDOWNMOUSE
PointerRNA * ptr
Definition wm_files.cc:4126