diff options
Diffstat (limited to 'source/blender/editors/interface/interface_widgets.c')
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 1181 |
1 files changed, 837 insertions, 344 deletions
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 9a1d47e0154..5a210d01f27 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,10 @@ #include "interface_intern.h" #include "GPU_basic_shader.h" +#include "GPU_batch.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #ifdef WITH_INPUT_IME # include "WM_types.h" @@ -79,6 +80,7 @@ enum { #define UI_BUT_UPDATE_DELAY ((void)0) #define UI_BUT_UNDO ((void)0) + /* ************** widget base functions ************** */ /** * - in: roundbox codes for corner types and radius @@ -98,6 +100,8 @@ enum { typedef struct uiWidgetTrias { unsigned int tot; + int type; + float size, center[2]; float vec[16][2]; const unsigned int (*index)[3]; @@ -105,21 +109,24 @@ typedef struct uiWidgetTrias { } uiWidgetTrias; /* max as used by round_box__edges */ +/* Make sure to change widget_base_vert.glsl accordingly. */ #define WIDGET_CURVE_RESOLU 9 #define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4) typedef struct uiWidgetBase { - + /* TODO remove these completely */ int totvert, halfwayvert; float outer_v[WIDGET_SIZE_MAX][2]; float inner_v[WIDGET_SIZE_MAX][2]; float inner_uv[WIDGET_SIZE_MAX][2]; - bool draw_inner, draw_outline, draw_emboss, draw_shadedir; + bool draw_inner, draw_outline, draw_emboss; uiWidgetTrias tria1; uiWidgetTrias tria2; - + + /* Widget shader parameters, must match the shader layout. */ + uiWidgetBaseParameters uniform_params; } uiWidgetBase; /** uiWidgetType: for time being only for visual appearance, @@ -206,52 +213,300 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} /** \} */ -/* ************************************************* */ +/* **************** Batch creations ****************** */ +/** + * In order to speed up UI drawing we create some batches that are then + * modified by specialized shaders to draw certain elements really fast. + * TODO: find a better place. Maybe it's own file? + **/ + +/* offset in triavec[] in shader per type */ +static const int tria_ofs[ROUNDBOX_TRIA_MAX] = {0, 0, 6, 22, 28}; +static const int tria_vcount[ROUNDBOX_TRIA_MAX] = {0, 3, 16, 3, 6}; + +static struct { + Gwn_Batch *roundbox_widget[ROUNDBOX_TRIA_MAX]; + + Gwn_Batch *roundbox_simple; + Gwn_Batch *roundbox_simple_aa; + Gwn_Batch *roundbox_simple_outline; + Gwn_Batch *roundbox_shadow; -void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3) + Gwn_VertFormat format; + uint vflag_id; +} g_ui_batch_cache = {{0}}; + +static Gwn_VertFormat *vflag_format(void) { - float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}}; - float color[4]; - int j; - - glEnable(GL_BLEND); - glGetFloatv(GL_CURRENT_COLOR, color); - color[3] *= 0.125f; - glColor4fv(color); + if (g_ui_batch_cache.format.attrib_ct == 0) { + Gwn_VertFormat *format = &g_ui_batch_cache.format; + g_ui_batch_cache.vflag_id = GWN_vertformat_attr_add(format, "vflag", GWN_COMP_U32, 1, GWN_FETCH_INT); + } + return &g_ui_batch_cache.format; +} - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, tri_arr); +#define INNER 0 +#define OUTLINE 1 +#define EMBOSS 2 +#define NO_AA 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); +static void set_roundbox_vertex_data( + Gwn_VertBufRaw *vflag_step, uint32_t d) +{ + uint32_t *data = GWN_vertbuf_raw_step(vflag_step); + *data = d; +} + +static uint32_t set_roundbox_vertex( + Gwn_VertBufRaw *vflag_step, + int corner_id, int corner_v, int jit_v, bool inner, bool emboss, int color) +{ + uint32_t *data = GWN_vertbuf_raw_step(vflag_step); + *data = corner_id; + *data |= corner_v << 2; + *data |= jit_v << 6; + *data |= color << 12; + *data |= (inner) ? (1 << 10) : 0; /* is inner vert */ + *data |= (emboss) ? (1 << 11) : 0; /* is emboss vert */ + return *data; +} + +static uint32_t set_tria_vertex( + Gwn_VertBufRaw *vflag_step, + int tria_type, int tria_v, int tria_id, int jit_v) +{ + uint32_t *data = GWN_vertbuf_raw_step(vflag_step); + if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS, ROUNDBOX_TRIA_MENU)) { + tria_v += tria_id * 3; + } + *data = tria_ofs[tria_type] + tria_v; + *data |= jit_v << 6; + *data |= (tria_id == 0) ? (1 << 10) : 0; /* is first tria */ + *data |= 1 << 14; /* is tria vert */ + return *data; +} + +static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data) +{ + const int tria_num = (tria == ROUNDBOX_TRIA_CHECK) ? 1 : 2; + /* for each tria */ + for (int t = 0; t < tria_num; ++t) { + for (int j = 0; j < WIDGET_AA_JITTER; j++) { + /* restart */ + set_roundbox_vertex_data(vflag_step, last_data); + set_tria_vertex(vflag_step, tria, 0, t, j); + for (int v = 0; v < tria_vcount[tria]; v++) { + last_data = set_tria_vertex(vflag_step, tria, v, t, j); + } + } } +} - glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); +Gwn_Batch *ui_batch_roundbox_widget_get(int tria) +{ + if (g_ui_batch_cache.roundbox_widget[tria] == NULL) { + uint32_t last_data; + Gwn_VertBufRaw vflag_step; + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format()); + int vcount = WIDGET_SIZE_MAX; /* inner */ + vcount += 2; /* restart */ + vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */ + vcount += 2; /* restart */ + vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */ + if (tria) { + vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */ + if (tria != ROUNDBOX_TRIA_CHECK) { + vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */ + } + } + GWN_vertbuf_data_alloc(vbo, vcount); + GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step); + /* Inner */ + for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) { + for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) { + last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER); + last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER); + } + } + /* restart */ + set_roundbox_vertex_data(&vflag_step, last_data); + set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE); + /* Outlines */ + for (int j = 0; j < WIDGET_AA_JITTER; j++) { + for (int c = 0; c < 4; c++) { + for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { + set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE); + set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE); + } + } + /* Close the loop. */ + set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE); + last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE); + } + /* restart */ + set_roundbox_vertex_data(&vflag_step, last_data); + set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS); + /* Emboss */ + bool rev = false; /* go back and forth : avoid degenerate triangle (but beware of backface cull) */ + for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) { + for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) { + int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0; + int end = WIDGET_CURVE_RESOLU; + for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) { + set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS); + last_data = set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS); + } + } + } + if (tria) { + roundbox_batch_add_tria(&vflag_step, tria, last_data); + } + g_ui_batch_cache.roundbox_widget[tria] = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]); + } + return g_ui_batch_cache.roundbox_widget[tria]; } -void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha) +Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased) { - float color[4]; - int j; - - glEnable(GL_BLEND); - glGetFloatv(GL_CURRENT_COLOR, color); - if (use_alpha) { - color[3] = 0.5f; + Gwn_Batch **batch = NULL; + + if (filled) { + if (antialiased) + batch = &g_ui_batch_cache.roundbox_simple_aa; + else + batch = &g_ui_batch_cache.roundbox_simple; } - 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 { + if (antialiased) + BLI_assert(0); /* Use GL_LINE_SMOOTH instead!!: */ + else + batch = &g_ui_batch_cache.roundbox_simple_outline; + } + + if (*batch == NULL) { + uint32_t last_data; + Gwn_VertBufRaw vflag_step; + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format()); + int vcount = WIDGET_SIZE_MAX; + vcount += (filled) ? 2 : 0; + vcount *= (antialiased) ? WIDGET_AA_JITTER : 1; + GWN_vertbuf_data_alloc(vbo, vcount); + GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step); + + if (filled) { + for (int j = 0; j < WIDGET_AA_JITTER; j++) { + if (!antialiased) { + j = NO_AA; + } + /* restart */ + set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, INNER); + for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) { + for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) { + last_data = set_roundbox_vertex(&vflag_step, c1, a1, j, true, false, INNER); + last_data = set_roundbox_vertex(&vflag_step, c2, a2, j, true, false, INNER); + } + } + /* restart */ + set_roundbox_vertex_data(&vflag_step, last_data); + if (!antialiased) { + break; + } + } + *batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + else { + for (int j = 0; j < WIDGET_AA_JITTER; j++) { + if (!antialiased) { + j = NO_AA; + } + for (int c = 0; c < 4; c++) { + for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { + set_roundbox_vertex(&vflag_step, c, a, j, true, false, INNER); + } + } + if (!antialiased) { + break; + } + } + *batch = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + + gpu_batch_presets_register(*batch); + } + return *batch; +} + +Gwn_Batch *ui_batch_roundbox_shadow_get(void) +{ + if (g_ui_batch_cache.roundbox_shadow == NULL) { + uint32_t last_data; + Gwn_VertBufRaw vflag_step; + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format()); + int vcount = (WIDGET_SIZE_MAX + 1) * 2 + 2 + WIDGET_SIZE_MAX; + GWN_vertbuf_data_alloc(vbo, vcount); + GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step); + + for (int c = 0; c < 4; c++) { + for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { + set_roundbox_vertex(&vflag_step, c, a, NO_AA, true, false, INNER); + set_roundbox_vertex(&vflag_step, c, a, NO_AA, false, false, INNER); + } + } + /* close loop */ + last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER); + last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, false, false, INNER); + /* restart */ + set_roundbox_vertex_data(&vflag_step, last_data); + set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER); + /* filled */ + for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) { + for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) { + set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER); + set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER); + } + } + g_ui_batch_cache.roundbox_shadow = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + gpu_batch_presets_register(g_ui_batch_cache.roundbox_shadow); + } + return g_ui_batch_cache.roundbox_shadow; +} + +#undef INNER +#undef OUTLINE +#undef EMBOSS +#undef NO_AA + +/* ************************************************* */ + +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 draw_color[4]; + + copy_v4_v4(draw_color, color); + draw_color[3] *= 0.125f; + + glEnable(GL_BLEND); + + 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 (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]); } + immEnd(); + + immUnbindProgram(); + glDisable(GL_BLEND); } @@ -260,11 +515,15 @@ static void widget_init(uiWidgetBase *wtb) wtb->totvert = wtb->halfwayvert = 0; wtb->tria1.tot = 0; wtb->tria2.tot = 0; + wtb->tria1.type = ROUNDBOX_TRIA_NONE; + wtb->tria1.size = 0; + wtb->tria2.size = 0; wtb->draw_inner = true; wtb->draw_outline = true; wtb->draw_emboss = true; - wtb->draw_shadedir = true; + + wtb->uniform_params.shade_dir = 1.0f; } /* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */ @@ -371,7 +630,18 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re if (2.0f * (radi + 1.0f) > minsize) radi = 0.5f * minsize - U.pixelsize; - + + wt->uniform_params.rad = rad; + wt->uniform_params.radi = radi; + wt->uniform_params.facxi = facxi; + wt->uniform_params.facyi = facyi; + wt->uniform_params.round_corners[0] = (roundboxalign & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f; + wt->uniform_params.round_corners[1] = (roundboxalign & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f; + wt->uniform_params.round_corners[2] = (roundboxalign & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f; + wt->uniform_params.round_corners[3] = (roundboxalign & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f; + BLI_rctf_rcti_copy(&wt->uniform_params.rect, rect); + BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi); + /* mult */ for (a = 0; a < WIDGET_CURVE_RESOLU; a++) { veci[a][0] = radi * cornervec[a][0]; @@ -521,18 +791,20 @@ static void shape_preset_init_trias_ex( /* center position and size */ centx = (float)rect->xmin + 0.4f * minsize; centy = (float)rect->ymin + 0.5f * minsize; - sizex = sizey = -0.5f * triasize * minsize; + tria->size = sizex = sizey = -0.5f * triasize * minsize; if (where == 'r') { centx = (float)rect->xmax - 0.4f * minsize; sizex = -sizex; } else if (where == 't') { + centx = (float)rect->xmin + 0.5f * minsize; centy = (float)rect->ymax - 0.5f * minsize; sizey = -sizey; i2 = 0; i1 = 1; } else if (where == 'b') { + centx = (float)rect->xmin + 0.5f * minsize; sizex = -sizex; i2 = 0; i1 = 1; } @@ -542,12 +814,16 @@ static void shape_preset_init_trias_ex( tria->vec[a][1] = sizey * verts[a][i2] + centy; } + tria->center[0] = centx; + tria->center[1] = centy; + tria->tot = tris_tot; tria->index = tris; } static void shape_preset_init_number_arrows(uiWidgetTrias *tria, const rcti *rect, float triasize, char where) { + tria->type = ROUNDBOX_TRIA_ARROWS; shape_preset_init_trias_ex( tria, rect, triasize, where, g_shape_preset_number_arrow_vert, ARRAY_SIZE(g_shape_preset_number_arrow_vert), @@ -564,29 +840,48 @@ static void shape_preset_init_hold_action(uiWidgetTrias *tria, const rcti *rect, static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where) { + tria->type = ROUNDBOX_TRIA_SCROLL; shape_preset_init_trias_ex( tria, rect, triasize, where, g_shape_preset_scroll_circle_vert, ARRAY_SIZE(g_shape_preset_scroll_circle_vert), 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_aa(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); + for (int k = 0; k < WIDGET_AA_JITTER; k++) { + for (int i = 0; i < tria->tot; ++i) + for (int j = 0; j < 3; ++j) + immVertex2f(pos, + tria->vec[tria->index[i][j]][0] + jit[k][0], + tria->vec[tria->index[i][j]][1] + jit[k][1]); + } +} + +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) { float centx, centy, size; int a; + tria->type = ROUNDBOX_TRIA_MENU; /* center position and size */ - centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect); - centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect); - size = 0.4f * BLI_rcti_size_y(rect); + tria->center[0] = centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect); + tria->center[1] = centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect); + tria->size = size = 0.4f * BLI_rcti_size_y(rect); for (a = 0; a < 6; a++) { tria->vec[a][0] = size * g_shape_preset_menu_arrow_vert[a][0] + centx; @@ -601,11 +896,12 @@ static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rc { float centx, centy, size; int a; + tria->type = ROUNDBOX_TRIA_CHECK; /* center position and size */ - centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect); - centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect); - size = 0.5f * BLI_rcti_size_y(rect); + tria->center[0] = centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect); + tria->center[1] = centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect); + tria->size = size = 0.5f * BLI_rcti_size_y(rect); for (a = 0; a < 6; a++) { tria->vec[a][0] = size * g_shape_preset_checkmark_vert[a][0] + centx; @@ -655,180 +951,206 @@ static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert, copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]); } -static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2][2]) -{ - int a; - for (a = 0; a < totvert; a++) { - triangle_strip[a * 2][0] = wtb->outer_v[a][0]; - triangle_strip[a * 2][1] = wtb->outer_v[a][1]; - triangle_strip[a * 2 + 1][0] = wtb->outer_v[a][0]; - triangle_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f; - } -} - -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) +static void widgetbase_set_uniform_colors_ubv( + uiWidgetBase *wtb, + const unsigned char *col1, const unsigned char *col2, + const unsigned char *outline, + const unsigned char *emboss, + const unsigned char *tria, + const bool alpha_check) { - int j, a; - - glEnable(GL_BLEND); + wtb->uniform_params.do_alpha_check = (float)alpha_check; + rgba_float_args_set_ch(wtb->uniform_params.color_inner1, col1[0], col1[1], col1[2], col1[3]); + rgba_float_args_set_ch(wtb->uniform_params.color_inner2, col2[0], col2[1], col2[2], col2[3]); + rgba_float_args_set_ch(wtb->uniform_params.color_outline, outline[0], outline[1], outline[2], outline[3]); + rgba_float_args_set_ch(wtb->uniform_params.color_emboss, emboss[0], emboss[1], emboss[2], emboss[3]); + rgba_float_args_set_ch(wtb->uniform_params.color_tria, tria[0], tria[1], tria[2], tria[3]); +} - /* backdrop non AA */ - if (wtb->draw_inner) { - BLI_assert(wtb->totvert != 0); - if (wcol->shaded == 0) { - if (wcol->alpha_check) { - float inner_v_half[WIDGET_SIZE_MAX][2]; - float x_mid = 0.0f; /* used for dumb clamping of values */ +/* keep in sync with shader */ +#define MAX_WIDGET_BASE_BATCH 6 - /* 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); +struct { + Gwn_Batch *batch; /* Batch type */ + uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]; + int count; + bool enabled; +} g_widget_base_batch = {0}; - /* 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); +void UI_widgetbase_draw_cache_flush(void) +{ + float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f}; - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + if (g_widget_base_batch.count == 0) + return; - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + Gwn_Batch *batch = g_widget_base_batch.batch; + if (g_widget_base_batch.count == 1) { + /* draw single */ + GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); + GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)g_widget_base_batch.params); + GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params); + GWN_batch_draw(batch); + } + else { + GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE_INST); + GWN_batch_uniform_4fv_array(batch, "parameters", 11 * MAX_WIDGET_BASE_BATCH, (float *)g_widget_base_batch.params); + GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params); + gpuBindMatrices(batch->interface); + GWN_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true); + GWN_batch_program_use_end(batch); + } + g_widget_base_batch.count = 0; +} - /* alpha fill */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +void UI_widgetbase_draw_cache_begin(void) +{ + BLI_assert(g_widget_base_batch.enabled == false); + g_widget_base_batch.enabled = true; +} - glColor4ubv((unsigned char *)wcol->inner); +void UI_widgetbase_draw_cache_end(void) +{ + BLI_assert(g_widget_base_batch.enabled == true); + g_widget_base_batch.enabled = false; - for (a = 0; a < wtb->totvert; a++) { - x_mid += wtb->inner_v[a][0]; - } - x_mid /= wtb->totvert; + glEnable(GL_BLEND); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + UI_widgetbase_draw_cache_flush(); - /* 1/2 solid color */ - glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255); + glDisable(GL_BLEND); +} - 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]; - } +static void draw_widgetbase_batch(Gwn_Batch *batch, uiWidgetBase *wtb) +{ + wtb->uniform_params.tria1_size = wtb->tria1.size; + wtb->uniform_params.tria2_size = wtb->tria2.size; + copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center); + copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center); + + if (g_widget_base_batch.enabled) { + if (g_widget_base_batch.batch == NULL) { + g_widget_base_batch.batch = ui_batch_roundbox_widget_get(ROUNDBOX_TRIA_ARROWS); + } - glVertexPointer(2, GL_FLOAT, 0, inner_v_half); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); - glDisableClientState(GL_VERTEX_ARRAY); - } - else { - /* simple fill */ - glColor4ubv((unsigned char *)wcol->inner); + /* draw multi */ + if (batch != g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE] && + batch != g_widget_base_batch.batch) + { + /* issue previous calls before changing batch type. */ + UI_widgetbase_draw_cache_flush(); + g_widget_base_batch.batch = batch; + } - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); - glDisableClientState(GL_VERTEX_ARRAY); - } + /* No need to change batch if tria is not visible. Just scale it to 0. */ + if (batch == g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE]) { + wtb->uniform_params.tria1_size = wtb->uniform_params.tria2_size = 0; } - else { - char col1[4], col2[4]; - unsigned char col_array[WIDGET_SIZE_MAX * 4]; - unsigned char *col_pt = col_array; - - 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]); - } + g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params; + g_widget_base_batch.count++; - 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); + if (g_widget_base_batch.count == MAX_WIDGET_BASE_BATCH) { + UI_widgetbase_draw_cache_flush(); } } - - /* for each AA step */ - if (wtb->draw_outline) { - BLI_assert(wtb->totvert != 0); - float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */ - float triangle_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */ + else { + float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f}; + /* draw single */ + GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); + GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&wtb->uniform_params); + GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params); + GWN_batch_draw(batch); + } +} - const unsigned char tcol[4] = {wcol->outline[0], - wcol->outline[1], - wcol->outline[2], - wcol->outline[3] / WIDGET_AA_JITTER}; - unsigned char emboss[4]; +static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) +{ + unsigned char inner_col1[4] = {0}; + unsigned char inner_col2[4] = {0}; + unsigned char emboss_col[4] = {0}; + unsigned char outline_col[4] = {0}; + unsigned char tria_col[4] = {0}; + /* For color widget. */ + bool alpha_check = (wcol->alpha_check && (wcol->shaded == 0)); - widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip); + glEnable(GL_BLEND); - if (wtb->draw_emboss) { - widget_verts_to_triangle_strip_open(wtb, wtb->halfwayvert, triangle_strip_emboss); - UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss); + /* backdrop non AA */ + if (wtb->draw_inner) { + if (wcol->shaded == 0) { + /* simple fill */ + inner_col1[0] = inner_col2[0] = (unsigned char)wcol->inner[0]; + inner_col1[1] = inner_col2[1] = (unsigned char)wcol->inner[1]; + inner_col1[2] = inner_col2[2] = (unsigned char)wcol->inner[2]; + inner_col1[3] = inner_col2[3] = (unsigned char)wcol->inner[3]; } + else { + /* gradient fill */ + shadecolors4((char *)inner_col1, (char *)inner_col2, wcol->inner, wcol->shadetop, wcol->shadedown); + } + } - glEnableClientState(GL_VERTEX_ARRAY); + if (wtb->draw_outline) { + outline_col[0] = wcol->outline[0]; + outline_col[1] = wcol->outline[1]; + outline_col[2] = wcol->outline[2]; + outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER; - for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); - - /* outline */ - glColor4ubv(tcol); - - glVertexPointer(2, GL_FLOAT, 0, triangle_strip); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 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); - } - } - - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + /* emboss bottom shadow */ + if (wtb->draw_emboss) { + UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss_col); } + } - glDisableClientState(GL_VERTEX_ARRAY); + if (wtb->tria1.type != ROUNDBOX_TRIA_NONE) + { + tria_col[0] = wcol->item[0]; + tria_col[1] = wcol->item[1]; + tria_col[2] = wcol->item[2]; + tria_col[3] = (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER); } - - /* decoration */ - if (wtb->tria1.tot || wtb->tria2.tot) { + + /* Draw everything in one drawcall */ + if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] || alpha_check) { + widgetbase_set_uniform_colors_ubv(wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, alpha_check); + + Gwn_Batch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type); + draw_widgetbase_batch(roundbox_batch, wtb); + } + + /* DEPRECATED: should be removed at some point. */ + if ((wtb->tria1.type == ROUNDBOX_TRIA_NONE) && + (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); - - /* for each AA step */ - for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); - if (wtb->tria1.tot) { - shape_preset_draw_trias(&wtb->tria1); - } - if (wtb->tria2.tot) { - shape_preset_draw_trias(&wtb->tria2); - } + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(tcol); - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + /* for each AA step */ + immBegin(GWN_PRIM_TRIS, (wtb->tria1.tot + wtb->tria2.tot) * 3 * WIDGET_AA_JITTER); + if (wtb->tria1.tot){ + shape_preset_draw_trias_aa(&wtb->tria1, pos); + } + if (wtb->tria2.tot) { + shape_preset_draw_trias_aa(&wtb->tria2, pos); } + immEnd(); + + immUnbindProgram(); } glDisable(GL_BLEND); @@ -1284,6 +1606,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) { @@ -1296,8 +1619,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) { @@ -1314,7 +1637,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); } } } @@ -1388,6 +1711,10 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b int selsta_draw, selwidth_draw; if (drawstr[0] != 0) { + /* We are drawing on top of widget bases. Flush cache. */ + glEnable(GL_BLEND); + UI_widgetbase_draw_cache_flush(); + glDisable(GL_BLEND); if (but->selsta >= but->ofs) { selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selsta - but->ofs); @@ -1398,11 +1725,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(); } } @@ -1424,14 +1756,23 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b else { t = 0; } + /* We are drawing on top of widget bases. Flush cache. */ + glEnable(GL_BLEND); + UI_widgetbase_draw_cache_flush(); + glDisable(GL_BLEND); - 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 @@ -1490,43 +1831,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); + } } } } @@ -1536,7 +1880,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); } } @@ -1660,6 +2004,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 @@ -1674,6 +2021,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 }; @@ -1918,6 +2267,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}, @@ -1940,6 +2302,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; @@ -2012,6 +2375,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); @@ -2025,6 +2390,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; @@ -2070,7 +2437,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); } @@ -2081,6 +2450,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); } } @@ -2198,23 +2569,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) @@ -2251,20 +2623,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, @@ -2304,18 +2677,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 */ @@ -2346,11 +2718,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); @@ -2358,25 +2737,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); } @@ -2386,7 +2772,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; @@ -2440,9 +2827,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; @@ -2500,22 +2892,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) @@ -2591,8 +2990,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 */ @@ -2641,6 +3043,11 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect) widgetbase_draw(&wtb, &wcol_tmp); + /* We are drawing on top of widget bases. Flush cache. */ + glEnable(GL_BLEND); + UI_widgetbase_draw_cache_flush(); + glDisable(GL_BLEND); + /* cursor */ x = rect->xmin + 0.5f * BLI_rcti_size_x(rect); y = rect->ymin + v * BLI_rcti_size_y(rect); @@ -2660,12 +3067,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 ***************** */ @@ -2741,11 +3158,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; @@ -2753,13 +3173,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(); } } @@ -2781,7 +3205,7 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s else rad = 0.5f * BLI_rcti_size_x(rect); - wtb.draw_shadedir = (horizontal) ? true : false; + wtb.uniform_params.shade_dir = (horizontal) ? 1.0f : 0.0; /* draw back part, colors swapped and shading inverted */ if (horizontal) @@ -2941,15 +3365,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); } } @@ -3062,7 +3487,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); @@ -3093,7 +3518,6 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat } widgetbase_draw(&wtb, wcol); - if (but->a1 == UI_PALETTE_COLOR && ((Palette *)but->rnapoin.id.data)->active_color == (int)but->a2) { float width = rect->xmax - rect->xmin; float height = rect->ymax - rect->ymin; @@ -3101,13 +3525,23 @@ 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(); + + /* We are drawing on top of widget bases. Flush cache. */ + glEnable(GL_BLEND); + UI_widgetbase_draw_cache_flush(); + glDisable(GL_BLEND); + + 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(); } } @@ -3169,6 +3603,8 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), /* decoration */ shape_preset_trias_from_rect_menu(&wtb.tria1, rect); + /* copy size and center to 2nd tria */ + wtb.tria2 = wtb.tria1; widgetbase_draw(&wtb, wcol); @@ -3423,12 +3859,55 @@ 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); + + /* We are drawing on top of widget bases. Flush cache. */ + glEnable(GL_BLEND); + UI_widgetbase_draw_cache_flush(); + glDisable(GL_BLEND); + + /* 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); @@ -3438,12 +3917,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 */ @@ -3505,6 +3989,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; @@ -3767,7 +4256,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: @@ -3969,15 +4462,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); } } } @@ -3995,33 +4494,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; @@ -4033,20 +4520,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) @@ -4065,8 +4552,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) { @@ -4075,8 +4562,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)) { @@ -4086,25 +4572,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(); } @@ -4188,8 +4683,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 */ @@ -4197,7 +4691,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; } } @@ -4255,8 +4749,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); } } |