diff options
Diffstat (limited to 'source/blender/editors/interface')
23 files changed, 3286 insertions, 1510 deletions
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 7392db0c91b..03a2c1ec414 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../gpu ../../imbuf ../../makesdna diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 5f36c5e21bf..9e6d9f23442 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -41,6 +41,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_userdef_types.h" +#include "DNA_workspace_types.h" #include "BLI_math.h" #include "BLI_listbase.h" @@ -56,7 +57,8 @@ #include "BKE_screen.h" #include "BKE_idprop.h" -#include "BIF_gl.h" +#include "GPU_glew.h" +#include "GPU_matrix.h" #include "BLF_api.h" #include "BLT_translation.h" @@ -68,11 +70,14 @@ #include "WM_api.h" #include "WM_types.h" #include "wm_subwindow.h" +#include "WM_message.h" #include "RNA_access.h" #include "BPY_extern.h" +#include "ED_screen.h" + #include "IMB_colormanagement.h" #include "interface_intern.h" @@ -509,6 +514,7 @@ static int ui_but_calc_float_precision(uiBut *but, double value) static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int dashInactiveLines) { rcti rect; + float color[4] = {1.0f}; if (line->from == NULL || line->to == NULL) return; @@ -518,15 +524,15 @@ static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int das rect.ymax = BLI_rctf_cent_y(&line->to->rect); if (dashInactiveLines) - UI_ThemeColor(TH_GRID); + UI_GetThemeColor4fv(TH_GRID, color); else if (line->flag & UI_SELECT) - glColor3ub(100, 100, 100); + rgba_float_args_set_ch(color, 100, 100, 100, 255); else if (highlightActiveLines && ((line->from->flag & UI_ACTIVE) || (line->to->flag & UI_ACTIVE))) - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4fv(TH_TEXT_HI, color); else - glColor3ub(0, 0, 0); + rgba_float_args_set_ch(color, 0, 0, 0, 255); - ui_draw_link_bezier(&rect); + ui_draw_link_bezier(&rect, color); } static void ui_draw_links(uiBlock *block) @@ -1214,6 +1220,20 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block) } } +void ui_but_override_flag(uiBut *but) +{ + bool is_overridden; + + RNA_property_override_status(&but->rnapoin, but->rnaprop, but->rnaindex, NULL, &is_overridden, NULL, NULL); + + if (is_overridden) { + but->flag |= UI_BUT_OVERRIDEN; + } + else { + but->flag &= ~UI_BUT_OVERRIDEN; + } +} + void UI_block_update_from_old(const bContext *C, uiBlock *block) { uiBut *but_old; @@ -1278,6 +1298,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x } ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f); + ui_but_override_flag(but); } @@ -1400,11 +1421,9 @@ void UI_block_draw(const bContext *C, uiBlock *block) ui_but_to_pixelrect(&rect, ar, block, NULL); /* pixel space for AA widgets */ - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + gpuPushProjectionMatrix(); + gpuPushMatrix(); + gpuLoadIdentity(); wmOrtho2_region_pixelspace(ar); @@ -1429,10 +1448,8 @@ void UI_block_draw(const bContext *C, uiBlock *block) } /* restore matrix */ - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + gpuPopProjectionMatrix(); + gpuPopMatrix(); if (multisample_enabled) glEnable(GL_MULTISAMPLE); @@ -1440,6 +1457,40 @@ void UI_block_draw(const bContext *C, uiBlock *block) ui_draw_links(block); } +static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlock *block) +{ + uiBut *but_prev = NULL; + /* possibly we should keep the region this block is contained in? */ + for (uiBut *but = block->buttons.first; but; but = but->next) { + if (but->rnapoin.type && but->rnaprop) { + /* quick check to avoid adding buttons representing a vector, multiple times. */ + if ((but_prev && + (but_prev->rnaprop == but->rnaprop) && + (but_prev->rnapoin.type == but->rnapoin.type) && + (but_prev->rnapoin.data == but->rnapoin.data) && + (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false) + { + /* TODO: could make this into utility function. */ + WM_msg_subscribe_rna( + mbus, &but->rnapoin, but->rnaprop, + &(const wmMsgSubscribeValue){ + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }, __func__); + but_prev = but; + } + } + } +} + +void UI_region_message_subscribe(ARegion *ar, struct wmMsgBus *mbus) +{ + for (uiBlock *block = ar->uiblocks.first; block; block = block->next) { + ui_block_message_subscribe(ar, mbus, block); + } +} + /* ************* EVENTS ************* */ /** @@ -1486,6 +1537,7 @@ int ui_but_is_pushed_ex(uiBut *but, double *value) break; case UI_BTYPE_ROW: case UI_BTYPE_LISTROW: + case UI_BTYPE_TAB: UI_GET_BUT_VALUE_INIT(but, *value); /* support for rna enum buts */ if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) { @@ -2425,7 +2477,7 @@ static void ui_but_string_free_internal(uiBut *but) bool ui_but_string_set(bContext *C, uiBut *but, const char *str) { - if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { + if (but->rnaprop && but->rnapoin.data && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { if (RNA_property_editable(&but->rnapoin, but->rnaprop)) { PropertyType type; @@ -2472,8 +2524,15 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) } else if (but->type == UI_BTYPE_TEXT) { /* string */ - if (ui_but_is_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax); - else BLI_strncpy(but->poin, str, but->hardmax); + if (!but->poin || (str[0] == '\0')) { + str = ""; + } + else if (ui_but_is_utf8(but)) { + BLI_strncpy_utf8(but->poin, str, but->hardmax); + } + else { + BLI_strncpy(but->poin, str, but->hardmax); + } return true; } @@ -2685,6 +2744,10 @@ static void ui_but_free(const bContext *C, uiBut *but) MEM_freeN(but->hold_argN); } + if (!but->editstr && but->free_search_arg) { + MEM_SAFE_FREE(but->search_arg); + } + if (but->active) { /* XXX solve later, buttons should be free-able without context ideally, * however they may have open tooltips or popup windows, which need to @@ -2837,11 +2900,13 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]); } else { + const bScreen *screen = WM_window_get_active_screen(window); + /* no subwindow created yet, for menus for example, so we * use the main window instead, since buttons are created * there anyway */ - wm_subwindow_matrix_get(window, window->screen->mainwin, block->winmat); - wm_subwindow_size_get(window, window->screen->mainwin, &getsizex, &getsizey); + wm_subwindow_matrix_get(window, screen->mainwin, block->winmat); + wm_subwindow_size_get(window, screen->mainwin, &getsizex, &getsizey); block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]); block->auto_open = true; @@ -3558,7 +3623,7 @@ static uiBut *ui_def_but_rna( } const char *info; - if (!RNA_property_editable_info(&but->rnapoin, prop, &info)) { + if (but->rnapoin.data && !RNA_property_editable_info(&but->rnapoin, prop, &info)) { ui_def_but_rna__disable(but, info); } @@ -4457,7 +4522,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c for (item = item_array; item->identifier; item++) { /* note: need to give the index rather than the identifier because the enum can be freed */ if (BLI_strcasestr(item->name, str)) { - if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), 0)) + if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), item->icon)) break; } } @@ -4588,7 +4653,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) tmp = BLI_strdup(RNA_property_identifier(but->rnaprop)); } else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) { - if (but->rnaprop) + if (but->rnaprop && but->rnapoin.data) tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type)); else if (but->optype) tmp = BLI_strdup(but->optype->idname); @@ -4683,7 +4748,10 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) if (ptr && prop) { if (!item) { int i; - + + /* so the context is passed to itemf functions */ + WM_operator_properties_sanitize(ptr, false); + RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items); for (i = 0, item = items; i < totitems; i++, item++) { if (item->identifier[0] && item->value == value) diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c index 500744c366d..9aeb685a907 100644 --- a/source/blender/editors/interface/interface_align.c +++ b/source/blender/editors/interface/interface_align.c @@ -110,9 +110,9 @@ enum { bool ui_but_can_align(const uiBut *but) { - return ( - !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) && - (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f)); + const bool btype_can_align = !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, + UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE); + return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f)); } /** diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index a04360b3395..812f4ef0747 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -39,11 +39,12 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_nla.h" +#include "DEG_depsgraph_build.h" + #include "ED_keyframing.h" #include "UI_interface.h" @@ -211,7 +212,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str) /* updates */ driver->flag |= DRIVER_FLAG_RECOMPILE; - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL); ok = true; } diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 9a05c12e00a..3ecb72353bc 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -50,13 +50,14 @@ #include "IMB_imbuf_types.h" #include "IMB_colormanagement.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "BLF_api.h" -#include "GPU_draw.h" -#include "GPU_basic_shader.h" +#include "GPU_batch.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "UI_interface.h" @@ -71,336 +72,462 @@ void UI_draw_roundbox_corner_set(int type) * if this is undone, it's not that big a deal, only makes curves edges * square for the */ roundboxtype = type; - } +#if 0 /* unused */ int UI_draw_roundbox_corner_get(void) { return roundboxtype; } +#endif + +void UI_draw_roundbox_3ubAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const unsigned char col[3], unsigned char alpha) +{ + float colv[4]; + colv[0] = ((float)col[0]) / 255; + colv[1] = ((float)col[1]) / 255; + colv[2] = ((float)col[2]) / 255; + colv[3] = ((float)alpha) / 255; + UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv); +} + +void UI_draw_roundbox_3fvAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[3], float alpha) +{ + float colv[4]; + colv[0] = col[0]; + colv[1] = col[1]; + colv[2] = col[2]; + colv[3] = alpha; + UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv); +} -void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad) +void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]) { float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; int a; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + /* mult */ for (a = 0; a < 7; a++) { mul_v2_fl(vec[a], rad); } - glBegin(mode); + unsigned int vert_ct = 0; + vert_ct += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; + vert_ct += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; + vert_ct += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; + vert_ct += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(col); + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_ct); /* start with corner right-bottom */ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - glVertex2f(maxx - rad, miny); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 7; a++) { - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - glVertex2f(maxx, miny + rad); + immVertex2f(pos, maxx, miny + rad); } else { - glVertex2f(maxx, miny); + immVertex2f(pos, maxx, miny); } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { - glVertex2f(maxx, maxy - rad); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 7; a++) { - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - glVertex2f(maxx - rad, maxy); + immVertex2f(pos, maxx - rad, maxy); } else { - glVertex2f(maxx, maxy); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - glVertex2f(minx + rad, maxy); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 7; a++) { - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - glVertex2f(minx, maxy - rad); + immVertex2f(pos, minx, maxy - rad); } else { - glVertex2f(minx, maxy); + immVertex2f(pos, minx, maxy); } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - glVertex2f(minx, miny + rad); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 7; a++) { - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - glVertex2f(minx + rad, miny); + immVertex2f(pos, minx + rad, miny); } else { - glVertex2f(minx, miny); + immVertex2f(pos, minx, miny); } - glEnd(); + immEnd(); + immUnbindProgram(); } -static void round_box_shade_col(const float col1[3], float const col2[3], const float fac) +static void round_box_shade_col(unsigned attrib, const float col1[3], float const col2[3], const float fac) { - float col[3] = { + float col[4] = { fac * col1[0] + (1.0f - fac) * col2[0], fac * col1[1] + (1.0f - fac) * col2[1], - fac * col1[2] + (1.0f - fac) * col2[2] + fac * col1[2] + (1.0f - fac) * col2[2], + 1.0f }; - glColor3fv(col); + immAttrib4fv(attrib, col); } /* linear horizontal shade within button or in outline */ /* view2d scrollers use it */ void UI_draw_roundbox_shade_x( - int mode, float minx, float miny, float maxx, float maxy, - float rad, float shadetop, float shadedown) + bool filled, float minx, float miny, float maxx, float maxy, + float rad, float shadetop, float shadedown, const float col[4]) { float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; const float div = maxy - miny; const float idiv = 1.0f / div; - float coltop[3], coldown[3], color[4]; + float coltop[3], coldown[3]; + int vert_count = 0; int a; - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + /* mult */ for (a = 0; a < 7; a++) { mul_v2_fl(vec[a], rad); } - /* get current color, needs to be outside of glBegin/End */ - glGetFloatv(GL_CURRENT_COLOR, color); /* 'shade' defines strength of shading */ - coltop[0] = min_ff(1.0f, color[0] + shadetop); - coltop[1] = min_ff(1.0f, color[1] + shadetop); - coltop[2] = min_ff(1.0f, color[2] + shadetop); - coldown[0] = max_ff(0.0f, color[0] + shadedown); - coldown[1] = max_ff(0.0f, color[1] + shadedown); - coldown[2] = max_ff(0.0f, color[2] + shadedown); + coltop[0] = min_ff(1.0f, col[0] + shadetop); + coltop[1] = min_ff(1.0f, col[1] + shadetop); + coltop[2] = min_ff(1.0f, col[2] + shadetop); + coldown[0] = max_ff(0.0f, col[0] + shadedown); + coldown[1] = max_ff(0.0f, col[1] + shadedown); + coldown[2] = max_ff(0.0f, col[2] + shadedown); - glBegin(mode); + vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; + + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count); /* start with corner right-bottom */ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(maxx - rad, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, vec[a][1] * idiv); - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - round_box_shade_col(coltop, coldown, rad * idiv); - glVertex2f(maxx, miny + rad); + round_box_shade_col(color, coltop, coldown, rad * idiv); + immVertex2f(pos, maxx, miny + rad); } else { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(maxx, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, maxx, miny); } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { - round_box_shade_col(coltop, coldown, (div - rad) * idiv); - glVertex2f(maxx, maxy - rad); + round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (div - rad + vec[a][1]) * idiv); - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(maxx - rad, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, maxx - rad, maxy); } else { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(maxx, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(minx + rad, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (div - vec[a][1]) * idiv); - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - round_box_shade_col(coltop, coldown, (div - rad) * idiv); - glVertex2f(minx, maxy - rad); + round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); + immVertex2f(pos, minx, maxy - rad); } else { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(minx, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, minx, maxy); } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - round_box_shade_col(coltop, coldown, rad * idiv); - glVertex2f(minx, miny + rad); + round_box_shade_col(color, coltop, coldown, rad * idiv); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (rad - vec[a][1]) * idiv); - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(minx + rad, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, minx + rad, miny); } else { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(minx, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, minx, miny); } - - glEnd(); + + immEnd(); + immUnbindProgram(); } +#if 0 /* unused */ /* linear vertical shade within button or in outline */ /* view2d scrollers use it */ void UI_draw_roundbox_shade_y( - int mode, float minx, float miny, float maxx, float maxy, - float rad, float shadeLeft, float shadeRight) + bool filled, float minx, float miny, float maxx, float maxy, + float rad, float shadeleft, float shaderight, const float col[4]) { float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; const float div = maxx - minx; const float idiv = 1.0f / div; - float colLeft[3], colRight[3], color[4]; + float colLeft[3], colRight[3]; + int vert_count = 0; int a; /* mult */ for (a = 0; a < 7; a++) { mul_v2_fl(vec[a], rad); } - /* get current color, needs to be outside of glBegin/End */ - glGetFloatv(GL_CURRENT_COLOR, color); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); /* 'shade' defines strength of shading */ - colLeft[0] = min_ff(1.0f, color[0] + shadeLeft); - colLeft[1] = min_ff(1.0f, color[1] + shadeLeft); - colLeft[2] = min_ff(1.0f, color[2] + shadeLeft); - colRight[0] = max_ff(0.0f, color[0] + shadeRight); - colRight[1] = max_ff(0.0f, color[1] + shadeRight); - colRight[2] = max_ff(0.0f, color[2] + shadeRight); + colLeft[0] = min_ff(1.0f, col[0] + shadeleft); + colLeft[1] = min_ff(1.0f, col[1] + shadeleft); + colLeft[2] = min_ff(1.0f, col[2] + shadeleft); + colRight[0] = max_ff(0.0f, col[0] + shaderight); + colRight[1] = max_ff(0.0f, col[1] + shaderight); + colRight[2] = max_ff(0.0f, col[2] + shaderight); + - glBegin(mode); + vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; + + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count); /* start with corner right-bottom */ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx - rad, miny); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, vec[a][0] * idiv); - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - round_box_shade_col(colLeft, colRight, rad * idiv); - glVertex2f(maxx, miny + rad); + round_box_shade_col(color, colLeft, colRight, rad * idiv); + immVertex2f(pos, maxx, miny + rad); } else { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, miny); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, miny); } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, maxy - rad); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (div - rad - vec[a][0]) * idiv); - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - round_box_shade_col(colLeft, colRight, (div - rad) * idiv); - glVertex2f(maxx - rad, maxy); + round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); + immVertex2f(pos, maxx - rad, maxy); } else { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, maxy); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - round_box_shade_col(colLeft, colRight, (div - rad) * idiv); - glVertex2f(minx + rad, maxy); + round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (div - rad + vec[a][0]) * idiv); - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, maxy - rad); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, maxy - rad); } else { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, maxy); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, maxy); } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, miny + rad); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (vec[a][0]) * idiv); - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx + rad, miny); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx + rad, miny); } else { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, miny); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, miny); } - - glEnd(); + + immEnd(); + immUnbindProgram(); } +#endif /* unused */ -/* plain antialiased unfilled rectangle */ -void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad) +void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]) { - float color[4]; - - if (roundboxtype & UI_RB_ALPHA) { - glGetFloatv(GL_CURRENT_COLOR, color); - color[3] = 0.5; - glColor4fv(color); - glEnable(GL_BLEND); - } - - /* set antialias line */ - glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); + int ofs_y = 4 * U.pixelsize; - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); - glDisable(GL_BLEND); - glDisable(GL_LINE_SMOOTH); -} + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color); -/* (old, used in outliner) plain antialiased filled box */ -void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad) -{ - ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA); + immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize)); + immUnbindProgram(); } -void UI_draw_text_underline(int pos_x, int pos_y, int len, int height) +/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */ + +/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */ +void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3]) { - int ofs_y = 4 * U.pixelsize; - glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize)); -} + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + /* add a 1px offset, looks nicer */ + const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize; + const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize; + int a; + float vec[4][2] = { + {0.195, 0.02}, + {0.55, 0.169}, + {0.831, 0.45}, + {0.98, 0.805}, + }; -/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */ + + /* mult */ + for (a = 0; a < 4; a++) { + mul_v2_fl(vec[a], rad); + } + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBeginAtMost(GWN_PRIM_LINE_STRIP, 25); + + immAttrib3ubv(col, highlight); + + /* start with corner left-top */ + if (roundboxtype & UI_CNR_TOP_LEFT) { + immVertex2f(pos, minx, maxy - rad); + for (a = 0; a < 4; a++) { + immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]); + } + immVertex2f(pos, minx + rad, maxy); + } + else { + immVertex2f(pos, minx, maxy); + } + + /* corner right-top */ + if (roundboxtype & UI_CNR_TOP_RIGHT) { + immVertex2f(pos, maxx - rad, maxy); + for (a = 0; a < 4; a++) { + immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]); + } + immVertex2f(pos, maxx, maxy - rad); + } + else { + immVertex2f(pos, maxx, maxy); + } + + immAttrib3ubv(col, highlight_fade); + + /* corner right-bottom */ + if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { + immVertex2f(pos, maxx, miny + rad); + for (a = 0; a < 4; a++) { + immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]); + } + immVertex2f(pos, maxx - rad, miny); + } + else { + immVertex2f(pos, maxx, miny); + } + + /* corner left-bottom */ + if (roundboxtype & UI_CNR_BOTTOM_LEFT) { + immVertex2f(pos, minx + rad, miny); + for (a = 0; a < 4; a++) { + immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]); + } + immVertex2f(pos, minx, miny + rad); + } + else { + immVertex2f(pos, minx, miny); + } + + immAttrib3ubv(col, highlight); + + /* back to corner left-top */ + immVertex2f(pos, minx, roundboxtype & UI_CNR_TOP_LEFT ? maxy - rad : maxy); + + immEnd(); + immUnbindProgram(); +} void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect) { @@ -411,15 +538,15 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w ImBuf *ibuf = (ImBuf *)but->poin; if (!ibuf) return; + + float facx = 1.0f; + float facy = 1.0f; int w = BLI_rcti_size_x(rect); int h = BLI_rcti_size_y(rect); /* scissor doesn't seem to be doing the right thing...? */ #if 0 - //glColor4f(1.0, 0.f, 0.f, 1.f); - //fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax) - /* prevent drawing outside widget area */ GLint scissor[4]; glGetIntegerv(GL_SCISSOR_BOX, scissor); @@ -427,16 +554,15 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w #endif glEnable(GL_BLEND); - glColor4f(0.0, 0.0, 0.0, 0.0); if (w != ibuf->x || h != ibuf->y) { - float facx = (float)w / (float)ibuf->x; - float facy = (float)h / (float)ibuf->y; - glPixelZoom(facx, facy); + facx = (float)w / (float)ibuf->x; + facy = (float)h / (float)ibuf->y; } - glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect); - - glPixelZoom(1.0f, 1.0f); + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, (float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect, + facx, facy, NULL); glDisable(GL_BLEND); @@ -451,43 +577,34 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w /** * Draw title and text safe areas. * - * The first 4 parameters are the offsets for the view, not the zones. + * \Note This functionn is to be used with the 2D dashed shader enabled. + * + * \param pos is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib + * \param line_origin is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib + * + * The next 4 parameters are the offsets for the view, not the zones. */ void UI_draw_safe_areas( - float x1, float x2, float y1, float y2, + uint pos, float x1, float x2, float y1, float y2, const float title_aspect[2], const float action_aspect[2]) { const float size_x_half = (x2 - x1) * 0.5f; const float size_y_half = (y2 - y1) * 0.5f; const float *safe_areas[] = {title_aspect, action_aspect}; - int safe_len = ARRAY_SIZE(safe_areas); - bool is_first = true; + const int safe_len = ARRAY_SIZE(safe_areas); for (int i = 0; i < safe_len; i++) { if (safe_areas[i][0] || safe_areas[i][1]) { - float margin_x, margin_y; - float minx, miny, maxx, maxy; + float margin_x = safe_areas[i][0] * size_x_half; + float margin_y = safe_areas[i][1] * size_y_half; - if (is_first) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0); - is_first = false; - } + float minx = x1 + margin_x; + float miny = y1 + margin_y; + float maxx = x2 - margin_x; + float maxy = y2 - margin_y; - margin_x = safe_areas[i][0] * size_x_half; - margin_y = safe_areas[i][1] * size_y_half; - - minx = x1 + margin_x; - miny = y1 + margin_y; - maxx = x2 - margin_x; - maxy = y2 - margin_y; - - glBegin(GL_LINE_LOOP); - glVertex2f(maxx, miny); - glVertex2f(maxx, maxy); - glVertex2f(minx, maxy); - glVertex2f(minx, miny); - glEnd(); + imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy); } } } @@ -501,52 +618,60 @@ static void draw_scope_end(const rctf *rect, GLint *scissor) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* outline */ - glColor4f(0.f, 0.f, 0.f, 0.5f); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.5f}; + UI_draw_roundbox_4fv(false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color); } static void histogram_draw_one( float r, float g, float b, float alpha, - float x, float y, float w, float h, const float *data, int res, const bool is_line) + float x, float y, float w, float h, const float *data, int res, const bool is_line, + unsigned int pos_attrib) { + float color[4] = {r, g, b, alpha}; + + /* that can happen */ + if (res == 0) + return; + glEnable(GL_LINE_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glColor4f(r, g, b, alpha); + + immUniformColor4fv(color); if (is_line) { /* curve outline */ glLineWidth(1.5); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, res); for (int i = 0; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); } - glEnd(); + immEnd(); } else { /* under the curve */ - glBegin(GL_TRIANGLE_STRIP); - glVertex2f(x, y); - glVertex2f(x, y + (data[0] * h)); + immBegin(GWN_PRIM_TRI_STRIP, res * 2); + immVertex2f(pos_attrib, x, y); + immVertex2f(pos_attrib, x, y + (data[0] * h)); for (int i = 1; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); - glVertex2f(x2, y); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y); } - glEnd(); + immEnd(); /* curve outline */ - glColor4f(0.f, 0.f, 0.f, 0.25f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, res); for (int i = 0; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); } - glEnd(); + immEnd(); } glDisable(GL_LINE_SMOOTH); @@ -559,7 +684,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) Histogram *hist = (Histogram *)but->poin; int res = hist->x_resolution; const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0; - + rctf rect = { .xmin = (float)recti->xmin + 1, .xmax = (float)recti->xmax - 1, @@ -573,9 +698,10 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - UI_ThemeColor4(TH_PREVIEW_BACK); + float color[4]; + UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, histogram can draw outside of boundary */ GLint scissor[4]; @@ -585,34 +711,48 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); /* draw grid lines here */ for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) { const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES; /* so we can tell the 1.0 color point */ if (i == HISTOGRAM_TOT_GRID_LINES) { - glColor4f(1.0f, 1.0f, 1.0f, 0.5f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f); } - fdrawline(rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h); - fdrawline(rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax); + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, rect.xmin, rect.ymin + fac * h); + immVertex2f(pos, rect.xmax, rect.ymin + fac * h); + + immVertex2f(pos, rect.xmin + fac * w, rect.ymin); + immVertex2f(pos, rect.xmin + fac * w, rect.ymax); + + immEnd(); } - + if (hist->mode == HISTO_MODE_LUMA) { - histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line); + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos); } else if (hist->mode == HISTO_MODE_ALPHA) { - histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line); + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos); } else { if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) - histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line); + histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos); if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G) - histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line); + histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos); if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B) - histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line); + histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos); } + + immUnbindProgram(); /* outline */ draw_scope_end(&rect, scissor); @@ -620,6 +760,25 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) #undef HISTOGRAM_TOT_GRID_LINES +static void waveform_draw_one(float *waveform, int nbr, const float col[3]) +{ + Gwn_VertFormat format = {0}; + unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, nbr); + + GWN_vertbuf_attr_fill(vbo, pos_id, waveform); + + /* TODO store the Gwn_Batch inside the scope */ + Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f); + GWN_batch_draw(batch); + + GWN_batch_discard(batch); +} + void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) { Scopes *scopes = (Scopes *)but->poin; @@ -642,7 +801,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), scopes->wavefrm_yfac = 0.98f; float w = BLI_rctf_size_x(&rect) - 7; float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac; - float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f; + float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f; float w3 = w / 3.0f; /* log scale for alpha */ @@ -660,9 +819,10 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - UI_ThemeColor4(TH_PREVIEW_BACK); + float color[4]; + UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, waveform can draw outside of boundary */ glGetIntegerv(GL_VIEWPORT, scissor); @@ -671,94 +831,119 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); - /* draw grid lines here */ + /* draw scale numbers first before binding any shader */ for (int i = 0; i < 6; i++) { char str[4]; BLI_snprintf(str, sizeof(str), "%-3d", i * 20); str[3] = '\0'; - fdrawline(rect.xmin + 22, yofs + (i / 5.f) * h, rect.xmax + 1, yofs + (i / 5.f) * h); - BLF_draw_default(rect.xmin + 1, yofs - 5 + (i / 5.f) * h, 0, str, sizeof(str) - 1); - /* in the loop because blf_draw reset it */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f); + BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1); + } + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); + + /* draw grid lines here */ + immBegin(GWN_PRIM_LINES, 12); + + for (int i = 0; i < 6; i++) { + immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h); + immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h); } + + immEnd(); + /* 3 vertical separation */ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) { + immBegin(GWN_PRIM_LINES, 4); + for (int i = 1; i < 3; i++) { - fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax); + immVertex2f(pos, rect.xmin + i * w3, rect.ymin); + immVertex2f(pos, rect.xmin + i * w3, rect.ymax); } + + immEnd(); } /* separate min max zone on the right */ - fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax); + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect.xmin + w, rect.ymin); + immVertex2f(pos, rect.xmin + w, rect.ymax); + immEnd(); + /* 16-235-240 level in case of ITU-R BT601/709 */ - glColor4f(1.f, 0.4f, 0.f, 0.2f); + immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f); if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) { - fdrawline(rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f); - fdrawline(rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f); - fdrawline(rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f); - fdrawline(rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f); + immBegin(GWN_PRIM_LINES, 8); + + immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f); + immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f); + + immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f); + immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f); + + immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f); + immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f); + + immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f); + immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f); + + immEnd(); } /* 7.5 IRE black point level for NTSC */ - if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) - fdrawline(rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f); + if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) { + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect.xmin, yofs + h * 0.075f); + immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f); + immEnd(); + } if (scopes->ok && scopes->waveform_1 != NULL) { - - /* LUMA (1 channel) */ glBlendFunc(GL_ONE, GL_ONE); - glColor3f(alpha, alpha, alpha); glPointSize(1.0); + /* LUMA (1 channel) */ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) { + float col[3] = {alpha, alpha, alpha}; - glBlendFunc(GL_ONE, GL_ONE); - - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); - - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w, h, 0.f); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuPushMatrix(); + gpuTranslate2f(rect.xmin, yofs); + gpuScale2f(w, h); - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col); + + gpuPopMatrix(); /* min max */ - glColor3f(0.5f, 0.5f, 0.5f); + immUniformColor3f(0.5f, 0.5f, 0.5f); min = yofs + scopes->minmax[0][0] * h; max = yofs + scopes->minmax[0][1] * h; CLAMP(min, rect.ymin, rect.ymax); CLAMP(max, rect.ymin, rect.ymax); - fdrawline(rect.xmax - 3, min, rect.xmax - 3, max); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect.xmax - 3, min); + immVertex2f(pos, rect.xmax - 3, max); + immEnd(); } /* RGB (3 channel) */ else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) { - glBlendFunc(GL_ONE, GL_ONE); - - glEnableClientState(GL_VERTEX_ARRAY); - - glPushMatrix(); + gpuPushMatrix(); + gpuTranslate2f(rect.xmin, yofs); + gpuScale2f(w, h); - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w, h, 0.f); + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]); + waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]); + waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]); - glColor3fv( colors_alpha[0] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glColor3fv( colors_alpha[1] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glColor3fv( colors_alpha[2] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); } /* PARADE / YCC (3 channels) */ else if (ELEM(scopes->wavefrm_mode, @@ -770,49 +955,47 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), { int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE); - glBlendFunc(GL_ONE, GL_ONE); - - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); + gpuPushMatrix(); + gpuTranslate2f(rect.xmin, yofs); + gpuScale2f(w3, h); - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w3, h, 0.f); + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]); - glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuTranslate2f(1.0f, 0.0f); + waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]); - glTranslatef(1.f, 0.f, 0.f); - glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuTranslate2f(1.0f, 0.0f); + waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]); - glTranslatef(1.f, 0.f, 0.f); - glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); } + /* min max */ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) { for (int c = 0; c < 3; c++) { if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB)) - glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f); + immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f); else - glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f); + immUniformColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f); min = yofs + scopes->minmax[c][0] * h; max = yofs + scopes->minmax[c][1] * h; CLAMP(min, rect.ymin, rect.ymax); CLAMP(max, rect.ymin, rect.ymax); - fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect.xmin + w + 2 + c * 2, min); + immVertex2f(pos, rect.xmin + w + 2 + c * 2, max); + immEnd(); } } } - + + immUnbindProgram(); + /* outline */ draw_scope_end(&rect, scissor); + + glDisable(GL_BLEND); } static float polar_to_x(float center, float diam, float ampli, float angle) @@ -825,10 +1008,10 @@ static float polar_to_y(float center, float diam, float ampli, float angle) return center + diam * ampli * sinf(angle); } -static void vectorscope_draw_target(float centerx, float centery, float diam, const float colf[3]) +static void vectorscope_draw_target(unsigned int pos, float centerx, float centery, float diam, const float colf[3]) { float y, u, v; - float tangle = 0.f, tampli; + float tangle = 0.0f, tampli; float dangle, dampli, dangle2, dampli2; rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v); @@ -840,41 +1023,41 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co tampli = sqrtf(u * u + v * v); /* small target vary by 2.5 degree and 2.5 IRE unit */ - glColor4f(1.0f, 1.0f, 1.0, 0.12f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f); dangle = DEG2RADF(2.5f); dampli = 2.5f / 200.0f; - glBegin(GL_LINE_LOOP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); - glEnd(); + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); + immEnd(); /* big target vary by 10 degree and 20% amplitude */ - glColor4f(1.0f, 1.0f, 1.0, 0.12f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f); dangle = DEG2RADF(10.0f); dampli = 0.2f * tampli; dangle2 = DEG2RADF(5.0f); dampli2 = 0.5f * dampli; - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2)); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2)); + immEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2)); + immEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2)); + immEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2)); + immEnd(); } void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) @@ -895,8 +1078,8 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco float w = BLI_rctf_size_x(&rect); float h = BLI_rctf_size_y(&rect); - float centerx = rect.xmin + w / 2; - float centery = rect.ymin + h / 2; + float centerx = rect.xmin + w * 0.5f; + float centery = rect.ymin + h * 0.5f; float diam = (w < h) ? w : h; float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha; @@ -904,9 +1087,10 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - UI_ThemeColor4(TH_PREVIEW_BACK); + float color[4]; + UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, hvectorscope can draw outside of boundary */ GLint scissor[4]; @@ -916,93 +1100,109 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); /* draw grid elements */ /* cross */ - fdrawline(centerx - (diam / 2) - 5, centery, centerx + (diam / 2) + 5, centery); - fdrawline(centerx, centery - (diam / 2) - 5, centerx, centery + (diam / 2) + 5); + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery); + immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery); + + immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5); + immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5); + + immEnd(); + /* circles */ for (int j = 0; j < 5; j++) { - glBegin(GL_LINE_LOOP); const int increment = 15; + immBegin(GWN_PRIM_LINE_LOOP, (int)(360 / increment)); for (int i = 0; i <= 360 - increment; i += increment) { const float a = DEG2RADF((float)i); - const float r = (j + 1) / 10.0f; - glVertex2f(polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a)); + const float r = (j + 1) * 0.1f; + immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a)); } - glEnd(); + immEnd(); } /* skin tone line */ - glColor4f(1.f, 0.4f, 0.f, 0.2f); - fdrawline(polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5, skin_rad), - polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1, skin_rad)); + immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad)); + immVertex2f(pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad)); + immEnd(); + /* saturation points */ for (int i = 0; i < 6; i++) - vectorscope_draw_target(centerx, centery, diam, colors[i]); + vectorscope_draw_target(pos, centerx, centery, diam, colors[i]); if (scopes->ok && scopes->vecscope != NULL) { /* pixel point cloud */ + float col[3] = {alpha, alpha, alpha}; + glBlendFunc(GL_ONE, GL_ONE); - glColor3f(alpha, alpha, alpha); + glPointSize(1.0); - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); + gpuPushMatrix(); + gpuTranslate2f(centerx, centery); + gpuScaleUniform(diam); - glTranslatef(centerx, centery, 0.f); - glScalef(diam, diam, 0.f); + waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col); - glVertexPointer(2, GL_FLOAT, 0, scopes->vecscope); - glPointSize(1.0); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); } + immUnbindProgram(); + /* outline */ draw_scope_end(&rect, scissor); glDisable(GL_BLEND); } -static void ui_draw_colorband_handle_tri_hlight(float x1, float y1, float halfwidth, float height) +static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, float y1, float halfwidth, float height) { glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_STRIP); - glVertex2f(x1 + halfwidth, y1); - glVertex2f(x1, y1 + height); - glVertex2f(x1 - halfwidth, y1); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, x1 + halfwidth, y1); + immVertex2f(pos, x1, y1 + height); + immVertex2f(pos, x1 - halfwidth, y1); + immEnd(); glDisable(GL_LINE_SMOOTH); } -static void ui_draw_colorband_handle_tri(float x1, float y1, float halfwidth, float height, bool fill) +static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, float halfwidth, float height, bool fill) { glEnable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH); - glBegin(fill ? GL_TRIANGLES : GL_LINE_LOOP); - glVertex2f(x1 + halfwidth, y1); - glVertex2f(x1, y1 + height); - glVertex2f(x1 - halfwidth, y1); - glEnd(); + immBegin(fill ? GWN_PRIM_TRIS : GWN_PRIM_LINE_LOOP, 3); + immVertex2f(pos, x1 + halfwidth, y1); + immVertex2f(pos, x1, y1 + height); + immVertex2f(pos, x1 - halfwidth, y1); + immEnd(); glDisable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH); } -static void ui_draw_colorband_handle_box(float x1, float y1, float x2, float y2, bool fill) +static void ui_draw_colorband_handle_box(unsigned int pos, float x1, float y1, float x2, float y2, bool fill) { - glBegin(fill ? GL_QUADS : GL_LINE_LOOP); - glVertex2f(x1, y1); - glVertex2f(x1, y2); - glVertex2f(x2, y2); - glVertex2f(x2, y1); - glEnd(); + immBegin(fill ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y1); + immEnd(); } static void ui_draw_colorband_handle( - const rcti *rect, float x, + uint shdr_pos, const rcti *rect, float x, const float rgb[3], struct ColorManagedDisplay *display, bool active) { @@ -1021,18 +1221,26 @@ static void ui_draw_colorband_handle( y1 = floorf(y1 + 0.5f); if (active || half_width < min_width) { - glBegin(GL_LINES); - glColor3ub(0, 0, 0); - glVertex2f(x, y1); - glVertex2f(x, y2); - glEnd(); - setlinestyle(active ? 2 : 1); - glBegin(GL_LINES); - glColor3ub(200, 200, 200); - glVertex2f(x, y1); - glVertex2f(x, y2); - glEnd(); - setlinestyle(0); + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + immUniformArray4fv("colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2); + immUniform1f("dash_width", active ? 4.0f : 2.0f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(shdr_pos, x, y1); + immVertex2f(shdr_pos, x, y2); + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* hide handles when zoomed out too far */ if (half_width < min_width) { @@ -1043,45 +1251,46 @@ static void ui_draw_colorband_handle( /* shift handle down */ y1 -= half_width; - glColor3ub(0, 0, 0); - ui_draw_colorband_handle_box(x - half_width, y1 - 1, x + half_width, y1 + height, false); + immUniformColor3ub(0, 0, 0); + ui_draw_colorband_handle_box(shdr_pos, x - half_width, y1 - 1, x + half_width, y1 + height, false); /* draw all triangles blended */ glEnable(GL_BLEND); - ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true); + ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true); if (active) - glColor3ub(196, 196, 196); + immUniformColor3ub(196, 196, 196); else - glColor3ub(96, 96, 96); - ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true); + immUniformColor3ub(96, 96, 96); + ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true); if (active) - glColor3ub(255, 255, 255); + immUniformColor3ub(255, 255, 255); else - glColor3ub(128, 128, 128); - ui_draw_colorband_handle_tri_hlight(x, y1 + height - 1, (half_width - 1), (half_width - 1)); + immUniformColor3ub(128, 128, 128); + ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height - 1, (half_width - 1), (half_width - 1)); - glColor3ub(0, 0, 0); - ui_draw_colorband_handle_tri_hlight(x, y1 + height, half_width, half_width); + immUniformColor3ub(0, 0, 0); + ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height, half_width, half_width); glDisable(GL_BLEND); - glColor3ub(128, 128, 128); - ui_draw_colorband_handle_box(x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true); + immUniformColor3ub(128, 128, 128); + ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true); if (display) { IMB_colormanagement_scene_linear_to_display_v3(colf, display); } - glColor3fv(colf); - ui_draw_colorband_handle_box(x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true); + immUniformColor3fv(colf); + ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true); } void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect) { struct ColorManagedDisplay *display = NULL; + unsigned int position, color; ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin); if (coba == NULL) return; @@ -1092,20 +1301,25 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti float x1 = rect->xmin; float sizex = rect->xmax - x1; float sizey = BLI_rcti_size_y(rect); - float sizey_solid = sizey / 4; + float sizey_solid = sizey * 0.25f; float y1 = rect->ymin; - /* Drawing the checkerboard. - * This could be optimized with a single checkerboard shader, - * instead of drawing twice and using stippling the second time. */ - /* layer: background, to show tranparency */ - glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255); - glRectf(x1, y1, x1 + sizex, rect->ymax); - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX); - glRectf(x1, y1, x1 + sizex, rect->ymax); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + Gwn_VertFormat *format = immVertexFormat(); + position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); + + /* Drawing the checkerboard. */ + immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f); + immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f); + immUniform1i("size", 8); + immRectf(position, x1, y1, x1 + sizex, rect->ymax); + immUnbindProgram(); + + /* New format */ + format = immVertexFormat(); + position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); /* layer: color ramp */ glEnable(GL_BLEND); @@ -1118,7 +1332,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[1] = y1 + sizey_solid; v2[1] = rect->ymax; - glBegin(GL_TRIANGLE_STRIP); + immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2); for (int a = 0; a <= sizex; a++) { float pos = ((float)a) / sizex; BKE_colorband_evaluate(coba, pos, colf); @@ -1127,17 +1341,17 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[0] = v2[0] = x1 + a; - glColor4fv(colf); - glVertex2fv(v1); - glVertex2fv(v2); + immAttrib4fv(color, colf); + immVertex2fv(position, v1); + immVertex2fv(position, v2); } - glEnd(); + immEnd(); /* layer: color ramp without alpha for reference when manipulating ramp properties */ v1[1] = y1; v2[1] = y1 + sizey_solid; - glBegin(GL_TRIANGLE_STRIP); + immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2); for (int a = 0; a <= sizex; a++) { float pos = ((float)a) / sizex; BKE_colorband_evaluate(coba, pos, colf); @@ -1146,31 +1360,48 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[0] = v2[0] = x1 + a; - glColor4f(colf[0], colf[1], colf[2], 1.0f); - glVertex2fv(v1); - glVertex2fv(v2); + immAttrib4f(color, colf[0], colf[1], colf[2], 1.0f); + immVertex2fv(position, v1); + immVertex2fv(position, v2); } - glEnd(); + immEnd(); + + immUnbindProgram(); glDisable(GL_BLEND); + /* New format */ + format = immVertexFormat(); + position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* layer: box outline */ - glColor4f(0.0, 0.0, 0.0, 1.0); - fdrawbox(x1, y1, x1 + sizex, rect->ymax); - + immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f); + imm_draw_box_wire_2d(position, x1, y1, x1 + sizex, rect->ymax); + /* layer: box outline */ glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - fdrawline(x1, y1, x1 + sizex, y1); - glColor4f(1.0f, 1.0f, 1.0f, 0.25f); - fdrawline(x1, y1 - 1, x1 + sizex, y1 - 1); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(position, x1, y1); + immVertex2f(position, x1 + sizex, y1); + immEnd(); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(position, x1, y1 - 1); + immVertex2f(position, x1 + sizex, y1 - 1); + immEnd(); + glDisable(GL_BLEND); /* layer: draw handles */ for (int a = 0; a < coba->tot; a++, cbd++) { if (a != coba->cur) { float pos = x1 + cbd->pos * (sizex - 1) + 1; - ui_draw_colorband_handle(rect, pos, &cbd->r, display, false); + ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, false); } } @@ -1178,117 +1409,100 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti if (coba->tot != 0) { cbd = &coba->data[coba->cur]; float pos = x1 + cbd->pos * (sizex - 1) + 1; - ui_draw_colorband_handle(rect, pos, &cbd->r, display, true); + ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, true); } + + immUnbindProgram(); } void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect) { - static GLuint displist = 0; + /* sphere color */ float diffuse[3] = {1.0f, 1.0f, 1.0f}; + float light[3]; float size; /* backdrop */ - glColor3ubv((unsigned char *)wcol->inner); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f); + UI_draw_roundbox_3ubAlpha(true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255); - /* sphere color */ glCullFace(GL_BACK); glEnable(GL_CULL_FACE); /* setup lights */ - GPULightData light = {0}; - light.type = GPU_LIGHT_SUN; - copy_v3_v3(light.diffuse, diffuse); - zero_v3(light.specular); - ui_but_v3_get(but, light.direction); - - GPU_basic_shader_light_set(0, &light); - for (int a = 1; a < 8; a++) - GPU_basic_shader_light_set(a, NULL); - - /* setup shader */ - GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING); + ui_but_v3_get(but, light); /* transform to button */ - glPushMatrix(); - glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f); + gpuPushMatrix(); if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect)) - size = BLI_rcti_size_x(rect) / 200.f; + size = 0.5f * BLI_rcti_size_x(rect); else - size = BLI_rcti_size_y(rect) / 200.f; - - glScalef(size, size, MIN2(size, 1.0f)); + size = 0.5f * BLI_rcti_size_y(rect); - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - GPU_basic_shader_bind(GPU_basic_shader_bound_options()); - gluSphere(qobj, 100.0, 32, 24); - gluDeleteQuadric(qobj); - - glEndList(); - } + gpuTranslate2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect)); + gpuScaleUniform(size); - glCallList(displist); + Gwn_Batch *sphere = GPU_batch_preset_sphere(2); + GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f); + GWN_batch_uniform_3fv(sphere, "light", light); + GWN_batch_draw(sphere); /* restore */ - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - GPU_default_lights(); glDisable(GL_CULL_FACE); /* AA circle */ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ubv((unsigned char *)wcol->inner); + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3ubv((unsigned char *)wcol->inner); - glutil_draw_lined_arc(0.0f, M_PI * 2.0, 100.0f, 32); + imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); /* matrix after circle */ - glPopMatrix(); + gpuPopMatrix(); - /* We disabled all blender lights above, so restore them here. */ - GPU_default_lights(); + immUnbindProgram(); } -static void ui_draw_but_curve_grid(const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step) +static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step) { - glBegin(GL_LINES); float dx = step * zoomx; float fx = rect->xmin + zoomx * (-offsx); if (fx > rect->xmin) fx -= dx * (floorf(fx - rect->xmin)); - while (fx < rect->xmax) { - glVertex2f(fx, rect->ymin); - glVertex2f(fx, rect->ymax); - fx += dx; - } float dy = step * zoomy; float fy = rect->ymin + zoomy * (-offsy); if (fy > rect->ymin) fy -= dy * (floorf(fy - rect->ymin)); + + float line_count = floorf((rect->xmax - fx) / dx) + 1.0f + + floorf((rect->ymax - fy) / dy) + 1.0f; + + immBegin(GWN_PRIM_LINES, (int)line_count * 2); + while (fx < rect->xmax) { + immVertex2f(pos, fx, rect->ymin); + immVertex2f(pos, fx, rect->ymax); + fx += dx; + } while (fy < rect->ymax) { - glVertex2f(rect->xmin, fy); - glVertex2f(rect->xmax, fy); + immVertex2f(pos, rect->xmin, fy); + immVertex2f(pos, rect->xmax, fy); fy += dy; } - glEnd(); + immEnd(); } static void gl_shaded_color(unsigned char *col, int shade) { - glColor3ub(col[0] - shade > 0 ? col[0] - shade : 0, - col[1] - shade > 0 ? col[1] - shade : 0, - col[2] - shade > 0 ? col[2] - shade : 0); + immUniformColor3ub(col[0] - shade > 0 ? col[0] - shade : 0, + col[1] - shade > 0 ? col[1] - shade : 0, + col[2] - shade > 0 ? col[2] - shade : 0); } void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti *rect) @@ -1324,10 +1538,8 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&cumap->curr); float offsx = cumap->curr.xmin - (1.0f / zoomx); float offsy = cumap->curr.ymin - (1.0f / zoomy); - - glLineWidth(1.0f); - /* backdrop */ + /* Do this first to not mess imm context */ if (but->a1 == UI_GRAD_H) { /* magic trigger for curve backgrounds */ float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */ @@ -1340,96 +1552,105 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti }; ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f); + } + glLineWidth(1.0f); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* backdrop */ + if (but->a1 == UI_GRAD_H) { /* grid, hsv uses different grid */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(0, 0, 0, 48); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.1666666f); + immUniformColor4ub(0, 0, 0, 48); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f); glDisable(GL_BLEND); } else { if (cumap->flag & CUMA_DO_CLIP) { gl_shaded_color((unsigned char *)wcol->inner, -20); - glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); - glColor3ubv((unsigned char *)wcol->inner); - glRectf(rect->xmin + zoomx * (cumap->clipr.xmin - offsx), - rect->ymin + zoomy * (cumap->clipr.ymin - offsy), - rect->xmin + zoomx * (cumap->clipr.xmax - offsx), - rect->ymin + zoomy * (cumap->clipr.ymax - offsy)); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformColor3ubv((unsigned char *)wcol->inner); + immRectf(pos, rect->xmin + zoomx * (cumap->clipr.xmin - offsx), + rect->ymin + zoomy * (cumap->clipr.ymin - offsy), + rect->xmin + zoomx * (cumap->clipr.xmax - offsx), + rect->ymin + zoomy * (cumap->clipr.ymax - offsy)); } else { - glColor3ubv((unsigned char *)wcol->inner); - glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformColor3ubv((unsigned char *)wcol->inner); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); } /* grid, every 0.25 step */ gl_shaded_color((unsigned char *)wcol->inner, -16); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f); /* grid, every 1.0 step */ gl_shaded_color((unsigned char *)wcol->inner, -24); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f); /* axes */ gl_shaded_color((unsigned char *)wcol->inner, -50); - glBegin(GL_LINES); - glVertex2f(rect->xmin, rect->ymin + zoomy * (-offsy)); - glVertex2f(rect->xmax, rect->ymin + zoomy * (-offsy)); - glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymax); - glEnd(); + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy)); + immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy)); + immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax); + immEnd(); } /* cfra option */ /* XXX 2.48 */ #if 0 if (cumap->flag & CUMA_DRAW_CFRA) { - glColor3ub(0x60, 0xc0, 0x40); - glBegin(GL_LINES); - glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax); - glEnd(); + immUniformColor3ub(0x60, 0xc0, 0x40); + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax); + immEnd(); } #endif /* sample option */ if (cumap->flag & CUMA_DRAW_SAMPLE) { - glBegin(GL_LINES); /* will draw one of the following 3 lines */ + immBegin(GWN_PRIM_LINES, 2); /* will draw one of the following 3 lines */ if (but->a1 == UI_GRAD_H) { float tsample[3]; float hsv[3]; linearrgb_to_srgb_v3_v3(tsample, cumap->sample); rgb_to_hsv_v(tsample, hsv); - glColor3ub(240, 240, 240); + immUniformColor3ub(240, 240, 240); - glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax); } else if (cumap->cur == 3) { float lum = IMB_colormanagement_get_luminance(cumap->sample); - glColor3ub(240, 240, 240); + immUniformColor3ub(240, 240, 240); - glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax); } else { if (cumap->cur == 0) - glColor3ub(240, 100, 100); + immUniformColor3ub(240, 100, 100); else if (cumap->cur == 1) - glColor3ub(100, 240, 100); + immUniformColor3ub(100, 240, 100); else - glColor3ub(100, 100, 240); + immUniformColor3ub(100, 100, 240); - glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax); } - glEnd(); + immEnd(); } /* the curve */ - glColor3ubv((unsigned char *)wcol->item); + immUniformColor3ubv((unsigned char *)wcol->item); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2); if (cuma->table == NULL) curvemapping_changed(cumap, false); @@ -1438,52 +1659,67 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti /* first point */ if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - glVertex2f(rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy)); + immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy)); } else { float fx = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]); float fy = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } for (int a = 0; a <= CM_TABLE; a++) { float fx = rect->xmin + zoomx * (cmp[a].x - offsx); float fy = rect->ymin + zoomy * (cmp[a].y - offsy); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } /* last point */ if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - glVertex2f(rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy)); + immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy)); } else { float fx = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]); float fy = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } - glEnd(); + immEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); + immUnbindProgram(); /* the points, use aspect to make them visible on edges */ + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + cmp = cuma->curve; glPointSize(3.0f); - glBegin(GL_POINTS); + immBegin(GWN_PRIM_POINTS, cuma->totpoint); for (int a = 0; a < cuma->totpoint; a++) { + float color[4]; if (cmp[a].flag & CUMA_SELECT) - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4fv(TH_TEXT_HI, color); else - UI_ThemeColor(TH_TEXT); + UI_GetThemeColor4fv(TH_TEXT, color); float fx = rect->xmin + zoomx * (cmp[a].x - offsx); float fy = rect->ymin + zoomy * (cmp[a].y - offsy); - glVertex2f(fx, fy); + immAttrib4fv(col, color); + immVertex2f(pos, fx, fy); } - glEnd(); + immEnd(); + immUnbindProgram(); /* restore scissortest */ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); /* outline */ - glColor3ubv((unsigned char *)wcol->outline); - fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv((unsigned char *)wcol->outline); + imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + + immUnbindProgram(); } void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) @@ -1513,9 +1749,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc (rect.ymax + 1) - (rect.ymin - 1)); if (scopes->track_disabled) { - glColor4f(0.7f, 0.3f, 0.3f, 0.3f); + float color[4] = {0.7f, 0.3f, 0.3f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); ok = true; } @@ -1542,62 +1778,72 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc } if (!ok && scopes->track_preview) { - glPushMatrix(); + gpuPushMatrix(); /* draw content of pattern area */ glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]); if (width > 0 && height > 0) { ImBuf *drawibuf = scopes->track_preview; + float col_sel[4], col_outline[4]; if (scopes->use_track_mask) { - glColor4f(0.0f, 0.0f, 0.0f, 0.3f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); } - glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, - drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, NULL); /* draw cross for pixel position */ - glTranslatef(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.f); + gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]); glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect)); - GPU_basic_shader_bind_enable(GPU_SHADER_LINE); - - for (int a = 0; a < 2; a++) { - if (a == 1) { - GPU_basic_shader_bind_enable(GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); - UI_ThemeColor(TH_SEL_MARKER); - } - else { - UI_ThemeColor(TH_MARKER_OUTLINE); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + + UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel); + UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline); + + /* Do stipple cross with geometry */ + immBegin(GWN_PRIM_LINES, 7 * 2 * 2); + float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f}; + for (int axe = 0; axe < 2; ++axe) { + for (int i = 0; i < 7; ++i) { + float x1 = pos_sel[i] * (1 - axe); + float y1 = pos_sel[i] * axe; + float x2 = pos_sel[i + 1] * (1 - axe); + float y2 = pos_sel[i + 1] * axe; + + if (i % 2 == 1) + immAttrib4fv(col, col_sel); + else + immAttrib4fv(col, col_outline); + + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); } - - glBegin(GL_LINES); - glVertex2f(-10.0f, 0.0f); - glVertex2f(10.0f, 0.0f); - glVertex2f(0.0f, -10.0f); - glVertex2f(0.0f, 10.0f); - glEnd(); } + immEnd(); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + immUnbindProgram(); } - glPopMatrix(); + gpuPopMatrix(); ok = true; } if (!ok) { - glColor4f(0.f, 0.f, 0.f, 0.3f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); } /* outline */ @@ -1643,26 +1889,31 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol BLI_rcti_size_x(&scissor_new), BLI_rcti_size_y(&scissor_new)); - glColor4ubv(but->col); - float x = 0.5f * (recti->xmin + recti->xmax); float y = 0.5f * (recti->ymin + recti->ymax); - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(but->col); + glEnable(GL_BLEND); - glBegin(GL_POLYGON); + immBegin(GWN_PRIM_TRI_FAN, 16); for (int a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); + immVertex2f(pos, x + size * si[a], y + size * co[a]); + immEnd(); - glColor4ub(0, 0, 0, 150); + immUniformColor4ub(0, 0, 0, 150); glLineWidth(1); glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_LOOP); + immBegin(GWN_PRIM_LINE_LOOP, 16); for (int a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); + immVertex2f(pos, x + size * si[a], y + size * co[a]); + immEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); + + immUnbindProgram(); /* restore scissortest */ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); @@ -1670,47 +1921,91 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol /* ****************************************************** */ +/* TODO: high quality UI drop shadows using GLSL shader and single draw call + * would replace / modify the following 3 functions - merwin + */ -static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha) +static void ui_shadowbox(unsigned pos, unsigned color, float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha) { + /* v1-_ + * | -_v2 + * | | + * | | + * | | + * v7_______v3____v4 + * \ | / + * \ | _v5 + * v8______v6_- + */ + const float v1[2] = {maxx, maxy - 0.3f * shadsize}; + const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize}; + const float v3[2] = {maxx, miny}; + const float v4[2] = {maxx + shadsize, miny}; + + const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize}; + + const float v6[2] = {maxx, miny - shadsize}; + const float v7[2] = {minx + 0.3f * shadsize, miny}; + const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize}; + /* right quad */ - glColor4ub(0, 0, 0, alpha); - glVertex2f(maxx, miny); - glVertex2f(maxx, maxy - 0.3f * shadsize); - glColor4ub(0, 0, 0, 0); - glVertex2f(maxx + shadsize, maxy - 0.75f * shadsize); - glVertex2f(maxx + shadsize, miny); - + immAttrib4ub(color, 0, 0, 0, alpha); + immVertex2fv(pos, v3); + immVertex2fv(pos, v1); + immAttrib4ub(color, 0, 0, 0, 0); + immVertex2fv(pos, v2); + + immVertex2fv(pos, v2); + immVertex2fv(pos, v4); + immAttrib4ub(color, 0, 0, 0, alpha); + immVertex2fv(pos, v3); + /* corner shape */ - glColor4ub(0, 0, 0, alpha); - glVertex2f(maxx, miny); - glColor4ub(0, 0, 0, 0); - glVertex2f(maxx + shadsize, miny); - glVertex2f(maxx + 0.7f * shadsize, miny - 0.7f * shadsize); - glVertex2f(maxx, miny - shadsize); - + /* immAttrib4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */ + immVertex2fv(pos, v3); + immAttrib4ub(color, 0, 0, 0, 0); + immVertex2fv(pos, v4); + immVertex2fv(pos, v5); + + immVertex2fv(pos, v5); + immVertex2fv(pos, v6); + immAttrib4ub(color, 0, 0, 0, alpha); + immVertex2fv(pos, v3); + /* bottom quad */ - glColor4ub(0, 0, 0, alpha); - glVertex2f(minx + 0.3f * shadsize, miny); - glVertex2f(maxx, miny); - glColor4ub(0, 0, 0, 0); - glVertex2f(maxx, miny - shadsize); - glVertex2f(minx + 0.5f * shadsize, miny - shadsize); + /* immAttrib4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */ + immVertex2fv(pos, v3); + immAttrib4ub(color, 0, 0, 0, 0); + immVertex2fv(pos, v6); + immVertex2fv(pos, v8); + + immVertex2fv(pos, v8); + immAttrib4ub(color, 0, 0, 0, alpha); + immVertex2fv(pos, v7); + immVertex2fv(pos, v3); } void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy) { glEnable(GL_BLEND); - - glBegin(GL_QUADS); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + immBegin(GWN_PRIM_TRIS, 54); /* accumulated outline boxes to make shade not linear, is more pleasant */ - ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8); - ui_shadowbox(minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8); - ui_shadowbox(minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8); - - glEnd(); + ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8); + ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8); + ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8); + immEnd(); + + immUnbindProgram(); + glDisable(GL_BLEND); } @@ -1719,8 +2014,8 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha { float rad; - if (radius > (BLI_rctf_size_y(rct) - 10.0f) / 2.0f) - rad = (BLI_rctf_size_y(rct) - 10.0f) / 2.0f; + if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f) + rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f; else rad = radius; @@ -1741,29 +2036,16 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha float calpha = dalpha; for (; i--; a -= aspect) { /* alpha ranges from 2 to 20 or so */ - glColor4f(0.0f, 0.0f, 0.0f, calpha); + float color[4] = {0.0f, 0.0f, 0.0f, calpha}; + UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color); calpha += dalpha; - - UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a); } /* outline emphasis */ glEnable(GL_LINE_SMOOTH); - glColor4ub(0, 0, 0, 100); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.4f}; + UI_draw_roundbox_4fv(false, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f, color); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } - -/** - * Reset GL state (keep minimal). - * - * \note Blender's internal code doesn't assume these are reset, - * but external callbacks may depend on their state. - */ -void UI_reinit_gl_state(void) -{ - glLineWidth(1.0f); - glPointSize(1.0f); -} diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 9cf40c07c0d..f72f67320cc 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -43,10 +43,12 @@ #include "BKE_screen.h" #include "BKE_report.h" #include "BKE_animsys.h" -#include "BKE_depsgraph.h" #include "BKE_idcode.h" #include "BKE_unit.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -184,8 +186,8 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c wmWindow *win = CTX_wm_window(C); int x = win->eventstate->x; int y = win->eventstate->y; - const unsigned char fg[4] = {255, 255, 255, 255}; - const unsigned char bg[4] = {0, 0, 0, 50}; + const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f}; if ((name[0] == '\0') || @@ -199,7 +201,7 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c y += U.widget_unit; - UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg); + UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg); } @@ -214,8 +216,8 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c */ static uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, event->x, event->y); + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y); ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_ANY, event->x, event->y); uiBut *but = ui_but_find_mouse_over(ar, event); @@ -307,10 +309,9 @@ static void eyedropper_exit(bContext *C, wmOperator *op) */ static void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]) { - /* we could use some clever */ - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my); + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); const char *display_device = CTX_data_scene(C)->display_settings.display_device; struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); @@ -909,8 +910,8 @@ static void datadropper_exit(bContext *C, wmOperator *op) static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id) { /* we could use some clever */ - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = BKE_screen_find_area_xy(win->screen, -1, mx, my); + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my); ScrArea *area_prev = CTX_wm_area(C); ARegion *ar_prev = CTX_wm_region(C); @@ -1210,9 +1211,9 @@ static void depthdropper_exit(bContext *C, wmOperator *op) static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth) { /* we could use some clever */ - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my); - Scene *scene = win->screen->scene; + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); + Scene *scene = CTX_data_scene(C); UnitSettings *unit = &scene->unit; const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0; @@ -1225,6 +1226,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, if (sa->spacetype == SPACE_VIEW3D) { ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); if (ar) { + struct Depsgraph *graph = CTX_data_depsgraph(C); View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; /* weak, we could pass in some reference point */ @@ -1234,6 +1236,9 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, my - ar->winrct.ymin}; float co[3]; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); @@ -1242,7 +1247,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) { + if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, mval, co, true, NULL)) { const float mval_center_fl[2] = { (float)ar->winx / 2, (float)ar->winy / 2}; @@ -1528,8 +1533,8 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve if (success) { /* send updates */ UI_context_update_anim_flag(C); - DAG_relations_tag_update(CTX_data_main(C)); - DAG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA); + DEG_relations_tag_update(CTX_data_main(C)); + DEG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA); WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index c78fe34e849..f28a398a46a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -186,7 +186,6 @@ typedef struct uiSelectContextStore { uiSelectContextElem *elems; int elems_len; bool do_free; - bool is_enabled; /* When set, simply copy values (don't apply difference). * Rules are: * - dragging numbers uses delta. @@ -202,7 +201,9 @@ static void ui_selectcontext_apply( bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data, const double value, const double value_orig); +#if 0 #define IS_ALLSELECT_EVENT(event) ((event)->alt != 0) +#endif /** just show a tinted color so users know its activated */ #define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE @@ -1182,14 +1183,11 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl ui_but_execute_begin(C, ar, but, &active_back); #ifdef USE_ALLSELECT - if (data->select_others.is_enabled) { - /* init once! */ - if (mbut_state->select_others.elems_len == 0) { - ui_selectcontext_begin(C, but, &mbut_state->select_others); - } - if (mbut_state->select_others.elems_len == 0) { - mbut_state->select_others.elems_len = -1; - } + if (mbut_state->select_others.elems_len == 0) { + ui_selectcontext_begin(C, but, &mbut_state->select_others); + } + if (mbut_state->select_others.elems_len == 0) { + mbut_state->select_others.elems_len = -1; } /* needed so we apply the right deltas */ @@ -2072,12 +2070,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton else # endif if (data->select_others.elems_len == 0) { - wmWindow *win = CTX_wm_window(C); - /* may have been enabled before activating */ - if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) { - ui_selectcontext_begin(C, but, &data->select_others); - data->select_others.is_enabled = true; - } + ui_selectcontext_begin(C, but, &data->select_others); } if (data->select_others.elems_len == 0) { /* dont check again */ @@ -2118,6 +2111,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton break; case UI_BTYPE_ROW: case UI_BTYPE_LISTROW: + case UI_BTYPE_TAB: ui_apply_but_ROW(C, block, but, data); break; case UI_BTYPE_SCROLL: @@ -3079,11 +3073,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) #ifdef USE_ALLSELECT if (is_num_but) { - if (IS_ALLSELECT_EVENT(win->eventstate)) { - data->select_others.is_enabled = true; - data->select_others.is_copy = true; - - } + data->select_others.is_copy = true; } #endif @@ -3170,6 +3160,9 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data) ui_searchbox_free(C, data->searchbox); data->searchbox = NULL; + if (but->free_search_arg) { + MEM_SAFE_FREE(but->search_arg); + } } but->editstr = NULL; @@ -3685,15 +3678,6 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat data->menu->popup = but->block->handle->popup; } -#ifdef USE_ALLSELECT - { - wmWindow *win = CTX_wm_window(C); - if (IS_ALLSELECT_EVENT(win->eventstate)) { - data->select_others.is_enabled = true; - } - } -#endif - /* this makes adjacent blocks auto open from now on */ //if (but->block->auto_open == 0) but->block->auto_open = 1; } @@ -3875,6 +3859,18 @@ static int ui_do_but_KEYEVT( return WM_UI_HANDLER_CONTINUE; } +static int ui_do_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +{ + if (data->state == BUTTON_STATE_HIGHLIGHT) { + if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_RELEASE) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + return WM_UI_HANDLER_CONTINUE; + } + } + + return WM_UI_HANDLER_CONTINUE; +} + static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, const int mouse_xy[2]) { int x = mouse_xy[0], y = mouse_xy[1]; @@ -5219,7 +5215,8 @@ static int ui_do_but_COLOR( if (!event->ctrl) { float color[3]; Scene *scene = CTX_data_scene(C); - Paint *paint = BKE_paint_get_active(scene); + ViewLayer *view_layer = CTX_data_view_layer(C); + Paint *paint = BKE_paint_get_active(scene, view_layer); Brush *brush = BKE_paint_brush(paint); if (brush->flag & BRUSH_USE_GRADIENT) { @@ -6127,6 +6124,7 @@ static int ui_do_but_CURVE( int mx, my, a; bool changed = false; Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); mx = event->x; my = event->y; @@ -6255,7 +6253,7 @@ static int ui_do_but_CURVE( } else { curvemapping_changed(cumap, true); /* remove doubles */ - BKE_paint_invalidate_cursor_overlay(scene, cumap); + BKE_paint_invalidate_cursor_overlay(scene, view_layer, cumap); } } @@ -6761,6 +6759,8 @@ static bool ui_but_menu(bContext *C, uiBut *but) MenuType *mt = WM_menutype_find("WM_MT_button_context", true); bool is_array, is_array_component; uiStringInfo label = {BUT_GET_LABEL, NULL}; + wmOperatorType *ot; + PointerRNA op_ptr; /* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/ /* return 0;*/ @@ -6787,11 +6787,11 @@ static bool ui_but_menu(bContext *C, uiBut *but) const PropertySubType subtype = RNA_property_subtype(prop); bool is_anim = RNA_property_animateable(ptr, prop); bool is_editable = RNA_property_editable(ptr, prop); + bool is_overridable; /*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */ bool is_set = RNA_property_is_set(ptr, prop); - /* Set the (button_pointer, button_prop) and pointer data for Python access to the hovered ui element. */ - uiLayoutSetContextFromBut(layout, but); + RNA_property_override_status(ptr, prop, -1, &is_overridable, NULL, NULL, NULL); /* second slower test, saved people finding keyframe items in menus when its not possible */ if (is_anim) @@ -6920,11 +6920,57 @@ static bool ui_but_menu(bContext *C, uiBut *but) ICON_NONE, "ANIM_OT_keyingset_button_remove"); } } - + + if (is_overridable) { + /* Override Operators */ + uiItemS(layout); + + if (but->flag & UI_BUT_OVERRIDEN) { + if (is_array_component) { + ot = WM_operatortype_find("UI_OT_override_type_set_button", false); + uiItemFullO_ptr(layout, ot, "Overrides Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", true); + uiItemFullO_ptr(layout, ot, "Single Override Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); + + uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"), + ICON_X, "UI_OT_override_remove_button", "all", true); + uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"), + ICON_X, "UI_OT_override_remove_button", "all", false); + } + else { + uiItemFullO(layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); + + uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"), + ICON_X, "UI_OT_override_remove_button", "all", true); + } + } + else { + if (is_array_component) { + ot = WM_operatortype_find("UI_OT_override_type_set_button", false); + uiItemFullO_ptr(layout, ot, "Define Overrides", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", true); + uiItemFullO_ptr(layout, ot, "Define Single Override", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); + } + else { + uiItemFullO(layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); + } + } + } + uiItemS(layout); - + /* Property Operators */ - + /* Copy Property Value * Paste Property Value */ @@ -7129,6 +7175,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case UI_BTYPE_HOTKEY_EVENT: retval = ui_do_but_HOTKEYEVT(C, but, data, event); break; + case UI_BTYPE_TAB: + retval = ui_do_but_TAB(C, but, data, event); + break; case UI_BTYPE_BUT_TOGGLE: case UI_BTYPE_TOGGLE: case UI_BTYPE_ICON_TOGGLE: @@ -8200,6 +8249,7 @@ void UI_context_update_anim_flag(const bContext *C) for (block = ar->uiblocks.first; block; block = block->next) { for (but = block->buttons.first; but; but = but->next) { ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f); + ui_but_override_flag(but); ED_region_tag_redraw(ar); if (but->active) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 0357fc8ff01..d048324d35e 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -33,8 +33,8 @@ #include "MEM_guardedalloc.h" -#include "GPU_extensions.h" -#include "GPU_basic_shader.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -59,7 +59,6 @@ #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "ED_datafiles.h" @@ -224,13 +223,17 @@ static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float viconutil_set_point(pts[1], cx - d2, cy - d); viconutil_set_point(pts[2], cx + d2, cy); - glColor4f(0.2f, 0.2f, 0.2f, alpha); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.2f, 0.2f, 0.2f, alpha); - glBegin(GL_TRIANGLES); - glVertex2iv(pts[0]); - glVertex2iv(pts[1]); - glVertex2iv(pts[2]); - glEnd(); + immBegin(GWN_PRIM_TRIS, 3); + immVertex2iv(pos, pts[0]); + immVertex2iv(pos, pts[1]); + immVertex2iv(pos, pts[2]); + immEnd(); + + immUnbindProgram(); } static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, short key_type) @@ -239,7 +242,6 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, * (since we're doing this offscreen, free from any particular space_id) */ struct bThemeState theme_state; - int xco, yco; UI_Theme_Store(&theme_state); UI_SetTheme(SPACE_ACTION, RGN_TYPE_WINDOW); @@ -248,16 +250,30 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, * while the draw_keyframe_shape() function needs the midpoint for * the keyframe */ - xco = x + w / 2; - yco = y + h / 2; - + int xco = x + w / 2; + int yco = y + h / 2; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(GWN_PRIM_POINTS, 1); + /* draw keyframe - * - xscale: 1.0 (since there's no timeline scaling to compensate for) - * - yscale: 0.3 * h (found out experimentally... dunno why!) + * - size: 0.6 * h (found out experimentally... dunno why!) * - sel: true (so that "keyframe" state shows the iconic yellow icon) */ - draw_keyframe_shape(xco, yco, 1.0f, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha); - + draw_keyframe_shape(xco, yco, 0.6f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha, + pos_id, size_id, color_id, outline_color_id); + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); + UI_Theme_Restore(&theme_state); } @@ -290,7 +306,7 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU { bTheme *btheme = UI_GetTheme(); ThemeWireColor *cs = &btheme->tarm[index]; - + /* Draw three bands of color: One per color * x-----a-----b-----c * | N | S | A | @@ -299,19 +315,24 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU const int a = x + w / 3; const int b = x + w / 3 * 2; const int c = x + w; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* XXX: Include alpha into this... */ /* normal */ - glColor3ubv((unsigned char *)cs->solid); - glRecti(x, y, a, y + h); - + immUniformColor3ubv((unsigned char *)cs->solid); + immRecti(pos, x, y, a, y + h); + /* selected */ - glColor3ubv((unsigned char *)cs->select); - glRecti(a, y, b, y + h); - + immUniformColor3ubv((unsigned char *)cs->select); + immRecti(pos, a, y, b, y + h); + /* active */ - glColor3ubv((unsigned char *)cs->active); - glRecti(b, y, c, y + h); + immUniformColor3ubv((unsigned char *)cs->active); + immRecti(pos, b, y, c, y + h); + + immUnbindProgram(); } #define DEF_VICON_COLORSET_DRAW_NTH(prefix, index) \ @@ -504,8 +525,12 @@ static void init_internal_icons(void) icongltex.id = 0; } +#if 0 /* should be a compile-time check (if needed at all) */ /* we only use a texture for cards with non-power of two */ if (GPU_full_non_power_of_two_support()) { +#else + { +#endif glGenTextures(1, &icongltex.id); if (icongltex.id) { @@ -533,11 +558,6 @@ static void init_internal_icons(void) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); - - if (glGetError() == GL_OUT_OF_MEMORY) { - glDeleteTextures(1, &icongltex.id); - icongltex.id = 0; - } } } } @@ -851,12 +871,15 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi { ID *id = (icon->type != 0) ? icon->obj : NULL; PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj; + /* Using jobs for screen previews crashes due to offscreen rendering. + * XXX would be nicer if PreviewImage could store if it supports jobs */ + const bool use_jobs = !id || (GS(id->name) != ID_SCR); if (prv) { const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; if (id || (prv->tag & PRV_TAG_DEFFERED) != 0) { - ui_id_preview_image_render_size(C, NULL, id, prv, size, true); + ui_id_preview_image_render_size(C, NULL, id, prv, size, use_jobs); } } break; @@ -936,7 +959,7 @@ PreviewImage *UI_icon_to_preview(int icon_id) } static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, - unsigned int *rect, float alpha, const float rgb[3], const bool is_preview) + unsigned int *rect, float alpha, const float rgb[3], const bool UNUSED(is_preview)) { ImBuf *ima = NULL; int draw_w = w; @@ -950,15 +973,13 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), BLI_assert(!"invalid icon size"); return; } - /* modulate color */ - if (alpha != 1.0f) - glPixelTransferf(GL_ALPHA_SCALE, alpha); + float col[4] = {1.0f, 1.0f, 1.0f, alpha}; if (rgb) { - glPixelTransferf(GL_RED_SCALE, rgb[0]); - glPixelTransferf(GL_GREEN_SCALE, rgb[1]); - glPixelTransferf(GL_BLUE_SCALE, rgb[2]); + col[0] = rgb[0]; + col[1] = rgb[1]; + col[2] = rgb[2]; } /* rect contains image in 'rendersize', we only scale if needed */ @@ -984,31 +1005,12 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), } /* draw */ - if (is_preview) { - glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect); - } - else { - int bound_options; - GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options); - - glRasterPos2f(draw_x, draw_y); - glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect); - - GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options); - } + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, draw_x, draw_y, draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, + 1.0f, 1.0f, col); if (ima) IMB_freeImBuf(ima); - - /* restore color */ - if (alpha != 0.0f) - glPixelTransferf(GL_ALPHA_SCALE, 1.0f); - - if (rgb) { - glPixelTransferf(GL_RED_SCALE, 1.0f); - glPixelTransferf(GL_GREEN_SCALE, 1.0f); - glPixelTransferf(GL_BLUE_SCALE, 1.0f); - } } static void icon_draw_texture( @@ -1017,38 +1019,39 @@ static void icon_draw_texture( { float x1, x2, y1, y2; - if (rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha); - else glColor4f(alpha, alpha, alpha, alpha); - x1 = ix * icongltex.invw; x2 = (ix + ih) * icongltex.invw; y1 = iy * icongltex.invh; y2 = (iy + ih) * icongltex.invh; - GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR); glBindTexture(GL_TEXTURE_2D, icongltex.id); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - /* sharper downscaling, has no effect when scale matches with a mip level */ - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.5f); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + if (rgb) immUniformColor3fvAlpha(rgb, alpha); + else immUniformColor4f(alpha, alpha, alpha, alpha); - glBegin(GL_QUADS); - glTexCoord2f(x1, y1); - glVertex2f(x, y); + immUniform1i("image", 0); - glTexCoord2f(x2, y1); - glVertex2f(x + w, y); + immBegin(GWN_PRIM_TRI_STRIP, 4); + immAttrib2f(texCoord, x1, y2); + immVertex2f(pos, x, y + h); - glTexCoord2f(x2, y2); - glVertex2f(x + w, y + h); + immAttrib2f(texCoord, x1, y1); + immVertex2f(pos, x, y); - glTexCoord2f(x1, y2); - glVertex2f(x, y + h); - glEnd(); + immAttrib2f(texCoord, x2, y2); + immVertex2f(pos, x + w, y + h); - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f); + immAttrib2f(texCoord, x2, y1); + immVertex2f(pos, x + w, y); + immEnd(); + + immUnbindProgram(); glBindTexture(GL_TEXTURE_2D, 0); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); } /* Drawing size for preview images */ @@ -1162,7 +1165,7 @@ void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, } } -static void ui_id_brush_render(const bContext *C, ID *id) +static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs) { PreviewImage *pi = BKE_previewimg_id_ensure(id); enum eIconSizes i; @@ -1174,7 +1177,7 @@ static void ui_id_brush_render(const bContext *C, ID *id) /* check if rect needs to be created; changed * only set by dynamic icons */ if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) { - icon_set_image(C, NULL, id, pi, i, true); + icon_set_image(C, NULL, id, pi, i, use_jobs); pi->flag[i] &= ~PRV_CHANGED; } } @@ -1187,7 +1190,7 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id) if (br->flag & BRUSH_CUSTOM_ICON) { BKE_icon_id_ensure(id); - ui_id_brush_render(C, id); + ui_id_icon_render(C, id, true); } else { Object *ob = CTX_data_active_object(C); @@ -1234,6 +1237,15 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id) return id->icon_id; } +static int ui_id_screen_get_icon(const bContext *C, ID *id) +{ + BKE_icon_id_ensure(id); + /* Don't use jobs here, offscreen rendering doesn't like this and crashes. */ + ui_id_icon_render(C, id, false); + + return id->icon_id; +} + int ui_id_icon_get(const bContext *C, ID *id, const bool big) { int iconid = 0; @@ -1252,6 +1264,9 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big) /* checks if not exists, or changed */ UI_id_icon_render(C, NULL, id, big, true); break; + case ID_SCR: + iconid = ui_id_screen_get_icon(C, id); + break; default: break; } @@ -1344,6 +1359,8 @@ int UI_idcode_icon_get(const int idcode) return ICON_COLOR; /* TODO! this would need its own icon! */ case ID_PC: return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */ + case ID_LP: + return ICON_RADIO; case ID_SCE: return ICON_SCENE_DATA; case ID_SPK: @@ -1388,6 +1405,11 @@ void UI_icon_draw(float x, float y, int icon_id) UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f); } +void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha) +{ + UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha); +} + void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha) { icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, true, false); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6a1a8b5c629..1269d87d33e 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -72,6 +72,7 @@ typedef enum { UI_WTYPE_NUMBER, UI_WTYPE_SLIDER, UI_WTYPE_EXEC, + UI_WTYPE_TAB, UI_WTYPE_TOOLTIP, /* strings */ @@ -258,6 +259,7 @@ struct uiBut { uiButSearchCreateFunc search_create_func; uiButSearchFunc search_func; + bool free_search_arg; void *search_arg; uiButHandleRenameFunc rename_func; @@ -281,7 +283,7 @@ struct uiBut { BIFIconID icon; char dt; /* drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the block */ signed char pie_dir; /* direction in a pie menu, used for collision detection (RadialDirection) */ - char changed; /* could be made into a single flag */ + bool changed; /* could be made into a single flag */ unsigned char unit_type; /* so buttons can support unit systems which are not RNA */ short modifier_key; short iconadd; @@ -507,6 +509,7 @@ extern bool ui_but_supports_cycling(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT; extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT; +void ui_but_override_flag(uiBut *but); extern void ui_block_bounds_calc(uiBlock *block); extern void ui_block_translate(uiBlock *block, int x, int y); @@ -654,6 +657,8 @@ extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, floa void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha); + +void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3]); void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect); void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect); void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect); @@ -696,15 +701,16 @@ struct wmIMEData *ui_but_ime_data_get(uiBut *but); #endif /* interface_widgets.c */ -void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); -void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha); +void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]); +void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, + float rad, bool use_alpha, const float color[4]); void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect); void ui_draw_pie_center(uiBlock *block); uiWidgetColors *ui_tooltip_get_theme(void); void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect); void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect); bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol); -void ui_draw_link_bezier(const rcti *rect); +void ui_draw_link_bezier(const rcti *rect, const float color[4]); extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect); /* theme color init */ @@ -761,4 +767,20 @@ void UI_OT_eyedropper_id(struct wmOperatorType *ot); void UI_OT_eyedropper_depth(struct wmOperatorType *ot); void UI_OT_eyedropper_driver(struct wmOperatorType *ot); +/* interface_util.c */ + +/** + * For use with #ui_rna_collection_search_cb. + */ +typedef struct uiRNACollectionSearch { + PointerRNA target_ptr; + PropertyRNA *target_prop; + + PointerRNA search_ptr; + PropertyRNA *search_prop; + + bool *but_changed; /* pointer to uiBut.changed */ +} uiRNACollectionSearch; +void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items); + #endif /* __INTERFACE_INTERN_H__ */ diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index fa27c6fc07b..d43b7511977 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -870,7 +870,7 @@ static uiBut *uiItemFullO_ptr_ex( return but; } -static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but) +static void ui_item_menu_hold(struct bContext *C, ARegion *butregion, uiBut *but) { uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE); uiLayout *layout = UI_popup_menu_layout(pup); @@ -878,6 +878,8 @@ static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but UI_popup_menu_but_set(pup, butregion, but); block->flag |= UI_BLOCK_POPUP_HOLD; + block->flag |= UI_BLOCK_IS_FLIP; + UI_block_direction_set(block, UI_DIR_DOWN); const char *menu_id = but->hold_argN; MenuType *mt = WM_menutype_find(menu_id, true); @@ -907,7 +909,7 @@ void uiItemFullOMenuHold_ptr( PointerRNA *r_opptr) { uiBut *but = uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr); - UI_but_func_hold_set(but, ui_item_hold_menu, BLI_strdup(menu_id)); + UI_but_func_hold_set(but, ui_item_menu_hold, BLI_strdup(menu_id)); } void uiItemFullO( @@ -1639,95 +1641,6 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname /* Pointer RNA button with search */ -typedef struct CollItemSearch { - struct CollItemSearch *next, *prev; - char *name; - int index; - int iconid; -} CollItemSearch; - -static int sort_search_items_list(const void *a, const void *b) -{ - const CollItemSearch *cis1 = a; - const CollItemSearch *cis2 = b; - - if (BLI_strcasecmp(cis1->name, cis2->name) > 0) - return 1; - else - return 0; -} - -static void rna_search_cb(const struct bContext *C, void *arg_but, const char *str, uiSearchItems *items) -{ - uiBut *but = arg_but; - char *name; - int i = 0, iconid = 0, flag = RNA_property_flag(but->rnaprop); - ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list"); - CollItemSearch *cis; - const bool skip_filter = !but->changed; - - /* build a temporary list of relevant items first */ - RNA_PROP_BEGIN (&but->rnasearchpoin, itemptr, but->rnasearchprop) - { - if (flag & PROP_ID_SELF_CHECK) - if (itemptr.data == but->rnapoin.id.data) - continue; - - /* use filter */ - if (RNA_property_type(but->rnaprop) == PROP_POINTER) { - if (RNA_property_pointer_poll(&but->rnapoin, but->rnaprop, &itemptr) == 0) - continue; - } - - if (itemptr.type && RNA_struct_is_ID(itemptr.type)) { - ID *id = itemptr.data; - char name_ui[MAX_ID_NAME]; - -#if 0 /* this name is used for a string comparison and can't be modified, TODO */ - /* if ever enabled, make name_ui be MAX_ID_NAME+1 */ - BKE_id_ui_prefix(name_ui, id); -#else - BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui)); -#endif - name = BLI_strdup(name_ui); - iconid = ui_id_icon_get(C, id, false); - } - else { - name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */ - iconid = 0; - } - - if (name) { - if (skip_filter || BLI_strcasestr(name, str)) { - cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch"); - cis->name = MEM_dupallocN(name); - cis->index = i; - cis->iconid = iconid; - BLI_addtail(items_list, cis); - } - MEM_freeN(name); - } - - i++; - } - RNA_PROP_END; - - BLI_listbase_sort(items_list, sort_search_items_list); - - /* add search items from temporary list */ - for (cis = items_list->first; cis; cis = cis->next) { - if (false == UI_search_item_add(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) { - break; - } - } - - for (cis = items_list->first; cis; cis = cis->next) { - MEM_freeN(cis->name); - } - BLI_freelistN(items_list); - MEM_freeN(items_list); -} - static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop) { StructRNA *srna; @@ -1768,6 +1681,8 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN /* turn button into search button */ if (searchprop) { + uiRNACollectionSearch *coll_search = MEM_mallocN(sizeof(*coll_search), __func__); + but->type = UI_BTYPE_SEARCH_MENU; but->hardmax = MAX2(but->hardmax, 256.0f); but->rnasearchpoin = *searchptr; @@ -1777,13 +1692,22 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN but->flag |= UI_BUT_VALUE_CLEAR; } + coll_search->target_ptr = *ptr; + coll_search->target_prop = prop; + coll_search->search_ptr = *searchptr; + coll_search->search_prop = searchprop; + coll_search->but_changed = &but->changed; + if (RNA_property_type(prop) == PROP_ENUM) { /* XXX, this will have a menu string, * but in this case we just want the text */ but->str[0] = 0; } - UI_but_func_search_set(but, ui_searchbox_create_generic, rna_search_cb, but, NULL, NULL); + UI_but_func_search_set( + but, ui_searchbox_create_generic, ui_rna_collection_search_cb, + coll_search, NULL, NULL); + but->free_search_arg = true; } else if (but->type == UI_BTYPE_SEARCH_MENU) { /* In case we fail to find proper searchprop, so other code might have already set but->type to search menu... */ diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 9c72942a575..eeda0a25195 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -42,14 +42,20 @@ #include "BLT_lang.h" #include "BKE_context.h" +#include "BKE_idprop.h" +#include "BKE_layer.h" #include "BKE_screen.h" #include "BKE_global.h" +#include "BKE_library_override.h" #include "BKE_node.h" #include "BKE_text.h" /* for UI_OT_reports_to_text */ #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_types.h" #include "UI_interface.h" @@ -328,6 +334,334 @@ static void UI_OT_unset_property_button(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } +/* Use/Unuse Property Button Operator ------------------------ */ + +static int use_property_button_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr, scene_props_ptr; + PropertyRNA *prop; + IDProperty *props; + + uiBut *but = UI_context_active_but_get(C); + + prop = but->rnaprop; + ptr = but->rnapoin; + props = (IDProperty *)ptr.data; + /* XXX Using existing data struct to pass another RNAPointer */ + scene_props_ptr = but->rnasearchpoin; + + const char *identifier = RNA_property_identifier(prop); + if (IDP_GetPropertyFromGroup(props, identifier)) { + return OPERATOR_CANCELLED; + } + + int array_len = RNA_property_array_length(&scene_props_ptr, prop); + bool is_array = array_len != 0; + + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + { + if (is_array) { + float values[RNA_MAX_ARRAY_LENGTH]; + RNA_property_float_get_array(&scene_props_ptr, prop, values); + BKE_collection_engine_property_add_float_array(props, identifier, values, array_len); + } + else { + float value = RNA_property_float_get(&scene_props_ptr, prop); + BKE_collection_engine_property_add_float(props, identifier, value); + } + break; + } + case PROP_ENUM: + { + int value = RNA_enum_get(&scene_props_ptr, identifier); + BKE_collection_engine_property_add_int(props, identifier, value); + break; + } + case PROP_INT: + { + int value = RNA_int_get(&scene_props_ptr, identifier); + BKE_collection_engine_property_add_int(props, identifier, value); + break; + } + case PROP_BOOLEAN: + { + int value = RNA_boolean_get(&scene_props_ptr, identifier); + BKE_collection_engine_property_add_bool(props, identifier, value); + break; + } + case PROP_STRING: + case PROP_POINTER: + case PROP_COLLECTION: + default: + break; + } + + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update((ID *)CTX_data_scene(C), 0); + + return OPERATOR_FINISHED; +} + +static void UI_OT_use_property_button(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Use property"; + ot->idname = "UI_OT_use_property_button"; + ot->description = "Create a property"; + + /* callbacks */ + ot->poll = ED_operator_regionactive; + ot->exec = use_property_button_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO; +} + +static int unuse_property_button_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr; + PropertyRNA *prop; + int index; + + /* try to unset the nominated property */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + const char *identifier = RNA_property_identifier(prop); + + IDProperty *props = (IDProperty *)ptr.data; + IDProperty *prop_to_remove = IDP_GetPropertyFromGroup(props, identifier); + IDP_FreeFromGroup(props, prop_to_remove); + + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update((ID *)CTX_data_scene(C), 0); + + return OPERATOR_FINISHED; +} + +static void UI_OT_unuse_property_button(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Unuse property"; + ot->idname = "UI_OT_unuse_property_button"; + ot->description = "Remove a property"; + + /* callbacks */ + ot->poll = ED_operator_regionactive; + ot->exec = unuse_property_button_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO; +} + + + + + +/* Note that we use different values for UI/UX than 'real' override operations, user does not care + * whether it's added or removed for the differential operation e.g. */ +enum { + UIOverride_Type_NOOP = 0, + UIOverride_Type_Replace = 1, + UIOverride_Type_Difference = 2, /* Add/subtract */ + UIOverride_Type_Factor = 3, /* Multiply */ + /* TODO: should/can we expose insert/remove ones for collections? Doubt it... */ +}; + +static EnumPropertyItem override_type_items[] = { + {UIOverride_Type_NOOP, "NOOP", 0, "NoOp", + "'No-Operation', place holder preventing automatic override to ever affect the property"}, + {UIOverride_Type_Replace, "REPLACE", 0, "Replace", "Completely replace value from linked data by local one"}, + {UIOverride_Type_Difference, "DIFFERENCE", 0, "Difference", "Store difference to linked data value"}, + {UIOverride_Type_Factor, "FACTOR", 0, "Factor", "Store factor to linked data value (useful e.g. for scale)"}, + {0, NULL, 0, NULL, NULL} +}; + + +static int override_type_set_button_poll(bContext *C) +{ + PointerRNA ptr; + PropertyRNA *prop; + int index; + bool is_overridable; + + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + RNA_property_override_status(&ptr, prop, index, &is_overridable, NULL, NULL, NULL); + + return (ptr.data && prop && is_overridable); +} + +static int override_type_set_button_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr; + PropertyRNA *prop; + int index; + bool created; + const bool all = RNA_boolean_get(op->ptr, "all"); + const int op_type = RNA_enum_get(op->ptr, "type"); + + short operation; + + switch (op_type) { + case UIOverride_Type_NOOP: + operation = IDOVERRIDESTATIC_OP_NOOP; + break; + case UIOverride_Type_Replace: + operation = IDOVERRIDESTATIC_OP_REPLACE; + break; + case UIOverride_Type_Difference: + operation = IDOVERRIDESTATIC_OP_ADD; /* override code will automatically switch to subtract if needed. */ + break; + case UIOverride_Type_Factor: + operation = IDOVERRIDESTATIC_OP_MULTIPLY; + break; + default: + operation = IDOVERRIDESTATIC_OP_REPLACE; + BLI_assert(0); + break; + } + + /* try to reset the nominated setting to its default value */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + BLI_assert(ptr.id.data != NULL); + + if (all) { + index = -1; + } + + IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get( + &ptr, prop, operation, index, true, NULL, &created); + if (!created) { + opop->operation = operation; + } + + return operator_button_property_finish(C, &ptr, prop); +} + +static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT); +} + +static void UI_OT_override_type_set_button(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Define Override Type"; + ot->idname = "UI_OT_override_type_set_button"; + ot->description = "Create an override operation, or set the type of an existing one"; + + /* callbacks */ + ot->poll = override_type_set_button_poll; + ot->exec = override_type_set_button_exec; + ot->invoke = override_type_set_button_invoke; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array"); + ot->prop = RNA_def_enum(ot->srna, "type", override_type_items, UIOverride_Type_Replace, + "Type", "Type of override operation"); + /* TODO: add itemf callback, not all aoptions are available for all data types... */ +} + + +static int override_remove_button_poll(bContext *C) +{ + PointerRNA ptr; + PropertyRNA *prop; + int index; + bool is_overridden; + + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + RNA_property_override_status(&ptr, prop, index, NULL, &is_overridden, NULL, NULL); + + return (ptr.data && ptr.id.data && prop && is_overridden); +} + +static int override_remove_button_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr, id_refptr, src; + PropertyRNA *prop; + int index; + const bool all = RNA_boolean_get(op->ptr, "all"); + + /* try to reset the nominated setting to its default value */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + ID *id = ptr.id.data; + IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop); + BLI_assert(oprop != NULL); + BLI_assert(id != NULL && id->override_static != NULL); + + const bool is_template = (id->override_static->reference == NULL); + + /* We need source (i.e. linked data) to restore values of deleted overrides... + * If this is an override template, we obviously do not need to restore anything. */ + if (!is_template) { + RNA_id_pointer_create(id->override_static->reference, &id_refptr); + if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) { + BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer"); + } + } + + if (!all && index != -1) { + bool is_strict_find; + /* Remove override operation for given item, add singular operations for the other items as needed. */ + IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find( + oprop, NULL, NULL, index, index, false, &is_strict_find); + BLI_assert(opop != NULL); + if (!is_strict_find) { + /* No specific override operation, we have to get generic one, + * and create item-specific override operations for all but given index, before removing generic one. */ + for (int idx = RNA_property_array_length(&ptr, prop); idx--; ) { + if (idx != index) { + BKE_override_static_property_operation_get(oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL); + } + } + } + BKE_override_static_property_operation_delete(oprop, opop); + if (!is_template) { + RNA_property_copy(&ptr, &src, prop, index); + } + if (BLI_listbase_is_empty(&oprop->operations)) { + BKE_override_static_property_delete(id->override_static, oprop); + } + } + else { + /* Just remove whole generic override operation of this property. */ + BKE_override_static_property_delete(id->override_static, oprop); + if (!is_template) { + RNA_property_copy(&ptr, &src, prop, -1); + } + } + + return operator_button_property_finish(C, &ptr, prop); +} + +static void UI_OT_override_remove_button(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Override"; + ot->idname = "UI_OT_override_remove_button"; + ot->description = "Remove an override operation"; + + /* callbacks */ + ot->poll = override_remove_button_poll; + ot->exec = override_remove_button_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array"); +} + + + + /* Copy To Selected Operator ------------------------ */ bool UI_context_copy_to_selected_list( @@ -1117,6 +1451,10 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_copy_python_command_button); WM_operatortype_append(UI_OT_reset_default_button); WM_operatortype_append(UI_OT_unset_property_button); + WM_operatortype_append(UI_OT_use_property_button); + WM_operatortype_append(UI_OT_unuse_property_button); + WM_operatortype_append(UI_OT_override_type_set_button); + WM_operatortype_append(UI_OT_override_remove_button); WM_operatortype_append(UI_OT_copy_to_selected_button); WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */ WM_operatortype_append(UI_OT_drop_color); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index d9685d7281b..c3759e232b0 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -50,9 +50,6 @@ #include "BKE_context.h" #include "BKE_screen.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" - #include "BLF_api.h" #include "WM_api.h" @@ -65,6 +62,8 @@ #include "UI_interface_icons.h" #include "UI_resources.h" +#include "GPU_immediate.h" + #include "interface_intern.h" /*********************** defines and structs ************************/ @@ -393,54 +392,42 @@ static void ui_offset_panel_block(uiBlock *block) /**************************** drawing *******************************/ -/* extern used by previewrender */ -#if 0 /*UNUSED 2.5*/ -static void uiPanelPush(uiBlock *block) -{ - glPushMatrix(); - - if (block->panel) - glTranslatef((float)block->panel->ofsx, (float)block->panel->ofsy, 0.0); -} - -static void uiPanelPop(uiBlock *UNUSED(block)) -{ - glPopMatrix(); -} -#endif - /* triangle 'icon' for panel header */ -void UI_draw_icon_tri(float x, float y, char dir) +void UI_draw_icon_tri(float x, float y, char dir, const float color[4]) { float f3 = 0.15 * U.widget_unit; float f5 = 0.25 * U.widget_unit; float f7 = 0.35 * U.widget_unit; if (dir == 'h') { - ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y); + ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color); } else if (dir == 't') { - ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3); + ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color); } else { /* 'v' = vertical, down */ - ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7); + ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color); } } /* triangle 'icon' inside rect */ static void ui_draw_tria_rect(const rctf *rect, char dir) { + float color[4]; + UI_GetThemeColor3fv(TH_TITLE, color); + color[3] = 1.0f; + if (dir == 'h') { float half = 0.5f * BLI_rctf_size_y(rect); - ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half); + ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half, color); } else { float half = 0.5f * BLI_rctf_size_x(rect); - ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin); + ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin, color); } } -static void ui_draw_anti_x(float x1, float y1, float x2, float y2) +static void ui_draw_anti_x(unsigned int pos, float x1, float y1, float x2, float y2) { /* set antialias line */ @@ -448,9 +435,16 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2) glEnable(GL_BLEND); glLineWidth(2.0); - - fdrawline(x1, y1, x2, y2); - fdrawline(x1, y2, x2, y1); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y1); + + immEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); @@ -458,16 +452,16 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2) } /* x 'icon' for panel header */ -static void ui_draw_x_icon(float x, float y) +static void ui_draw_x_icon(unsigned int pos, float x, float y) { - ui_draw_anti_x(x, y, x + 9.375f, y + 9.375f); + ui_draw_anti_x(pos, x, y, x + 9.375f, y + 9.375f); } #define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */ -static void ui_draw_panel_scalewidget(const rcti *rect) +static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect) { float xmin, xmax, dx; float ymin, ymax, dy; @@ -481,16 +475,33 @@ static void ui_draw_panel_scalewidget(const rcti *rect) dy = 0.5f * (ymax - ymin); glEnable(GL_BLEND); - glColor4ub(255, 255, 255, 50); - fdrawline(xmin, ymin, xmax, ymax); - fdrawline(xmin + dx, ymin, xmax, ymax - dy); + immUniformColor4ub(255, 255, 255, 50); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, xmin, ymin); + immVertex2f(pos, xmax, ymax); + + immVertex2f(pos, xmin + dx, ymin); + immVertex2f(pos, xmax, ymax - dy); + + immEnd(); - glColor4ub(0, 0, 0, 50); - fdrawline(xmin, ymin + 1, xmax, ymax + 1); - fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1); + immUniformColor4ub(0, 0, 0, 50); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, xmin, ymin + 1); + immVertex2f(pos, xmax, ymax + 1); + + immVertex2f(pos, xmin + dx, ymin + 1); + immVertex2f(pos, xmax, ymax - dy + 1); + + immEnd(); + glDisable(GL_BLEND); } -static void ui_draw_panel_dragwidget(const rctf *rect) +static void ui_draw_panel_dragwidget(unsigned int pos, const rctf *rect) { unsigned char col_back[3], col_high[3], col_dark[3]; const int col_tint = 84; @@ -519,10 +530,10 @@ static void ui_draw_panel_dragwidget(const rctf *rect) const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin)); const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin)); - glColor3ubv(col_dark); - glRectf(x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom); - glColor3ubv(col_high); - glRectf(x_co - box_size, y_co, x_co, y_co + box_size); + immUniformColor3ubv(col_dark); + immRectf(pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom); + immUniformColor3ubv(col_high); + immRectf(pos, x_co - box_size, y_co, x_co, y_co + box_size); } } } @@ -534,29 +545,30 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r rcti hrect; int pnl_icons; const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname; + unsigned char col_title[4]; /* + 0.001f to avoid flirting with float inaccuracy */ if (panel->control & UI_PNL_CLOSE) pnl_icons = (panel->labelofs + 2 * PNL_ICON + 5) / block->aspect + 0.001f; else pnl_icons = (panel->labelofs + PNL_ICON + 5) / block->aspect + 0.001f; - - /* active tab */ + /* draw text label */ - UI_ThemeColor(TH_TITLE); - + UI_GetThemeColor3ubv(TH_TITLE, col_title); + col_title[3] = 255; + hrect = *rect; if (dir == 'h') { hrect.xmin = rect->xmin + pnl_icons; hrect.ymin += 2.0f / block->aspect; - UI_fontstyle_draw(&style->paneltitle, &hrect, activename); + UI_fontstyle_draw(&style->paneltitle, &hrect, activename, col_title); } else { /* ignore 'pnl_icons', otherwise the text gets offset horizontally * + 0.001f to avoid flirting with float inaccuracy */ hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f; - UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename); + UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename, col_title); } } @@ -566,7 +578,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con Panel *panel = block->panel; rcti headrect; rctf itemrect; - int ofsx; + float color[4]; const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false; const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false; @@ -579,6 +591,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con headrect.ymin = headrect.ymax; headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + { float minx = rect->xmin; float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax; @@ -588,11 +603,18 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) { /* draw with background color */ - UI_ThemeColor4(TH_PANEL_HEADER); - glRectf(minx, headrect.ymin + 1, maxx, y); + immUniformThemeColor(TH_PANEL_HEADER); + immRectf(pos, minx, headrect.ymin + 1, maxx, y); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, minx, y); + immVertex2f(pos, maxx, y); + + immVertex2f(pos, minx, y); + immVertex2f(pos, maxx, y); - fdrawline(minx, y, maxx, y); - fdrawline(minx, y, maxx, y); + immEnd(); } else if (!(panel->runtime_flag & PNL_FIRST)) { /* draw embossed separator */ @@ -602,15 +624,26 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con maxx -= 5.0f / block->aspect; } - glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - fdrawline(minx, y, maxx, y); - glColor4f(1.0f, 1.0f, 1.0f, 0.25f); - fdrawline(minx, y - 1, maxx, y - 1); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, minx, y); + immVertex2f(pos, maxx, y); + immEnd(); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, minx, y - 1); + immVertex2f(pos, maxx, y - 1); + immEnd(); } glDisable(GL_BLEND); } + immUnbindProgram(); + /* draw optional pin icon */ #ifdef USE_PIN_HIDDEN @@ -626,9 +659,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con glDisable(GL_BLEND); } + /* horizontal title */ if (is_closed_x == false) { ui_draw_aligned_panel_header(style, block, &headrect, 'h'); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); /* itemrect smaller */ itemrect.xmax = headrect.xmax - 5.0f / block->aspect; @@ -637,7 +672,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con itemrect.ymax = headrect.ymax; BLI_rctf_scale(&itemrect, 0.7f); - ui_draw_panel_dragwidget(&itemrect); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + ui_draw_panel_dragwidget(pos, &itemrect); + immUnbindProgram(); } /* if the panel is minimized vertically: @@ -649,6 +686,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con else if (is_closed_x) { /* draw vertical title */ ui_draw_aligned_panel_header(style, block, &headrect, 'v'); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); } /* an open panel */ else { @@ -657,33 +695,37 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con if (panel->control & UI_PNL_SOLID) UI_draw_roundbox_corner_set(UI_CNR_ALL); else UI_draw_roundbox_corner_set(UI_CNR_NONE); - UI_ThemeColorShade(TH_BACK, -120); - UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8); + UI_GetThemeColorShade4fv(TH_BACK, -120, color); + UI_draw_roundbox_aa(false, 0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8, color); } + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* panel backdrop */ if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) { /* draw with background color */ glEnable(GL_BLEND); - UI_ThemeColor4(TH_PANEL_BACK); - glRecti(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformThemeColor(TH_PANEL_BACK); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); } if (panel->control & UI_PNL_SCALE) - ui_draw_panel_scalewidget(rect); + ui_draw_panel_scalewidget(pos, rect); + + immUnbindProgram(); } /* draw optional close icon */ - ofsx = 6; if (panel->control & UI_PNL_CLOSE) { - UI_ThemeColor(TH_TITLE); - ui_draw_x_icon(rect->xmin + 2 + ofsx, rect->ymax + 2); - ofsx = 22; + const int ofsx = 6; + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor3(TH_TITLE); + ui_draw_x_icon(pos, rect->xmin + 2 + ofsx, rect->ymax + 2); + immUnbindProgram(); } /* draw collapse icon */ - UI_ThemeColor(TH_TITLE); /* itemrect smaller */ itemrect.xmin = headrect.xmin + 5.0f / block->aspect; @@ -699,8 +741,6 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con ui_draw_tria_rect(&itemrect, 'h'); else ui_draw_tria_rect(&itemrect, 'v'); - - (void)ofsx; } /************************** panel alignment *************************/ @@ -1513,12 +1553,13 @@ void UI_panel_category_clear_all(ARegion *ar) BLI_freelistN(&ar->panels_category); } -/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */ +/* based on UI_draw_roundbox, check on making a version which allows us to skip some sides */ static void ui_panel_category_draw_tab( - int mode, float minx, float miny, float maxx, float maxy, float rad, + bool filled, float minx, float miny, float maxx, float maxy, float rad, int roundboxtype, - const bool use_highlight, const bool use_shadow, - const unsigned char highlight_fade[3]) + bool use_highlight, bool use_shadow, + const unsigned char highlight_fade[3], + const unsigned char col[3]) { float vec[4][2] = { {0.195, 0.02}, @@ -1527,74 +1568,96 @@ static void ui_panel_category_draw_tab( {0.98, 0.805}}; int a; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + /* mult */ for (a = 0; a < 4; a++) { mul_v2_fl(vec[a], rad); } - glBegin(mode); + unsigned int vert_ct = 0; + if (use_highlight) { + vert_ct += (roundboxtype & UI_CNR_TOP_RIGHT) ? 6 : 1; + vert_ct += (roundboxtype & UI_CNR_TOP_LEFT) ? 6 : 1; + } + if (use_highlight && !use_shadow) { + vert_ct++; + } + else { + vert_ct += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 6 : 1; + vert_ct += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 6 : 1; + } + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_STRIP, vert_ct); + + immAttrib3ubv(color, col); /* start with corner right-top */ if (use_highlight) { if (roundboxtype & UI_CNR_TOP_RIGHT) { - glVertex2f(maxx, maxy - rad); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 4; a++) { - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - glVertex2f(maxx - rad, maxy); + immVertex2f(pos, maxx - rad, maxy); } else { - glVertex2f(maxx, maxy); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - glVertex2f(minx + rad, maxy); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 4; a++) { - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - glVertex2f(minx, maxy - rad); + immVertex2f(pos, minx, maxy - rad); } else { - glVertex2f(minx, maxy); + immVertex2f(pos, minx, maxy); } } if (use_highlight && !use_shadow) { if (highlight_fade) { - glColor3ubv(highlight_fade); + immAttrib3ubv(color, highlight_fade); } - glVertex2f(minx, miny + rad); - glEnd(); + immVertex2f(pos, minx, miny + rad); + immEnd(); + immUnbindProgram(); return; } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - glVertex2f(minx, miny + rad); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 4; a++) { - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - glVertex2f(minx + rad, miny); + immVertex2f(pos, minx + rad, miny); } else { - glVertex2f(minx, miny); + immVertex2f(pos, minx, miny); } /* corner right-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - glVertex2f(maxx - rad, miny); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 4; a++) { - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - glVertex2f(maxx, miny + rad); + immVertex2f(pos, maxx, miny + rad); } else { - glVertex2f(maxx, miny); + immVertex2f(pos, maxx, miny); } - glEnd(); + immEnd(); + immUnbindProgram(); } @@ -1717,21 +1780,26 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) /* begin drawing */ glEnable(GL_LINE_SMOOTH); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draw the background */ if (is_alpha) { glEnable(GL_BLEND); - glColor4ubv(theme_col_tab_bg); + immUniformColor4ubv(theme_col_tab_bg); } else { - glColor3ubv(theme_col_tab_bg); + immUniformColor3ubv(theme_col_tab_bg); } - glRecti(v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax); + immRecti(pos, v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax); if (is_alpha) { glDisable(GL_BLEND); } + immUnbindProgram(); + for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) { const rcti *rct = &pc_dyn->rect; const char *category_id = pc_dyn->idname; @@ -1754,28 +1822,33 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) if (is_active) #endif { - glColor3ubv(is_active ? theme_col_tab_active : theme_col_tab_inactive); - ui_panel_category_draw_tab(GL_POLYGON, rct->xmin, rct->ymin, rct->xmax, rct->ymax, - tab_curve_radius - px, roundboxtype, true, true, NULL); + ui_panel_category_draw_tab(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, + tab_curve_radius - px, roundboxtype, true, true, NULL, + is_active ? theme_col_tab_active : theme_col_tab_inactive); /* tab outline */ - glColor3ubv(theme_col_tab_outline); - ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px, - tab_curve_radius, roundboxtype, true, true, NULL); + ui_panel_category_draw_tab(false, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px, + tab_curve_radius, roundboxtype, true, true, NULL, theme_col_tab_outline); + /* tab highlight (3d look) */ - glColor3ubv(is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive); - ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, + ui_panel_category_draw_tab(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, tab_curve_radius, roundboxtype, true, false, - is_active ? theme_col_back : theme_col_tab_inactive); + is_active ? theme_col_back : theme_col_tab_inactive, + is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive); } /* tab blackline */ if (!is_active) { - glColor3ubv(theme_col_tab_divider); - glRecti(v2d->mask.xmin + category_tabs_width - px, - rct->ymin - tab_v_pad, - v2d->mask.xmin + category_tabs_width, - rct->ymax + tab_v_pad); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv(theme_col_tab_divider); + immRecti(pos, v2d->mask.xmin + category_tabs_width - px, + rct->ymin - tab_v_pad, + v2d->mask.xmin + category_tabs_width, + rct->ymax + tab_v_pad); + + immUnbindProgram(); } if (do_scaletabs) { @@ -1788,7 +1861,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) /* tab titles */ /* draw white shadow to give text more depth */ - glColor3ubv(theme_col_text); + BLF_color3ubv(fontid, theme_col_text); /* main tab title */ BLF_draw(fontid, category_id_draw, category_draw_len); @@ -1796,33 +1869,36 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) glDisable(GL_BLEND); /* tab blackline remaining (last tab) */ + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); if (pc_dyn->prev == NULL) { - glColor3ubv(theme_col_tab_divider); - glRecti(v2d->mask.xmin + category_tabs_width - px, - rct->ymax + px, - v2d->mask.xmin + category_tabs_width, - v2d->mask.ymax); + immUniformColor3ubv(theme_col_tab_divider); + immRecti(pos, v2d->mask.xmin + category_tabs_width - px, + rct->ymax + px, + v2d->mask.xmin + category_tabs_width, + v2d->mask.ymax); } if (pc_dyn->next == NULL) { - glColor3ubv(theme_col_tab_divider); - glRecti(v2d->mask.xmin + category_tabs_width - px, - 0, - v2d->mask.xmin + category_tabs_width, - rct->ymin); + immUniformColor3ubv(theme_col_tab_divider); + immRecti(pos, v2d->mask.xmin + category_tabs_width - px, + 0, + v2d->mask.xmin + category_tabs_width, + rct->ymin); } #ifdef USE_FLAT_INACTIVE /* draw line between inactive tabs */ if (is_active == false && is_active_prev == false && pc_dyn->prev) { - glColor3ubv(theme_col_tab_divider); - glRecti(v2d->mask.xmin + (category_tabs_width / 5), - rct->ymax + px, - (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5), - rct->ymax + (px * 3)); + immUniformColor3ubv(theme_col_tab_divider); + immRecti(pos, v2d->mask.xmin + (category_tabs_width / 5), + rct->ymax + px, + (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5), + rct->ymax + (px * 3)); } is_active_prev = is_active; #endif + immUnbindProgram(); /* not essential, but allows events to be handled right up until the region edge [#38171] */ pc_dyn->rect.xmin = v2d->mask.xmin; diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index aa3e2464237..a0aecb12b84 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -603,11 +603,13 @@ void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block) /* if loading new .blend while popup is open, window will be NULL */ if (block->handle) { if (win) { + const bScreen *screen = WM_window_get_active_screen(win); + UI_popup_handlers_remove(&win->modalhandlers, block->handle); ui_popup_block_free(C, block->handle); /* In the case we have nested popups, closing one may need to redraw another, see: T48874 */ - for (ARegion *ar = win->screen->regionbase.first; ar; ar = ar->next) { + for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { ED_region_tag_refresh_ui(ar); } } diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 15053f0d8ca..24990c593ac 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -324,7 +324,7 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar) * Use to refresh centered popups on screen resizing (for splash). */ static void ui_block_region_popup_window_listener( - bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene)) { switch (wmn->category) { case NC_WINDOW: diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index c9d313a4bab..f14f9af8785 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -397,7 +397,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str) return match; } -static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) +static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar) { uiSearchboxData *data = ar->regiondata; @@ -415,6 +415,9 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) if (data->preview) { /* draw items */ for (a = 0; a < data->items.totitem; a++) { + /* ensure icon is up-to-date */ + ui_icon_ensure_deferred(C, data->items.icons[a], data->preview); + ui_searchbox_butrect(&rect, data, a); /* widget itself */ diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 7d10087dcd9..f71b71fce43 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -157,6 +157,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) uiWidgetColors *theme = ui_tooltip_get_theme(); rcti bbox = data->bbox; float tip_colors[UI_TIP_LC_MAX][3]; + unsigned char drawcol[4] = {0, 0, 0, 255}; /* to store color in while drawing (alpha is always 255) */ float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */ float *value_color = tip_colors[UI_TIP_LC_VALUE]; @@ -225,9 +226,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) fstyle_header.shadowalpha = 1.0f; fstyle_header.word_wrap = true; + rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_MAIN]); UI_fontstyle_set(&fstyle_header); - glColor3fv(tip_colors[UI_TIP_LC_MAIN]); - UI_fontstyle_draw(&fstyle_header, &bbox, field->text); + UI_fontstyle_draw(&fstyle_header, &bbox, field->text, drawcol); fstyle_header.shadow = 0; @@ -238,8 +239,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) bbox.xmin += xofs; bbox.ymax -= yofs; - glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]); - UI_fontstyle_draw(&fstyle_header, &bbox, field->text_suffix); + rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]); + UI_fontstyle_draw(&fstyle_header, &bbox, field->text_suffix, drawcol); /* undo offset */ bbox.xmin -= xofs; @@ -254,8 +255,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) UI_fontstyle_set(&fstyle_mono); /* XXX, needed because we dont have mono in 'U.uifonts' */ BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi); - glColor3fv(tip_colors[field->format.color_id]); - UI_fontstyle_draw(&fstyle_mono, &bbox, field->text); + rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]); + UI_fontstyle_draw(&fstyle_mono, &bbox, field->text, drawcol); } else { uiFontStyle fstyle_normal = data->fstyle; @@ -263,9 +264,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) fstyle_normal.word_wrap = true; /* draw remaining data */ + rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]); UI_fontstyle_set(&fstyle_normal); - glColor3fv(tip_colors[field->format.color_id]); - UI_fontstyle_draw(&fstyle_normal, &bbox, field->text); + UI_fontstyle_draw(&fstyle_normal, &bbox, field->text, drawcol); } bbox.ymax -= data->lineh * field->geom.lines; @@ -306,6 +307,65 @@ static void ui_tooltip_region_free_cb(ARegion *ar) /** \name ToolTip Creation * \{ */ +static uiTooltipData *ui_tooltip_data_from_keymap(bContext *C, wmKeyMap *keymap) +{ + char buf[512]; + + /* create tooltip data */ + uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData"); + + BLI_assert(data->fields_len < MAX_TOOLTIP_LINES); + + for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + wmOperatorType *ot = WM_operatortype_find(kmi->idname, true); + if (ot != NULL) { + /* Tip */ + { + uiTooltipField *field = text_field_add( + data, &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_MAIN, + .is_pad = true, + }); + field->text = BLI_strdup(ot->description[0] ? ot->description : ot->name); + } + /* Shortcut */ + { + uiTooltipField *field = text_field_add( + data, &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_NORMAL, + }); + bool found = false; + if (WM_keymap_item_to_string(kmi, false, buf, sizeof(buf))) { + found = true; + } + field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None"); + } + + /* Python */ + { + uiTooltipField *field = text_field_add( + data, &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_PYTHON, + }); + char *str = WM_operator_pystring_ex(C, NULL, false, false, ot, kmi->ptr); + WM_operator_pystring_abbreviate(str, 32); + field->text = BLI_sprintfN(TIP_("Python: %s"), str); + MEM_freeN(str); + } + } + } + if (data->fields_len == 0) { + MEM_freeN(data); + return NULL; + } + else { + return data; + } +} + static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) { uiStringInfo but_tip = {BUT_GET_TIP, NULL}; @@ -586,8 +646,27 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) if (but->drawflag & UI_BUT_NO_TOOLTIP) { return NULL; } + uiTooltipData *data = NULL; + + /* custom tips for pre-defined operators */ + if (but->optype) { + if (STREQ(but->optype->idname, "WM_OT_tool_set")) { + char keymap[64] = ""; + RNA_string_get(but->opptr, "keymap", keymap); + if (keymap[0]) { + ScrArea *sa = CTX_wm_area(C); + wmKeyMap *km = WM_keymap_find_all(C, keymap, sa->spacetype, RGN_TYPE_WINDOW); + if (km != NULL) { + data = ui_tooltip_data_from_keymap(C, km); + } + } + } + } + /* toolsystem exception */ - uiTooltipData *data = ui_tooltip_data_from_button(C, but); + if (data == NULL) { + data = ui_tooltip_data_from_button(C, but); + } if (data == NULL) { return NULL; } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index dd1d38bbe2e..fa25a119ada 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -61,6 +61,9 @@ ARegion *ui_region_temp_add(bScreen *sc) void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar) { wmWindow *win = CTX_wm_window(C); + + BLI_assert(ar->regiontype == RGN_TYPE_TEMPORARY); + BLI_assert(BLI_findindex(&sc->regionbase, ar) != -1); if (win) wm_draw_region_clear(win, ar); diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index 8b41302b5bb..01456e2e122 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -149,7 +149,7 @@ static uiFont *uifont_to_blfont(int id) void UI_fontstyle_draw_ex( - const uiFontStyle *fs, const rcti *rect, const char *str, + const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4], size_t len, float *r_xofs, float *r_yofs) { int xofs = 0, yofs; @@ -196,6 +196,7 @@ void UI_fontstyle_draw_ex( /* clip is very strict, so we give it some space */ BLF_clipping(fs->uifont_id, rect->xmin - 2, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4); BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f); + BLF_color4ubv(fs->uifont_id, col); BLF_draw(fs->uifont_id, str, len); @@ -205,17 +206,17 @@ void UI_fontstyle_draw_ex( *r_yofs = yofs; } -void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str) +void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4]) { float xofs, yofs; UI_fontstyle_draw_ex( - fs, rect, str, + fs, rect, str, col, BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs); } /* drawn same as above, but at 90 degree angle */ -void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str) +void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4]) { float height; int xofs, yofs; @@ -249,6 +250,7 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch BLF_enable(fs->uifont_id, BLF_ROTATION); BLF_rotation(fs->uifont_id, angle); + BLF_color4ubv(fs->uifont_id, col); if (fs->shadow) { BLF_enable(fs->uifont_id, BLF_SHADOW); @@ -275,13 +277,14 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch * * For drawing on-screen labels. */ -void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str) +void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const unsigned char col[4]) { if (fs->kerning == 1) BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); UI_fontstyle_set(fs); BLF_position(fs->uifont_id, x, y, 0.0f); + BLF_color4ubv(fs->uifont_id, col); BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); if (fs->kerning == 1) @@ -293,7 +296,7 @@ void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const cha */ void UI_fontstyle_draw_simple_backdrop( const uiFontStyle *fs, float x, float y, const char *str, - const unsigned char fg[4], const unsigned char bg[4]) + const float col_fg[4], const float col_bg[4]) { if (fs->kerning == 1) BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); @@ -307,21 +310,19 @@ void UI_fontstyle_draw_simple_backdrop( const float margin = height / 4.0f; /* backdrop */ - glColor4ubv(bg); + float color[4] = { col_bg[0], col_bg[1], col_bg[2], 0.5f }; - UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA); - UI_draw_roundbox( + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa(true, x - margin, (y + decent) - margin, x + width + margin, (y + decent) + height + margin, - margin); - - glColor4ubv(fg); + margin, color); } - BLF_position(fs->uifont_id, x, y, 0.0f); + BLF_color4fv(fs->uifont_id, col_fg); BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); if (fs->kerning == 1) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index e113098a769..5a2200fbe49 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -56,11 +56,12 @@ #include "BKE_colorband.h" #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idcode.h" #include "BKE_idprop.h" +#include "BKE_layer.h" #include "BKE_library.h" +#include "BKE_library_override.h" #include "BKE_linestyle.h" #include "BKE_main.h" #include "BKE_modifier.h" @@ -72,6 +73,9 @@ #include "BKE_sca.h" #include "BKE_screen.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_screen.h" #include "ED_object.h" #include "ED_render.h" @@ -91,11 +95,126 @@ // #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. +/* defines for templateID/TemplateSearch */ +#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6) +#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y + void UI_template_fix_linking(void) { } +/** + * Add a block button for the search menu for templateID and templateSearch. + */ +static void template_add_button_search_menu( + const bContext *C, uiLayout *layout, uiBlock *block, + PointerRNA *ptr, PropertyRNA *prop, + uiBlockCreateFunc block_func, void *block_argN, const char * const tip, + const bool use_previews, const bool editable) +{ + PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop); + ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL; + const ID *idfrom = ptr->id.data; + const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop); + uiBut *but; + + if (use_previews) { + ARegion *region = CTX_wm_region(C); + const bool use_big_size = (region->regiontype != RGN_TYPE_HEADER); /* silly check, could be more generic */ + /* Ugly exception for screens here, drawing their preview in icon size looks ugly/useless */ + const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR)); + const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f); + const short height = UI_UNIT_Y * (use_big_size ? 6 : 1); + + but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, width, height, tip); + if (use_preview_icon) { + int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type); + ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + } + else { + ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); + UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); + } + + if ((idfrom && idfrom->lib) || !editable) + UI_but_flag_enable(but, UI_BUT_DISABLED); + if (use_big_size) { + uiLayoutRow(layout, true); + } + } + else { + but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, tip); + ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); + if (id) { + /* default dragging of icon for id browse buttons */ + UI_but_drag_set_id(but, id); + } + UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); + + if ((idfrom && idfrom->lib) || !editable) + UI_but_flag_enable(but, UI_BUT_DISABLED); + } +} + +static uiBlock *template_common_search_menu( + const bContext *C, ARegion *region, + uiButSearchFunc search_func, void *search_arg, + uiButHandleFunc handle_func, void *active_item, + const int preview_rows, const int preview_cols) +{ + static char search[256]; + wmWindow *win = CTX_wm_window(C); + uiBlock *block; + uiBut *but; + + /* clear initial search string, then all items show */ + search[0] = 0; + + block = UI_block_begin(C, region, "_popup", UI_EMBOSS); + UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); + + /* preview thumbnails */ + if (preview_rows > 0 && preview_cols > 0) { + const int w = 4 * U.widget_unit * preview_cols; + const int h = 5 * U.widget_unit * preview_rows; + + /* fake button, it holds space for search items */ + uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL); + + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y, + preview_rows, preview_cols, ""); + } + /* list view */ + else { + const int searchbox_width = UI_searchbox_size_x(); + const int searchbox_height = UI_searchbox_size_y(); + + /* fake button, it holds space for search items */ + uiDefBut( + block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, + NULL, 0, 0, 0, 0, NULL); + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, + searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); + } + UI_but_func_search_set( + but, ui_searchbox_create_generic, search_func, + search_arg, handle_func, active_item); + + + UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); + UI_block_direction_set(block, UI_DIR_DOWN); + + /* give search-field focus */ + UI_but_focus_on_enter_event(win, but); + /* this type of search menu requires undo */ + but->flag |= UI_BUT_UNDO; + + return block; +} + /********************** Header Template *************************/ void uiTemplateHeader(uiLayout *layout, bContext *C) @@ -177,61 +296,16 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str, /* ID Search browse menu, open */ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) { - static char search[256]; static TemplateID template_ui; - PointerRNA idptr; - wmWindow *win = CTX_wm_window(C); - uiBlock *block; - uiBut *but; - - /* clear initial search string, then all items show */ - search[0] = 0; + PointerRNA active_item_ptr; + /* arg_litem is malloced, can be freed by parent button */ template_ui = *((TemplateID *)arg_litem); - - /* get active id for showing first item */ - idptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop); + active_item_ptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop); - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); - - /* preview thumbnails */ - if (template_ui.prv_rows > 0 && template_ui.prv_cols > 0) { - int w = 4 * U.widget_unit * template_ui.prv_cols; - int h = 5 * U.widget_unit * template_ui.prv_rows; - - /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL); - - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y, - template_ui.prv_rows, template_ui.prv_cols, ""); - UI_but_func_search_set( - but, ui_searchbox_create_generic, id_search_cb, - &template_ui, id_search_call_cb, idptr.data); - } - /* list view */ - else { - const int searchbox_width = UI_searchbox_size_x(); - const int searchbox_height = UI_searchbox_size_y(); - - /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL); - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); - UI_but_func_search_set( - but, ui_searchbox_create_generic, id_search_cb, - &template_ui, id_search_call_cb, idptr.data); - } - - - UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); - UI_block_direction_set(block, UI_DIR_DOWN); - - /* give search-field focus */ - UI_but_focus_on_enter_event(win, but); - /* this type of search menu requires undo */ - but->flag |= UI_BUT_UNDO; - - return block; + return template_common_search_menu( + C, ar, id_search_cb, &template_ui, id_search_call_cb, active_item_ptr.data, + template_ui.prv_rows, template_ui.prv_cols); } /************************ ID Template ***************************/ @@ -319,6 +393,20 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } } break; + case UI_ID_OVERRIDE: + if (id) { + Main *bmain = CTX_data_main(C); + ID *override_id = BKE_override_static_create_from(bmain, id); + if (override_id != NULL) { + BKE_main_id_clear_newpoins(bmain); + + /* Assign new pointer, takes care of updates/notifiers */ + RNA_id_pointer_create(override_id, &idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr); + RNA_property_update(C, &template_ui->ptr, template_ui->prop); + } + } + break; case UI_ID_ALONE: if (id) { const bool do_scene_obj = (GS(id->name) == ID_OB) && @@ -330,13 +418,13 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) Scene *scene = CTX_data_scene(C); ED_object_single_user(bmain, scene, (struct Object *)id); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } else { if (id) { Main *bmain = CTX_data_main(C); id_single_user(C, id, &template_ui->ptr, template_ui->prop); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } } } @@ -348,7 +436,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } } -static const char *template_id_browse_tip(StructRNA *type) +static const char *template_id_browse_tip(const StructRNA *type) { if (type) { switch (RNA_type_to_ID_code(type)) { @@ -380,6 +468,8 @@ static const char *template_id_browse_tip(StructRNA *type) case ID_PAL: return N_("Browse Palette Data to be linked"); case ID_PC: return N_("Browse Paint Curve Data to be linked"); case ID_CF: return N_("Browse Cache Files to be linked"); + case ID_WS: return N_("Browse Workspace to be linked"); + case ID_LP: return N_("Browse LightProbe to be linked"); } } return N_("Browse ID data to be linked"); @@ -409,6 +499,7 @@ static void template_ID( // ListBase *lb; // UNUSED ID *id, *idfrom; const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop); + const bool use_previews = template_ui->preview = (flag & UI_ID_PREVIEWS) != 0; idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); id = idptr.data; @@ -421,29 +512,11 @@ static void template_ID( if (idptr.type) type = idptr.type; - if (flag & UI_ID_PREVIEWS) { - template_ui->preview = true; - - but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template_ui), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, - TIP_(template_id_browse_tip(type))); - ui_def_but_icon(but, id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type), - UI_HAS_ICON | UI_BUT_ICON_PREVIEW); - - if ((idfrom && idfrom->lib) || !editable) - UI_but_flag_enable(but, UI_BUT_DISABLED); - - uiLayoutRow(layout, true); - } - else if (flag & UI_ID_BROWSE) { - but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template_ui), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, - TIP_(template_id_browse_tip(type))); - ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); - /* default dragging of icon for id browse buttons */ - UI_but_drag_set_id(but, id); - UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); - - if ((idfrom && idfrom->lib) || !editable) - UI_but_flag_enable(but, UI_BUT_DISABLED); + if (flag & UI_ID_BROWSE) { + template_add_button_search_menu( + C, layout, block, &template_ui->ptr, template_ui->prop, + id_search_menu, MEM_dupallocN(template_ui), TIP_(template_id_browse_tip(type)), + use_previews, editable); } /* text button with name */ @@ -453,8 +526,9 @@ static void template_ID( //text_idbutton(id, name); name[0] = '\0'; - but = uiDefButR(block, UI_BTYPE_TEXT, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, - &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); + but = uiDefButR( + block, UI_BTYPE_TEXT, 0, name, 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT, + &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_RENAME)); if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT); @@ -465,13 +539,27 @@ static void template_ID( UI_but_flag_enable(but, UI_BUT_DISABLED); } else { + const bool disabled = (!id_make_local(CTX_data_main(C), id, true /* test */, false) || + (idfrom && idfrom->lib)); but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Direct linked library data-block, click to make local")); - if (!id_make_local(CTX_data_main(C), id, true /* test */, false) || (idfrom && idfrom->lib)) + if (disabled) { UI_but_flag_enable(but, UI_BUT_DISABLED); - } + } + else { + UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL)); + } - UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL)); + but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_OVERRIDE, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0, 0, 0, 0, + TIP_("Direct linked library data-block, click to create static override")); + if (disabled) { + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + else { + UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_OVERRIDE)); + } + } } if (id->us > 1) { @@ -499,7 +587,7 @@ static void template_ID( if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT); - if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) { + if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { uiDefButR(block, UI_BTYPE_TOGGLE, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL); } } @@ -533,6 +621,8 @@ static void template_ID( BLT_I18NCONTEXT_ID_PARTICLESETTINGS, BLT_I18NCONTEXT_ID_GPENCIL, BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, + BLT_I18NCONTEXT_ID_WORKSPACE, + BLT_I18NCONTEXT_ID_LIGHTPROBE, ); if (newop) { @@ -740,6 +830,208 @@ void uiTemplateAnyID( uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE); } +/********************* Search Template ********************/ + +typedef struct TemplateSearch { + uiRNACollectionSearch search_data; + + bool use_previews; + int preview_rows, preview_cols; +} TemplateSearch; + +static void template_search_handle_cb(bContext *C, void *arg_template, void *item) +{ + TemplateSearch *template_search = arg_template; + uiRNACollectionSearch *coll_search = &template_search->search_data; + StructRNA *type = RNA_property_pointer_type(&coll_search->target_ptr, coll_search->target_prop); + PointerRNA item_ptr; + + RNA_pointer_create(NULL, type, item, &item_ptr); + RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr); + RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop); +} + +static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_template) +{ + static TemplateSearch template_search; + PointerRNA active_ptr; + + /* arg_template is malloced, can be freed by parent button */ + template_search = *((TemplateSearch *)arg_template); + active_ptr = RNA_property_pointer_get(&template_search.search_data.target_ptr, + template_search.search_data.target_prop); + + return template_common_search_menu( + C, region, ui_rna_collection_search_cb, &template_search, + template_search_handle_cb, active_ptr.data, + template_search.preview_rows, template_search.preview_cols); +} + +static void template_search_add_button_searchmenu( + const bContext *C, uiLayout *layout, uiBlock *block, + TemplateSearch *template_search, const bool editable) +{ + const char *ui_description = RNA_property_ui_description(template_search->search_data.target_prop); + + template_add_button_search_menu( + C, layout, block, + &template_search->search_data.target_ptr, template_search->search_data.target_prop, + template_search_menu, MEM_dupallocN(template_search), ui_description, + template_search->use_previews, editable); +} + +static void template_search_add_button_name( + uiBlock *block, PointerRNA *active_ptr, const StructRNA *type) +{ + uiDefAutoButR( + block, active_ptr, RNA_struct_name_property(type), 0, "", ICON_NONE, + 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT); +} + +static void template_search_add_button_operator( + uiBlock *block, const char * const operator_name, + const int opcontext, const int icon, const bool editable) +{ + if (!operator_name) { + return; + } + + uiBut *but = uiDefIconButO( + block, UI_BTYPE_BUT, operator_name, opcontext, icon, + 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + + if (!editable) { + UI_but_drawflag_enable(but, UI_BUT_DISABLED); + } +} + +static void template_search_buttons( + const bContext *C, uiLayout *layout, TemplateSearch *template_search, + const char *newop, const char *unlinkop) +{ + uiBlock *block = uiLayoutGetBlock(layout); + uiRNACollectionSearch *search_data = &template_search->search_data; + StructRNA *type = RNA_property_pointer_type(&search_data->target_ptr, search_data->target_prop); + const bool editable = RNA_property_editable(&search_data->target_ptr, search_data->target_prop); + PointerRNA active_ptr = RNA_property_pointer_get(&search_data->target_ptr, search_data->target_prop); + + if (active_ptr.type) { + /* can only get correct type when there is an active item */ + type = active_ptr.type; + } + + uiLayoutRow(layout, true); + UI_block_align_begin(block); + + template_search_add_button_searchmenu(C, layout, block, template_search, editable); + template_search_add_button_name(block, &active_ptr, type); + template_search_add_button_operator(block, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, editable); + template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable); + + UI_block_align_end(block); +} + +static PropertyRNA *template_search_get_searchprop( + PointerRNA *targetptr, PropertyRNA *targetprop, + PointerRNA *searchptr, const char * const searchpropname) +{ + PropertyRNA *searchprop; + + if (searchptr && !searchptr->data) { + searchptr = NULL; + } + + if (!searchptr && !searchpropname) { + /* both NULL means we don't use a custom rna collection to search in */ + } + else if (!searchptr && searchpropname) { + RNA_warning("searchpropname defined (%s) but searchptr is missing", searchpropname); + } + else if (searchptr && !searchpropname) { + RNA_warning("searchptr defined (%s) but searchpropname is missing", RNA_struct_identifier(searchptr->type)); + } + else if (!(searchprop = RNA_struct_find_property(searchptr, searchpropname))) { + RNA_warning("search collection property not found: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); + } + else if (RNA_property_type(searchprop) != PROP_COLLECTION) { + RNA_warning("search collection property is not a collection type: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); + } + /* check if searchprop has same type as targetprop */ + else if (RNA_property_pointer_type(searchptr, searchprop) != RNA_property_pointer_type(targetptr, targetprop)) { + RNA_warning("search collection items from %s.%s are not of type %s", + RNA_struct_identifier(searchptr->type), searchpropname, + RNA_struct_identifier(RNA_property_pointer_type(targetptr, targetprop))); + } + else { + return searchprop; + } + + return NULL; +} + +static TemplateSearch *template_search_setup( + PointerRNA *ptr, const char * const propname, + PointerRNA *searchptr, const char * const searchpropname) +{ + TemplateSearch *template_search; + PropertyRNA *prop, *searchprop; + + prop = RNA_struct_find_property(ptr, propname); + + if (!prop || RNA_property_type(prop) != PROP_POINTER) { + RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + return NULL; + } + searchprop = template_search_get_searchprop(ptr, prop, searchptr, searchpropname); + + template_search = MEM_callocN(sizeof(*template_search), __func__); + template_search->search_data.target_ptr = *ptr; + template_search->search_data.target_prop = prop; + template_search->search_data.search_ptr = *searchptr; + template_search->search_data.search_prop = searchprop; + + return template_search; +} + +/** + * Search menu to pick an item from a collection. + * A version of uiTemplateID that works for non-ID types. + */ +void uiTemplateSearch( + uiLayout *layout, bContext *C, + PointerRNA *ptr, const char *propname, + PointerRNA *searchptr, const char *searchpropname, + const char *newop, const char *unlinkop) +{ + TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname); + if (template_search != NULL) { + template_search_buttons(C, layout, template_search, newop, unlinkop); + MEM_freeN(template_search); + } +} + +void uiTemplateSearchPreview( + uiLayout *layout, bContext *C, + PointerRNA *ptr, const char *propname, + PointerRNA *searchptr, const char *searchpropname, + const char *newop, const char *unlinkop, + const int rows, const int cols) +{ + TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname); + + if (template_search != NULL) { + template_search->use_previews = true; + template_search->preview_rows = rows; + template_search->preview_cols = cols; + + template_search_buttons(C, layout, template_search, newop, unlinkop); + + MEM_freeN(template_search); + } +} + /********************* RNA Path Builder Template ********************/ /* ---------- */ @@ -793,7 +1085,7 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v) ob->partype = PAROBJECT; WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); ED_undo_push(C, "Modifier convert to real"); } @@ -937,7 +1229,7 @@ static uiLayout *draw_modifier( /* When Modifier is a simulation, show button to switch to context rather than the delete button. */ if (modifier_can_delete(md) && (!modifier_is_simulation(md) || - STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME))) + STREQ(scene->view_render.engine_id, RE_engine_id_BLENDER_GAME))) { uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove"); } @@ -1074,7 +1366,7 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event) Main *bmain = CTX_data_main(C); if (ob->pose) BKE_pose_tag_recalc(bmain, ob->pose); /* checks & sorts pose channels */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); break; } #endif @@ -1088,8 +1380,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event) * object_test_constraints(ob); * if (ob->pose) BKE_pose_update_constraint_flags(ob->pose); */ - if (ob->type == OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); - else DAG_id_tag_update(&ob->id, OB_RECALC_OB); + if (ob->type == OB_ARMATURE) DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); + else DEG_id_tag_update(&ob->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); } @@ -3854,6 +4146,7 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) if (propptr.data) { uiBut *but = uiLayoutGetBlock(layout)->buttons.last; + WM_operator_properties_sanitize(&propptr, false); template_keymap_item_properties(layout, NULL, &propptr); /* attach callbacks to compensate for missing properties update, @@ -3870,6 +4163,66 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) } } +/********************************* Overrides *************************************/ + +void uiTemplateOverrideProperty( + uiLayout *layout, PointerRNA *collection_props_ptr, PointerRNA *scene_props_ptr, const char *propname, + const char *name, const char *text_ctxt, int translate, int icon, + const char *custom_template) +{ + bool is_set = false; + uiLayout *row, *col; + + PointerRNA *ptr; + PropertyRNA *prop; + + IDProperty *collection_props = collection_props_ptr->data; + + if (IDP_GetPropertyFromGroup(collection_props, propname)) { + prop = RNA_struct_find_property(collection_props_ptr, propname); + ptr = collection_props_ptr; + is_set = RNA_property_is_set(ptr, prop); + } + else { + /* property doesn't exist yet */ + prop = RNA_struct_find_property(scene_props_ptr, propname); + ptr = scene_props_ptr; + } + + /* Get translated name (label). */ + name = RNA_translate_ui_text(name, text_ctxt, NULL, prop, translate); + + row = uiLayoutRow(layout, false); + col = uiLayoutColumn(row, false); + + uiLayoutSetEnabled(col, is_set); + + if (custom_template && STREQ(custom_template, "icon_view")) { + uiTemplateIconView(col, ptr, propname, false, 5.0f); + } + else { + uiItemFullR(col, ptr, prop, -1, 0, 0, name, icon); + } + + col = uiLayoutColumn(row, false); + uiBut *but; + uiBlock *block = uiLayoutGetBlock(col); + UI_block_emboss_set(block, UI_EMBOSS_NONE); + + if (is_set) { + but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_unuse_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + } + else { + but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_use_property_button", WM_OP_EXEC_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + /* XXX - Using existing data struct to pass another RNAPointer */ + but->rnasearchpoin = *scene_props_ptr; + } + + but->rnapoin = *collection_props_ptr; + but->rnaprop = prop; + UI_block_emboss_set(block, UI_EMBOSS); +} + /********************************* Color management *************************************/ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname) diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 1927d7280f3..f0317087ddc 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -215,8 +215,90 @@ int uiDefAutoButsRNA( return tot; } -/***************************** ID Utilities *******************************/ +/* *** RNA collection search menu *** */ +typedef struct CollItemSearch { + struct CollItemSearch *next, *prev; + void *data; + char *name; + int index; + int iconid; +} CollItemSearch; + +static int sort_search_items_list(const void *a, const void *b) +{ + const CollItemSearch *cis1 = a; + const CollItemSearch *cis2 = b; + + if (BLI_strcasecmp(cis1->name, cis2->name) > 0) + return 1; + else + return 0; +} + +void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items) +{ + uiRNACollectionSearch *data = arg; + char *name; + int i = 0, iconid = 0, flag = RNA_property_flag(data->target_prop); + ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list"); + CollItemSearch *cis; + const bool skip_filter = !(data->but_changed && *data->but_changed); + + /* build a temporary list of relevant items first */ + RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) + { + + if (flag & PROP_ID_SELF_CHECK) + if (itemptr.data == data->target_ptr.id.data) + continue; + + /* use filter */ + if (RNA_property_type(data->target_prop) == PROP_POINTER) { + if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0) + continue; + } + + name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */ + iconid = 0; + if (itemptr.type && RNA_struct_is_ID(itemptr.type)) { + iconid = ui_id_icon_get(C, itemptr.data, false); + } + + if (name) { + if (skip_filter || BLI_strcasestr(name, str)) { + cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch"); + cis->data = itemptr.data; + cis->name = MEM_dupallocN(name); + cis->index = i; + cis->iconid = iconid; + BLI_addtail(items_list, cis); + } + MEM_freeN(name); + } + + i++; + } + RNA_PROP_END; + + BLI_listbase_sort(items_list, sort_search_items_list); + + /* add search items from temporary list */ + for (cis = items_list->first; cis; cis = cis->next) { + if (UI_search_item_add(items, cis->name, cis->data, cis->iconid) == false) { + break; + } + } + + for (cis = items_list->first; cis; cis = cis->next) { + MEM_freeN(cis->name); + } + BLI_freelistN(items_list); + MEM_freeN(items_list); +} + + +/***************************** ID Utilities *******************************/ int UI_icon_from_id(ID *id) { Object *ob; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 39ee8e2885d..cc4f53cbabf 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -47,9 +47,6 @@ #include "RNA_access.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" - #include "BLF_api.h" #include "UI_interface.h" @@ -58,6 +55,9 @@ #include "interface_intern.h" #include "GPU_basic_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #ifdef WITH_INPUT_IME # include "WM_types.h" @@ -208,48 +208,58 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} /* ************************************************* */ -void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3) +void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, + const float color[4]) { float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}}; - float color[4]; - int j; - + float draw_color[4]; + + copy_v4_v4(draw_color, color); + draw_color[3] *= 0.125f; + glEnable(GL_BLEND); - glGetFloatv(GL_CURRENT_COLOR, color); - color[3] *= 0.125f; - glColor4fv(color); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, tri_arr); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4fv(draw_color); + immBegin(GWN_PRIM_TRIS, 3 * WIDGET_AA_JITTER); /* for each AA step */ - for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); - glDrawArrays(GL_TRIANGLES, 0, 3); - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + for (int j = 0; j < WIDGET_AA_JITTER; j++) { + immVertex2f(pos, tri_arr[0][0] + jit[j][0], tri_arr[0][1] + jit[j][1]); + immVertex2f(pos, tri_arr[1][0] + jit[j][0], tri_arr[1][1] + jit[j][1]); + immVertex2f(pos, tri_arr[2][0] + jit[j][0], tri_arr[2][1] + jit[j][1]); } - glDisableClientState(GL_VERTEX_ARRAY); + immEnd(); + + immUnbindProgram(); + glDisable(GL_BLEND); } -void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha) +/* belongs in interface_draw.c, but needs WIDGET_AA_JITTER from this file */ +void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]) { - float color[4]; - int j; - glEnable(GL_BLEND); - glGetFloatv(GL_CURRENT_COLOR, color); - if (use_alpha) { - color[3] = 0.5f; + + if (filled) { + /* plain antialiased filled box */ + const float alpha = color[3] * 0.125f; + + for (int j = 0; j < WIDGET_AA_JITTER; j++) { + gpuPushMatrix(); + gpuTranslate2fv(jit[j]); + UI_draw_roundbox_3fvAlpha(true, minx, miny, maxx, maxy, rad, color, alpha); + gpuPopMatrix(); + } } - color[3] *= 0.125f; - glColor4fv(color); - - for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); - UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad); - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + else { + /* plain antialiased unfilled box */ + glEnable(GL_LINE_SMOOTH); + UI_draw_roundbox_4fv(false, minx, miny, maxx, maxy, rad, color); + glDisable(GL_LINE_SMOOTH); } glDisable(GL_BLEND); @@ -570,12 +580,27 @@ static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rec g_shape_preset_scroll_circle_face, ARRAY_SIZE(g_shape_preset_scroll_circle_face)); } -static void shape_preset_draw_trias(uiWidgetTrias *tria) +static void shape_preset_draw_trias(uiWidgetTrias *tria, uint pos) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, tria->vec); - glDrawElements(GL_TRIANGLES, tria->tot * 3, GL_UNSIGNED_INT, tria->index); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_TRIS, tria->tot * 3); + for (int i = 0; i < tria->tot; ++i) + for (int j = 0; j < 3; ++j) + immVertex2fv(pos, tria->vec[tria->index[i][j]]); + immEnd(); +} + +static void widget_draw_vertex_buffer(unsigned int pos, unsigned int col, int mode, + const float quads_pos[WIDGET_SIZE_MAX][2], + const unsigned char quads_col[WIDGET_SIZE_MAX][4], + unsigned int totvert) +{ + immBegin(mode, totvert); + for (int i = 0; i < totvert; ++i) { + if (quads_col) + immAttrib4ubv(col, quads_col[i]); + immVertex2fv(pos, quads_pos[i]); + } + immEnd(); } static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *rect) @@ -666,21 +691,18 @@ static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int tot } } -static void widgetbase_outline(uiWidgetBase *wtb) +static void widgetbase_outline(uiWidgetBase *wtb, unsigned int pos) { float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */ widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, triangle_strip); - glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2); - glDisableClientState(GL_VERTEX_ARRAY); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2); } static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) { int j, a; - + glEnable(GL_BLEND); /* backdrop non AA */ @@ -690,78 +712,76 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) float inner_v_half[WIDGET_SIZE_MAX][2]; float x_mid = 0.0f; /* used for dumb clamping of values */ - /* dark checkers */ - glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); - /* light checkers */ - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX); + /* checkers */ + immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f); + immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f); + immUniform1i("size", 8); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + immUnbindProgram(); /* alpha fill */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv((unsigned char *)wcol->inner); - glColor4ubv((unsigned char *)wcol->inner); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for (a = 0; a < wtb->totvert; a++) { x_mid += wtb->inner_v[a][0]; } x_mid /= wtb->totvert; - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert); /* 1/2 solid color */ - glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255); + immUniformColor3ubv((unsigned char *)wcol->inner); for (a = 0; a < wtb->totvert; a++) { inner_v_half[a][0] = MIN2(wtb->inner_v[a][0], x_mid); inner_v_half[a][1] = wtb->inner_v[a][1]; } - glVertexPointer(2, GL_FLOAT, 0, inner_v_half); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); - glDisableClientState(GL_VERTEX_ARRAY); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, inner_v_half, NULL, wtb->totvert); + + immUnbindProgram(); } else { /* simple fill */ - glColor4ubv((unsigned char *)wcol->inner); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv((unsigned char *)wcol->inner); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); - glDisableClientState(GL_VERTEX_ARRAY); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert); + + immUnbindProgram(); } } else { char col1[4], col2[4]; - unsigned char col_array[WIDGET_SIZE_MAX * 4]; - unsigned char *col_pt = col_array; - + unsigned char col_array[WIDGET_SIZE_MAX][4]; + unsigned char *col_pt = &col_array[0][0]; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown); for (a = 0; a < wtb->totvert; a++, col_pt += 4) { round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]); } - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, col_array); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); + widget_draw_vertex_buffer(pos, col, GL_TRIANGLE_FAN, wtb->inner_v, col_array, wtb->totvert); + immUnbindProgram(); } } - + /* for each AA step */ if (wtb->draw_outline) { float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */ @@ -780,53 +800,55 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss); } - glEnableClientState(GL_VERTEX_ARRAY); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); + gpuTranslate2fv(jit[j]); /* outline */ - glColor4ubv(tcol); + immUniformColor4ubv(tcol); - glVertexPointer(2, GL_FLOAT, 0, triangle_strip); - glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2); /* emboss bottom shadow */ if (wtb->draw_emboss) { if (emboss[3]) { - glColor4ubv(emboss); - glVertexPointer(2, GL_FLOAT, 0, triangle_strip_emboss); - glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->halfwayvert * 2); + immUniformColor4ubv(emboss); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip_emboss, NULL, wtb->halfwayvert * 2); } } - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + gpuTranslate2f(-jit[j][0], -jit[j][1]); } - - glDisableClientState(GL_VERTEX_ARRAY); + immUnbindProgram(); } - + /* decoration */ if (wtb->tria1.tot || wtb->tria2.tot) { const unsigned char tcol[4] = {wcol->item[0], wcol->item[1], wcol->item[2], (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)}; - glColor4ubv(tcol); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(tcol); /* for each AA step */ for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); + gpuTranslate2fv(jit[j]); - if (wtb->tria1.tot) { - shape_preset_draw_trias(&wtb->tria1); - } - if (wtb->tria2.tot) { - shape_preset_draw_trias(&wtb->tria2); - } + if (wtb->tria1.tot) + shape_preset_draw_trias(&wtb->tria1, pos); - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + if (wtb->tria2.tot) + shape_preset_draw_trias(&wtb->tria2, pos); + + gpuTranslate2f(-jit[j][0], -jit[j][1]); } + + immUnbindProgram(); } glDisable(GL_BLEND); @@ -1282,6 +1304,7 @@ static void widget_draw_text_ime_underline( int ofs_x, width; int rect_x = BLI_rcti_size_x(rect); int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end; + float fcol[4]; if (drawstr[0] != 0) { if (but->pos >= but->ofs) { @@ -1294,8 +1317,8 @@ static void widget_draw_text_ime_underline( width = BLF_width(fstyle->uifont_id, drawstr + but->ofs, ime_data->composite_len + but->pos - but->ofs); - glColor4ubv((unsigned char *)wcol->text); - UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1); + rgba_uchar_to_float(fcol, wcol->text); + UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1, fcol); /* draw the thick line */ if (sel_start != -1 && sel_end != -1) { @@ -1312,7 +1335,7 @@ static void widget_draw_text_ime_underline( width = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_end + sel_start - but->ofs); - UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2); + UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2, fcol); } } } @@ -1396,11 +1419,16 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs); - glColor4ubv((unsigned char *)wcol->item); - glRecti(rect->xmin + selsta_draw, - rect->ymin + 2, - min_ii(rect->xmin + selwidth_draw, rect->xmax - 2), - rect->ymax - 2); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4ubv((unsigned char *)wcol->item); + immRecti(pos, rect->xmin + selsta_draw, + rect->ymin + 2, + min_ii(rect->xmin + selwidth_draw, rect->xmax - 2), + rect->ymax - 2); + + immUnbindProgram(); } } @@ -1423,13 +1451,18 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b t = 0; } - glColor3f(0.2, 0.6, 0.9); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(0.2f, 0.6f, 0.9f); tx = rect->xmin + t + 2; ty = rect->ymin + 2; /* draw cursor */ - glRecti(rect->xmin + t, ty, tx, rect->ymax - 2); + immRecti(pos, rect->xmin + t, ty, tx, rect->ymax - 2); + + immUnbindProgram(); } #ifdef WITH_INPUT_IME @@ -1488,43 +1521,46 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b } #endif - glColor4ubv((unsigned char *)wcol->text); - if (!use_right_only) { /* for underline drawing */ float font_xofs, font_yofs; - UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, - drawstr_left_len - but->ofs, &font_xofs, &font_yofs); + int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) : (drawstr_left_len - but->ofs); - if (but->menu_key != '\0') { - char fixedbuf[128]; - const char *str; + if (drawlen > 0) { + UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, (unsigned char *)wcol->text, + drawlen, &font_xofs, &font_yofs); - BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len)); + if (but->menu_key != '\0') { + char fixedbuf[128]; + const char *str; - str = strchr(fixedbuf, but->menu_key - 32); /* upper case */ - if (str == NULL) - str = strchr(fixedbuf, but->menu_key); + BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawlen)); - if (str) { - int ul_index = -1; - float ul_advance; + str = strchr(fixedbuf, but->menu_key - 32); /* upper case */ + if (str == NULL) + str = strchr(fixedbuf, but->menu_key); - ul_index = (int)(str - fixedbuf); + if (str) { + int ul_index = -1; + float ul_advance; - if (fstyle->kerning == 1) { - BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); - } + ul_index = (int)(str - fixedbuf); + + if (fstyle->kerning == 1) { + BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + } - fixedbuf[ul_index] = '\0'; - ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index); + fixedbuf[ul_index] = '\0'; + ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index); - BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f); - BLF_draw(fstyle->uifont_id, "_", 2); + BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f); + BLF_color4ubv(fstyle->uifont_id, (unsigned char *)wcol->text); + BLF_draw(fstyle->uifont_id, "_", 2); - if (fstyle->kerning == 1) { - BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + if (fstyle->kerning == 1) { + BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + } } } } @@ -1534,7 +1570,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b if (drawstr_right) { fstyle->align = UI_STYLE_TEXT_RIGHT; rect->xmax -= UI_TEXT_CLIP_MARGIN; - UI_fontstyle_draw(fstyle, rect, drawstr_right); + UI_fontstyle_draw(fstyle, rect, drawstr_right, (unsigned char *)wcol->text); } } @@ -1657,6 +1693,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB widget_draw_text(fstyle, wcol, but, rect); ui_but_text_password_hide(password_str, but, true); + + /* if a widget uses font shadow it has to be deactivated now */ + BLF_disable(fstyle->uifont_id, BLF_SHADOW); } #undef UI_TEXT_CLIP_MARGIN @@ -1671,6 +1710,8 @@ static struct uiWidgetStateColors wcol_state_colors = { {215, 211, 75, 255}, {180, 0, 255, 255}, {153, 0, 230, 255}, + {74, 137, 137, 255}, + {49, 112, 112, 255}, 0.5f, 0.0f }; @@ -1915,6 +1956,19 @@ static struct uiWidgetColors wcol_list_item = { 0, 0 }; +struct uiWidgetColors wcol_tab = { + {255, 255, 255, 255}, + {83, 83, 83, 255}, + {114, 114, 114, 255}, + {90, 90, 90, 255}, + + {0, 0, 0, 255}, + {0, 0, 0, 255}, + + 0, + 0, 0 +}; + /* free wcol struct to play with */ static struct uiWidgetColors wcol_tmp = { {0, 0, 0, 255}, @@ -1937,6 +1991,7 @@ void ui_widget_color_init(ThemeUI *tui) tui->wcol_tool = wcol_tool; tui->wcol_text = wcol_text; tui->wcol_radio = wcol_radio; + tui->wcol_tab = wcol_tab; tui->wcol_option = wcol_option; tui->wcol_toggle = wcol_toggle; tui->wcol_num = wcol_num; @@ -2009,6 +2064,8 @@ static void widget_state(uiWidgetType *wt, int state) widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend); else if (state & UI_BUT_DRIVEN) widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend); + else if (state & UI_BUT_OVERRIDEN) + widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden_sel, wcol_state->blend); copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); @@ -2022,6 +2079,8 @@ static void widget_state(uiWidgetType *wt, int state) widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend); else if (state & UI_BUT_DRIVEN) widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend); + else if (state & UI_BUT_OVERRIDEN) + widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden, wcol_state->blend); if (state & UI_ACTIVE) { /* mouse over? */ wt->wcol.inner[0] = wt->wcol.inner[0] >= 240 ? 255 : wt->wcol.inner[0] + 15; @@ -2067,7 +2126,9 @@ static void widget_state_numslider(uiWidgetType *wt, int state) widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend); else if (state & UI_BUT_DRIVEN) widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend); - + else if (state & UI_BUT_OVERRIDEN) + widget_state_blend(wt->wcol.item, wcol_state->inner_overridden_sel, blend); + if (state & UI_SELECT) SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown); } @@ -2078,6 +2139,8 @@ static void widget_state_numslider(uiWidgetType *wt, int state) widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend); else if (state & UI_BUT_DRIVEN) widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend); + else if (state & UI_BUT_OVERRIDEN) + widget_state_blend(wt->wcol.item, wcol_state->inner_overridden, blend); } } @@ -2195,23 +2258,24 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r /* we draw a number of increasing size alpha quad strips */ alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout; - - glEnableClientState(GL_VERTEX_ARRAY); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); for (step = 1; step <= (int)radout; step++) { float expfac = sqrtf(step / radout); round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step); - glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac)); + immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac)); widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip); - glVertexPointer(2, GL_FLOAT, 0, triangle_strip); - glDrawArrays(GL_TRIANGLE_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */ + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, totvert * 2); } - glDisableClientState(GL_VERTEX_ARRAY); + immUnbindProgram(); } static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction) @@ -2248,20 +2312,21 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir static void ui_hsv_cursor(float x, float y) { - glPushMatrix(); - glTranslatef(x, y, 0.0f); - - glColor3f(1.0f, 1.0f, 1.0f); - glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 8); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(1.0f, 1.0f, 1.0f); + imm_draw_circle_fill_2d(pos, x, y, 3.0f * U.pixelsize, 8); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3f(0.0f, 0.0f, 0.0f); - glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 12); + immUniformColor3f(0.0f, 0.0f, 0.0f); + imm_draw_circle_wire_2d(pos, x, y, 3.0f * U.pixelsize, 12); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - - glPopMatrix(); + + immUnbindProgram(); } void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, @@ -2301,18 +2366,17 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *rect) { + /* TODO(merwin): reimplement as shader for pixel-perfect colors */ + const int tot = 64; const float radstep = 2.0f * (float)M_PI / (float)tot; const float centx = BLI_rcti_cent_x_fl(rect); const float centy = BLI_rcti_cent_y_fl(rect); float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f; - /* gouraud triangle fan */ ColorPicker *cpicker = but->custom_data; const float *hsv_ptr = cpicker->color_data; - float xpos, ypos, ang = 0.0f; float rgb[3], hsvo[3], hsv[3], col[3], colcent[3]; - int a; bool color_profile = ui_but_is_colorpicker_display_space(but); /* color */ @@ -2343,11 +2407,18 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2); - glBegin(GL_TRIANGLE_FAN); - glColor3fv(colcent); - glVertex2f(centx, centy); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + immBegin(GWN_PRIM_TRI_FAN, tot + 2); + immAttrib3fv(color, colcent); + immVertex2f(pos, centx, centy); - for (a = 0; a <= tot; a++, ang += radstep) { + float ang = 0.0f; + for (int a = 0; a <= tot; a++, ang += radstep) { float si = sinf(ang); float co = cosf(ang); @@ -2355,25 +2426,32 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * ui_color_picker_to_rgb_v(hsv, col); - glColor3fv(col); - glVertex2f(centx + co * radius, centy + si * radius); + immAttrib3fv(color, col); + immVertex2f(pos, centx + co * radius, centy + si * radius); } - glEnd(); - + immEnd(); + immUnbindProgram(); + /* fully rounded outline */ - glPushMatrix(); - glTranslatef(centx, centy, 0.0f); + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3ubv((unsigned char *)wcol->outline); - glutil_draw_lined_arc(0.0f, M_PI * 2.0, radius, tot + 1); + + immUniformColor3ubv((unsigned char *)wcol->outline); + imm_draw_circle_wire_2d(pos, centx, centy, radius, tot); + + immUnbindProgram(); + glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - glPopMatrix(); /* cursor */ + float xpos, ypos; ui_hsvcircle_pos_from_vals(but, rect, hsvo, &xpos, &ypos); - ui_hsv_cursor(xpos, ypos); } @@ -2383,7 +2461,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha) { /* allows for 4 steps (red->yellow) */ - const float color_step = 1.0f / 48.0f; + const int steps = 48; + const float color_step = 1.0f / steps; int a; float h = hsv[0], s = hsv[1], v = hsv[2]; float dx, dy, sx1, sx2, sy; @@ -2437,9 +2516,14 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons copy_v3_v3(col1[3], col1[2]); break; } - + /* old below */ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBegin(GWN_PRIM_TRIS, steps * 3 * 6); for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */ const float dx_next = dx + color_step; @@ -2497,22 +2581,29 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons sy = rect->ymin; dy = (float)BLI_rcti_size_y(rect) / 3.0f; - glBegin(GL_QUADS); for (a = 0; a < 3; a++, sy += dy) { - glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha); - glVertex2f(sx1, sy); + immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha); + immVertex2f(pos, sx1, sy); - glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha); - glVertex2f(sx2, sy); + immAttrib4f(col, col1[a][0], col1[a][1], col1[a][2], alpha); + immVertex2f(pos, sx2, sy); + + immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha); + immVertex2f(pos, sx2, sy + dy); - glColor4f(col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha); - glVertex2f(sx2, sy + dy); + immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha); + immVertex2f(pos, sx1, sy); + + immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha); + immVertex2f(pos, sx2, sy + dy); - glColor4f(col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha); - glVertex2f(sx1, sy + dy); + immAttrib4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha); + immVertex2f(pos, sx1, sy + dy); } - glEnd(); } + immEnd(); + + immUnbindProgram(); } bool ui_but_is_colorpicker_display_space(uiBut *but) @@ -2588,8 +2679,11 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect) ui_hsv_cursor(x, y); /* outline */ - glColor3ub(0, 0, 0); - fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax)); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ub(0, 0, 0); + imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax)); + immUnbindProgram(); } /* vertical 'value' slider, using new widget code */ @@ -2657,12 +2751,22 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol) wcol->text[2], 30 }; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glEnable(GL_BLEND); - glColor4ubv(col); + immUniformColor4ubv(col); glLineWidth(1.0f); - sdrawline(rect->xmin, y, rect->xmax, y); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect->xmin, y); + immVertex2f(pos, rect->xmax, y); + immEnd(); + glDisable(GL_BLEND); + + immUnbindProgram(); } /* ************ button callbacks, draw ***************** */ @@ -2734,11 +2838,14 @@ bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol) } #define LINK_RESOL 24 -void ui_draw_link_bezier(const rcti *rect) +void ui_draw_link_bezier(const rcti *rect, const float color[4]) { float coord_array[LINK_RESOL + 1][2]; if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + #if 0 /* unused */ /* we can reuse the dist variable here to increment the GL curve eval amount*/ const float dist = 1.0f / (float)LINK_RESOL; @@ -2746,13 +2853,17 @@ void ui_draw_link_bezier(const rcti *rect) glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, coord_array); - glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL + 1); - glDisableClientState(GL_VERTEX_ARRAY); + immUniformColor4fv(color); + + immBegin(GWN_PRIM_LINE_STRIP, LINK_RESOL + 1); + for (int i = 0; i <= LINK_RESOL; ++i) + immVertex2fv(pos, coord_array[i]); + immEnd(); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); + + immUnbindProgram(); } } @@ -2934,15 +3045,16 @@ static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, in if (but->flag & UI_SELECT) { rcti rectlink; + float color[4]; - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4fv(TH_TEXT_HI, color); rectlink.xmin = BLI_rcti_cent_x(rect); rectlink.ymin = BLI_rcti_cent_y(rect); rectlink.xmax = but->linkto[0]; rectlink.ymax = but->linkto[1]; - ui_draw_link_bezier(&rectlink); + ui_draw_link_bezier(&rectlink, color); } } @@ -3055,7 +3167,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat ui_but_v3_get(but, col); - if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) { + if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_OVERRIDEN | UI_BUT_REDALERT)) { /* draw based on state - color for keyed etc */ widgetbase_draw(&wtb, wcol); @@ -3094,13 +3206,18 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat float bw = rgb_to_grayscale(col); bw += (bw < 0.5f) ? 0.5f : -0.5f; - - glColor4f(bw, bw, bw, 1.0); - glBegin(GL_TRIANGLES); - glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height); - glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height); - glVertex2f(rect->xmin + 0.5f * width, rect->ymin + 0.9f * height); - glEnd(); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(bw, bw, bw); + immBegin(GWN_PRIM_TRIS, 3); + immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.9f * height); + immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.5f * height); + immVertex2f(pos, rect->xmin + 0.5f * width, rect->ymin + 0.9f * height); + immEnd(); + + immUnbindProgram(); } } @@ -3416,12 +3533,50 @@ static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, in widgetbase_draw(&wtb, wcol); } +static void widget_tab(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) +{ + const uiStyle *style = UI_style_get(); + const float rad = 0.15f * U.widget_unit; + const int fontid = style->widget.uifont_id; + const bool is_active = (but->flag & UI_SELECT); + + uiWidgetBase wtb; + unsigned char theme_col_tab_highlight[3]; + + /* create outline highlight colors */ + if (is_active) { + interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner_sel, + (unsigned char *)wcol->outline, 0.2f); + } + else { + interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner, + (unsigned char *)wcol->outline, 0.12f); + } + + widget_init(&wtb); + + /* half rounded */ + round_box_edges(&wtb, roundboxalign, rect, rad); + + /* draw inner */ + wtb.draw_outline = 0; + widgetbase_draw(&wtb, wcol); + + /* draw outline (3d look) */ + ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (unsigned char *)wcol->inner); + + /* text shadow */ + BLF_enable(fontid, BLF_SHADOW); + BLF_shadow(fontid, 3, (const float[4]){1.0f, 1.0f, 1.0f, 0.25f}); + BLF_shadow_offset(fontid, 0, -1); +} + static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect) { uiWidgetBase wtb; const float rad = 0.25f * U.widget_unit; unsigned char col[4]; - + /* state copy! */ wt->wcol = *(wt->wcol_theme); @@ -3431,12 +3586,17 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType * /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */ but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* make mask to draw over image */ UI_GetThemeColor3ubv(TH_BACK, col); - glColor3ubv(col); - + immUniformColor3ubv(col); + round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad); - widgetbase_outline(&wtb); + widgetbase_outline(&wtb, pos); + + immUnbindProgram(); } /* outline */ @@ -3498,6 +3658,11 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) wt.draw = widget_roundbut_exec; break; + case UI_WTYPE_TAB: + wt.custom = widget_tab; + wt.wcol_theme = &btheme->tui.wcol_tab; + break; + case UI_WTYPE_TOOLTIP: wt.wcol_theme = &btheme->tui.wcol_tooltip; wt.draw = widget_menu_back; @@ -3760,7 +3925,11 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct if (but->block->flag & UI_BLOCK_LOOP) wt->wcol_theme = &btheme->tui.wcol_menu_back; break; - + + case UI_BTYPE_TAB: + wt = widget_type(UI_WTYPE_TAB); + break; + case UI_BTYPE_BUT_TOGGLE: case UI_BTYPE_TOGGLE: case UI_BTYPE_TOGGLE_N: @@ -3962,15 +4131,21 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) wt->draw(&wt->wcol, rect, 0, 0); if (block) { + float draw_color[4]; + unsigned char *color = (unsigned char *)wt->wcol.text; + + draw_color[0] = ((float)color[0]) / 255.0f; + draw_color[1] = ((float)color[1]) / 255.0f; + draw_color[2] = ((float)color[2]) / 255.0f; + draw_color[3] = 1.0f; + if (block->flag & UI_BLOCK_CLIPTOP) { /* XXX no scaling for UI here yet */ - glColor3ubv((unsigned char *)wt->wcol.text); - UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't'); + UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't', draw_color); } if (block->flag & UI_BLOCK_CLIPBOTTOM) { /* XXX no scaling for UI here yet */ - glColor3ubv((unsigned char *)wt->wcol.text); - UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v'); + UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v', draw_color); } } } @@ -3988,33 +4163,21 @@ static void draw_disk_shaded( float y1, y2; float fac; unsigned char r_col[4]; + unsigned int pos, col; - glBegin(GL_TRIANGLE_STRIP); - - s = sinf(start); - c = cosf(start); - - y1 = s * radius_int; - y2 = s * radius_ext; - + Gwn_VertFormat *format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); if (shaded) { - fac = (y1 + radius_ext) * radius_ext_scale; - round_box_shade_col4_r(r_col, col1, col2, fac); - - glColor4ubv(r_col); + col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); } - - glVertex2f(c * radius_int, s * radius_int); - - if (shaded) { - fac = (y2 + radius_ext) * radius_ext_scale; - round_box_shade_col4_r(r_col, col1, col2, fac); - - glColor4ubv(r_col); + else { + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv((unsigned char *)col1); } - glVertex2f(c * radius_ext, s * radius_ext); - for (i = 1; i < subd; i++) { + immBegin(GWN_PRIM_TRI_STRIP, subd * 2); + for (i = 0; i < subd; i++) { float a; a = start + ((i) / (float)(subd - 1)) * angle; @@ -4026,20 +4189,20 @@ static void draw_disk_shaded( if (shaded) { fac = (y1 + radius_ext) * radius_ext_scale; round_box_shade_col4_r(r_col, col1, col2, fac); - - glColor4ubv(r_col); + immAttrib4ubv(col, r_col); } - glVertex2f(c * radius_int, s * radius_int); + immVertex2f(pos, c * radius_int, s * radius_int); if (shaded) { fac = (y2 + radius_ext) * radius_ext_scale; round_box_shade_col4_r(r_col, col1, col2, fac); - - glColor4ubv(r_col); + immAttrib4ubv(col, r_col); } - glVertex2f(c * radius_ext, s * radius_ext); + immVertex2f(pos, c * radius_ext, s * radius_ext); } - glEnd(); + immEnd(); + + immUnbindProgram(); } void ui_draw_pie_center(uiBlock *block) @@ -4058,8 +4221,8 @@ void ui_draw_pie_center(uiBlock *block) float angle = atan2f(pie_dir[1], pie_dir[0]); float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4; - glPushMatrix(); - glTranslatef(cx, cy, 0.0f); + gpuPushMatrix(); + gpuTranslate2f(cx, cy); glEnable(GL_BLEND); if (btheme->tui.wcol_pie_menu.shaded) { @@ -4068,8 +4231,7 @@ void ui_draw_pie_center(uiBlock *block) draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true); } else { - glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner); - draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, NULL, NULL, false); + draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner, NULL, false); } if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) { @@ -4079,25 +4241,34 @@ void ui_draw_pie_center(uiBlock *block) draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, col1, col2, true); } else { - glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner_sel); - draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, NULL, NULL, false); + draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner_sel, NULL, false); } } - glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.outline); - glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd); - glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv((unsigned char *)btheme->tui.wcol_pie_menu.outline); + + imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_internal, subd); + imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_external, subd); + + immUnbindProgram(); if (U.pie_menu_confirm > 0 && !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) { float pie_confirm_radius = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm); float pie_confirm_external = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm + 7.0f); - glColor4ub(btheme->tui.wcol_pie_menu.text_sel[0], btheme->tui.wcol_pie_menu.text_sel[1], btheme->tui.wcol_pie_menu.text_sel[2], 64); - draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, NULL, NULL, false); + const char col[4] = {btheme->tui.wcol_pie_menu.text_sel[0], + btheme->tui.wcol_pie_menu.text_sel[1], + btheme->tui.wcol_pie_menu.text_sel[2], + 64}; + + draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, col, NULL, false); } glDisable(GL_BLEND); - glPopMatrix(); + gpuPopMatrix(); } @@ -4181,8 +4352,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); } - glColor4ubv((unsigned char *)wt->wcol.text); - UI_fontstyle_draw(fstyle, rect, drawstr); + UI_fontstyle_draw(fstyle, rect, drawstr, (unsigned char *)wt->wcol.text); } /* part text right aligned */ @@ -4190,7 +4360,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic if (cpoin) { fstyle->align = UI_STYLE_TEXT_RIGHT; rect->xmax = _rect.xmax - 5; - UI_fontstyle_draw(fstyle, rect, cpoin + 1); + UI_fontstyle_draw(fstyle, rect, cpoin + 1, (unsigned char *)wt->wcol.text); *cpoin = UI_SEP_CHAR; } } @@ -4248,8 +4418,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int BLI_strncpy(drawstr, name, sizeof(drawstr)); UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); - glColor4ubv((unsigned char *)wt->wcol.text); - UI_fontstyle_draw(fstyle, &trect, drawstr); + UI_fontstyle_draw(fstyle, &trect, drawstr, (unsigned char *)wt->wcol.text); } } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index d12e7cc036b..2eae452debb 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -53,6 +53,8 @@ #include "BIF_gl.h" +#include "BLF_api.h" + #include "UI_interface.h" #include "UI_interface_icons.h" @@ -665,6 +667,17 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case TH_AXIS_Z: cp = btheme->tui.zaxis; break; + case TH_MANIPULATOR_HI: + cp = btheme->tui.manipulator_hi; break; + case TH_MANIPULATOR_PRIMARY: + cp = btheme->tui.manipulator_primary; break; + case TH_MANIPULATOR_SECONDARY: + cp = btheme->tui.manipulator_secondary; break; + case TH_MANIPULATOR_A: + cp = btheme->tui.manipulator_a; break; + case TH_MANIPULATOR_B: + cp = btheme->tui.manipulator_b; break; + case TH_INFO_SELECTED: cp = ts->info_selected; break; @@ -835,6 +848,15 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space) rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255); } +static void ui_theme_space_init_manipulator_colors(bTheme *btheme) +{ + rgba_char_args_set(btheme->tui.manipulator_hi, 255, 255, 255, 255); + rgba_char_args_set(btheme->tui.manipulator_primary, 222, 255, 13, 255); + rgba_char_args_set(btheme->tui.manipulator_secondary, 0, 255, 255, 255); + rgba_char_args_set(btheme->tui.manipulator_a, 23, 127, 23, 255); + rgba_char_args_set(btheme->tui.manipulator_b, 127, 23, 23, 255); +} + /** * initialize default theme * \note: when you add new colors, created & saved themes need initialized @@ -875,6 +897,9 @@ void ui_theme_init_default(void) /* common (new) variables */ ui_theme_init_new(btheme); + /* Manipulator. */ + ui_theme_space_init_manipulator_colors(btheme); + /* space view3d */ rgba_char_args_set_fl(btheme->tv3d.back, 0.225, 0.225, 0.225, 1.0); rgba_char_args_set(btheme->tv3d.text, 0, 0, 0, 255); @@ -1272,25 +1297,35 @@ void UI_ThemeColor4(int colorid) cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); glColor4ubv(cp); - } /* set the color with offset for shades */ void UI_ThemeColorShade(int colorid, int offset) { - int r, g, b; + unsigned char col[4]; + UI_GetThemeColorShade4ubv(colorid, offset, col); + glColor4ubv(col); +} + +void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) +{ + int r, g, b, a; const unsigned char *cp; cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); - r = offset + (int) cp[0]; + r = coloffset + (int) cp[0]; CLAMP(r, 0, 255); - g = offset + (int) cp[1]; + g = coloffset + (int) cp[1]; CLAMP(g, 0, 255); - b = offset + (int) cp[2]; + b = coloffset + (int) cp[2]; CLAMP(b, 0, 255); - glColor4ub(r, g, b, cp[3]); + a = alphaoffset + (int) cp[3]; + CLAMP(a, 0, 255); + + glColor4ub(r, g, b, a); } -void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) + +void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]) { int r, g, b, a; const unsigned char *cp; @@ -1304,7 +1339,11 @@ void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) CLAMP(b, 0, 255); a = alphaoffset + (int) cp[3]; CLAMP(a, 0, 255); - glColor4ub(r, g, b, a); + + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = a; } void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]) @@ -1320,6 +1359,19 @@ void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned c col[2] = floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); } +void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3]) +{ + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + r_col[0] = ((1.0f - fac) * cp1[0] + fac * cp2[0]) / 255.0f; + r_col[1] = ((1.0f - fac) * cp1[1] + fac * cp2[1]) / 255.0f; + r_col[2] = ((1.0f - fac) * cp1[2] + fac * cp2[2]) / 255.0f; +} + /* blend between to theme colors, and set it */ void UI_ThemeColorBlend(int colorid1, int colorid2, float fac) { @@ -1372,6 +1424,12 @@ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int off glColor4ub(r, g, b, a); } +void UI_FontThemeColor(int fontid, int colorid) +{ + unsigned char color[4]; + UI_GetThemeColor4ubv(colorid, color); + BLF_color4ubv(fontid, color); +} /* get individual values, not scaled */ float UI_GetThemeValuef(int colorid) @@ -1470,6 +1528,111 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]) col[2] = b; } +void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3]) +{ + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + + float blend[3]; + blend[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]); + blend[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]); + blend[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); + + F3TOCHAR3(blend, col); +} + +void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4]) +{ + int r, g, b; + const unsigned char *cp; + + cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + r = offset + (int) cp[0]; + CLAMP(r, 0, 255); + g = offset + (int) cp[1]; + CLAMP(g, 0, 255); + b = offset + (int) cp[2]; + CLAMP(b, 0, 255); + + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = cp[3]; +} + +void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]) +{ + int r, g, b, a; + const unsigned char *cp; + + cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + + r = coloffset + (int) cp[0]; + CLAMP(r, 0, 255); + g = coloffset + (int) cp[1]; + CLAMP(g, 0, 255); + b = coloffset + (int) cp[2]; + CLAMP(b, 0, 255); + a = alphaoffset + (int) cp[3]; + CLAMP(b, 0, 255); + + col[0] = ((float)r) / 255.0f; + col[1] = ((float)g) / 255.0f; + col[2] = ((float)b) / 255.0f; + col[3] = ((float)a) / 255.0f; +} + +void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3]) +{ + int r, g, b; + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + + r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]); + CLAMP(r, 0, 255); + g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]); + CLAMP(g, 0, 255); + b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); + CLAMP(b, 0, 255); + + col[0] = ((float)r) / 255.0f; + col[1] = ((float)g) / 255.0f; + col[2] = ((float)b) / 255.0f; +} + +void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]) +{ + int r, g, b, a; + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + + r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]); + CLAMP(r, 0, 255); + g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]); + CLAMP(g, 0, 255); + b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); + CLAMP(b, 0, 255); + a = offset + floorf((1.0f - fac) * cp1[3] + fac * cp2[3]); + CLAMP(a, 0, 255); + + col[0] = ((float)r) / 255.0f; + col[1] = ((float)g) / 255.0f; + col[2] = ((float)b) / 255.0f; + col[3] = ((float)a) / 255.0f; +} + /* get the color, in char pointer */ void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]) { @@ -1658,11 +1821,9 @@ void init_userdef_do_versions(void) U.savetime = 1; // XXX error(STRINGIFY(BLENDER_STARTUP_FILE)" is buggy, please consider removing it.\n"); } - /* transform widget settings */ - if (U.tw_hotspot == 0) { - U.tw_hotspot = 14; - U.tw_size = 25; /* percentage of window size */ - U.tw_handlesize = 16; /* percentage of widget radius */ + if (U.manipulator_size == 0) { + U.manipulator_size = 75; + U.manipulator_flag |= USER_MANIPULATOR_DRAW; } if (U.pad_rot_angle == 0.0f) U.pad_rot_angle = 15.0f; @@ -2500,9 +2661,6 @@ void init_userdef_do_versions(void) if (!USER_VERSION_ATLEAST(269, 9)) { bTheme *btheme; - - U.tw_size = U.tw_size * 5.0f; - /* Action Editor (and NLA Editor) - Keyframe Colors */ /* Graph Editor - larger vertex size defaults */ for (btheme = U.themes.first; btheme; btheme = btheme->next) { @@ -2776,13 +2934,35 @@ void init_userdef_do_versions(void) U.uiflag |= USER_LOCK_CURSOR_ADJUST; } + if (!USER_VERSION_ATLEAST(280, 1)) { + /* interface_widgets.c */ + struct uiWidgetColors wcol_tab = { + {255, 255, 255, 255}, + {83, 83, 83, 255}, + {114, 114, 114, 255}, + {90, 90, 90, 255}, + + {0, 0, 0, 255}, + {0, 0, 0, 255}, + + 0, + 0, 0 + }; + + for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { + btheme->tui.wcol_tab = wcol_tab; + } + } + /** * Include next version bump. * * (keep this block even if it becomes empty). */ - { - + if (((bTheme *)U.themes.first)->tui.manipulator_hi[3] == 0) { + for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { + ui_theme_space_init_manipulator_colors(btheme); + } } if (U.pixelsize == 0.0f) @@ -2791,11 +2971,8 @@ void init_userdef_do_versions(void) if (U.image_draw_method == 0) U.image_draw_method = IMAGE_DRAW_METHOD_2DTEXTURE; - // keep the following until the new audaspace is default to be built with -#ifdef WITH_SYSTEM_AUDASPACE // we default to the first audio device U.audiodevice = 0; -#endif /* funny name, but it is GE stuff, moves userdef stuff to engine */ // XXX space_set_commmandline_options(); diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 38432395a17..a94ef0d1d5b 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -49,11 +49,11 @@ #include "BKE_screen.h" #include "BKE_global.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "WM_api.h" -#include "BIF_gl.h" - #include "BLF_api.h" #include "ED_screen.h" @@ -1100,9 +1100,6 @@ void UI_view2d_view_ortho(View2D *v2d) /* set matrix on all appropriate axes */ wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax); - - /* XXX is this necessary? */ - glLoadIdentity(); } /** @@ -1130,9 +1127,6 @@ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis) wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, ar->winy - yofs); else wmOrtho2(-xofs, ar->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs); - - /* XXX is this necessary? */ - glLoadIdentity(); } @@ -1144,7 +1138,7 @@ void UI_view2d_view_restore(const bContext *C) int height = BLI_rcti_size_y(&ar->winrct) + 1; wmOrtho2(0.0f, (float)width, 0.0f, (float)height); - glLoadIdentity(); + gpuLoadIdentity(); // ED_region_pixelspace(CTX_wm_region(C)); } @@ -1298,12 +1292,45 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) { float vec1[2], vec2[2]; int a, step; + int vertical_minor_step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC), + horizontal_major_step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC); + unsigned char grid_line_color[3]; /* check for grid first, as it may not exist */ if (grid == NULL) return; - glBegin(GL_LINES); + /* Count the needed vertices for the gridlines */ + unsigned vertex_count = 0; + if (flag & V2D_VERTICAL_LINES) { + /* vertical lines */ + vertex_count += 2 * vertical_minor_step; /* minor gridlines */ + vertex_count += 2 * (vertical_minor_step + 2); /* major gridlines */ + } + if (flag & V2D_HORIZONTAL_LINES) { + /* horizontal lines */ + vertex_count += 2 * (horizontal_major_step + 1); /* major gridlines */ + + /* fine lines */ + if (flag & V2D_HORIZONTAL_FINELINES) + vertex_count += 2 * (horizontal_major_step + 1); + } + /* axes */ + if (flag & V2D_HORIZONTAL_AXIS) + vertex_count += 2; + if (flag & V2D_VERTICAL_AXIS) + vertex_count += 2; + + /* If there is nothing to render, exit early */ + if (vertex_count == 0) + return; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, vertex_count); /* vertical lines */ if (flag & V2D_VERTICAL_LINES) { @@ -1313,24 +1340,31 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec2[1] = v2d->cur.ymax; /* minor gridlines */ - step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC); - UI_ThemeColor(TH_GRID); - - for (a = 0; a < step; a++) { - glVertex2fv(vec1); - glVertex2fv(vec2); - - vec2[0] = vec1[0] += grid->dx; + step = vertical_minor_step; + if (step != 0) { + UI_GetThemeColor3ubv(TH_GRID, grid_line_color); + + for (a = 0; a < step; a++) { + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); + + vec2[0] = vec1[0] += grid->dx; + } } /* major gridlines */ vec2[0] = vec1[0] -= 0.5f * grid->dx; - UI_ThemeColorShade(TH_GRID, 16); + + UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color); step++; for (a = 0; a <= step; a++) { - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); vec2[0] = vec1[0] -= grid->dx; } @@ -1343,12 +1377,15 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec1[0] = grid->startx; vec2[0] = v2d->cur.xmax; - step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC); - - UI_ThemeColor(TH_GRID); + step = horizontal_major_step; + + UI_GetThemeColor3ubv(TH_GRID, grid_line_color); + for (a = 0; a <= step; a++) { - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); vec2[1] = vec1[1] += grid->dy; } @@ -1358,10 +1395,12 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) step++; if (flag & V2D_HORIZONTAL_FINELINES) { - UI_ThemeColorShade(TH_GRID, 16); + UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color); for (a = 0; a < step; a++) { - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); vec2[1] = vec1[1] -= grid->dy; } @@ -1369,7 +1408,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) } /* Axes are drawn as darker lines */ - UI_ThemeColorShade(TH_GRID, -50); + UI_GetThemeColorShade3ubv(TH_GRID, -50, grid_line_color); /* horizontal axis */ if (flag & V2D_HORIZONTAL_AXIS) { @@ -1377,8 +1416,10 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec2[0] = v2d->cur.xmax; vec1[1] = vec2[1] = 0.0f; - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); } /* vertical axis */ @@ -1387,91 +1428,157 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec2[1] = v2d->cur.ymax; vec1[0] = vec2[0] = 0.0f; - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); } - glEnd(); + immEnd(); + immUnbindProgram(); } /* Draw a constant grid in given 2d-region */ void UI_view2d_constant_grid_draw(View2D *v2d, float step) { - float start; - - UI_ThemeColorShade(TH_BACK, -10); + float start_x, start_y; + int count_x, count_y; - start = v2d->cur.xmin - (float)fmod(v2d->cur.xmin, step); + start_x = v2d->cur.xmin; + if (start_x < 0.0) + start_x += -(float)fmod(v2d->cur.xmin, step); + else + start_x += (step - (float)fmod(v2d->cur.xmin, step)); + + if (start_x > v2d->cur.xmax) + count_x = 0; + else + count_x = (v2d->cur.xmax - start_x) / step + 1; + + start_y = v2d->cur.ymin; + if (start_y < 0.0) + start_y += -(float)fmod(v2d->cur.ymin, step); + else + start_y += (step - (float)fabs(fmod(v2d->cur.ymin, step))); + + if (start_y > v2d->cur.ymax) + count_y = 0; + else + count_y = (v2d->cur.ymax - start_y) / step + 1; - glBegin(GL_LINES); - for (; start < v2d->cur.xmax; start += step) { - glVertex2f(start, v2d->cur.ymin); - glVertex2f(start, v2d->cur.ymax); - } + if (count_x > 0 || count_y > 0) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + float theme_color[3]; - start = v2d->cur.ymin - (float)fmod(v2d->cur.ymin, step); - for (; start < v2d->cur.ymax; start += step) { - glVertex2f(v2d->cur.xmin, start); - glVertex2f(v2d->cur.xmax, start); - } + UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, count_x * 2 + count_y * 2 + 4); + + immAttrib3fv(color, theme_color); + for (int i = 0; i < count_x ; start_x += step, i++) { + immVertex2f(pos, start_x, v2d->cur.ymin); + immVertex2f(pos, start_x, v2d->cur.ymax); + } + + for (int i = 0; i < count_y; start_y += step, i++) { + immVertex2f(pos, v2d->cur.xmin, start_y); + immVertex2f(pos, v2d->cur.xmax, start_y); + } - /* X and Y axis */ - UI_ThemeColorShade(TH_BACK, -18); - glVertex2f(0.0f, v2d->cur.ymin); - glVertex2f(0.0f, v2d->cur.ymax); - glVertex2f(v2d->cur.xmin, 0.0f); - glVertex2f(v2d->cur.xmax, 0.0f); + /* X and Y axis */ + UI_GetThemeColorShade3fv(TH_BACK, -18, theme_color); + + immAttrib3fv(color, theme_color); + immVertex2f(pos, 0.0f, v2d->cur.ymin); + immVertex2f(pos, 0.0f, v2d->cur.ymax); + immVertex2f(pos, v2d->cur.xmin, 0.0f); + immVertex2f(pos, v2d->cur.xmax, 0.0f); - glEnd(); + immEnd(); + immUnbindProgram(); + } } /* Draw a multi-level grid in given 2d-region */ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels) { + /* Exit if there is nothing to draw */ + if (totlevels == 0) + return; + int offset = -10; float lstep = step; - int level; + unsigned char grid_line_color[3]; + + /* Make an estimate of at least how many vertices will be needed */ + unsigned vertex_count = 4; + vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1); + vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); glLineWidth(1.0f); - for (level = 0; level < totlevels; ++level) { - int i; - float start; - - UI_ThemeColorShade(colorid, offset); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBeginAtMost(GWN_PRIM_LINES, vertex_count); + + for (int level = 0; level < totlevels; ++level) { + UI_GetThemeColorShade3ubv(colorid, offset, grid_line_color); - i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep)); - start = i * lstep; + int i = (int)(v2d->cur.xmin / lstep); + if (v2d->cur.xmin > 0.0f) + i++; + float start = i * lstep; - glBegin(GL_LINES); for (; start < v2d->cur.xmax; start += lstep, ++i) { if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) continue; - glVertex2f(start, v2d->cur.ymin); - glVertex2f(start, v2d->cur.ymax); + + immSkipAttrib(color); + immVertex2f(pos, start, v2d->cur.ymin); + immAttrib3ubv(color, grid_line_color); + immVertex2f(pos, start, v2d->cur.ymax); } - i = (v2d->cur.ymin >= 0.0f ? -(int)(-v2d->cur.ymin / lstep) : (int)(v2d->cur.ymin / lstep)); + i = (int)(v2d->cur.ymin / lstep); + if (v2d->cur.ymin > 0.0f) + i++; start = i * lstep; for (; start < v2d->cur.ymax; start += lstep, ++i) { if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) continue; - glVertex2f(v2d->cur.xmin, start); - glVertex2f(v2d->cur.xmax, start); + + immSkipAttrib(color); + immVertex2f(pos, v2d->cur.xmin, start); + immAttrib3ubv(color, grid_line_color); + immVertex2f(pos, v2d->cur.xmax, start); } - /* X and Y axis */ - UI_ThemeColorShade(colorid, offset - 8); - glVertex2f(0.0f, v2d->cur.ymin); - glVertex2f(0.0f, v2d->cur.ymax); - glVertex2f(v2d->cur.xmin, 0.0f); - glVertex2f(v2d->cur.xmax, 0.0f); - - glEnd(); - lstep *= level_size; offset -= 6; } + + /* X and Y axis */ + UI_GetThemeColorShade3ubv(colorid, -18 + ((totlevels - 1) * -6), grid_line_color); + + immSkipAttrib(color); + immVertex2f(pos, 0.0f, v2d->cur.ymin); + immAttrib3ubv(color, grid_line_color); + immVertex2f(pos, 0.0f, v2d->cur.ymax); + + immSkipAttrib(color); + immVertex2f(pos, v2d->cur.xmin, 0.0f); + immAttrib3ubv(color, grid_line_color); + immVertex2f(pos, v2d->cur.xmax, 0.0f); + + immEnd(); + immUnbindProgram(); } /* the price we pay for not exposting structs :( */ @@ -1693,6 +1800,10 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v Scene *scene = CTX_data_scene(C); rcti vert, hor; int scroll = view2d_scroll_mapped(v2d->scroll); + unsigned char scrollers_back_color[4]; + + /* Color for scrollbar backs */ + UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color); /* make copies of rects for less typing */ vert = vs->vert; @@ -1704,7 +1815,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v uiWidgetColors wcol = btheme->tui.wcol_scroll; rcti slider; int state; - unsigned char col[4]; slider.xmin = vs->hor_min; slider.xmax = vs->hor_max; @@ -1728,16 +1838,23 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v } /* clean rect behind slider, but not with transparent background */ - UI_GetThemeColor4ubv(TH_BACK, col); - if (col[3] == 255) { - glColor3ub(col[0], col[1], col[2]); - glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax); + if (scrollers_back_color[3] == 255) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv(scrollers_back_color); + immRecti(pos, v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax); + + immUnbindProgram(); } UI_draw_widget_scroll(&wcol, &hor, &slider, state); /* scale indicators */ if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) { + const int font_id = BLF_default(); View2DGrid *grid = vs->grid; float fac, dfac, fac2, val; @@ -1752,7 +1869,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v dfac = dfac * BLI_rcti_size_x(&hor); /* set starting value, and text color */ - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(font_id, TH_TEXT); val = grid->startx; /* if we're clamping to whole numbers only, make sure entries won't be repeated */ @@ -1764,7 +1881,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v } if (vs->xunits == V2D_UNIT_FRAMES) grid->powerx = 1; - + /* draw numbers in the appropriate range */ if (dfac > 0.0f) { float h = 0.1f * UI_UNIT_Y + (float)(hor.ymin); @@ -1805,7 +1922,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v uiWidgetColors wcol = btheme->tui.wcol_scroll; rcti slider; int state; - unsigned char col[4]; slider.xmin = vert.xmin; slider.xmax = vert.xmax; @@ -1829,10 +1945,16 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v } /* clean rect behind slider, but not with transparent background */ - UI_GetThemeColor4ubv(TH_BACK, col); - if (col[3] == 255) { - glColor3ub(col[0], col[1], col[2]); - glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax); + if (scrollers_back_color[3] == 255) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv(scrollers_back_color); + immRecti(pos, v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax); + + immUnbindProgram(); } UI_draw_widget_scroll(&wcol, &vert, &slider, state); @@ -1856,7 +1978,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v dfac = dfac * BLI_rcti_size_y(&vert); /* set starting value, and text color */ - UI_ThemeColor(TH_TEXT); + const int font_id = BLF_default(); + UI_FontThemeColor(font_id, TH_TEXT); val = grid->starty; /* if vertical clamping (to whole numbers) is used (i.e. in Sequencer), apply correction */ @@ -1865,9 +1988,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v /* draw vertical steps */ if (dfac > 0.0f) { - - BLF_rotation_default(M_PI_2); - BLF_enable_default(BLF_ROTATION); + BLF_rotation(font_id, M_PI_2); + BLF_enable(font_id, BLF_ROTATION); for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) { @@ -1878,7 +2000,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v scroll_printstr(scene, (float)(vert.xmax) - 2.0f, fac, val, grid->powery, vs->yunits, 'v'); } - BLF_disable_default(BLF_ROTATION); + BLF_disable(font_id, BLF_ROTATION); } } } @@ -2400,7 +2522,8 @@ void UI_view2d_text_cache_draw(ARegion *ar) int col_pack_prev = 0; /* investigate using BLF_ascender() */ - const float default_height = g_v2d_strings ? BLF_height_default("28", 3) : 0.0f; + const int font_id = BLF_default(); + const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f; wmOrtho2_region_pixelspace(ar); @@ -2411,7 +2534,7 @@ void UI_view2d_text_cache_draw(ARegion *ar) if (yofs < 1) yofs = 1; if (col_pack_prev != v2s->col.pack) { - glColor3ubv(v2s->col.ub); + BLF_color3ubv(font_id, v2s->col.ub); col_pack_prev = v2s->col.pack; } @@ -2419,11 +2542,11 @@ void UI_view2d_text_cache_draw(ARegion *ar) BLF_draw_default((float)(v2s->mval[0] + xofs), (float)(v2s->mval[1] + yofs), 0.0, v2s->str, BLF_DRAW_STR_DUMMY_MAX); else { - BLF_clipping_default(v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4); - BLF_enable_default(BLF_CLIPPING); + BLF_enable(font_id, BLF_CLIPPING); + BLF_clipping(font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4); BLF_draw_default(v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX); - BLF_disable_default(BLF_CLIPPING); + BLF_disable(font_id, BLF_CLIPPING); } } g_v2d_strings = NULL; @@ -2432,11 +2555,6 @@ void UI_view2d_text_cache_draw(ARegion *ar) BLI_memarena_free(g_v2d_strings_arena); g_v2d_strings_arena = NULL; } - - // glMatrixMode(GL_PROJECTION); - // glPopMatrix(); - // glMatrixMode(GL_MODELVIEW); - // glPopMatrix(); } |