Blender  V2.93
interface_region_color_picker.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "MEM_guardedalloc.h"
31 
32 #include "DNA_userdef_types.h"
33 
34 #include "BLI_listbase.h"
35 #include "BLI_math.h"
36 #include "BLI_string.h"
37 #include "BLI_utildefines.h"
38 
39 #include "BKE_context.h"
40 
41 #include "WM_types.h"
42 
43 #include "RNA_access.h"
44 
45 #include "UI_interface.h"
46 
47 #include "BLT_translation.h"
48 
49 #include "ED_screen.h"
50 
51 #include "IMB_colormanagement.h"
52 
53 #include "interface_intern.h"
54 
59 };
60 
61 /* -------------------------------------------------------------------- */
65 static void ui_color_picker_rgb_round(float rgb[3])
66 {
67  /* Handle small rounding errors in color space conversions. Doing these for
68  * all color space conversions would be expensive, but for the color picker
69  * we can do the extra work. */
70  for (int i = 0; i < 3; i++) {
71  if (fabsf(rgb[i]) < 1e-6f) {
72  rgb[i] = 0.0f;
73  }
74  else if (fabsf(1.0f - rgb[i]) < 1e-6f) {
75  rgb[i] = 1.0f;
76  }
77  }
78 }
79 
80 void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3])
81 {
82  /* Convert RGB to HSV, remaining as compatible as possible with the existing
83  * r_hsv value (for example when value goes to zero, preserve the hue). */
84  switch (U.color_picker_type) {
85  case USER_CP_CIRCLE_HSL:
86  rgb_to_hsl_compat_v(rgb, r_cp);
87  break;
88  default:
89  rgb_to_hsv_compat_v(rgb, r_cp);
90  break;
91  }
92 }
93 
94 void ui_color_picker_rgb_to_hsv(const float rgb[3], float r_cp[3])
95 {
96  switch (U.color_picker_type) {
97  case USER_CP_CIRCLE_HSL:
98  rgb_to_hsl_v(rgb, r_cp);
99  break;
100  default:
101  rgb_to_hsv_v(rgb, r_cp);
102  break;
103  }
104 }
105 
106 void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3])
107 {
108  switch (U.color_picker_type) {
109  case USER_CP_CIRCLE_HSL:
110  hsl_to_rgb_v(r_cp, rgb);
111  break;
112  default:
113  hsv_to_rgb_v(r_cp, rgb);
114  break;
115  }
116 }
117 
118 /* Returns true if the button is for a color with gamma baked in,
119  * or if it's a color picker for such a button. */
121 {
122  if (but->rnaprop) {
124  return true;
125  }
126  }
127 
128  return but->block->is_color_gamma_picker;
129 }
130 
132 {
133  /* Map to color picking space for HSV values and HSV cube/circle,
134  * assuming it is more perceptually linear than the scene linear
135  * space for intuitive color picking. */
136  if (!ui_but_is_color_gamma(but)) {
139  }
140 }
141 
143 {
144  if (!ui_but_is_color_gamma(but)) {
147  }
148 }
149 
152 /* -------------------------------------------------------------------- */
157  uiBut *from_but,
158  const float rgb_scene_linear[3])
159 {
160  /* Convert from RGB to HSV in scene linear space color for number editing. */
161  if (cpicker->is_init == false) {
162  ui_color_picker_rgb_to_hsv(rgb_scene_linear, cpicker->hsv_scene_linear);
163  }
164  else {
165  ui_color_picker_rgb_to_hsv_compat(rgb_scene_linear, cpicker->hsv_scene_linear);
166  }
167 
168  /* Convert from RGB to HSV in perceptually linear space for picker widgets. */
169  float rgb_perceptual[3];
170  copy_v3_v3(rgb_perceptual, rgb_scene_linear);
171  if (from_but) {
172  ui_scene_linear_to_perceptual_space(from_but, rgb_perceptual);
173  }
174 
175  if (cpicker->is_init == false) {
176  ui_color_picker_rgb_to_hsv(rgb_perceptual, cpicker->hsv_perceptual);
177  copy_v3_v3(cpicker->hsv_perceptual_init, cpicker->hsv_perceptual);
178  }
179  else {
180  ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, cpicker->hsv_perceptual);
181  }
182 
183  cpicker->is_init = true;
184 }
185 
186 /* for picker, while editing hsv */
188 {
189  float rgb_perceptual[3];
190  ColorPicker *cpicker = but->custom_data;
191  float *hsv_perceptual = cpicker->hsv_perceptual;
192 
193  ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_perceptual);
194 
195  ui_but_v3_set(but, rgb_perceptual);
196 }
197 
198 /* Updates all buttons who share the same color picker as the one passed
199  * also used by small picker, be careful with name checks below... */
201  uiBlock *block,
202  ColorPicker *cpicker,
203  const float rgb_scene_linear[3])
204 {
205  ui_color_picker_update_hsv(cpicker, from_but, rgb_scene_linear);
206 
207  /* this updates button strings,
208  * is hackish... but button pointers are on stack of caller function */
209  LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
210  if (bt->custom_data != cpicker) {
211  continue;
212  }
213 
214  if (bt->rnaprop) {
215  ui_but_v3_set(bt, rgb_scene_linear);
216 
217  /* original button that created the color picker already does undo
218  * push, so disable it on RNA buttons in the color picker block */
220  }
221  else if (STREQ(bt->str, "Hex: ")) {
222  float rgb_hex[3];
223  uchar rgb_hex_uchar[3];
224  char col[16];
225 
226  /* Hex code is assumed to be in sRGB space
227  * (coming from other applications, web, etc) */
228  copy_v3_v3(rgb_hex, rgb_scene_linear);
229  if (from_but && !ui_but_is_color_gamma(from_but)) {
231  ui_color_picker_rgb_round(rgb_hex);
232  }
233 
234  rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
235  BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
236 
237  strcpy(bt->poin, col);
238  }
239  else if (bt->str[1] == ' ') {
240  if (bt->str[0] == 'R') {
241  ui_but_value_set(bt, rgb_scene_linear[0]);
242  }
243  else if (bt->str[0] == 'G') {
244  ui_but_value_set(bt, rgb_scene_linear[1]);
245  }
246  else if (bt->str[0] == 'B') {
247  ui_but_value_set(bt, rgb_scene_linear[2]);
248  }
249  else if (bt->str[0] == 'H') {
250  ui_but_value_set(bt, cpicker->hsv_scene_linear[0]);
251  }
252  else if (bt->str[0] == 'S') {
253  ui_but_value_set(bt, cpicker->hsv_scene_linear[1]);
254  }
255  else if (bt->str[0] == 'V') {
256  ui_but_value_set(bt, cpicker->hsv_scene_linear[2]);
257  }
258  else if (bt->str[0] == 'L') {
259  ui_but_value_set(bt, cpicker->hsv_scene_linear[2]);
260  }
261  }
262 
263  ui_but_update(bt);
264  }
265 }
266 
267 static void ui_colorpicker_rgba_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
268 {
269  uiBut *but = (uiBut *)bt1;
270  uiPopupBlockHandle *popup = but->block->handle;
271  PropertyRNA *prop = but->rnaprop;
272  PointerRNA ptr = but->rnapoin;
273  float rgb_scene_linear[4];
274 
275  if (prop) {
276  RNA_property_float_get_array(&ptr, prop, rgb_scene_linear);
277  ui_update_color_picker_buts_rgb(but, but->block, but->custom_data, rgb_scene_linear);
278  }
279 
280  if (popup) {
281  popup->menuretval = UI_RETURN_UPDATE;
282  }
283 }
284 
285 static void ui_colorpicker_hsv_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
286 {
287  uiBut *but = (uiBut *)bt1;
288  uiPopupBlockHandle *popup = but->block->handle;
289  float rgb_scene_linear[3];
290  ColorPicker *cpicker = but->custom_data;
291 
292  ui_color_picker_hsv_to_rgb(cpicker->hsv_scene_linear, rgb_scene_linear);
293  ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb_scene_linear);
294 
295  if (popup) {
296  popup->menuretval = UI_RETURN_UPDATE;
297  }
298 }
299 
300 static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
301 {
302  uiBut *but = (uiBut *)bt1;
303  uiPopupBlockHandle *popup = but->block->handle;
304  ColorPicker *cpicker = but->custom_data;
305  char *hexcol = (char *)hexcl;
306  float rgb[3];
307 
308  hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2);
309 
310  /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
311  if (!ui_but_is_color_gamma(but)) {
314  }
315 
316  ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
317 
318  if (popup) {
319  popup->menuretval = UI_RETURN_UPDATE;
320  }
321 }
322 
323 static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
324 {
325  uiBut *but = (uiBut *)bt1;
326  uiPopupBlockHandle *popup = but->block->handle;
327 
328  if (popup) {
329  ColorPicker *cpicker = but->custom_data;
330  BLI_assert(cpicker->is_init);
331  popup->menuretval = (equals_v3v3(cpicker->hsv_perceptual, cpicker->hsv_perceptual_init) ?
333  UI_RETURN_OK);
334  }
335 }
336 
337 static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormode)
338 {
339  /* tag buttons */
340  LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
341  if ((bt->func == ui_colorpicker_rgba_update_cb) && (bt->type == UI_BTYPE_NUM_SLIDER) &&
342  (bt->rnaindex != 3)) {
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  else if (bt->func == ui_colorpicker_hex_rna_cb || bt->type == UI_BTYPE_LABEL) {
351  /* HEX input or gamma correction status label */
352  SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HEX), UI_HIDDEN);
353  }
354  }
355 }
356 
357 static void ui_colorpicker_create_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
358 {
359  uiBut *bt = bt1;
360  const short colormode = ui_but_value_get(bt);
361  ui_colorpicker_hide_reveal(bt->block, colormode);
362 }
363 
364 #define PICKER_H (7.5f * U.widget_unit)
365 #define PICKER_W (7.5f * U.widget_unit)
366 #define PICKER_SPACE (0.3f * U.widget_unit)
367 #define PICKER_BAR (0.7f * U.widget_unit)
368 
369 #define PICKER_TOTAL_W (PICKER_W + PICKER_SPACE + PICKER_BAR)
370 
371 static void ui_colorpicker_circle(uiBlock *block,
372  PointerRNA *ptr,
373  PropertyRNA *prop,
374  ColorPicker *cpicker)
375 {
376  uiBut *bt;
377  uiButHSVCube *hsv_but;
378 
379  /* HS circle */
380  bt = uiDefButR_prop(block,
382  0,
383  "",
384  0,
385  0,
386  PICKER_H,
387  PICKER_W,
388  ptr,
389  prop,
390  -1,
391  0.0,
392  0.0,
393  0.0,
394  0,
395  TIP_("Color"));
397  bt->custom_data = cpicker;
398 
399  /* value */
400  if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
401  hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
403  0,
404  "",
406  0,
407  PICKER_BAR,
408  PICKER_H,
409  ptr,
410  prop,
411  -1,
412  0.0,
413  0.0,
414  0,
415  0,
416  "Lightness");
417  hsv_but->gradient_type = UI_GRAD_L_ALT;
418  UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
419  }
420  else {
421  hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
423  0,
424  "",
426  0,
427  PICKER_BAR,
428  PICKER_H,
429  ptr,
430  prop,
431  -1,
432  0.0,
433  0.0,
434  0,
435  0,
436  TIP_("Value"));
437  hsv_but->gradient_type = UI_GRAD_V_ALT;
438  UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
439  }
440  hsv_but->but.custom_data = cpicker;
441 }
442 
443 static void ui_colorpicker_square(uiBlock *block,
444  PointerRNA *ptr,
445  PropertyRNA *prop,
447  ColorPicker *cpicker)
448 {
449  uiButHSVCube *hsv_but;
450 
452 
453  /* HS square */
454  hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
456  0,
457  "",
458  0,
461  PICKER_H,
462  ptr,
463  prop,
464  -1,
465  0.0,
466  0.0,
467  0,
468  0,
469  TIP_("Color"));
470  hsv_but->gradient_type = type;
471  UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
472  hsv_but->but.custom_data = cpicker;
473 
474  /* value */
475  hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
477  0,
478  "",
479  0,
480  0,
482  PICKER_BAR,
483  ptr,
484  prop,
485  -1,
486  0.0,
487  0.0,
488  0,
489  0,
490  TIP_("Value"));
491  hsv_but->gradient_type = type + 3;
492  UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
493  hsv_but->but.custom_data = cpicker;
494 }
495 
496 /* a HS circle, V slider, rgb/hsv/hex sliders */
497 static void ui_block_colorpicker(uiBlock *block,
498  uiBut *from_but,
499  float rgba_scene_linear[4],
500  bool show_picker)
501 {
502  /* ePickerType */
503  static char colormode = 1;
504  uiBut *bt;
505  int width, butwidth;
506  static char hexcol[128];
507  float softmin, softmax, hardmin, hardmax, step, precision;
508  int yco;
509  ColorPicker *cpicker = ui_block_colorpicker_create(block);
510  PointerRNA *ptr = &from_but->rnapoin;
511  PropertyRNA *prop = from_but->rnaprop;
512 
514  butwidth = width - 1.5f * UI_UNIT_X;
515 
516  /* sneaky way to check for alpha */
517  rgba_scene_linear[3] = FLT_MAX;
518 
519  RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
520  RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
521  RNA_property_float_get_array(ptr, prop, rgba_scene_linear);
522 
523  ui_color_picker_update_hsv(cpicker, from_but, rgba_scene_linear);
524 
525  /* when the softmax isn't defined in the RNA,
526  * using very large numbers causes sRGB/linear round trip to fail. */
527  if (softmax == FLT_MAX) {
528  softmax = 1.0f;
529  }
530 
531  switch (U.color_picker_type) {
532  case USER_CP_SQUARE_SV:
533  ui_colorpicker_square(block, ptr, prop, UI_GRAD_SV, cpicker);
534  break;
535  case USER_CP_SQUARE_HS:
536  ui_colorpicker_square(block, ptr, prop, UI_GRAD_HS, cpicker);
537  break;
538  case USER_CP_SQUARE_HV:
539  ui_colorpicker_square(block, ptr, prop, UI_GRAD_HV, cpicker);
540  break;
541 
542  /* user default */
543  case USER_CP_CIRCLE_HSV:
544  case USER_CP_CIRCLE_HSL:
545  default:
546  ui_colorpicker_circle(block, ptr, prop, cpicker);
547  break;
548  }
549 
550  /* mode */
551  yco = -1.5f * UI_UNIT_Y;
552  UI_block_align_begin(block);
553  bt = uiDefButC(block,
554  UI_BTYPE_ROW,
555  0,
556  IFACE_("RGB"),
557  0,
558  yco,
559  width / 3,
560  UI_UNIT_Y,
561  &colormode,
562  0.0,
563  (float)PICKER_TYPE_RGB,
564  0,
565  0,
566  "");
570  bt->custom_data = cpicker;
571  bt = uiDefButC(block,
572  UI_BTYPE_ROW,
573  0,
574  IFACE_((U.color_picker_type == USER_CP_CIRCLE_HSL) ? "HSL" : "HSV"),
575  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  bt = uiDefButC(block,
590  UI_BTYPE_ROW,
591  0,
592  IFACE_("Hex"),
593  2 * width / 3,
594  yco,
595  width / 3,
596  UI_UNIT_Y,
597  &colormode,
598  0.0,
600  0,
601  0,
602  "");
606  bt->custom_data = cpicker;
607  UI_block_align_end(block);
608 
609  yco = -3.0f * UI_UNIT_Y;
610  if (show_picker) {
611  bt = uiDefIconButO(block,
612  UI_BTYPE_BUT,
613  "UI_OT_eyedropper_color",
615  ICON_EYEDROPPER,
616  butwidth + 10,
617  yco,
618  UI_UNIT_X,
619  UI_UNIT_Y,
620  NULL);
624  bt->custom_data = cpicker;
625  }
626 
627  /* Note: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */
628 
629  /* RGB values */
630  UI_block_align_begin(block);
631  bt = uiDefButR_prop(block,
633  0,
634  IFACE_("R:"),
635  0,
636  yco,
637  butwidth,
638  UI_UNIT_Y,
639  ptr,
640  prop,
641  0,
642  0.0,
643  0.0,
644  0,
645  3,
646  TIP_("Red"));
648  bt->custom_data = cpicker;
649  bt = uiDefButR_prop(block,
651  0,
652  IFACE_("G:"),
653  0,
654  yco -= UI_UNIT_Y,
655  butwidth,
656  UI_UNIT_Y,
657  ptr,
658  prop,
659  1,
660  0.0,
661  0.0,
662  0,
663  3,
664  TIP_("Green"));
666  bt->custom_data = cpicker;
667  bt = uiDefButR_prop(block,
669  0,
670  IFACE_("B:"),
671  0,
672  yco -= UI_UNIT_Y,
673  butwidth,
674  UI_UNIT_Y,
675  ptr,
676  prop,
677  2,
678  0.0,
679  0.0,
680  0,
681  3,
682  TIP_("Blue"));
684  bt->custom_data = cpicker;
685 
686  /* Could use:
687  * uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND | UI_ITEM_R_SLIDER, "", ICON_NONE);
688  * but need to use UI_but_func_set for updating other fake buttons */
689 
690  /* HSV values */
691  yco = -3.0f * UI_UNIT_Y;
692  UI_block_align_begin(block);
693  bt = uiDefButF(block,
695  0,
696  IFACE_("H:"),
697  0,
698  yco,
699  butwidth,
700  UI_UNIT_Y,
701  cpicker->hsv_scene_linear,
702  0.0,
703  1.0,
704  10,
705  3,
706  TIP_("Hue"));
709  bt->custom_data = cpicker;
710  bt = uiDefButF(block,
712  0,
713  IFACE_("S:"),
714  0,
715  yco -= UI_UNIT_Y,
716  butwidth,
717  UI_UNIT_Y,
718  cpicker->hsv_scene_linear + 1,
719  0.0,
720  1.0,
721  10,
722  3,
723  TIP_("Saturation"));
726  bt->custom_data = cpicker;
727  if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
728  bt = uiDefButF(block,
730  0,
731  IFACE_("L:"),
732  0,
733  yco -= UI_UNIT_Y,
734  butwidth,
735  UI_UNIT_Y,
736  cpicker->hsv_scene_linear + 2,
737  0.0,
738  1.0,
739  10,
740  3,
741  TIP_("Lightness"));
742  }
743  else {
744  bt = uiDefButF(block,
746  0,
747  IFACE_("V:"),
748  0,
749  yco -= UI_UNIT_Y,
750  butwidth,
751  UI_UNIT_Y,
752  cpicker->hsv_scene_linear + 2,
753  0.0,
754  softmax,
755  10,
756  3,
757  TIP_("Value"));
758  }
760 
761  bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */
763  bt->custom_data = cpicker;
764 
765  UI_block_align_end(block);
766 
767  if (rgba_scene_linear[3] != FLT_MAX) {
768  bt = uiDefButR_prop(block,
770  0,
771  IFACE_("A: "),
772  0,
773  yco -= UI_UNIT_Y,
774  butwidth,
775  UI_UNIT_Y,
776  ptr,
777  prop,
778  3,
779  0.0,
780  0.0,
781  0,
782  3,
783  TIP_("Alpha"));
785  bt->custom_data = cpicker;
786  }
787  else {
788  rgba_scene_linear[3] = 1.0f;
789  }
790 
791  /* Hex color is in sRGB space. */
792  float rgb_hex[3];
793  uchar rgb_hex_uchar[3];
794 
795  copy_v3_v3(rgb_hex, rgba_scene_linear);
796 
797  if (!ui_but_is_color_gamma(from_but)) {
799  ui_color_picker_rgb_round(rgb_hex);
800  }
801 
802  rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
803  BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
804 
805  yco = -3.0f * UI_UNIT_Y;
806  bt = uiDefBut(block,
808  0,
809  IFACE_("Hex: "),
810  0,
811  yco,
812  butwidth,
813  UI_UNIT_Y,
814  hexcol,
815  0,
816  8,
817  0,
818  0,
819  TIP_("Hex triplet for color (#RRGGBB)"));
822  bt->custom_data = cpicker;
823  uiDefBut(block,
825  0,
826  IFACE_("(Gamma Corrected)"),
827  0,
828  yco - UI_UNIT_Y,
829  butwidth,
830  UI_UNIT_Y,
831  NULL,
832  0.0,
833  0.0,
834  0,
835  0,
836  "");
837 
838  ui_colorpicker_hide_reveal(block, colormode);
839 }
840 
842  uiBlock *block,
843  const wmEvent *event)
844 {
845  float add = 0.0f;
846 
847  if (event->type == WHEELUPMOUSE) {
848  add = 0.05f;
849  }
850  else if (event->type == WHEELDOWNMOUSE) {
851  add = -0.05f;
852  }
853 
854  if (add != 0.0f) {
855  LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
856  if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) {
857  uiPopupBlockHandle *popup = block->handle;
858  ColorPicker *cpicker = but->custom_data;
859  float *hsv_perceptual = cpicker->hsv_perceptual;
860 
861  float rgb_perceptual[3];
862  ui_but_v3_get(but, rgb_perceptual);
863  ui_scene_linear_to_perceptual_space(but, rgb_perceptual);
864  ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, hsv_perceptual);
865 
866  hsv_perceptual[2] = clamp_f(hsv_perceptual[2] + add, 0.0f, 1.0f);
867 
868  float rgb_scene_linear[3];
869  ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_scene_linear);
870  ui_perceptual_to_scene_linear_space(but, rgb_scene_linear);
871  ui_but_v3_set(but, rgb_scene_linear);
872 
873  ui_update_color_picker_buts_rgb(but, block, cpicker, rgb_scene_linear);
874  if (popup) {
875  popup->menuretval = UI_RETURN_UPDATE;
876  }
877 
878  return 1;
879  }
880  }
881  }
882  return 0;
883 }
884 
886 {
887  uiBut *but = arg_but;
888  uiBlock *block;
889  bool show_picker = true;
890 
891  block = UI_block_begin(C, handle->region, __func__, UI_EMBOSS);
892 
893  if (ui_but_is_color_gamma(but)) {
894  block->is_color_gamma_picker = true;
895  }
896 
897  if (but->block) {
898  /* if color block is invoked from a popup we wouldn't be able to set color properly
899  * this is because color picker will close popups first and then will try to figure
900  * out active button RNA, and of course it'll fail
901  */
902  show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0;
903  }
904 
905  copy_v3_v3(handle->retvec, but->editvec);
906 
907  ui_block_colorpicker(block, but, handle->retvec, show_picker);
908 
912 
914 
915  /* and lets go */
916  block->direction = UI_DIR_UP;
917 
918  return block;
919 }
920 
922 {
923  ColorPicker *cpicker = MEM_callocN(sizeof(ColorPicker), "color_picker");
924  BLI_addhead(&block->color_pickers.list, cpicker);
925 
926  return cpicker;
927 }
928 
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
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:68
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:254
void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:342
void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
Definition: math_color.c:74
void hex_to_rgb(const char *hexcol, float *r_r, float *r_g, float *r_b)
Definition: math_color.c:198
void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
Definition: math_color.c:315
void rgb_to_hsl_compat_v(const float rgb[3], float r_hsl[3])
Definition: math_color.c:309
void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
Definition: math_color.c:422
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:86
unsigned int uint
Definition: BLI_sys_types.h:83
#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 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
_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
void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3])
void IMB_colormanagement_scene_linear_to_srgb_v3(float pixel[3])
void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3])
void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3])
Read Guarded memory(de)allocation.
@ PROP_COLOR_GAMMA
Definition: RNA_types.h:151
#define C
Definition: RandGen.cpp:39
void UI_but_flag_disable(uiBut *but, int flag)
Definition: interface.c:6082
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.c:5082
#define UI_UNIT_Y
@ UI_BUT_ICON_LEFT
Definition: UI_interface.h:260
@ UI_BUT_TEXT_LEFT
Definition: UI_interface.h:259
@ UI_EMBOSS
Definition: UI_interface.h:107
void UI_block_theme_style_set(uiBlock *block, char theme_style)
Definition: interface.c:3547
@ UI_BUT_UNDO
Definition: UI_interface.h:208
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.c:4687
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.c:4896
void UI_block_bounds_set_normal(struct uiBlock *block, int addval)
Definition: interface.c:580
void UI_but_drawflag_disable(uiBut *but, int flag)
Definition: interface.c:6097
@ UI_BLOCK_LOOP
Definition: UI_interface.h:140
@ UI_BLOCK_MOVEMOUSE_QUIT
Definition: UI_interface.h:148
@ UI_BLOCK_KEEP_OPEN
Definition: UI_interface.h:149
@ UI_BLOCK_POPUP
Definition: UI_interface.h:150
@ UI_BLOCK_OUT_1
Definition: UI_interface.h:151
void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
Definition: interface.c:6294
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.c:5166
void UI_block_align_begin(uiBlock *block)
Definition: interface.c:3821
@ UI_RETURN_UPDATE
Definition: UI_interface.h:184
@ UI_RETURN_CANCEL
Definition: UI_interface.h:176
@ UI_RETURN_OK
Definition: UI_interface.h:178
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
eButGradientType
Definition: UI_interface.h:398
@ UI_GRAD_L_ALT
Definition: UI_interface.h:407
@ UI_GRAD_SV
Definition: UI_interface.h:399
@ UI_GRAD_V_ALT
Definition: UI_interface.h:406
@ UI_GRAD_HV
Definition: UI_interface.h:400
@ UI_GRAD_HS
Definition: UI_interface.h:401
@ UI_DIR_UP
Definition: UI_interface.h:122
#define UI_UNIT_X
@ UI_BTYPE_BUT
Definition: UI_interface.h:334
@ UI_BTYPE_NUM_SLIDER
Definition: UI_interface.h:343
@ UI_BTYPE_HSVCIRCLE
Definition: UI_interface.h:372
@ UI_BTYPE_TEXT
Definition: UI_interface.h:336
@ UI_BTYPE_HSVCUBE
Definition: UI_interface.h:360
@ UI_BTYPE_LABEL
Definition: UI_interface.h:358
@ UI_BTYPE_ROW
Definition: UI_interface.h:335
@ UI_BLOCK_THEME_STYLE_POPUP
Definition: UI_interface.h:671
uiBut * uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, int x, int y, short width, short height, const char *tip)
Definition: interface.c:5587
void UI_block_align_end(uiBlock *block)
Definition: interface.c:3834
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:197
unsigned int U
Definition: btGjkEpa3.h:78
uint col
void ui_but_update(uiBut *but)
Definition: interface.c:3811
double ui_but_value_get(uiBut *but)
Definition: interface.c:2431
void ui_but_value_set(uiBut *but, double value)
Definition: interface.c:2496
void ui_but_v3_set(uiBut *but, const float vec[3])
Definition: interface.c:2279
void ui_but_v3_get(uiBut *but, float vec[3])
Definition: interface.c:2230
@ UI_HIDDEN
static void ui_color_picker_rgb_round(float rgb[3])
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))
static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormode)
#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 PICKER_BAR
#define fabsf(x)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static void add(GHash *messages, MemArena *memarena, const Message *msg)
Definition: msgfmt.c:268
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:3033
void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
Definition: rna_access.c:1466
void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
Definition: rna_access.c:1426
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1160
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:577
@ WHEELUPMOUSE
@ WHEELDOWNMOUSE
PointerRNA * ptr
Definition: wm_files.c:3157