59
62
#include "UI_view2d.h"
61
64
#include "BLF_api.h"
65
#include "BLF_translation.h"
63
67
#include "ED_screen.h"
65
69
#include "interface_intern.h"
67
#define MENU_BUTTON_HEIGHT 20
68
#define MENU_SEPR_HEIGHT 6
70
#define MENU_SHADOW_SIDE 8
71
#define MENU_SHADOW_BOTTOM 10
71
#define MENU_SEPR_HEIGHT 6
73
#define MENU_SHADOW_SIDE 8
74
#define MENU_SHADOW_BOTTOM 10
74
77
/*********************** Menu Data Parsing ********************* */
76
79
typedef struct MenuEntry {
83
86
typedef struct MenuData {
89
92
int nitems, itemssize;
92
static MenuData *menudata_new(char *instr)
95
static MenuData *menudata_new(const char *instr)
94
MenuData *md= MEM_mallocN(sizeof(*md), "MenuData");
97
MenuData *md = MEM_mallocN(sizeof(*md), "MenuData");
100
md->nitems= md->itemssize= 0;
103
md->nitems = md->itemssize = 0;
105
static void menudata_set_title(MenuData *md, char *title, int titleicon)
108
static void menudata_set_title(MenuData *md, const char *title, int titleicon)
109
112
if (!md->titleicon)
110
md->titleicon= titleicon;
113
md->titleicon = titleicon;
113
static void menudata_add_item(MenuData *md, char *str, int retval, int icon, int sepr)
116
static void menudata_add_item(MenuData *md, const char *str, int retval, int icon, int sepr)
115
if (md->nitems==md->itemssize) {
116
int nsize= md->itemssize?(md->itemssize<<1):1;
117
MenuEntry *oitems= md->items;
118
if (md->nitems == md->itemssize) {
119
int nsize = md->itemssize ? (md->itemssize << 1) : 1;
120
MenuEntry *oitems = md->items;
119
md->items= MEM_mallocN(nsize*sizeof(*md->items), "md->items");
122
md->items = MEM_mallocN(nsize * sizeof(*md->items), "md->items");
121
memcpy(md->items, oitems, md->nitems*sizeof(*md->items));
124
memcpy(md->items, oitems, md->nitems * sizeof(*md->items));
122
125
MEM_freeN(oitems);
125
md->itemssize= nsize;
128
md->itemssize = nsize;
128
md->items[md->nitems].str= str;
129
md->items[md->nitems].retval= retval;
130
md->items[md->nitems].icon= icon;
131
md->items[md->nitems].sepr= sepr;
131
md->items[md->nitems].str = str;
132
md->items[md->nitems].retval = retval;
133
md->items[md->nitems].icon = icon;
134
md->items[md->nitems].sepr = sepr;
135
void menudata_free(MenuData *md)
138
static void menudata_free(MenuData *md)
137
MEM_freeN(md->instr);
140
MEM_freeN((void *)md->instr);
139
142
MEM_freeN(md->items);
144
* Parse menu description strings, string is of the
145
* form "[sss%t|]{(sss[%xNN]|), (%l|), (sss%l|)}", ssss%t indicates the
146
* menu title, sss or sss%xNN indicates an option,
147
* if %xNN is given then NN is the return value if
148
* that option is selected otherwise the return value
149
* is the index of the option (starting with 1). %l
150
* indicates a seperator, sss%l indicates a label and
153
* @param str String to be parsed.
154
* @retval new menudata structure, free with menudata_free()
156
MenuData *decompose_menu_string(char *str)
148
* Parse menu description strings, string is of the
149
* form "[sss%t|]{(sss[%xNN]|), (%l|), (sss%l|)}", ssss%t indicates the
150
* menu title, sss or sss%xNN indicates an option,
151
* if %xNN is given then NN is the return value if
152
* that option is selected otherwise the return value
153
* is the index of the option (starting with 1). %l
154
* indicates a seperator, sss%l indicates a label and
157
* \param str String to be parsed.
158
* \retval new menudata structure, free with menudata_free()
160
static MenuData *decompose_menu_string(const char *str)
158
char *instr= BLI_strdup(str);
159
MenuData *md= menudata_new(instr);
160
char *nitem= NULL, *s= instr;
161
int nicon=0, nretval= 1, nitem_is_title= 0, nitem_is_sepr= 0;
162
char *instr = BLI_strdup(str);
163
MenuData *md = menudata_new(instr);
164
const char *nitem = NULL;
166
int nicon = 0, nretval = 1, nitem_is_title = 0, nitem_is_sepr = 0;
172
} else if (s[1]=='t') {
177
} else if (s[1]=='l') {
179
if(!nitem) nitem= "";
183
} else if (s[1]=='i') {
173
nretval = atoi(s + 2);
178
else if (s[1] == 't') {
179
nitem_is_title = (s != instr); /* check for empty title */
184
else if (s[1] == 'l') {
186
if (!nitem) nitem = "";
191
else if (s[1] == 'i') {
189
} else if (c=='|' || c == '\n' || c=='\0') {
198
else if (c == '|' || c == '\n' || c == '\0') {
202
if (nitem_is_title) {
194
203
menudata_set_title(md, nitem, nicon);
197
else if(nitem_is_sepr) {
206
else if (nitem_is_sepr) {
198
207
/* prevent separator to get a value */
199
208
menudata_add_item(md, nitem, -1, nicon, 1);
200
nretval= md->nitems+1;
209
nretval = md->nitems + 1;
204
213
menudata_add_item(md, nitem, nretval, nicon, 0);
205
nretval= md->nitems+1;
214
nretval = md->nitems + 1;
274
289
/******************** Creating Temporary regions ******************/
276
ARegion *ui_add_temporary_region(bScreen *sc)
291
static ARegion *ui_add_temporary_region(bScreen *sc)
280
ar= MEM_callocN(sizeof(ARegion), "area region");
295
ar = MEM_callocN(sizeof(ARegion), "area region");
281
296
BLI_addtail(&sc->regionbase, ar);
283
ar->regiontype= RGN_TYPE_TEMPORARY;
284
ar->alignment= RGN_ALIGN_FLOAT;
298
ar->regiontype = RGN_TYPE_TEMPORARY;
299
ar->alignment = RGN_ALIGN_FLOAT;
289
void ui_remove_temporary_region(bContext *C, bScreen *sc, ARegion *ar)
304
static void ui_remove_temporary_region(bContext *C, bScreen *sc, ARegion *ar)
306
if (CTX_wm_window(C))
292
307
wm_draw_region_clear(CTX_wm_window(C), ar);
294
309
ED_region_exit(C, ar);
295
BKE_area_region_free(NULL, ar); /* NULL: no spacetype */
310
BKE_area_region_free(NULL, ar); /* NULL: no spacetype */
296
311
BLI_freelinkN(&sc->regionbase, ar);
299
314
/************************* Creating Tooltips **********************/
322
} uiTooltipLineColor;
323
#define UI_TIP_LC_MAX 5
301
325
#define MAX_TOOLTIP_LINES 8
303
326
typedef struct uiTooltipData {
305
328
uiFontStyle fstyle;
306
329
char lines[MAX_TOOLTIP_LINES][512];
307
int linedark[MAX_TOOLTIP_LINES];
330
uiTooltipLineColor color_id[MAX_TOOLTIP_LINES];
309
332
int toth, spaceh, lineh;
312
static void ui_tooltip_region_draw(const bContext *C, ARegion *ar)
314
uiTooltipData *data= ar->regiondata;
315
rcti bbox= data->bbox;
318
ui_draw_menu_back(U.uistyles.first, NULL, &data->bbox);
335
static void rgb_tint(float col[3],
336
float h, float h_strength,
337
float v, float v_strength)
339
float col_hsv_from[3];
342
rgb_to_hsv(col[0], col[1], col[2], col_hsv_from + 0, col_hsv_from + 1, col_hsv_from + 2);
345
col_hsv_to[1] = h_strength;
346
col_hsv_to[2] = (col_hsv_from[2] * (1.0f - v_strength)) + (v * v_strength);
348
hsv_to_rgb(col_hsv_to[0], col_hsv_to[1], col_hsv_to[2], col + 0, col + 1, col + 2);
351
static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
353
uiTooltipData *data = ar->regiondata;
354
uiWidgetColors *theme = ui_tooltip_get_theme();
355
rcti bbox = data->bbox;
356
float tip_colors[UI_TIP_LC_MAX][3];
358
float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */
359
float *normal_color = tip_colors[UI_TIP_LC_NORMAL];
360
float *python_color = tip_colors[UI_TIP_LC_PYTHON];
361
float *alert_color = tip_colors[UI_TIP_LC_ALERT];
362
float *submenu_color = tip_colors[UI_TIP_LC_SUBMENU];
364
float background_color[3];
368
/* draw background */
369
ui_draw_tooltip_background(UI_GetStyle(), NULL, &bbox);
371
/* set background_color */
372
rgb_uchar_to_float(background_color, (const unsigned char *)theme->inner);
374
/* calculate normal_color */
375
rgb_uchar_to_float(main_color, (const unsigned char *)theme->text);
376
copy_v3_v3(normal_color, main_color);
377
copy_v3_v3(python_color, main_color);
378
copy_v3_v3(alert_color, main_color);
379
copy_v3_v3(submenu_color, main_color);
381
/* find the brightness difference between background and text colors */
383
tone_bg = rgb_to_grayscale(background_color);
384
/* tone_fg = rgb_to_grayscale(main_color); */
386
rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.3f); /* a shade darker (to bg) */
387
rgb_tint(python_color, 0.666f, 0.25f, tone_bg, 0.3f); /* blue */
388
rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* bright red */
389
rgb_tint(submenu_color, 0.0f, 0.0f, tone_bg, 0.3f); /* a shade darker (to bg) */
321
392
uiStyleFontSet(&data->fstyle);
323
bbox.ymax= bbox.ymax - 0.5f*((bbox.ymax - bbox.ymin) - data->toth);
324
bbox.ymin= bbox.ymax - data->lineh;
326
for(a=0; a<data->totline; a++) {
327
if(!data->linedark[a]) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
328
else glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
330
uiStyleFontDraw(&data->fstyle, &bbox, data->lines[a]);
394
bbox.ymax = bbox.ymax - 0.5f * ((bbox.ymax - bbox.ymin) - data->toth);
395
bbox.ymin = bbox.ymax - data->lineh;
397
for (i = 0; i < data->totline; i++) {
398
glColor3fv(tip_colors[data->color_id[i]]);
399
uiStyleFontDraw(&data->fstyle, &bbox, data->lines[i]);
331
400
bbox.ymin -= data->lineh + data->spaceh;
332
401
bbox.ymax -= data->lineh + data->spaceh;
336
static void ui_tooltip_region_free(ARegion *ar)
405
static void ui_tooltip_region_free_cb(ARegion *ar)
338
407
uiTooltipData *data;
340
data= ar->regiondata;
409
data = ar->regiondata;
342
ar->regiondata= NULL;
411
ar->regiondata = NULL;
345
414
ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
347
uiStyle *style= U.uistyles.first; // XXX pass on as arg
416
uiStyle *style = UI_GetStyle();
348
417
static ARegionType type;
350
419
uiTooltipData *data;
351
420
IDProperty *prop;
353
float fonth, fontw, aspect= but->block->aspect;
422
float fonth, fontw, aspect = but->block->aspect;
354
423
float x1f, x2f, y1f, y2f;
355
424
int x1, x2, y1, y2, winx, winy, ofsx, ofsy, w, h, a;
357
if(but->flag & UI_BUT_NO_TOOLTIP)
426
if (but->flag & UI_BUT_NO_TOOLTIP)
360
429
/* create tooltip data */
361
data= MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
363
if(but->tip && strlen(but->tip)) {
430
data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
432
/* special case, enum rna buttons only have enum item description, use general enum description too before the specific one */
433
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
434
const char *descr = RNA_property_description(but->rnaprop);
435
if (descr && descr[0]) {
436
BLI_strncpy(data->lines[data->totline], descr, sizeof(data->lines[0]));
437
data->color_id[data->totline] = UI_TIP_LC_MAIN;
441
if (ELEM(but->type, ROW, MENU)) {
442
EnumPropertyItem *item;
443
int i, totitem, free;
444
int value = (but->type == ROW) ? but->hardmax : ui_get_but_val(but);
446
RNA_property_enum_items_gettexted(C, &but->rnapoin, but->rnaprop, &item, &totitem, &free);
448
for (i = 0; i < totitem; i++) {
449
if (item[i].identifier[0] && item[i].value == value) {
450
if (item[i].description && item[i].description[0]) {
451
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "%s: %s", item[i].name, item[i].description);
452
data->color_id[data->totline] = UI_TIP_LC_SUBMENU;
465
if (but->tip && but->tip[0] != '\0') {
364
466
BLI_strncpy(data->lines[data->totline], but->tip, sizeof(data->lines[0]));
467
data->color_id[data->totline] = UI_TIP_LC_MAIN;
368
if(but->optype && !(but->block->flag & UI_BLOCK_LOOP)) {
471
if (but->optype && !(but->block->flag & UI_BLOCK_LOOP)) {
369
472
/* operator keymap (not menus, they already have it) */
370
prop= (but->opptr)? but->opptr->data: NULL;
473
prop = (but->opptr) ? but->opptr->data : NULL;
372
if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) {
373
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "Shortcut: %s", buf);
374
data->linedark[data->totline]= 1;
475
if (WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, TRUE,
478
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), buf);
479
data->color_id[data->totline] = UI_TIP_LC_NORMAL;
379
if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
484
if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
380
485
/* full string */
381
486
ui_get_but_string(but, buf, sizeof(buf));
383
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "Value: %s", buf);
384
data->linedark[data->totline]= 1;
488
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Value: %s"), buf);
489
data->color_id[data->totline] = UI_TIP_LC_NORMAL;
390
int unit_type = RNA_SUBTYPE_UNIT(RNA_property_subtype(but->rnaprop));
495
int unit_type = uiButGetUnitType(but);
392
497
if (unit_type == PROP_UNIT_ROTATION) {
393
498
if (RNA_property_type(but->rnaprop) == PROP_FLOAT) {
394
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "Radians: %f", RNA_property_float_get_index(&but->rnapoin, but->rnaprop, but->rnaindex));
395
data->linedark[data->totline]= 1;
499
float value = RNA_property_array_check(but->rnaprop) ? RNA_property_float_get_index(&but->rnapoin, but->rnaprop, but->rnaindex) : RNA_property_float_get(&but->rnapoin, but->rnaprop);
500
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Radians: %f"), value);
501
data->color_id[data->totline] = UI_TIP_LC_NORMAL;
400
if(but->flag & UI_BUT_DRIVEN) {
401
if(ui_but_anim_expression_get(but, buf, sizeof(buf))) {
506
if (but->flag & UI_BUT_DRIVEN) {
507
if (ui_but_anim_expression_get(but, buf, sizeof(buf))) {
403
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "Expression: %s", buf);
404
data->linedark[data->totline]= 1;
509
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Expression: %s"), buf);
510
data->color_id[data->totline] = UI_TIP_LC_NORMAL;
410
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "Python: %s.%s", RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop));
411
data->linedark[data->totline]= 1;
516
if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) {
517
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s.%s"), RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop));
518
data->color_id[data->totline] = UI_TIP_LC_PYTHON;
414
if(but->rnapoin.id.data) {
415
ID *id= but->rnapoin.id.data;
416
if(id->lib && id->lib->name) {
417
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "Library: %s", id->lib->name);
418
data->linedark[data->totline]= 1;
522
if (but->rnapoin.id.data) {
523
ID *id = but->rnapoin.id.data;
524
if (id->lib && id->lib->name) {
525
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Library: %s"), id->lib->name);
526
data->color_id[data->totline] = UI_TIP_LC_NORMAL;
810
961
void ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
812
uiSearchboxData *data= ar->regiondata;
963
uiSearchboxData *data = ar->regiondata;
815
data->items.autocpl= autocomplete_begin(str, ui_get_but_string_max_length(but));
966
data->items.autocpl = autocomplete_begin(str, ui_get_but_string_max_length(but));
817
968
but->search_func(C, but->search_arg, but->editstr, &data->items);
819
970
autocomplete_end(data->items.autocpl, str);
820
data->items.autocpl= NULL;
971
data->items.autocpl = NULL;
824
static void ui_searchbox_region_draw(const bContext *C, ARegion *ar)
975
static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
826
uiSearchboxData *data= ar->regiondata;
977
uiSearchboxData *data = ar->regiondata;
828
979
/* pixel space */
829
wmOrtho2(-0.01f, ar->winx-0.01f, -0.01f, ar->winy-0.01f);
980
wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
832
ui_draw_search_back(U.uistyles.first, NULL, &data->bbox);
983
ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
835
if(data->items.totitem) {
986
if (data->items.totitem) {
839
990
if (data->preview) {
841
for(a=0; a<data->items.totitem; a++) {
992
for (a = 0; a < data->items.totitem; a++) {
842
993
ui_searchbox_butrect(&rect, data, a);
844
995
/* widget itself */
845
996
if (data->preview)
846
ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0);
997
ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a + 1) == data->active ? UI_ACTIVE : 0);
848
ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0);
999
ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a + 1) == data->active ? UI_ACTIVE : 0);
851
1002
/* indicate more */
852
if(data->items.more) {
853
ui_searchbox_butrect(&rect, data, data->items.maxitem-1);
1003
if (data->items.more) {
1004
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
854
1005
glEnable(GL_BLEND);
855
UI_icon_draw(rect.xmax-18, rect.ymin-7, ICON_TRIA_DOWN);
1006
UI_icon_draw(rect.xmax - 18, rect.ymin - 7, ICON_TRIA_DOWN);
856
1007
glDisable(GL_BLEND);
858
if(data->items.offset) {
1009
if (data->items.offset) {
859
1010
ui_searchbox_butrect(&rect, data, 0);
860
1011
glEnable(GL_BLEND);
861
UI_icon_draw(rect.xmin, rect.ymax-9, ICON_TRIA_UP);
1012
UI_icon_draw(rect.xmin, rect.ymax - 9, ICON_TRIA_UP);
862
1013
glDisable(GL_BLEND);
866
1018
/* draw items */
867
for(a=0; a<data->items.totitem; a++) {
1019
for (a = 0; a < data->items.totitem; a++) {
868
1020
ui_searchbox_butrect(&rect, data, a);
870
1022
/* widget itself */
871
ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0);
1023
ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a + 1) == data->active ? UI_ACTIVE : 0);
874
1026
/* indicate more */
875
if(data->items.more) {
876
ui_searchbox_butrect(&rect, data, data->items.maxitem-1);
1027
if (data->items.more) {
1028
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
877
1029
glEnable(GL_BLEND);
878
UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymin-9, ICON_TRIA_DOWN);
1030
UI_icon_draw((rect.xmax - rect.xmin) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
879
1031
glDisable(GL_BLEND);
881
if(data->items.offset) {
1033
if (data->items.offset) {
882
1034
ui_searchbox_butrect(&rect, data, 0);
883
1035
glEnable(GL_BLEND);
884
UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymax-7, ICON_TRIA_UP);
1036
UI_icon_draw((rect.xmax - rect.xmin) / 2, rect.ymax - 7, ICON_TRIA_UP);
885
1037
glDisable(GL_BLEND);
891
static void ui_searchbox_region_free(ARegion *ar)
1043
static void ui_searchbox_region_free_cb(ARegion *ar)
893
uiSearchboxData *data= ar->regiondata;
1045
uiSearchboxData *data = ar->regiondata;
896
1048
/* free search data */
897
for(a=0; a<data->items.maxitem; a++)
1049
for (a = 0; a < data->items.maxitem; a++) {
898
1050
MEM_freeN(data->items.names[a]);
899
1052
MEM_freeN(data->items.names);
900
1053
MEM_freeN(data->items.pointers);
901
1054
MEM_freeN(data->items.icons);
903
1056
MEM_freeN(data);
904
ar->regiondata= NULL;
1057
ar->regiondata = NULL;
907
static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, uiBlock *block);
909
1060
ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
911
uiStyle *style= U.uistyles.first; // XXX pass on as arg
1062
uiStyle *style = UI_GetStyle();
912
1063
static ARegionType type;
914
1065
uiSearchboxData *data;
915
float aspect= but->block->aspect;
1066
float aspect = but->block->aspect;
916
1067
float x1f, x2f, y1f, y2f;
917
1068
int x1, x2, y1, y2, winx, winy, ofsx, ofsy;
919
1070
/* create area region */
920
ar= ui_add_temporary_region(CTX_wm_screen(C));
1071
ar = ui_add_temporary_region(CTX_wm_screen(C));
922
1073
memset(&type, 0, sizeof(ARegionType));
923
type.draw= ui_searchbox_region_draw;
924
type.free= ui_searchbox_region_free;
1074
type.draw = ui_searchbox_region_draw_cb;
1075
type.free = ui_searchbox_region_free_cb;
927
1078
/* create searchbox data */
928
data= MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
1079
data = MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
930
1081
/* set font, get bb */
931
data->fstyle= style->widget; /* copy struct */
932
data->fstyle.align= UI_STYLE_TEXT_CENTER;
1082
data->fstyle = style->widget; /* copy struct */
1083
data->fstyle.align = UI_STYLE_TEXT_CENTER;
933
1084
ui_fontscale(&data->fstyle.points, aspect);
934
1085
uiStyleFontSet(&data->fstyle);
936
ar->regiondata= data;
1087
ar->regiondata = data;
938
1089
/* special case, hardcoded feature, not draw backdrop when called from menus,
939
assume for design that popup already added it */
940
if(but->block->flag & UI_BLOCK_LOOP)
1090
* assume for design that popup already added it */
1091
if (but->block->flag & UI_BLOCK_LOOP)
943
1094
if (but->a1 > 0 && but->a2 > 0) {
944
1095
data->preview = 1;
1072
1265
uiSafetyRct *saferct;
1075
int xsize, ysize, xof=0, yof=0, center;
1076
short dir1= 0, dir2=0;
1267
/*float aspect;*/ /*UNUSED*/
1268
int xsize, ysize, xof = 0, yof = 0, center;
1269
short dir1 = 0, dir2 = 0;
1078
1271
/* transform to window coordinates, using the source button region/block */
1079
butrct.xmin= but->x1; butrct.xmax= but->x2;
1080
butrct.ymin= but->y1; butrct.ymax= but->y2;
1272
butrct.xmin = but->x1; butrct.xmax = but->x2;
1273
butrct.ymin = but->y1; butrct.ymax = but->y2;
1082
1275
ui_block_to_window_fl(butregion, but->block, &butrct.xmin, &butrct.ymin);
1083
1276
ui_block_to_window_fl(butregion, but->block, &butrct.xmax, &butrct.ymax);
1085
1278
/* calc block rect */
1086
if(block->minx == 0.0f && block->maxx == 0.0f) {
1087
if(block->buttons.first) {
1088
block->minx= block->miny= 10000;
1089
block->maxx= block->maxy= -10000;
1279
if (block->minx == 0.0f && block->maxx == 0.0f) {
1280
if (block->buttons.first) {
1281
block->minx = block->miny = 10000;
1282
block->maxx = block->maxy = -10000;
1091
bt= block->buttons.first;
1093
if(bt->x1 < block->minx) block->minx= bt->x1;
1094
if(bt->y1 < block->miny) block->miny= bt->y1;
1284
bt = block->buttons.first;
1286
if (bt->x1 < block->minx) block->minx = bt->x1;
1287
if (bt->y1 < block->miny) block->miny = bt->y1;
1096
if(bt->x2 > block->maxx) block->maxx= bt->x2;
1097
if(bt->y2 > block->maxy) block->maxy= bt->y2;
1289
if (bt->x2 > block->maxx) block->maxx = bt->x2;
1290
if (bt->y2 > block->maxy) block->maxy = bt->y2;
1103
1296
/* we're nice and allow empty blocks too */
1104
block->minx= block->miny= 0;
1105
block->maxx= block->maxy= 20;
1297
block->minx = block->miny = 0;
1298
block->maxx = block->maxy = 20;
1109
aspect= (float)(block->maxx - block->minx + 4);
1302
/*aspect= (float)(block->maxx - block->minx + 4);*/ /*UNUSED*/
1110
1303
ui_block_to_window_fl(butregion, but->block, &block->minx, &block->miny);
1111
1304
ui_block_to_window_fl(butregion, but->block, &block->maxx, &block->maxy);
1113
1306
//block->minx-= 2.0; block->miny-= 2.0;
1114
1307
//block->maxx+= 2.0; block->maxy+= 2.0;
1116
xsize= block->maxx - block->minx+4; // 4 for shadow
1117
ysize= block->maxy - block->miny+4;
1118
aspect/= (float)xsize;
1309
xsize = block->maxx - block->minx + 4; // 4 for shadow
1310
ysize = block->maxy - block->miny + 4;
1311
/*aspect/= (float)xsize;*/ /*UNUSED*/
1121
int left=0, right=0, top=0, down=0;
1314
int left = 0, right = 0, top = 0, down = 0;
1122
1315
int winx, winy;
1124
1318
wm_window_get_size(window, &winx, &winy);
1126
if(block->direction & UI_CENTER) center= ysize/2;
1320
if (block->direction & UI_CENTER) center = ysize / 2;
1323
/* check if there's space at all */
1324
if (butrct.xmin - xsize > 0.0f) left = 1;
1325
if (butrct.xmax + xsize < winx) right = 1;
1326
if (butrct.ymin - ysize + center > 0.0f) down = 1;
1327
if (butrct.ymax + ysize - center < winy) top = 1;
1129
if( butrct.xmin-xsize > 0.0) left= 1;
1130
if( butrct.xmax+xsize < winx) right= 1;
1131
if( butrct.ymin-ysize+center > 0.0) down= 1;
1132
if( butrct.ymax+ysize-center < winy) top= 1;
1329
if (top == 0 && down == 0) {
1330
if (butrct.ymin - ysize < winy - butrct.ymax - ysize)
1134
dir1= block->direction & UI_DIRECTION;
1336
dir1 = block->direction & UI_DIRECTION;
1136
1338
/* secundary directions */
1137
if(dir1 & (UI_TOP|UI_DOWN)) {
1138
if(dir1 & UI_LEFT) dir2= UI_LEFT;
1139
else if(dir1 & UI_RIGHT) dir2= UI_RIGHT;
1140
dir1 &= (UI_TOP|UI_DOWN);
1339
if (dir1 & (UI_TOP | UI_DOWN)) {
1340
if (dir1 & UI_LEFT) dir2 = UI_LEFT;
1341
else if (dir1 & UI_RIGHT) dir2 = UI_RIGHT;
1342
dir1 &= (UI_TOP | UI_DOWN);
1143
if(dir2==0) if(dir1==UI_LEFT || dir1==UI_RIGHT) dir2= UI_DOWN;
1144
if(dir2==0) if(dir1==UI_TOP || dir1==UI_DOWN) dir2= UI_LEFT;
1345
if (dir2 == 0) if (dir1 == UI_LEFT || dir1 == UI_RIGHT) dir2 = UI_DOWN;
1346
if (dir2 == 0) if (dir1 == UI_TOP || dir1 == UI_DOWN) dir2 = UI_LEFT;
1146
/* no space at all? dont change */
1148
if(dir1==UI_LEFT && left==0) dir1= UI_RIGHT;
1149
if(dir1==UI_RIGHT && right==0) dir1= UI_LEFT;
1348
/* no space at all? don't change */
1349
if (left || right) {
1350
if (dir1 == UI_LEFT && left == 0) dir1 = UI_RIGHT;
1351
if (dir1 == UI_RIGHT && right == 0) dir1 = UI_LEFT;
1150
1352
/* this is aligning, not append! */
1151
if(dir2==UI_LEFT && right==0) dir2= UI_RIGHT;
1152
if(dir2==UI_RIGHT && left==0) dir2= UI_LEFT;
1155
if(dir1==UI_TOP && top==0) dir1= UI_DOWN;
1156
if(dir1==UI_DOWN && down==0) dir1= UI_TOP;
1157
if(dir2==UI_TOP && top==0) dir2= UI_DOWN;
1158
if(dir2==UI_DOWN && down==0) dir2= UI_TOP;
1162
xof= butrct.xmin - block->maxx;
1163
if(dir2==UI_TOP) yof= butrct.ymin - block->miny-center;
1164
else yof= butrct.ymax - block->maxy+center;
1166
else if(dir1==UI_RIGHT) {
1167
xof= butrct.xmax - block->minx;
1168
if(dir2==UI_TOP) yof= butrct.ymin - block->miny-center;
1169
else yof= butrct.ymax - block->maxy+center;
1171
else if(dir1==UI_TOP) {
1172
yof= butrct.ymax - block->miny;
1173
if(dir2==UI_RIGHT) xof= butrct.xmax - block->maxx;
1174
else xof= butrct.xmin - block->minx;
1353
if (dir2 == UI_LEFT && right == 0) dir2 = UI_RIGHT;
1354
if (dir2 == UI_RIGHT && left == 0) dir2 = UI_LEFT;
1357
if (dir1 == UI_TOP && top == 0) dir1 = UI_DOWN;
1358
if (dir1 == UI_DOWN && down == 0) dir1 = UI_TOP;
1359
if (dir2 == UI_TOP && top == 0) dir2 = UI_DOWN;
1360
if (dir2 == UI_DOWN && down == 0) dir2 = UI_TOP;
1363
if (dir1 == UI_LEFT) {
1364
xof = butrct.xmin - block->maxx;
1365
if (dir2 == UI_TOP) yof = butrct.ymin - block->miny - center;
1366
else yof = butrct.ymax - block->maxy + center;
1368
else if (dir1 == UI_RIGHT) {
1369
xof = butrct.xmax - block->minx;
1370
if (dir2 == UI_TOP) yof = butrct.ymin - block->miny - center;
1371
else yof = butrct.ymax - block->maxy + center;
1373
else if (dir1 == UI_TOP) {
1374
yof = butrct.ymax - block->miny;
1375
if (dir2 == UI_RIGHT) xof = butrct.xmax - block->maxx;
1376
else xof = butrct.xmin - block->minx;
1175
1377
// changed direction?
1176
if((dir1 & block->direction)==0) {
1177
if(block->direction & UI_SHIFT_FLIPPED)
1178
xof+= dir2==UI_LEFT?25:-25;
1378
if ((dir1 & block->direction) == 0) {
1379
if (block->direction & UI_SHIFT_FLIPPED)
1380
xof += dir2 == UI_LEFT ? 25 : -25;
1179
1381
uiBlockFlipOrder(block);
1182
else if(dir1==UI_DOWN) {
1183
yof= butrct.ymin - block->maxy;
1184
if(dir2==UI_RIGHT) xof= butrct.xmax - block->maxx;
1185
else xof= butrct.xmin - block->minx;
1384
else if (dir1 == UI_DOWN) {
1385
yof = butrct.ymin - block->maxy;
1386
if (dir2 == UI_RIGHT) xof = butrct.xmax - block->maxx;
1387
else xof = butrct.xmin - block->minx;
1186
1388
// changed direction?
1187
if((dir1 & block->direction)==0) {
1188
if(block->direction & UI_SHIFT_FLIPPED)
1189
xof+= dir2==UI_LEFT?25:-25;
1389
if ((dir1 & block->direction) == 0) {
1390
if (block->direction & UI_SHIFT_FLIPPED)
1391
xof += dir2 == UI_LEFT ? 25 : -25;
1190
1392
uiBlockFlipOrder(block);
1194
1396
/* and now we handle the exception; no space below or to top */
1195
if(top==0 && down==0) {
1196
if(dir1==UI_LEFT || dir1==UI_RIGHT) {
1397
if (top == 0 && down == 0) {
1398
if (dir1 == UI_LEFT || dir1 == UI_RIGHT) {
1197
1399
// align with bottom of screen
1400
// yof= ysize; (not with menu scrolls)
1202
1404
/* or no space left or right */
1203
if(left==0 && right==0) {
1204
if(dir1==UI_TOP || dir1==UI_DOWN) {
1405
if (left == 0 && right == 0) {
1406
if (dir1 == UI_TOP || dir1 == UI_DOWN) {
1205
1407
// align with left size of screen
1206
xof= -block->minx+5;
1408
xof = -block->minx + 5;
1210
1412
// apply requested offset in the block
1211
xof += block->xofs/block->aspect;
1212
yof += block->yofs/block->aspect;
1413
xof += block->xofs / block->aspect;
1414
yof += block->yofs / block->aspect;
1416
/* clamp to window bounds, could be made into an option if its ever annoying */
1417
if ( (offscreen = (block->miny + yof)) < 0) yof -= offscreen; /* bottom */
1418
else if ((offscreen = (block->maxy + yof) - winy) > 0) yof -= offscreen; /* top */
1419
if ( (offscreen = (block->minx + xof)) < 0) xof -= offscreen; /* left */
1420
else if ((offscreen = (block->maxx + xof) - winx) > 0) xof -= offscreen; /* right */
1424
/* apply offset, buttons in window coords */
1217
for(bt= block->buttons.first; bt; bt= bt->next) {
1426
for (bt = block->buttons.first; bt; bt = bt->next) {
1218
1427
ui_block_to_window_fl(butregion, but->block, &bt->x1, &bt->y1);
1219
1428
ui_block_to_window_fl(butregion, but->block, &bt->x2, &bt->y2);
1395
1661
void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
1397
1663
ui_remove_temporary_region(C, CTX_wm_screen(C), handle->region);
1665
if (handle->scrolltimer)
1666
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), handle->scrolltimer);
1398
1668
MEM_freeN(handle);
1401
1671
/***************************** Menu Button ***************************/
1403
static void ui_block_func_MENUSTR(bContext *C, uiLayout *layout, void *arg_str)
1673
static void ui_block_func_MENUSTR(bContext *UNUSED(C), uiLayout *layout, void *arg_str)
1405
uiBlock *block= uiLayoutGetBlock(layout);
1406
uiPopupBlockHandle *handle= block->handle;
1407
uiLayout *split, *column=NULL;
1675
uiBlock *block = uiLayoutGetBlock(layout);
1676
uiPopupBlockHandle *handle = block->handle;
1677
uiLayout *split, *column = NULL;
1410
1680
MenuEntry *entry;
1411
char *instr= arg_str;
1681
const char *instr = arg_str;
1412
1682
int columns, rows, a, b;
1683
int column_start = 0, column_end = 0;
1414
1685
uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
1416
1687
/* compute menu data */
1417
md= decompose_menu_string(instr);
1688
md = decompose_menu_string(instr);
1419
1690
/* columns and row estimation */
1420
columns= (md->nitems+20)/20;
1424
columns= (md->nitems+25)/25;
1426
rows= md->nitems/columns;
1429
while(rows*columns<md->nitems)
1691
columns = (md->nitems + 20) / 20;
1695
columns = (md->nitems + 25) / 25;
1697
rows = md->nitems / columns;
1700
while (rows * columns < md->nitems)
1432
1703
/* create title */
1705
if (md->titleicon) {
1435
1706
uiItemL(layout, md->title, md->titleicon);
1438
uiItemL(layout, md->title, 0);
1439
bt= block->buttons.last;
1440
bt->flag= UI_TEXT_LEFT;
1709
uiItemL(layout, md->title, ICON_NONE);
1710
bt = block->buttons.last;
1711
bt->flag = UI_TEXT_LEFT;
1444
1715
/* inconsistent, but menus with labels do not look good flipped */
1445
for(a=0, b=0; a<md->nitems; a++, b++) {
1446
entry= &md->items[a];
1448
if(entry->sepr && entry->str[0])
1717
for (a = 0; a < md->nitems; a++, entry++) {
1718
if (entry->sepr && entry->str[0]) {
1449
1719
block->flag |= UI_BLOCK_NO_FLIP;
1452
1724
/* create items */
1453
split= uiLayoutSplit(layout, 0, 0);
1455
for(a=0, b=0; a<md->nitems; a++, b++) {
1456
if(block->flag & UI_BLOCK_NO_FLIP)
1457
entry= &md->items[a];
1725
split = uiLayoutSplit(layout, 0, 0);
1727
for (a = 0; a < md->nitems; a++) {
1728
if (a == column_end) {
1729
/* start new column, and find out where it ends in advance, so we
1730
* can flip the order of items properly per column */
1732
column_end = md->nitems;
1734
for (b = a + 1; b < md->nitems; b++) {
1735
entry = &md->items[b];
1737
/* new column on N rows or on separation label */
1738
if (((b - a) % rows == 0) || (entry->sepr && entry->str[0])) {
1744
column = uiLayoutColumn(split, 0);
1747
if (block->flag & UI_BLOCK_NO_FLIP)
1748
entry = &md->items[a];
1459
entry= &md->items[md->nitems-a-1];
1461
/* new column on N rows or on separation label */
1462
if((b % rows == 0) || (entry->sepr && entry->str[0])) {
1463
column= uiLayoutColumn(split, 0);
1750
entry = &md->items[column_start + column_end - 1 - a];
1468
1753
uiItemL(column, entry->str, entry->icon);
1469
bt= block->buttons.last;
1470
bt->flag= UI_TEXT_LEFT;
1754
bt = block->buttons.last;
1755
bt->flag = UI_TEXT_LEFT;
1472
else if(entry->icon) {
1473
uiDefIconTextButF(block, BUTM|FLO, B_NOP, entry->icon, entry->str, 0, 0,
1474
UI_UNIT_X*5, UI_UNIT_Y, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
1757
else if (entry->icon) {
1758
uiDefIconTextButF(block, BUTM | FLO, B_NOP, entry->icon, entry->str, 0, 0,
1759
UI_UNIT_X * 5, UI_UNIT_Y, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
1477
uiDefButF(block, BUTM|FLO, B_NOP, entry->str, 0, 0,
1478
UI_UNIT_X*5, UI_UNIT_X, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
1762
uiDefButF(block, BUTM | FLO, B_NOP, entry->str, 0, 0,
1763
UI_UNIT_X * 5, UI_UNIT_X, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
1482
1767
menudata_free(md);
1485
void ui_block_func_ICONROW(bContext *C, uiLayout *layout, void *arg_but)
1770
void ui_block_func_ICONROW(bContext *UNUSED(C), uiLayout *layout, void *arg_but)
1487
uiBlock *block= uiLayoutGetBlock(layout);
1488
uiPopupBlockHandle *handle= block->handle;
1489
uiBut *but= arg_but;
1772
uiBlock *block = uiLayoutGetBlock(layout);
1773
uiPopupBlockHandle *handle = block->handle;
1774
uiBut *but = arg_but;
1492
1777
uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
1494
for(a=(int)but->hardmin; a<=(int)but->hardmax; a++)
1495
uiDefIconButF(block, BUTM|FLO, B_NOP, but->icon+(a-but->hardmin), 0, 0, UI_UNIT_X*5, UI_UNIT_Y,
1496
&handle->retvalue, (float)a, 0.0, 0, 0, "");
1779
for (a = (int)but->hardmin; a <= (int)but->hardmax; a++)
1780
uiDefIconButF(block, BUTM | FLO, B_NOP, but->icon + (a - but->hardmin), 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
1781
&handle->retvalue, (float)a, 0.0, 0, 0, "");
1499
void ui_block_func_ICONTEXTROW(bContext *C, uiLayout *layout, void *arg_but)
1784
void ui_block_func_ICONTEXTROW(bContext *UNUSED(C), uiLayout *layout, void *arg_but)
1501
uiBlock *block= uiLayoutGetBlock(layout);
1502
uiPopupBlockHandle *handle= block->handle;
1503
uiBut *but= arg_but, *bt;
1786
uiBlock *block = uiLayoutGetBlock(layout);
1787
uiPopupBlockHandle *handle = block->handle;
1788
uiBut *but = arg_but, *bt;
1505
1790
MenuEntry *entry;
1508
1793
uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
1510
md= decompose_menu_string(but->str);
1795
md = decompose_menu_string(but->str);
1514
bt= uiDefBut(block, LABEL, 0, md->title, 0, 0, UI_UNIT_X*5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1515
bt->flag= UI_TEXT_LEFT;
1799
bt = uiDefBut(block, LABEL, 0, md->title, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1800
bt->flag = UI_TEXT_LEFT;
1518
1803
/* loop through the menu options and draw them out with icons & text labels */
1519
for(a=0; a<md->nitems; a++) {
1520
entry= &md->items[md->nitems-a-1];
1804
for (a = 0; a < md->nitems; a++) {
1805
entry = &md->items[md->nitems - a - 1];
1523
1808
uiItemS(layout);
1525
uiDefIconTextButF(block, BUTM|FLO, B_NOP, (short)((but->icon)+(entry->retval-but->hardmin)), entry->str,
1526
0, 0, UI_UNIT_X*5, UI_UNIT_Y, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
1810
uiDefIconTextButF(block, BUTM | FLO, B_NOP, (short)((but->icon) + (entry->retval - but->hardmin)), entry->str,
1811
0, 0, UI_UNIT_X * 5, UI_UNIT_Y, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
1529
1814
menudata_free(md);
1533
static void ui_warp_pointer(short x, short y)
1818
static void ui_warp_pointer(int x, int y)
1535
1820
/* XXX 2.50 which function to use for this? */
1536
/* OSX has very poor mousewarp support, it sends events;
1537
this causes a menu being pressed immediately ... */
1821
/* OSX has very poor mouse-warp support, it sends events;
1822
* this causes a menu being pressed immediately ... */
1539
1824
warp_pointer(x, y);
1544
1829
/********************* Color Button ****************/
1546
1831
/* picker sizes S hsize, F full size, D spacer, B button/pallette height */
1552
1837
/* for picker, while editing hsv */
1553
1838
void ui_set_but_hsv(uiBut *but)
1841
float *hsv = ui_block_hsv_get(but->block);
1557
hsv_to_rgb(but->hsv[0], but->hsv[1], but->hsv[2], col, col+1, col+2);
1843
hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col + 1, col + 2);
1558
1844
ui_set_but_vectorf(but, col);
1561
1847
/* also used by small picker, be careful with name checks below... */
1562
void ui_update_block_buts_rgb(uiBlock *block, float *rgb, float *rhsv)
1848
static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3])
1851
float *hsv = ui_block_hsv_get(block);
1567
1853
/* this is to keep the H and S value when V is equal to zero
1568
1854
* and we are working in HSV mode, of course!
1576
rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
1856
rgb_to_hsv_compat(rgb[0], rgb[1], rgb[2], hsv, hsv + 1, hsv + 2);
1578
1858
// this updates button strings, is hackish... but button pointers are on stack of caller function
1579
for(bt= block->buttons.first; bt; bt= bt->next) {
1859
for (bt = block->buttons.first; bt; bt = bt->next) {
1580
1860
if (bt->rnaprop) {
1582
1862
ui_set_but_vectorf(bt, rgb);
1585
else if(strcmp(bt->str, "Hex: ")==0) {
1865
else if (strcmp(bt->str, "Hex: ") == 0) {
1586
1866
float rgb_gamma[3];
1587
1867
double intpart;
1698
1979
/* tag buttons */
1699
for(bt= block->buttons.first; bt; bt= bt->next) {
1980
for (bt = block->buttons.first; bt; bt = bt->next) {
1701
1982
if (bt->type == LABEL) {
1702
if( bt->str[1]=='G') {
1703
if(colormode==2) bt->flag &= ~UI_HIDDEN;
1983
if (bt->str[1] == 'G') {
1984
if (colormode == 2) bt->flag &= ~UI_HIDDEN;
1704
1985
else bt->flag |= UI_HIDDEN;
1708
if(bt->type==NUMSLI || bt->type==TEX) {
1709
if( bt->str[1]=='e') {
1710
if(colormode==2) bt->flag &= ~UI_HIDDEN;
1711
else bt->flag |= UI_HIDDEN;
1713
else if( ELEM3(bt->str[0], 'R', 'G', 'B')) {
1714
if(colormode==0) bt->flag &= ~UI_HIDDEN;
1715
else bt->flag |= UI_HIDDEN;
1717
else if( ELEM3(bt->str[0], 'H', 'S', 'V')) {
1718
if(colormode==1) bt->flag &= ~UI_HIDDEN;
1989
if (bt->type == NUMSLI || bt->type == TEX) {
1990
if (bt->str[1] == 'e') {
1991
if (colormode == 2) bt->flag &= ~UI_HIDDEN;
1992
else bt->flag |= UI_HIDDEN;
1994
else if (ELEM3(bt->str[0], 'R', 'G', 'B')) {
1995
if (colormode == 0) bt->flag &= ~UI_HIDDEN;
1996
else bt->flag |= UI_HIDDEN;
1998
else if (ELEM3(bt->str[0], 'H', 'S', 'V')) {
1999
if (colormode == 1) bt->flag &= ~UI_HIDDEN;
1719
2000
else bt->flag |= UI_HIDDEN;
1725
static void do_picker_new_mode_cb(bContext *C, void *bt1, void *colv)
2006
static void do_picker_new_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
1728
short colormode= ui_get_but_val(bt);
2009
short colormode = ui_get_but_val(bt);
1729
2010
picker_new_hide_reveal(bt->block, colormode);
1732
2013
/* picker sizes S hsize, F full size, D spacer, B button/pallette height */
1733
#define SPICK1 150.0
1736
#define PICKER_H 150
1737
#define PICKER_W 150
1738
#define PICKER_SPACE 6
1739
#define PICKER_BAR 14
1741
#define PICKER_TOTAL_W (PICKER_W+PICKER_SPACE+PICKER_BAR)
1743
static void circle_picker(uiBlock *block, PointerRNA *ptr, const char *propname)
2014
#define SPICK1 150.0
2017
#define PICKER_H 150
2018
#define PICKER_W 150
2019
#define PICKER_SPACE 6
2020
#define PICKER_BAR 14
2022
#define PICKER_TOTAL_W (PICKER_W + PICKER_SPACE + PICKER_BAR)
2024
static void circle_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop)
1747
2028
/* HS circle */
1748
bt= uiDefButR(block, HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, propname, 0, 0.0, 0.0, 0, 0, "Color");
2029
bt = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, prop, 0, 0.0, 0.0, 0, 0, "Color");
1749
2030
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
1752
bt= uiDefButR(block, HSVCUBE, 0, "", PICKER_W+PICKER_SPACE,0,PICKER_BAR,PICKER_H, ptr, propname, 0, 0.0, 0.0, UI_GRAD_V_ALT, 0, "Value");
2033
bt = uiDefButR_prop(block, HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H, ptr, prop, 0, 0.0, 0.0, UI_GRAD_V_ALT, 0, "Value");
1753
2034
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
1757
static void square_picker(uiBlock *block, PointerRNA *ptr, const char *propname, int type)
2038
static void square_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int type)
1760
2041
int bartype = type + 3;
1762
2043
/* HS square */
1763
bt= uiDefButR(block, HSVCUBE, 0, "", 0, PICKER_BAR+PICKER_SPACE, PICKER_TOTAL_W, PICKER_H, ptr, propname, 0, 0.0, 0.0, type, 0, "Color");
2044
bt = uiDefButR_prop(block, HSVCUBE, 0, "", 0, PICKER_BAR + PICKER_SPACE, PICKER_TOTAL_W, PICKER_H, ptr, prop, 0, 0.0, 0.0, type, 0, "Color");
1764
2045
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
1767
bt= uiDefButR(block, HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, propname, 0, 0.0, 0.0, bartype, 0, "Value");
2048
bt = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, prop, 0, 0.0, 0.0, bartype, 0, "Value");
1768
2049
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
1772
2053
/* a HS circle, V slider, rgb/hsv/hex sliders */
1773
static void uiBlockPicker(uiBlock *block, float *rgb, PointerRNA *ptr, PropertyRNA *prop)
2054
static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, PropertyRNA *prop)
1775
static short colormode= 0; /* temp? 0=rgb, 1=hsv, 2=hex */
2056
static short colormode = 0; /* temp? 0=rgb, 1=hsv, 2=hex */
1777
2058
int width, butwidth;
1778
2059
static char tip[50];
1779
static float hsv[3];
1780
2060
static char hexcol[128];
1781
2061
float rgb_gamma[3];
1782
2062
float min, max, step, precision;
1783
const char *propname = RNA_property_identifier(prop);
1785
width= PICKER_TOTAL_W;
2063
float *hsv = ui_block_hsv_get(block);
2065
ui_block_hsv_get(block);
2067
width = PICKER_TOTAL_W;
1786
2068
butwidth = width - UI_UNIT_X - 10;
1788
/* existence of profile means storage is in linear colour space, with display correction */
2070
/* existence of profile means storage is in linear color space, with display correction */
2071
/* XXX That tip message is not use anywhere! */
1789
2072
if (block->color_profile == BLI_PR_NONE) {
1790
sprintf(tip, "Value in Display Color Space");
1791
copy_v3_v3(rgb_gamma, rgb);
1793
sprintf(tip, "Value in Linear RGB Color Space");
2073
BLI_strncpy(tip, N_("Value in Display Color Space"), sizeof(tip));
2074
copy_v3_v3(rgb_gamma, rgba);
2077
BLI_strncpy(tip, N_("Value in Linear RGB Color Space"), sizeof(tip));
1794
2078
/* make an sRGB version, for Hex code */
1795
linearrgb_to_srgb_v3_v3(rgb_gamma, rgb);
2079
linearrgb_to_srgb_v3_v3(rgb_gamma, rgba);
1798
2082
/* sneaky way to check for alpha */
1801
2085
RNA_property_float_ui_range(ptr, prop, &min, &max, &step, &precision);
1802
RNA_property_float_get_array(ptr, prop, rgb);
1803
rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
2086
RNA_property_float_get_array(ptr, prop, rgba);
1805
2088
switch (U.color_picker_type) {
1806
2089
case USER_CP_CIRCLE:
1807
circle_picker(block, ptr, propname);
2090
circle_picker(block, ptr, prop);
1809
2092
case USER_CP_SQUARE_SV:
1810
square_picker(block, ptr, propname, UI_GRAD_SV);
2093
square_picker(block, ptr, prop, UI_GRAD_SV);
1812
2095
case USER_CP_SQUARE_HS:
1813
square_picker(block, ptr, propname, UI_GRAD_HS);
2096
square_picker(block, ptr, prop, UI_GRAD_HS);
1815
2098
case USER_CP_SQUARE_HV:
1816
square_picker(block, ptr, propname, UI_GRAD_HV);
2099
square_picker(block, ptr, prop, UI_GRAD_HV);
1821
2104
uiBlockBeginAlign(block);
1822
bt= uiDefButS(block, ROW, 0, "RGB", 0, -30, width/3, UI_UNIT_Y, &colormode, 0.0, 0.0, 0, 0, "");
1823
uiButSetFunc(bt, do_picker_new_mode_cb, bt, rgb);
1824
bt= uiDefButS(block, ROW, 0, "HSV", width/3, -30, width/3, UI_UNIT_Y, &colormode, 0.0, 1.0, 0, 0, "");
1825
uiButSetFunc(bt, do_picker_new_mode_cb, bt, hsv);
1826
bt= uiDefButS(block, ROW, 0, "Hex", 2*width/3, -30, width/3, UI_UNIT_Y, &colormode, 0.0, 2.0, 0, 0, "");
1827
uiButSetFunc(bt, do_picker_new_mode_cb, bt, hexcol);
2105
bt = uiDefButS(block, ROW, 0, IFACE_("RGB"), 0, -30, width / 3, UI_UNIT_Y, &colormode, 0.0, 0.0, 0, 0, "");
2106
uiButSetFunc(bt, do_picker_new_mode_cb, bt, NULL);
2107
bt = uiDefButS(block, ROW, 0, IFACE_("HSV"), width / 3, -30, width / 3, UI_UNIT_Y, &colormode, 0.0, 1.0, 0, 0, "");
2108
uiButSetFunc(bt, do_picker_new_mode_cb, bt, NULL);
2109
bt = uiDefButS(block, ROW, 0, IFACE_("Hex"), 2 * width / 3, -30, width / 3, UI_UNIT_Y, &colormode, 0.0, 2.0, 0, 0, "");
2110
uiButSetFunc(bt, do_picker_new_mode_cb, bt, NULL);
1828
2111
uiBlockEndAlign(block);
1830
bt= uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth+10, -60, UI_UNIT_X, UI_UNIT_Y, NULL);
2113
bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, -60, UI_UNIT_X, UI_UNIT_Y, NULL);
1831
2114
uiButSetFunc(bt, close_popup_cb, bt, NULL);
1833
2116
/* RGB values */
1834
2117
uiBlockBeginAlign(block);
1835
bt= uiDefButR(block, NUMSLI, 0, "R ", 0, -60, butwidth, UI_UNIT_Y, ptr, propname, 0, 0.0, 0.0, 0, 3, "Red");
1836
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
1837
bt= uiDefButR(block, NUMSLI, 0, "G ", 0, -80, butwidth, UI_UNIT_Y, ptr, propname, 1, 0.0, 0.0, 0, 3, "Green");
1838
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
1839
bt= uiDefButR(block, NUMSLI, 0, "B ", 0, -100, butwidth, UI_UNIT_Y, ptr, propname, 2, 0.0, 0.0, 0, 3, "Blue");
2118
bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("R "), 0, -60, butwidth, UI_UNIT_Y, ptr, prop, 0, 0.0, 0.0, 0, 3, TIP_("Red"));
2119
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
2120
bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("G "), 0, -80, butwidth, UI_UNIT_Y, ptr, prop, 1, 0.0, 0.0, 0, 3, TIP_("Green"));
2121
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
2122
bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("B "), 0, -100, butwidth, UI_UNIT_Y, ptr, prop, 2, 0.0, 0.0, 0, 3, TIP_("Blue"));
1840
2123
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
1842
// could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", 0);
2125
// could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", ICON_NONE);
1843
2126
// but need to use uiButSetFunc for updating other fake buttons
1845
2128
/* HSV values */
1846
2129
uiBlockBeginAlign(block);
1847
bt= uiDefButF(block, NUMSLI, 0, "H ", 0, -60, butwidth, UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, "Hue");
1848
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
1849
bt= uiDefButF(block, NUMSLI, 0, "S ", 0, -80, butwidth, UI_UNIT_Y, hsv+1, 0.0, 1.0, 10, 3, "Saturation");
1850
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
1851
bt= uiDefButF(block, NUMSLI, 0, "V ", 0, -100, butwidth, UI_UNIT_Y, hsv+2, 0.0, max, 10, 3, "Value");
2130
bt = uiDefButF(block, NUMSLI, 0, IFACE_("H "), 0, -60, butwidth, UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, TIP_("Hue"));
2131
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
2132
bt = uiDefButF(block, NUMSLI, 0, IFACE_("S "), 0, -80, butwidth, UI_UNIT_Y, hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation"));
2133
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
2134
bt = uiDefButF(block, NUMSLI, 0, IFACE_("V "), 0, -100, butwidth, UI_UNIT_Y, hsv + 2, 0.0, max, 10, 3, TIP_("Value"));
1852
2135
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
1853
2136
uiBlockEndAlign(block);
1855
if(rgb[3] != FLT_MAX) {
1856
bt= uiDefButR(block, NUMSLI, 0, "A ", 0, -120, butwidth, UI_UNIT_Y, ptr, propname, 3, 0.0, 0.0, 0, 0, "Alpha");
2138
if (rgba[3] != FLT_MAX) {
2139
bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("A "), 0, -120, butwidth, UI_UNIT_Y, ptr, prop, 3, 0.0, 0.0, 0, 0, TIP_("Alpha"));
1857
2140
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
1863
rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
1865
sprintf(hexcol, "%02X%02X%02X", FTOCHAR(rgb_gamma[0]), FTOCHAR(rgb_gamma[1]), FTOCHAR(rgb_gamma[2]));
1867
bt= uiDefBut(block, TEX, 0, "Hex: ", 0, -60, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, "Hex triplet for color (#RRGGBB)");
2146
BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", FTOCHAR(rgb_gamma[0]), FTOCHAR(rgb_gamma[1]), FTOCHAR(rgb_gamma[2]));
2148
bt = uiDefBut(block, TEX, 0, IFACE_("Hex: "), 0, -60, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
1868
2149
uiButSetFunc(bt, do_hex_rna_cb, bt, hexcol);
1869
uiDefBut(block, LABEL, 0, "(Gamma Corrected)", 0, -80, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
2150
uiDefBut(block, LABEL, 0, IFACE_("(Gamma Corrected)"), 0, -80, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
2152
rgb_to_hsv(rgba[0], rgba[1], rgba[2], hsv, hsv + 1, hsv + 2);
1871
2154
picker_new_hide_reveal(block, colormode);
1875
static int ui_picker_small_wheel(const bContext *C, uiBlock *block, wmEvent *event)
2158
static int ui_picker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, wmEvent *event)
1879
if(event->type==WHEELUPMOUSE)
1881
else if(event->type==WHEELDOWNMOUSE)
2162
if (event->type == WHEELUPMOUSE)
2164
else if (event->type == WHEELDOWNMOUSE)
1887
for(but= block->buttons.first; but; but= but->next) {
1888
if(but->type==HSVCUBE && but->active==NULL) {
1889
uiPopupBlockHandle *popup= block->handle;
2170
for (but = block->buttons.first; but; but = but->next) {
2171
if (but->type == HSVCUBE && but->active == NULL) {
2172
uiPopupBlockHandle *popup = block->handle;
2174
float *hsv = ui_block_hsv_get(block);
1892
2176
ui_get_but_vectorf(but, col);
1894
rgb_to_hsv(col[0], col[1], col[2], but->hsv, but->hsv+1, but->hsv+2);
1895
but->hsv[2]= CLAMPIS(but->hsv[2]+add, 0.0f, 1.0f);
1896
hsv_to_rgb(but->hsv[0], but->hsv[1], but->hsv[2], col, col+1, col+2);
2178
rgb_to_hsv_compat(col[0], col[1], col[2], hsv, hsv + 1, hsv + 2);
2179
hsv[2] = CLAMPIS(hsv[2] + add, 0.0f, 1.0f);
2180
hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col + 1, col + 2);
1898
2182
ui_set_but_vectorf(but, col);
1900
ui_update_block_buts_rgb(block, col, NULL);
1902
popup->menuretval= UI_RETURN_UPDATE;
2184
ui_update_block_buts_rgb(block, col);
2186
popup->menuretval = UI_RETURN_UPDATE;