Blender  V3.3
interface_region_color_picker.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. All rights reserved. */
3 
10 #include <cstdarg>
11 #include <cstdlib>
12 #include <cstring>
13 
14 #include "MEM_guardedalloc.h"
15 
16 #include "DNA_userdef_types.h"
17 
18 #include "BLI_listbase.h"
19 #include "BLI_math.h"
20 #include "BLI_string.h"
21 #include "BLI_utildefines.h"
22 
23 #include "BKE_context.h"
24 
25 #include "WM_types.h"
26 
27 #include "RNA_access.h"
28 
29 #include "UI_interface.h"
30 
31 #include "BLT_translation.h"
32 
33 #include "ED_screen.h"
34 
35 #include "IMB_colormanagement.h"
36 
37 #include "interface_intern.h"
38 
43 };
44 
45 /* -------------------------------------------------------------------- */
49 static void ui_color_picker_rgb_round(float rgb[3])
50 {
51  /* Handle small rounding errors in color space conversions. Doing these for
52  * all color space conversions would be expensive, but for the color picker
53  * we can do the extra work. */
54  for (int i = 0; i < 3; i++) {
55  if (fabsf(rgb[i]) < 5e-5f) {
56  rgb[i] = 0.0f;
57  }
58  else if (fabsf(1.0f - rgb[i]) < 5e-5f) {
59  rgb[i] = 1.0f;
60  }
61  }
62 }
63 
64 void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3])
65 {
66  /* Convert RGB to HSV, remaining as compatible as possible with the existing
67  * r_hsv value (for example when value goes to zero, preserve the hue). */
68  switch (U.color_picker_type) {
69  case USER_CP_CIRCLE_HSL:
70  rgb_to_hsl_compat_v(rgb, r_cp);
71  break;
72  default:
73  rgb_to_hsv_compat_v(rgb, r_cp);
74  break;
75  }
76 }
77 
78 void ui_color_picker_rgb_to_hsv(const float rgb[3], float r_cp[3])
79 {
80  switch (U.color_picker_type) {
81  case USER_CP_CIRCLE_HSL:
82  rgb_to_hsl_v(rgb, r_cp);
83  break;
84  default:
85  rgb_to_hsv_v(rgb, r_cp);
86  break;
87  }
88 }
89 
90 void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3])
91 {
92  switch (U.color_picker_type) {
93  case USER_CP_CIRCLE_HSL:
94  hsl_to_rgb_v(r_cp, rgb);
95  break;
96  default:
97  hsv_to_rgb_v(r_cp, rgb);
98  break;
99  }
100 }
101 
103 {
104  if (but->rnaprop) {
106  return true;
107  }
108  }
109 
110  return but->block->is_color_gamma_picker;
111 }
112 
114 {
115  /* Map to color picking space for HSV values and HSV cube/circle,
116  * assuming it is more perceptually linear than the scene linear
117  * space for intuitive color picking. */
118  if (!ui_but_is_color_gamma(but)) {
121  }
122 }
123 
125 {
126  if (!ui_but_is_color_gamma(but)) {
129  }
130 }
131 
134 /* -------------------------------------------------------------------- */
139  uiBut *from_but,
140  const float rgb_scene_linear[3])
141 {
142  /* Convert from RGB to HSV in scene linear space color for number editing. */
143  if (cpicker->is_init == false) {
144  ui_color_picker_rgb_to_hsv(rgb_scene_linear, cpicker->hsv_scene_linear);
145  }
146  else {
147  ui_color_picker_rgb_to_hsv_compat(rgb_scene_linear, cpicker->hsv_scene_linear);
148  }
149 
150  /* Convert from RGB to HSV in perceptually linear space for picker widgets. */
151  float rgb_perceptual[3];
152  copy_v3_v3(rgb_perceptual, rgb_scene_linear);
153  if (from_but) {
154  ui_scene_linear_to_perceptual_space(from_but, rgb_perceptual);
155  }
156 
157  if (cpicker->is_init == false) {
158  ui_color_picker_rgb_to_hsv(rgb_perceptual, cpicker->hsv_perceptual);
159  copy_v3_v3(cpicker->hsv_perceptual_init, cpicker->hsv_perceptual);
160  }
161  else {
162  ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, cpicker->hsv_perceptual);
163  }
164 
165  cpicker->is_init = true;
166 }
167 
169 {
170  float rgb_perceptual[3];
171  ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
172  float *hsv_perceptual = cpicker->hsv_perceptual;
173 
174  ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_perceptual);
175 
176  ui_but_v3_set(but, rgb_perceptual);
177 }
178 
179 /* Updates all buttons who share the same color picker as the one passed
180  * also used by small picker, be careful with name checks below... */
182  uiBlock *block,
183  ColorPicker *cpicker,
184  const float rgb_scene_linear[3])
185 {
186  ui_color_picker_update_hsv(cpicker, from_but, rgb_scene_linear);
187 
188  /* this updates button strings,
189  * is hackish... but button pointers are on stack of caller function */
190  LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
191  if (bt->custom_data != cpicker) {
192  continue;
193  }
194 
195  if (bt->rnaprop) {
196  ui_but_v3_set(bt, rgb_scene_linear);
197 
198  /* original button that created the color picker already does undo
199  * push, so disable it on RNA buttons in the color picker block */
201  }
202  else if (STREQ(bt->str, "Hex: ")) {
203  float rgb_hex[3];
204  uchar rgb_hex_uchar[3];
205  char col[16];
206 
207  /* Hex code is assumed to be in sRGB space
208  * (coming from other applications, web, etc) */
209  copy_v3_v3(rgb_hex, rgb_scene_linear);
210  if (from_but && !ui_but_is_color_gamma(from_but)) {
212  ui_color_picker_rgb_round(rgb_hex);
213  }
214 
215  rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
216  BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
217 
218  strcpy(bt->poin, col);
219  }
220  else if (bt->str[1] == ' ') {
221  if (bt->str[0] == 'R') {
222  ui_but_value_set(bt, rgb_scene_linear[0]);
223  }
224  else if (bt->str[0] == 'G') {
225  ui_but_value_set(bt, rgb_scene_linear[1]);
226  }
227  else if (bt->str[0] == 'B') {
228  ui_but_value_set(bt, rgb_scene_linear[2]);
229  }
230  else if (bt->str[0] == 'H') {
231  ui_but_value_set(bt, cpicker->hsv_scene_linear[0]);
232  }
233  else if (bt->str[0] == 'S') {
234  ui_but_value_set(bt, cpicker->hsv_scene_linear[1]);
235  }
236  else if (bt->str[0] == 'V') {
237  ui_but_value_set(bt, cpicker->hsv_scene_linear[2]);
238  }
239  else if (bt->str[0] == 'L') {
240  ui_but_value_set(bt, cpicker->hsv_scene_linear[2]);
241  }
242  }
243 
244  ui_but_update(bt);
245  }
246 }
247 
248 static void ui_colorpicker_rgba_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
249 {
250  uiBut *but = (uiBut *)bt1;
251  uiPopupBlockHandle *popup = but->block->handle;
252  PropertyRNA *prop = but->rnaprop;
253  PointerRNA ptr = but->rnapoin;
254  float rgb_scene_linear[4];
255 
256  if (prop) {
257  RNA_property_float_get_array(&ptr, prop, rgb_scene_linear);
259  but, but->block, static_cast<ColorPicker *>(but->custom_data), rgb_scene_linear);
260  }
261 
262  if (popup) {
263  popup->menuretval = UI_RETURN_UPDATE;
264  }
265 }
266 
267 static void ui_colorpicker_hsv_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
268 {
269  uiBut *but = (uiBut *)bt1;
270  uiPopupBlockHandle *popup = but->block->handle;
271  float rgb_scene_linear[3];
272  ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
273 
274  ui_color_picker_hsv_to_rgb(cpicker->hsv_scene_linear, rgb_scene_linear);
275  ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb_scene_linear);
276 
277  if (popup) {
278  popup->menuretval = UI_RETURN_UPDATE;
279  }
280 }
281 
282 static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
283 {
284  uiBut *but = (uiBut *)bt1;
285  uiPopupBlockHandle *popup = but->block->handle;
286  ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
287  char *hexcol = (char *)hexcl;
288  float rgb[3];
289 
290  hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2);
291 
292  /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
293  if (!ui_but_is_color_gamma(but)) {
296  }
297 
298  ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
299 
300  if (popup) {
301  popup->menuretval = UI_RETURN_UPDATE;
302  }
303 }
304 
305 static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
306 {
307  uiBut *but = (uiBut *)bt1;
308  uiPopupBlockHandle *popup = but->block->handle;
309 
310  if (popup) {
311  ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
312  BLI_assert(cpicker->is_init);
313  popup->menuretval = (equals_v3v3(cpicker->hsv_perceptual, cpicker->hsv_perceptual_init) ?
315  UI_RETURN_OK);
316  }
317 }
318 
319 static void ui_colorpicker_hide_reveal(uiBlock *block, ePickerType colormode)
320 {
321  /* tag buttons */
322  LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
323  if ((bt->func == ui_colorpicker_rgba_update_cb) && (bt->type == UI_BTYPE_NUM_SLIDER) &&
324  (bt->rnaindex != 3)) {
325  /* RGB sliders (color circle and alpha are always shown) */
326  SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_RGB), UI_HIDDEN);
327  }
328  else if (bt->func == ui_colorpicker_hsv_update_cb) {
329  /* HSV sliders */
330  SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HSV), UI_HIDDEN);
331  }
332  else if (bt->func == ui_colorpicker_hex_rna_cb || bt->type == UI_BTYPE_LABEL) {
333  /* HEX input or gamma correction status label */
334  SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HEX), UI_HIDDEN);
335  }
336  }
337 }
338 
339 static void ui_colorpicker_create_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
340 {
341  uiBut *bt = static_cast<uiBut *>(bt1);
342  const short colormode = ui_but_value_get(bt);
344 }
345 
346 #define PICKER_H (7.5f * U.widget_unit)
347 #define PICKER_W (7.5f * U.widget_unit)
348 #define PICKER_SPACE (0.3f * U.widget_unit)
349 #define PICKER_BAR (0.7f * U.widget_unit)
350 
351 #define PICKER_TOTAL_W (PICKER_W + PICKER_SPACE + PICKER_BAR)
352 
353 static void ui_colorpicker_circle(uiBlock *block,
354  PointerRNA *ptr,
355  PropertyRNA *prop,
356  ColorPicker *cpicker)
357 {
358  uiBut *bt;
359  uiButHSVCube *hsv_but;
360 
361  /* HS circle */
362  bt = uiDefButR_prop(block,
364  0,
365  "",
366  0,
367  0,
368  PICKER_H,
369  PICKER_W,
370  ptr,
371  prop,
372  -1,
373  0.0,
374  0.0,
375  0.0,
376  0,
377  TIP_("Color"));
379  bt->custom_data = cpicker;
380 
381  /* value */
382  if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
383  hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
385  0,
386  "",
388  0,
389  PICKER_BAR,
390  PICKER_H,
391  ptr,
392  prop,
393  -1,
394  0.0,
395  0.0,
396  0,
397  0,
398  "Lightness");
399  hsv_but->gradient_type = UI_GRAD_L_ALT;
400  UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr);
401  }
402  else {
403  hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
405  0,
406  "",
408  0,
409  PICKER_BAR,
410  PICKER_H,
411  ptr,
412  prop,
413  -1,
414  0.0,
415  0.0,
416  0,
417  0,
418  TIP_("Value"));
419  hsv_but->gradient_type = UI_GRAD_V_ALT;
420  UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr);
421  }
422  hsv_but->but.custom_data = cpicker;
423 }
424 
425 static void ui_colorpicker_square(uiBlock *block,
426  PointerRNA *ptr,
427  PropertyRNA *prop,
429  ColorPicker *cpicker)
430 {
431  uiButHSVCube *hsv_but;
432 
434 
435  /* HS square */
436  hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
438  0,
439  "",
440  0,
443  PICKER_H,
444  ptr,
445  prop,
446  -1,
447  0.0,
448  0.0,
449  0,
450  0,
451  TIP_("Color"));
452  hsv_but->gradient_type = type;
453  UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr);
454  hsv_but->but.custom_data = cpicker;
455 
456  /* value */
457  hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
459  0,
460  "",
461  0,
462  0,
464  PICKER_BAR,
465  ptr,
466  prop,
467  -1,
468  0.0,
469  0.0,
470  0,
471  0,
472  TIP_("Value"));
473  hsv_but->gradient_type = (eButGradientType)(type + 3);
474  UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr);
475  hsv_but->but.custom_data = cpicker;
476 }
477 
478 /* a HS circle, V slider, rgb/hsv/hex sliders */
479 static void ui_block_colorpicker(uiBlock *block,
480  uiBut *from_but,
481  float rgba_scene_linear[4],
482  bool show_picker)
483 {
484  /* ePickerType */
485  static char colormode = 1;
486  uiBut *bt;
487  int width, butwidth;
488  static char hexcol[128];
489  float softmin, softmax, hardmin, hardmax, step, precision;
490  int yco;
491  ColorPicker *cpicker = ui_block_colorpicker_create(block);
492  PointerRNA *ptr = &from_but->rnapoin;
493  PropertyRNA *prop = from_but->rnaprop;
494 
496  butwidth = width - 1.5f * UI_UNIT_X;
497 
498  /* sneaky way to check for alpha */
499  rgba_scene_linear[3] = FLT_MAX;
500 
501  RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
502  RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
503  RNA_property_float_get_array(ptr, prop, rgba_scene_linear);
504 
505  ui_color_picker_update_hsv(cpicker, from_but, rgba_scene_linear);
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) {
514  case USER_CP_SQUARE_SV:
515  ui_colorpicker_square(block, ptr, prop, UI_GRAD_SV, cpicker);
516  break;
517  case USER_CP_SQUARE_HS:
518  ui_colorpicker_square(block, ptr, prop, UI_GRAD_HS, cpicker);
519  break;
520  case USER_CP_SQUARE_HV:
521  ui_colorpicker_square(block, ptr, prop, UI_GRAD_HV, cpicker);
522  break;
523 
524  /* user default */
525  case USER_CP_CIRCLE_HSV:
526  case USER_CP_CIRCLE_HSL:
527  default:
528  ui_colorpicker_circle(block, ptr, prop, cpicker);
529  break;
530  }
531 
532  /* mode */
533  yco = -1.5f * UI_UNIT_Y;
534  UI_block_align_begin(block);
535  bt = uiDefButC(block,
536  UI_BTYPE_ROW,
537  0,
538  IFACE_("RGB"),
539  0,
540  yco,
541  width / 3,
542  UI_UNIT_Y,
543  &colormode,
544  0.0,
545  (float)PICKER_TYPE_RGB,
546  0,
547  0,
548  "");
552  bt->custom_data = cpicker;
553  bt = uiDefButC(block,
554  UI_BTYPE_ROW,
555  0,
556  IFACE_((U.color_picker_type == USER_CP_CIRCLE_HSL) ? "HSL" : "HSV"),
557  width / 3,
558  yco,
559  width / 3,
560  UI_UNIT_Y,
561  &colormode,
562  0.0,
564  0,
565  0,
566  "");
570  bt->custom_data = cpicker;
571  bt = uiDefButC(block,
572  UI_BTYPE_ROW,
573  0,
574  IFACE_("Hex"),
575  2 * width / 3,
576  yco,
577  width / 3,
578  UI_UNIT_Y,
579  &colormode,
580  0.0,
582  0,
583  0,
584  "");
588  bt->custom_data = cpicker;
589  UI_block_align_end(block);
590 
591  yco = -3.0f * UI_UNIT_Y;
592  if (show_picker) {
593  bt = uiDefIconButO(block,
594  UI_BTYPE_BUT,
595  "UI_OT_eyedropper_color",
597  ICON_EYEDROPPER,
598  butwidth + 10,
599  yco,
600  UI_UNIT_X,
601  UI_UNIT_Y,
602  nullptr);
605  UI_but_func_set(bt, ui_popup_close_cb, bt, nullptr);
606  bt->custom_data = cpicker;
607  }
608 
609  /* NOTE: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */
610 
611  /* RGB values */
612  UI_block_align_begin(block);
613  bt = uiDefButR_prop(block,
615  0,
616  IFACE_("R:"),
617  0,
618  yco,
619  butwidth,
620  UI_UNIT_Y,
621  ptr,
622  prop,
623  0,
624  0.0,
625  0.0,
626  0,
627  3,
628  TIP_("Red"));
630  bt->custom_data = cpicker;
631  bt = uiDefButR_prop(block,
633  0,
634  IFACE_("G:"),
635  0,
636  yco -= UI_UNIT_Y,
637  butwidth,
638  UI_UNIT_Y,
639  ptr,
640  prop,
641  1,
642  0.0,
643  0.0,
644  0,
645  3,
646  TIP_("Green"));
648  bt->custom_data = cpicker;
649  bt = uiDefButR_prop(block,
651  0,
652  IFACE_("B:"),
653  0,
654  yco -= UI_UNIT_Y,
655  butwidth,
656  UI_UNIT_Y,
657  ptr,
658  prop,
659  2,
660  0.0,
661  0.0,
662  0,
663  3,
664  TIP_("Blue"));
666  bt->custom_data = cpicker;
667 
668  /* Could use:
669  * uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND | UI_ITEM_R_SLIDER, "", ICON_NONE);
670  * but need to use UI_but_func_set for updating other fake buttons */
671 
672  /* HSV values */
673  yco = -3.0f * UI_UNIT_Y;
674  UI_block_align_begin(block);
675  bt = uiDefButF(block,
677  0,
678  IFACE_("H:"),
679  0,
680  yco,
681  butwidth,
682  UI_UNIT_Y,
683  cpicker->hsv_scene_linear,
684  0.0,
685  1.0,
686  10,
687  3,
688  TIP_("Hue"));
691  bt->custom_data = cpicker;
692  bt = uiDefButF(block,
694  0,
695  IFACE_("S:"),
696  0,
697  yco -= UI_UNIT_Y,
698  butwidth,
699  UI_UNIT_Y,
700  cpicker->hsv_scene_linear + 1,
701  0.0,
702  1.0,
703  10,
704  3,
705  TIP_("Saturation"));
708  bt->custom_data = cpicker;
709  if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
710  bt = uiDefButF(block,
712  0,
713  IFACE_("L:"),
714  0,
715  yco -= UI_UNIT_Y,
716  butwidth,
717  UI_UNIT_Y,
718  cpicker->hsv_scene_linear + 2,
719  0.0,
720  1.0,
721  10,
722  3,
723  TIP_("Lightness"));
724  }
725  else {
726  bt = uiDefButF(block,
728  0,
729  IFACE_("V:"),
730  0,
731  yco -= UI_UNIT_Y,
732  butwidth,
733  UI_UNIT_Y,
734  cpicker->hsv_scene_linear + 2,
735  0.0,
736  softmax,
737  10,
738  3,
739  TIP_("Value"));
740  }
742 
743  bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */
745  bt->custom_data = cpicker;
746 
747  UI_block_align_end(block);
748 
749  if (rgba_scene_linear[3] != FLT_MAX) {
750  bt = uiDefButR_prop(block,
752  0,
753  IFACE_("A: "),
754  0,
755  yco -= UI_UNIT_Y,
756  butwidth,
757  UI_UNIT_Y,
758  ptr,
759  prop,
760  3,
761  0.0,
762  0.0,
763  0,
764  3,
765  TIP_("Alpha"));
767  bt->custom_data = cpicker;
768  }
769  else {
770  rgba_scene_linear[3] = 1.0f;
771  }
772 
773  /* Hex color is in sRGB space. */
774  float rgb_hex[3];
775  uchar rgb_hex_uchar[3];
776 
777  copy_v3_v3(rgb_hex, rgba_scene_linear);
778 
779  if (!ui_but_is_color_gamma(from_but)) {
781  ui_color_picker_rgb_round(rgb_hex);
782  }
783 
784  rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
785  BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
786 
787  yco = -3.0f * UI_UNIT_Y;
788  bt = uiDefBut(block,
790  0,
791  IFACE_("Hex: "),
792  0,
793  yco,
794  butwidth,
795  UI_UNIT_Y,
796  hexcol,
797  0,
798  8,
799  0,
800  0,
801  TIP_("Hex triplet for color (#RRGGBB)"));
804  bt->custom_data = cpicker;
805  uiDefBut(block,
807  0,
808  IFACE_("(Gamma Corrected)"),
809  0,
810  yco - UI_UNIT_Y,
811  butwidth,
812  UI_UNIT_Y,
813  nullptr,
814  0.0,
815  0.0,
816  0,
817  0,
818  "");
819 
820  ui_colorpicker_hide_reveal(block, (ePickerType)colormode);
821 }
822 
824  uiBlock *block,
825  const wmEvent *event)
826 {
827  float add = 0.0f;
828 
829  if (event->type == WHEELUPMOUSE) {
830  add = 0.05f;
831  }
832  else if (event->type == WHEELDOWNMOUSE) {
833  add = -0.05f;
834  }
835 
836  if (add != 0.0f) {
837  LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
838  if (but->type == UI_BTYPE_HSVCUBE && but->active == nullptr) {
839  uiPopupBlockHandle *popup = block->handle;
840  ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
841  float *hsv_perceptual = cpicker->hsv_perceptual;
842 
843  float rgb_perceptual[3];
844  ui_but_v3_get(but, rgb_perceptual);
845  ui_scene_linear_to_perceptual_space(but, rgb_perceptual);
846  ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, hsv_perceptual);
847 
848  hsv_perceptual[2] = clamp_f(hsv_perceptual[2] + add, 0.0f, 1.0f);
849 
850  float rgb_scene_linear[3];
851  ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_scene_linear);
852  ui_perceptual_to_scene_linear_space(but, rgb_scene_linear);
853  ui_but_v3_set(but, rgb_scene_linear);
854 
855  ui_update_color_picker_buts_rgb(but, block, cpicker, rgb_scene_linear);
856  if (popup) {
857  popup->menuretval = UI_RETURN_UPDATE;
858  }
859 
860  return 1;
861  }
862  }
863  }
864  return 0;
865 }
866 
868 {
869  uiBut *but = static_cast<uiBut *>(arg_but);
870  uiBlock *block;
871  bool show_picker = true;
872 
873  block = UI_block_begin(C, handle->region, __func__, UI_EMBOSS);
874 
875  if (ui_but_is_color_gamma(but)) {
876  block->is_color_gamma_picker = true;
877  }
878 
879  if (but->block) {
880  /* if color block is invoked from a popup we wouldn't be able to set color properly
881  * this is because color picker will close popups first and then will try to figure
882  * out active button RNA, and of course it'll fail
883  */
884  show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0;
885  }
886 
887  copy_v3_v3(handle->retvec, but->editvec);
888 
889  ui_block_colorpicker(block, but, handle->retvec, show_picker);
890 
894 
896 
897  /* and lets go */
898  block->direction = UI_DIR_UP;
899 
900  return block;
901 }
902 
904 {
905  ColorPicker *cpicker = MEM_cnew<ColorPicker>(__func__);
906  BLI_addhead(&block->color_pickers.list, cpicker);
907 
908  return cpicker;
909 }
910 
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
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.c:49
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:232
void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:318
void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
Definition: math_color.c:54
void hex_to_rgb(const char *hexcol, float *r_r, float *r_g, float *r_b)
Definition: math_color.c:177
void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
Definition: math_color.c:292
void rgb_to_hsl_compat_v(const float rgb[3], float r_hsl[3])
Definition: math_color.c:287
void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
Definition: math_color.c:391
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK3_EX(pre, a, post)
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define STREQ(a, b)
#define TIP_(msgid)
#define IFACE_(msgid)
@ USER_CP_SQUARE_SV
@ USER_CP_CIRCLE_HSL
@ USER_CP_SQUARE_HS
@ USER_CP_SQUARE_HV
@ USER_CP_CIRCLE_HSV
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
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.
@ PROP_COLOR_GAMMA
Definition: RNA_types.h:165
#define C
Definition: RandGen.cpp:25
@ UI_BUT_ICON_LEFT
Definition: UI_interface.h:260
@ UI_BUT_TEXT_LEFT
Definition: UI_interface.h:259
void UI_but_flag_disable(uiBut *but, int flag)
Definition: interface.cc:5863
uiBut * uiDefButC(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:5196
#define UI_UNIT_Y
@ UI_BUT_UNDO
Definition: UI_interface.h:205
@ UI_EMBOSS
Definition: UI_interface.h:108
void UI_block_theme_style_set(uiBlock *block, char theme_style)
Definition: interface.cc:3634
@ UI_RETURN_UPDATE
Definition: UI_interface.h:181
@ UI_RETURN_CANCEL
Definition: UI_interface.h:173
@ UI_RETURN_OK
Definition: UI_interface.h:175
uiBut * uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:4806
uiBut * uiDefButF(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:5042
void UI_block_bounds_set_normal(struct uiBlock *block, int addval)
Definition: interface.cc:582
@ UI_BLOCK_THEME_STYLE_POPUP
Definition: UI_interface.h:770
@ UI_DIR_UP
Definition: UI_interface.h:123
void UI_but_drawflag_disable(uiBut *but, int flag)
Definition: interface.cc:5878
void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
Definition: interface.cc:6000
uiBut * uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:5280
void UI_block_align_begin(uiBlock *block)
Definition: interface.cc:3910
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
eButGradientType
Definition: UI_interface.h:399
@ UI_GRAD_L_ALT
Definition: UI_interface.h:408
@ UI_GRAD_SV
Definition: UI_interface.h:400
@ UI_GRAD_V_ALT
Definition: UI_interface.h:407
@ UI_GRAD_HV
Definition: UI_interface.h:401
@ UI_GRAD_HS
Definition: UI_interface.h:402
#define UI_UNIT_X
@ UI_BTYPE_BUT
Definition: UI_interface.h:330
@ UI_BTYPE_NUM_SLIDER
Definition: UI_interface.h:339
@ UI_BTYPE_HSVCIRCLE
Definition: UI_interface.h:368
@ UI_BTYPE_TEXT
Definition: UI_interface.h:332
@ UI_BTYPE_HSVCUBE
Definition: UI_interface.h:356
@ UI_BTYPE_LABEL
Definition: UI_interface.h:354
@ UI_BTYPE_ROW
Definition: UI_interface.h:331
uiBut * uiDefIconButO(uiBlock *block, int type, const char *opname, wmOperatorCallContext opcontext, int icon, int x, int y, short width, short height, const char *tip)
Definition: interface.cc:5608
@ UI_BLOCK_LOOP
Definition: UI_interface.h:135
@ UI_BLOCK_MOVEMOUSE_QUIT
Definition: UI_interface.h:143
@ UI_BLOCK_KEEP_OPEN
Definition: UI_interface.h:144
@ UI_BLOCK_POPUP
Definition: UI_interface.h:145
@ UI_BLOCK_OUT_1
Definition: UI_interface.h:146
void UI_block_align_end(uiBlock *block)
Definition: interface.cc:3923
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:201
unsigned int U
Definition: btGjkEpa3.h:78
uint col
void ui_but_update(uiBut *but)
Definition: interface.cc:3900
double ui_but_value_get(uiBut *but)
Definition: interface.cc:2492
void ui_but_value_set(uiBut *but, double value)
Definition: interface.cc:2557
void ui_but_v3_set(uiBut *but, const float vec[3])
Definition: interface.cc:2338
void ui_but_v3_get(uiBut *but, float vec[3])
Definition: interface.cc:2291
@ 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)
uiBlock * ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
void ui_perceptual_to_scene_linear_space(uiBut *but, float rgb[3])
void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3])
static void ui_colorpicker_rgba_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
#define PICKER_SPACE
static void ui_update_color_picker_buts_rgb(uiBut *from_but, uiBlock *block, ColorPicker *cpicker, const float rgb_scene_linear[3])
#define PICKER_TOTAL_W
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])
static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
static void ui_colorpicker_hsv_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
void ui_but_hsv_set(uiBut *but)
static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, const wmEvent *event)
static void ui_colorpicker_create_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
ColorPicker * ui_block_colorpicker_create(struct uiBlock *block)
static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba_scene_linear[4], bool show_picker)
void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3])
static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
bool ui_but_is_color_gamma(uiBut *but)
#define fabsf(x)
Definition: metal/compat.h:219
bool add(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
static const pxr::TfToken rgb("rgb", pxr::TfToken::Immortal)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:2879
void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
Definition: rna_access.c:1311
void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
Definition: rna_access.c:1274
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1015
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 struct bContext *C, struct uiBlock *, const struct wmEvent *)
eButGradientType gradient_type
void * custom_data
float * editvec
float hardmax
uiBlock * block
struct PropertyRNA * rnaprop
struct PointerRNA rnapoin
struct ARegion * region
short type
Definition: WM_types.h:678
@ WHEELUPMOUSE
@ WHEELDOWNMOUSE
PointerRNA * ptr
Definition: wm_files.c:3480