Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-11-03 12:26:35 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-11-03 12:57:09 +0300
commit2a87bd89951204a5dd15b60ba86cbba72fc3b088 (patch)
treed4eaa0a5bab4f6ca0da0b3d1c0fa8fa8272c0f6a /source/blender/editors/interface/interface_region_color_picker.c
parentd19d094ca9bb4f05b0f95c9f168340050864f103 (diff)
Cleanup: split interface_regions.c
Each region type is quite separate and file was getting too big.
Diffstat (limited to 'source/blender/editors/interface/interface_region_color_picker.c')
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c650
1 files changed, 650 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
new file mode 100644
index 00000000000..4309e913d9e
--- /dev/null
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -0,0 +1,650 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_region_color_picker.c
+ * \ingroup edinterface
+ *
+ * Color Picker Region & Color Utils
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_userdef_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+
+#include "WM_types.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "ED_screen.h"
+
+#include "IMB_colormanagement.h"
+
+#include "interface_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Color Conversion
+ * \{ */
+
+void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3])
+{
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ rgb_to_hsl_compat_v(rgb, r_cp);
+ break;
+ default:
+ rgb_to_hsv_compat_v(rgb, r_cp);
+ break;
+ }
+}
+
+void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3])
+{
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ rgb_to_hsl_v(rgb, r_cp);
+ break;
+ default:
+ rgb_to_hsv_v(rgb, r_cp);
+ break;
+ }
+}
+
+void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3])
+{
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ hsl_to_rgb_v(r_cp, rgb);
+ break;
+ default:
+ hsv_to_rgb_v(r_cp, rgb);
+ break;
+ }
+}
+
+void ui_color_picker_to_rgb(float r_cp0, float r_cp1, float r_cp2, float *r, float *g, float *b)
+{
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ hsl_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b);
+ break;
+ default:
+ hsv_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b);
+ break;
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Color Picker
+ * \{ */
+
+/* for picker, while editing hsv */
+void ui_but_hsv_set(uiBut *but)
+{
+ float col[3];
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+
+ ui_color_picker_to_rgb_v(hsv, col);
+
+ ui_but_v3_set(but, col);
+}
+
+/* Updates all buttons who share the same color picker as the one passed
+ * also used by small picker, be careful with name checks below... */
+static void ui_update_color_picker_buts_rgb(
+ uiBlock *block, ColorPicker *cpicker, const float rgb[3], bool is_display_space)
+{
+ uiBut *bt;
+ float *hsv = cpicker->color_data;
+ struct ColorManagedDisplay *display = NULL;
+ /* this is to keep the H and S value when V is equal to zero
+ * and we are working in HSV mode, of course!
+ */
+ if (is_display_space) {
+ ui_rgb_to_color_picker_compat_v(rgb, hsv);
+ }
+ else {
+ /* we need to convert to display space to use hsv, because hsv is stored in display space */
+ float rgb_display[3];
+
+ copy_v3_v3(rgb_display, rgb);
+ ui_block_cm_to_display_space_v3(block, rgb_display);
+ ui_rgb_to_color_picker_compat_v(rgb_display, hsv);
+ }
+
+ if (block->color_profile)
+ display = ui_block_cm_display_get(block);
+
+ /* this updates button strings, is hackish... but button pointers are on stack of caller function */
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt->custom_data != cpicker)
+ continue;
+
+ if (bt->rnaprop) {
+ ui_but_v3_set(bt, rgb);
+
+ /* original button that created the color picker already does undo
+ * push, so disable it on RNA buttons in the color picker block */
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ }
+ else if (STREQ(bt->str, "Hex: ")) {
+ float rgb_gamma[3];
+ unsigned char rgb_gamma_uchar[3];
+ double intpart;
+ char col[16];
+
+ /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
+
+ copy_v3_v3(rgb_gamma, rgb);
+
+ if (display) {
+ /* make a display version, for Hex code */
+ IMB_colormanagement_scene_linear_to_display_v3(rgb_gamma, display);
+ }
+
+ if (rgb_gamma[0] > 1.0f) rgb_gamma[0] = modf(rgb_gamma[0], &intpart);
+ if (rgb_gamma[1] > 1.0f) rgb_gamma[1] = modf(rgb_gamma[1], &intpart);
+ if (rgb_gamma[2] > 1.0f) rgb_gamma[2] = modf(rgb_gamma[2], &intpart);
+
+ rgb_float_to_uchar(rgb_gamma_uchar, rgb_gamma);
+ BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3_EX((uint), rgb_gamma_uchar, ));
+
+ strcpy(bt->poin, col);
+ }
+ else if (bt->str[1] == ' ') {
+ if (bt->str[0] == 'R') {
+ ui_but_value_set(bt, rgb[0]);
+ }
+ else if (bt->str[0] == 'G') {
+ ui_but_value_set(bt, rgb[1]);
+ }
+ else if (bt->str[0] == 'B') {
+ ui_but_value_set(bt, rgb[2]);
+ }
+ else if (bt->str[0] == 'H') {
+ ui_but_value_set(bt, hsv[0]);
+ }
+ else if (bt->str[0] == 'S') {
+ ui_but_value_set(bt, hsv[1]);
+ }
+ else if (bt->str[0] == 'V') {
+ ui_but_value_set(bt, hsv[2]);
+ }
+ else if (bt->str[0] == 'L') {
+ ui_but_value_set(bt, hsv[2]);
+ }
+ }
+
+ ui_but_update(bt);
+ }
+}
+
+static void ui_colorpicker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+{
+ uiBut *but = (uiBut *)bt1;
+ uiPopupBlockHandle *popup = but->block->handle;
+ PropertyRNA *prop = but->rnaprop;
+ PointerRNA ptr = but->rnapoin;
+ float rgb[4];
+
+ if (prop) {
+ RNA_property_float_get_array(&ptr, prop, rgb);
+ ui_update_color_picker_buts_rgb(
+ but->block, but->custom_data, rgb, (RNA_property_subtype(prop) == PROP_COLOR_GAMMA));
+ }
+
+ if (popup)
+ popup->menuretval = UI_RETURN_UPDATE;
+}
+
+static void ui_color_wheel_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+{
+ uiBut *but = (uiBut *)bt1;
+ uiPopupBlockHandle *popup = but->block->handle;
+ float rgb[3];
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
+
+ ui_color_picker_to_rgb_v(hsv, rgb);
+
+ /* hsv is saved in display space so convert back */
+ if (use_display_colorspace) {
+ ui_block_cm_to_scene_linear_v3(but->block, rgb);
+ }
+
+ ui_update_color_picker_buts_rgb(but->block, cpicker, rgb, !use_display_colorspace);
+
+ if (popup)
+ popup->menuretval = UI_RETURN_UPDATE;
+}
+
+static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
+{
+ uiBut *but = (uiBut *)bt1;
+ uiPopupBlockHandle *popup = but->block->handle;
+ ColorPicker *cpicker = but->custom_data;
+ char *hexcol = (char *)hexcl;
+ float rgb[3];
+
+ hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2);
+
+ /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
+ if (but->block->color_profile) {
+ /* so we need to linearise it for Blender */
+ ui_block_cm_to_scene_linear_v3(but->block, rgb);
+ }
+
+ ui_update_color_picker_buts_rgb(but->block, cpicker, rgb, false);
+
+ if (popup)
+ popup->menuretval = UI_RETURN_UPDATE;
+}
+
+static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+{
+ uiBut *but = (uiBut *)bt1;
+ uiPopupBlockHandle *popup = but->block->handle;
+
+ if (popup)
+ popup->menuretval = UI_RETURN_OK;
+}
+
+static void ui_colorpicker_hide_reveal(uiBlock *block, short colormode)
+{
+ uiBut *bt;
+
+ /* tag buttons */
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if ((bt->func == ui_colorpicker_rna_cb) && bt->type == UI_BTYPE_NUM_SLIDER && bt->rnaindex != 3) {
+ /* RGB sliders (color circle and alpha are always shown) */
+ if (colormode == 0) bt->flag &= ~UI_HIDDEN;
+ else bt->flag |= UI_HIDDEN;
+ }
+ else if (bt->func == ui_color_wheel_rna_cb) {
+ /* HSV sliders */
+ if (colormode == 1) bt->flag &= ~UI_HIDDEN;
+ else bt->flag |= UI_HIDDEN;
+ }
+ else if (bt->func == ui_colorpicker_hex_rna_cb || bt->type == UI_BTYPE_LABEL) {
+ /* hex input or gamma correction status label */
+ if (colormode == 2) bt->flag &= ~UI_HIDDEN;
+ else bt->flag |= UI_HIDDEN;
+ }
+ }
+}
+
+static void ui_colorpicker_create_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+{
+ uiBut *bt = bt1;
+ short colormode = ui_but_value_get(bt);
+ ui_colorpicker_hide_reveal(bt->block, colormode);
+}
+
+#define PICKER_H (7.5f * U.widget_unit)
+#define PICKER_W (7.5f * U.widget_unit)
+#define PICKER_SPACE (0.3f * U.widget_unit)
+#define PICKER_BAR (0.7f * U.widget_unit)
+
+#define PICKER_TOTAL_W (PICKER_W + PICKER_SPACE + PICKER_BAR)
+
+static void ui_colorpicker_circle(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, ColorPicker *cpicker)
+{
+ uiBut *bt;
+
+ /* HS circle */
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W,
+ ptr, prop, -1, 0.0, 0.0, 0.0, 0, TIP_("Color"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+
+ /* value */
+ if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H,
+ ptr, prop, -1, 0.0, 0.0, UI_GRAD_L_ALT, 0, "Lightness");
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ }
+ else {
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H,
+ ptr, prop, -1, 0.0, 0.0, UI_GRAD_V_ALT, 0, TIP_("Value"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ }
+ bt->custom_data = cpicker;
+}
+
+
+static void ui_colorpicker_square(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int type, ColorPicker *cpicker)
+{
+ uiBut *bt;
+ int bartype = type + 3;
+
+ /* HS square */
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_HSVCUBE, 0, "", 0, PICKER_BAR + PICKER_SPACE, PICKER_TOTAL_W, PICKER_H,
+ ptr, prop, -1, 0.0, 0.0, type, 0, TIP_("Color"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+
+ /* value */
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR,
+ ptr, prop, -1, 0.0, 0.0, bartype, 0, TIP_("Value"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+}
+
+/* a HS circle, V slider, rgb/hsv/hex sliders */
+static void ui_block_colorpicker(
+ uiBlock *block, float rgba[4], PointerRNA *ptr, PropertyRNA *prop, bool show_picker)
+{
+ static short colormode = 0; /* temp? 0=rgb, 1=hsv, 2=hex */
+ uiBut *bt;
+ int width, butwidth;
+ static char tip[50];
+ static char hexcol[128];
+ float rgb_gamma[3];
+ unsigned char rgb_gamma_uchar[3];
+ float softmin, softmax, hardmin, hardmax, step, precision;
+ int yco;
+ ColorPicker *cpicker = ui_block_colorpicker_create(block);
+ float *hsv = cpicker->color_data;
+
+ width = PICKER_TOTAL_W;
+ butwidth = width - 1.5f * UI_UNIT_X;
+
+ /* existence of profile means storage is in linear color space, with display correction */
+ /* XXX That tip message is not use anywhere! */
+ if (!block->color_profile) {
+ BLI_strncpy(tip, N_("Value in Display Color Space"), sizeof(tip));
+ copy_v3_v3(rgb_gamma, rgba);
+ }
+ else {
+ BLI_strncpy(tip, N_("Value in Linear RGB Color Space"), sizeof(tip));
+
+ /* make a display version, for Hex code */
+ copy_v3_v3(rgb_gamma, rgba);
+ ui_block_cm_to_display_space_v3(block, rgb_gamma);
+ }
+
+ /* sneaky way to check for alpha */
+ rgba[3] = FLT_MAX;
+
+ RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
+ RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
+ RNA_property_float_get_array(ptr, prop, rgba);
+
+ /* when the softmax isn't defined in the RNA,
+ * using very large numbers causes sRGB/linear round trip to fail. */
+ if (softmax == FLT_MAX) {
+ softmax = 1.0f;
+ }
+
+ switch (U.color_picker_type) {
+ case USER_CP_SQUARE_SV:
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_SV, cpicker);
+ break;
+ case USER_CP_SQUARE_HS:
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_HS, cpicker);
+ break;
+ case USER_CP_SQUARE_HV:
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_HV, cpicker);
+ break;
+
+ /* user default */
+ case USER_CP_CIRCLE_HSV:
+ case USER_CP_CIRCLE_HSL:
+ default:
+ ui_colorpicker_circle(block, ptr, prop, cpicker);
+ break;
+ }
+
+ /* mode */
+ yco = -1.5f * UI_UNIT_Y;
+ UI_block_align_begin(block);
+ bt = uiDefButS(
+ block, UI_BTYPE_ROW, 0, IFACE_("RGB"), 0, yco, width / 3, UI_UNIT_Y,
+ &colormode, 0.0, 0.0, 0, 0, "");
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
+ bt = uiDefButS(
+ block, UI_BTYPE_ROW, 0, IFACE_("HSL"), width / 3, yco, width / 3, UI_UNIT_Y,
+ &colormode, 0.0, 1.0, 0, 0, "");
+ }
+ else {
+ bt = uiDefButS(
+ block, UI_BTYPE_ROW, 0, IFACE_("HSV"), width / 3, yco, width / 3, UI_UNIT_Y,
+ &colormode, 0.0, 1.0, 0, 0, "");
+ }
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButS(
+ block, UI_BTYPE_ROW, 0, IFACE_("Hex"), 2 * width / 3, yco, width / 3, UI_UNIT_Y,
+ &colormode, 0.0, 2.0, 0, 0, "");
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ UI_block_align_end(block);
+
+ yco = -3.0f * UI_UNIT_Y;
+ if (show_picker) {
+ bt = uiDefIconButO(
+ block, UI_BTYPE_BUT, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER,
+ butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
+ UI_but_func_set(bt, ui_popup_close_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ }
+
+ /* RGB values */
+ UI_block_align_begin(block);
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("R:"), 0, yco, butwidth, UI_UNIT_Y,
+ ptr, prop, 0, 0.0, 0.0, 0, 3, TIP_("Red"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("G:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y,
+ ptr, prop, 1, 0.0, 0.0, 0, 3, TIP_("Green"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("B:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y,
+ ptr, prop, 2, 0.0, 0.0, 0, 3, TIP_("Blue"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+
+ /* could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", ICON_NONE);
+ * but need to use UI_but_func_set for updating other fake buttons */
+
+ /* HSV values */
+ yco = -3.0f * UI_UNIT_Y;
+ UI_block_align_begin(block);
+ bt = uiDefButF(
+ block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("H:"), 0, yco, butwidth,
+ UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, TIP_("Hue"));
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
+ bt = uiDefButF(
+ block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("S:"), 0, yco -= UI_UNIT_Y,
+ butwidth, UI_UNIT_Y, hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation"));
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
+ if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
+ bt = uiDefButF(
+ block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("L:"), 0, yco -= UI_UNIT_Y,
+ butwidth, UI_UNIT_Y, hsv + 2, 0.0, 1.0, 10, 3, TIP_("Lightness"));
+ }
+ else {
+ bt = uiDefButF(
+ block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("V:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y,
+ hsv + 2, 0.0, softmax, 10, 3, TIP_("Value"));
+ }
+
+ bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
+
+ UI_block_align_end(block);
+
+ if (rgba[3] != FLT_MAX) {
+ bt = uiDefButR_prop(
+ block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("A: "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y,
+ ptr, prop, 3, 0.0, 0.0, 0, 3, TIP_("Alpha"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ }
+ else {
+ rgba[3] = 1.0f;
+ }
+
+ rgb_float_to_uchar(rgb_gamma_uchar, rgb_gamma);
+ BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((uint), rgb_gamma_uchar, ));
+
+ yco = -3.0f * UI_UNIT_Y;
+ bt = uiDefBut(
+ block, UI_BTYPE_TEXT, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y,
+ hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
+ UI_but_func_set(bt, ui_colorpicker_hex_rna_cb, bt, hexcol);
+ bt->custom_data = cpicker;
+ uiDefBut(
+ block, UI_BTYPE_LABEL, 0, IFACE_("(Gamma Corrected)"), 0, yco - UI_UNIT_Y,
+ butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+
+ ui_rgb_to_color_picker_v(rgb_gamma, hsv);
+
+ ui_colorpicker_hide_reveal(block, colormode);
+}
+
+
+static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, const wmEvent *event)
+{
+ float add = 0.0f;
+
+ if (event->type == WHEELUPMOUSE)
+ add = 0.05f;
+ else if (event->type == WHEELDOWNMOUSE)
+ add = -0.05f;
+
+ if (add != 0.0f) {
+ uiBut *but;
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) {
+ uiPopupBlockHandle *popup = block->handle;
+ float rgb[3];
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
+
+ ui_but_v3_get(but, rgb);
+
+ if (use_display_colorspace)
+ ui_block_cm_to_display_space_v3(block, rgb);
+
+ ui_rgb_to_color_picker_compat_v(rgb, hsv);
+
+ hsv[2] = CLAMPIS(hsv[2] + add, 0.0f, 1.0f);
+ ui_color_picker_to_rgb_v(hsv, rgb);
+
+ if (use_display_colorspace)
+ ui_block_cm_to_scene_linear_v3(block, rgb);
+
+ ui_but_v3_set(but, rgb);
+
+ ui_update_color_picker_buts_rgb(block, cpicker, rgb, !use_display_colorspace);
+ if (popup)
+ popup->menuretval = UI_RETURN_UPDATE;
+
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
+{
+ uiBut *but = arg_but;
+ uiBlock *block;
+ bool show_picker = true;
+
+ block = UI_block_begin(C, handle->region, __func__, UI_EMBOSS);
+
+ if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ block->color_profile = false;
+ }
+
+ if (but->block) {
+ /* if color block is invoked from a popup we wouldn't be able to set color properly
+ * this is because color picker will close popups first and then will try to figure
+ * out active button RNA, and of course it'll fail
+ */
+ show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0;
+ }
+
+ copy_v3_v3(handle->retvec, but->editvec);
+
+ ui_block_colorpicker(block, handle->retvec, &but->rnapoin, but->rnaprop, show_picker);
+
+ block->flag = UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT;
+ UI_block_bounds_set_normal(block, 0.5 * UI_UNIT_X);
+
+ block->block_event_func = ui_colorpicker_small_wheel_cb;
+
+ /* and lets go */
+ block->direction = UI_DIR_UP;
+
+ return block;
+}
+
+ColorPicker *ui_block_colorpicker_create(struct uiBlock *block)
+{
+ ColorPicker *cpicker = MEM_callocN(sizeof(ColorPicker), "color_picker");
+ BLI_addhead(&block->color_pickers.list, cpicker);
+
+ return cpicker;
+}
+
+/** \} */