Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Sun, 1 Jul 2018 18:15:21 +0000 (20:15 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 1 Jul 2018 18:15:21 +0000 (20:15 +0200)
15 files changed:
1  2 
intern/cycles/blender/blender_camera.cpp
intern/cycles/blender/blender_object.cpp
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_draw.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_ops.c
source/blender/editors/interface/interface_panel.c
source/blender/editors/interface/interface_query.c
source/blender/editors/interface/interface_region_search.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_utils.c
source/blender/editors/interface/interface_widgets.c
source/blender/editors/interface/view2d.c
source/blender/editors/interface/view2d_ops.c

index da1135da00ab01470531b122d93f40bb85aeadfe,50cd1c544c48f5e532bb39b40030cffd17d43bc0..3e724fd5c5cfa711c40865cd2907e6e5c34543b5
@@@ -81,84 -78,15 +81,86 @@@ 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_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[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}};
 +      uiWidgetBaseParameters widget_params = {
 +              .recti.xmin = minx, .recti.ymin = miny,
 +              .recti.xmax = maxx, .recti.ymax = maxy,
 +              .radi = rad,
 +              .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
 +              .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
 +              .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
 +              .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
 +              .color_inner1[0] = color[0], .color_inner2[0] = color[0],
 +              .color_inner1[1] = color[1], .color_inner2[1] = color[1],
 +              .color_inner1[2] = color[2], .color_inner2[2] = color[2],
 +              .color_inner1[3] = color[3], .color_inner2[3] = color[3],
 +              .alpha_discard = 1.0f,
 +      };
 +
 +      GPU_blend(true);
 +
 +      if (filled) {
 +              /* plain antialiased filled box */
 +              widget_params.color_inner1[3] *= 0.125f;
 +              widget_params.color_inner2[3] *= 0.125f;
 +
 +              /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
 +               * If it has been scaled, then it's no longer valid. */
 +              Gwn_Batch *batch = ui_batch_roundbox_get(filled, true);
 +              GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
 +              GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
 +              GWN_batch_draw(batch);
 +      }
 +      else {
 +              /* plain antialiased unfilled box */
 +              GPU_line_smooth(true);
 +
 +              Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
 +              GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
 +              GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
 +              GWN_batch_draw(batch);
 +
 +              GPU_line_smooth(false);
 +      }
 +
 +      GPU_blend(false);
 +}
 +
 +void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4])
 +{
 +#if 0
+       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);
@@@ -263,24 -158,17 +265,26 @@@ static void round_box_shade_col(unsigne
  /* 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}};
 +#if 0
 -              {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
+       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);
  /* 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}};
+       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}};
++              {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 */
  
        /* 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);
 -      }
 +      int ofs_y = 4 * U.pixelsize;
  
 -      /* set antialias line */
 -      glEnable(GL_LINE_SMOOTH);
 -      glEnable(GL_BLEND);
 +      Gwn_VertFormat *format = immVertexFormat();
 +      unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
  
 -      UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
 +      immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +      immUniformColor4fv(color);
  
 -      glDisable(GL_BLEND);
 -      glDisable(GL_LINE_SMOOTH);
 +      immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
 +      immUnbindProgram();
  }
  
 -/* (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);
 -}
 +/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
  
 -void UI_draw_text_underline(int pos_x, int pos_y, int len, int height)
 +/* 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},
++              {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)
  {
  
        /* 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);
 -      glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin + rect->ymin, w, h);
 +      int scissor[4];
 +      GPU_scissor_geti(scissor);
 +      GPU_scissor(rect->xmin, rect->ymin, w, h);
  #endif
  
 -      glEnable(GL_BLEND);
 -      glColor4f(0.0, 0.0, 0.0, 0.0);
 +      GPU_blend(true);
  
        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);
++      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);
 +      GPU_blend(false);
  
  #if 0
        // restore scissortest
@@@ -793,28 -574,22 +800,29 @@@ void ui_draw_but_HISTOGRAM(ARegion *UNU
        float w = BLI_rctf_size_x(&rect);
        float h = BLI_rctf_size_y(&rect) * hist->ymax;
  
 -      glEnable(GL_BLEND);
 -      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +      GPU_blend(true);
 +      GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_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];
 -      glGetIntegerv(GL_VIEWPORT, scissor);
 -      glScissor(ar->winrct.xmin + (rect.xmin - 1),
 -                ar->winrct.ymin + (rect.ymin - 1),
 -                (rect.xmax + 1) - (rect.xmin - 1),
 -                (rect.ymax + 1) - (rect.ymin - 1));
 -
 -      glColor4f(1.f, 1.f, 1.f, 0.08f);
 +      int scissor[4];
 +      GPU_scissor_geti(scissor);
-       GPU_scissor((rect.xmin - 1),
-                 (rect.ymin - 1),
-                 (rect.xmax + 1) - (rect.xmin - 1),
-                 (rect.ymax + 1) - (rect.ymin - 1));
++      GPU_scissor(
++              (rect.xmin - 1),
++              (rect.ymin - 1),
++              (rect.xmax + 1) - (rect.xmin - 1),
++              (rect.ymax + 1) - (rect.ymin - 1));
 +
 +      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;
@@@ -914,25 -661,22 +922,26 @@@ void ui_draw_but_WAVEFORM(ARegion *UNUS
                }
        }
  
 -      glEnable(GL_BLEND);
 -      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +      /* Flush text cache before changing scissors. */
 +      BLF_batch_draw_flush();
  
 -      UI_ThemeColor4(TH_PREVIEW_BACK);
 +      GPU_blend(true);
 +      GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
 +
 +      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);
 -      glScissor(ar->winrct.xmin + (rect.xmin - 1),
 -                ar->winrct.ymin + (rect.ymin - 1),
 -                (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 */
 +      GPU_scissor_geti(scissor);
-       GPU_scissor((rect.xmin - 1),
-                 (rect.ymin - 1),
-                 (rect.xmax + 1) - (rect.xmin - 1),
-                 (rect.ymax + 1) - (rect.ymin - 1));
++      GPU_scissor(
++              (rect.xmin - 1),
++              (rect.ymin - 1),
++              (rect.xmax + 1) - (rect.xmin - 1),
++              (rect.ymax + 1) - (rect.ymin - 1));
 +
 +      /* 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);
@@@ -1188,62 -905,44 +1197,63 @@@ void ui_draw_but_VECTORSCOPE(ARegion *U
  
        float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
  
 -      glEnable(GL_BLEND);
 -      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +      GPU_blend(true);
 +      GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_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];
 -      glGetIntegerv(GL_VIEWPORT, scissor);
 -      glScissor(ar->winrct.xmin + (rect.xmin - 1),
 -                ar->winrct.ymin + (rect.ymin - 1),
 -                (rect.xmax + 1) - (rect.xmin - 1),
 -                (rect.ymax + 1) - (rect.ymin - 1));
 -
 -      glColor4f(1.f, 1.f, 1.f, 0.08f);
 +      int scissor[4];
 +      GPU_scissor_geti(scissor);
-       GPU_scissor((rect.xmin - 1),
-                 (rect.ymin - 1),
-                 (rect.xmax + 1) - (rect.xmin - 1),
-                 (rect.ymax + 1) - (rect.ymin - 1));
++      GPU_scissor(
++              (rect.xmin - 1),
++              (rect.ymin - 1),
++              (rect.xmax + 1) - (rect.xmin - 1),
++              (rect.ymax + 1) - (rect.ymin - 1));
 +
 +      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 */
@@@ -1583,30 -1279,20 +1593,32 @@@ static void ui_draw_but_curve_grid(unsi
        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;
 +
++      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)
  {
-       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);
 -      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)
        CurveMap *cuma = &cumap->cm[cumap->cur];
  
        /* need scissor test, curve can draw outside of boundary */
 -      GLint scissor[4];
 -      glGetIntegerv(GL_VIEWPORT, scissor);
 +      int scissor[4];
 +      GPU_scissor_geti(scissor);
        rcti scissor_new = {
 -              .xmin = ar->winrct.xmin + rect->xmin,
 -              .ymin = ar->winrct.ymin + rect->ymin,
 -              .xmax = ar->winrct.xmin + rect->xmax,
 -              .ymax = ar->winrct.ymin + rect->ymax
 +              .xmin = rect->xmin,
 +              .ymin = rect->ymin,
 +              .xmax = rect->xmax,
 +              .ymax = rect->ymax
        };
 -      BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
 -      glScissor(scissor_new.xmin,
 -                scissor_new.ymin,
 -                BLI_rcti_size_x(&scissor_new),
 -                BLI_rcti_size_y(&scissor_new));
 +      rcti scissor_region = {0, ar->winx, 0, ar->winy};
 +      BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
-       GPU_scissor(scissor_new.xmin,
-                 scissor_new.ymin,
-                 BLI_rcti_size_x(&scissor_new),
-                 BLI_rcti_size_y(&scissor_new));
++      GPU_scissor(
++              scissor_new.xmin,
++              scissor_new.ymin,
++              BLI_rcti_size_x(&scissor_new),
++              BLI_rcti_size_y(&scissor_new));
  
        /* calculate offset and zoom */
        float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&cumap->curr);
        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));
++                      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 */
@@@ -1842,21 -1505,21 +1856,22 @@@ void ui_draw_but_TRACKPREVIEW(ARegion *
        int width  = BLI_rctf_size_x(&rect) + 1;
        int height = BLI_rctf_size_y(&rect);
  
 -      glEnable(GL_BLEND);
 -      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +      GPU_blend(true);
 +      GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
  
        /* need scissor test, preview image can draw outside of boundary */
 -      GLint scissor[4];
 -      glGetIntegerv(GL_VIEWPORT, scissor);
 -      glScissor(ar->winrct.xmin + (rect.xmin - 1),
 -                ar->winrct.ymin + (rect.ymin - 1),
 -                (rect.xmax + 1) - (rect.xmin - 1),
 -                (rect.ymax + 1) - (rect.ymin - 1));
 +      int scissor[4];
 +      GPU_scissor_geti(scissor);
-       GPU_scissor((rect.xmin - 1),
-                 (rect.ymin - 1),
-                 (rect.xmax + 1) - (rect.xmin - 1),
-                 (rect.ymax + 1) - (rect.ymin - 1));
++      GPU_scissor(
++              (rect.xmin - 1),
++              (rect.ymin - 1),
++              (rect.xmax + 1) - (rect.xmin - 1),
++              (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;
        }
  
                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);
 -                      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);
 +                      gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
-                       GPU_scissor(rect.xmin,
-                                 rect.ymin,
-                                 BLI_rctf_size_x(&rect),
-                                 BLI_rctf_size_y(&rect));
++                      GPU_scissor(
++                              rect.xmin,
++                              rect.ymin,
++                              BLI_rctf_size_x(&rect),
++                              BLI_rctf_size_y(&rect));
 +
 +                      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;
        }
@@@ -1976,25 -1631,25 +1993,26 @@@ void ui_draw_but_NODESOCKET(ARegion *ar
            0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
        };
  
 -      GLint scissor[4];
 +      int scissor[4];
  
        /* need scissor test, can draw outside of boundary */
 -      glGetIntegerv(GL_VIEWPORT, scissor);
 +      GPU_scissor_geti(scissor);
  
        rcti scissor_new = {
 -              .xmin = ar->winrct.xmin + recti->xmin,
 -              .ymin = ar->winrct.ymin + recti->ymin,
 -              .xmax = ar->winrct.xmin + recti->xmax,
 -              .ymax = ar->winrct.ymin + recti->ymax
 +              .xmin = recti->xmin,
 +              .ymin = recti->ymin,
 +              .xmax = recti->xmax,
 +              .ymax = recti->ymax
        };
  
 -      BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
 -      glScissor(scissor_new.xmin,
 -                scissor_new.ymin,
 -                BLI_rcti_size_x(&scissor_new),
 -                BLI_rcti_size_y(&scissor_new));
 +      rcti scissor_region = {0, ar->winx, 0, ar->winy};
  
 -      glColor4ubv(but->col);
 +      BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
-       GPU_scissor(scissor_new.xmin,
-                 scissor_new.ymin,
-                 BLI_rcti_size_x(&scissor_new),
-                 BLI_rcti_size_y(&scissor_new));
++      GPU_scissor(
++              scissor_new.xmin,
++              scissor_new.ymin,
++              BLI_rcti_size_x(&scissor_new),
++              BLI_rcti_size_y(&scissor_new));
  
        float x = 0.5f * (recti->xmin + recti->xmax);
        float y = 0.5f * (recti->ymin + recti->ymax);
index 062a7681372736f35b2a6824c2ca522a6f4c0643,e830d70e3088312708c72e9561473b2fc29f907f..4ff19d66bac372aeb32f899dab7afbcb13667359
@@@ -583,21 -540,10 +583,22 @@@ static void ui_item_array
                                RNA_property_boolean_get_array(ptr, prop, boolarr);
                        }
  
 +                      const char *str_buf = show_text ? str: "";
                        for (a = 0; a < len; a++) {
 -                              if (!icon_only) str[0] = RNA_property_array_item_char(prop, a);
 -                              if (boolarr) icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
 -                              but = uiDefAutoButR(block, ptr, prop, a, str, icon, 0, 0, w, UI_UNIT_Y);
 +                              int width_item;
 +
 +                              if (!icon_only && show_text) {
 +                                      str[0] = RNA_property_array_item_char(prop, a);
 +                              }
 +                              if (boolarr) {
 +                                      icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
 +                              }
 +
-                               width_item = (compact && type == PROP_BOOLEAN) ?
-                                                min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) : w;
++                              width_item = (
++                                      (compact && type == PROP_BOOLEAN) ?
++                                      min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) : w);
 +
 +                              but = uiDefAutoButR(block, ptr, prop, a, str_buf, icon, 0, 0, width_item, UI_UNIT_Y);
                                if (slider && but->type == UI_BTYPE_NUM)
                                        but->type = UI_BTYPE_NUM_SLIDER;
                                if (toggle && but->type == UI_BTYPE_CHECKBOX)
@@@ -773,14 -697,15 +774,15 @@@ static uiBut *ui_item_with_label
  
        if (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
                UI_block_layout_set_current(block, uiLayoutRow(sub, true));
 -              but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w - UI_UNIT_X, h);
 +              but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, prop_but_width - UI_UNIT_X, h);
  
                /* BUTTONS_OT_file_browse calls UI_context_active_but_prop_get_filebrowser */
-               uiDefIconButO(block, UI_BTYPE_BUT, subtype == PROP_DIRPATH ? "BUTTONS_OT_directory_browse" : "BUTTONS_OT_file_browse",
-                             WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
+               uiDefIconButO(
+                       block, UI_BTYPE_BUT, subtype == PROP_DIRPATH ? "BUTTONS_OT_directory_browse" : "BUTTONS_OT_file_browse",
+                       WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
        }
        else if (flag & UI_ITEM_R_EVENT) {
 -              but = uiDefButR_prop(block, UI_BTYPE_KEY_EVENT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL);
 +              but = uiDefButR_prop(block, UI_BTYPE_KEY_EVENT, 0, name, x, y, prop_but_width, h, ptr, prop, index, 0, 0, -1, -1, NULL);
        }
        else if (flag & UI_ITEM_R_FULL_EVENT) {
                if (RNA_struct_is_a(ptr->type, &RNA_KeyMapItem)) {
                                UI_but_flag_enable(but, UI_BUT_IMMEDIATE);
                }
        }
 -      else
 -              but = uiDefAutoButR(block, ptr, prop, index, (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY)) ? NULL : "", icon, x, y, w, h);
 +      else {
 +              const char *str = (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY)) ? NULL : "";
-               but = uiDefAutoButR(block, ptr, prop, index, str, icon,
-                                   x, y, prop_but_width, h);
++              but = uiDefAutoButR(
++                      block, ptr, prop, index, str, icon,
++                      x, y, prop_but_width, h);
 +      }
  
        UI_block_layout_set_current(block, layout);
        return but;
@@@ -1963,10 -1786,7 +1967,10 @@@ void ui_but_add_search(uiBut *but, Poin
                        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, 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... */
index 571c1327f78d202ed2cbabb4e8faa18db077f0d2,a1dbbfd037b8ba5ae2a2f40f18a3d15c6323d1b3..0f08f8c7ed98a7253d135b400fe74cfa10ca92d4
@@@ -334,216 -328,6 +334,217 @@@ static void UI_OT_unset_property_button
        ot->flag = OPTYPE_UNDO;
  }
  
-                             "'No-Operation', place holder preventing automatic override to ever affect the property"},
 +
 +/* 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",
-                                               &ptr, prop, operation, index, true, NULL, &created);
++       "'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;
 +
 +      UI_context_active_but_prop_get(C, &ptr, &prop, &index);
 +
 +      const int override_status = RNA_property_static_override_status(&ptr, prop, index);
 +
 +      return (ptr.data && prop && (override_status & RNA_OVERRIDE_STATUS_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(
-       ot->prop = RNA_def_enum(ot->srna, "type", override_type_items, UIOverride_Type_Replace,
-                               "Type", "Type of override operation");
++              &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))
 +{
 +#if 0  /* Disabled for now */
 +      return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
 +#else
 +      RNA_enum_set(op->ptr, "type", IDOVERRIDESTATIC_OP_REPLACE);
 +      return override_type_set_button_exec(C, op);
 +#endif
 +}
 +
 +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");
-                                                       oprop, NULL, NULL, index, index, false, &is_strict_find);
++      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 options are available for all data types... */
 +}
 +
 +
 +static int override_remove_button_poll(bContext *C)
 +{
 +      PointerRNA ptr;
 +      PropertyRNA *prop;
 +      int index;
 +
 +      UI_context_active_but_prop_get(C, &ptr, &prop, &index);
 +
 +      const int override_status = RNA_property_static_override_status(&ptr, prop, index);
 +
 +      return (ptr.data && ptr.id.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN));
 +}
 +
 +static int override_remove_button_exec(bContext *C, wmOperator *op)
 +{
 +      Main *bmain = CTX_data_main(C);
 +      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(bmain, &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(bmain, &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(
index 1e3a080c097072286dadbdf1b7ea94e6997c7e0f,744f6b3c4d0c307b066f090c042de712e1f3b845..8107254f30b01604eca4929923494ba78b6eee04
@@@ -530,55 -480,19 +530,56 @@@ static void ui_draw_panel_scalewidget(u
        dx = 0.5f * (xmax - xmin);
        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);
 +      GPU_blend(true);
 +      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();
 +
 +      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();
 +
 +      GPU_blend(false);
 +}
  
- static void immRectf_tris_color_ex(unsigned int pos, float x1, float y1, float x2, float y2,
-                               unsigned int col, const float color[3])
 -      glColor4ub(0, 0, 0, 50);
 -      fdrawline(xmin, ymin + 1, xmax, ymax + 1);
 -      fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1);
 -      glDisable(GL_BLEND);
++static void immRectf_tris_color_ex(
++        unsigned int pos, float x1, float y1, float x2, float y2,
++        unsigned int col, const float color[3])
 +{
 +      immAttrib4fv(col, color);
 +      immVertex2f(pos, x1, y1);
 +      immAttrib4fv(col, color);
 +      immVertex2f(pos, x2, y1);
 +      immAttrib4fv(col, color);
 +      immVertex2f(pos, x2, y2);
 +
 +      immAttrib4fv(col, color);
 +      immVertex2f(pos, x1, y1);
 +      immAttrib4fv(col, color);
 +      immVertex2f(pos, x2, y2);
 +      immAttrib4fv(col, color);
 +      immVertex2f(pos, x1, y2);
  }
 -static void ui_draw_panel_dragwidget(const rctf *rect)
 +
 +static void ui_draw_panel_dragwidget(unsigned int pos, unsigned int col, const rctf *rect)
  {
 -      unsigned char col_back[3], col_high[3], col_dark[3];
 +      float col_high[4], col_dark[4];
        const int col_tint = 84;
  
        const int px = (int)U.pixelsize;
                        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));
  
-                       immRectf_tris_color_ex(pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom,
-                                              col, col_dark);
-                       immRectf_tris_color_ex(pos, x_co - box_size, y_co, x_co, y_co + box_size,
-                                              col, col_high);
 -                      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);
++                      immRectf_tris_color_ex(
++                              pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom,
++                              col, col_dark);
++                      immRectf_tris_color_ex(
++                              pos, x_co - box_size, y_co, x_co, y_co + box_size,
++                              col, col_high);
                }
        }
 +      immEnd();
  }
  
 +/* For button layout next to label. */
 +void UI_panel_label_offset(uiBlock *block, int *x, int *y)
 +{
 +      Panel *panel = block->panel;
 +      uiStyle *style = UI_style_get_dpi();
 +      const bool is_subpanel = (panel->type && panel->type->parent);
 +
 +      *x = UI_UNIT_X * 1.1f;
 +      *y = (UI_UNIT_Y * 1.1f) + style->panelspace;
 +
 +      if (is_subpanel) {
 +              *x += 5.0f / block->aspect;
 +      }
 +}
  
  static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const rcti *rect, char dir)
  {
@@@ -750,38 -619,26 +753,39 @@@ void ui_draw_aligned_panel(uiStyle *sty
        if (show_pin)
  #endif
        {
 -              glEnable(GL_BLEND);
 +              GPU_blend(true);
-               UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), headrect.ymin + (5.0f / block->aspect),
-                                   (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
-                                   (block->aspect / UI_DPI_FAC), 1.0f);
+               UI_icon_draw_aspect(
+                       headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), headrect.ymin + (5.0f / block->aspect),
+                       (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
+                       (block->aspect / UI_DPI_FAC), 1.0f);
 -              glDisable(GL_BLEND);
 +              GPU_blend(false);
        }
  
 +
        /* horizontal title */
        if (is_closed_x == false) {
 -              ui_draw_aligned_panel_header(style, block, &headrect, 'h');
 -
 -              /* itemrect smaller */
 -              itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
 -              itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect);
 -              itemrect.ymin = headrect.ymin;
 -              itemrect.ymax = headrect.ymax;
 -
 -              BLI_rctf_scale(&itemrect, 0.7f);
 -              ui_draw_panel_dragwidget(&itemrect);
 +              ui_draw_aligned_panel_header(style, block, &titlerect, 'h');
 +
 +              if (show_drag) {
 +                      unsigned int col;
 +                      Gwn_VertFormat *format = immVertexFormat();
 +                      pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +                      col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
 +
 +                      /* itemrect smaller */
 +                      itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
 +                      itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect);
 +                      itemrect.ymin = headrect.ymin;
 +                      itemrect.ymax = headrect.ymax;
 +
 +                      BLI_rctf_scale(&itemrect, 0.7f);
 +                      immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
 +                      ui_draw_panel_dragwidget(pos, col, &itemrect);
 +                      immUnbindProgram();
 +
 +                      /* Restore format for the following draws. */
 +                      pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +              }
        }
  
        /* if the panel is minimized vertically:
@@@ -2004,19 -1755,22 +2008,22 @@@ void UI_panel_category_draw_all(ARegio
                if (is_active)
  #endif
                {
-                       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);
 -                      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);
++                              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 */
-                       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);
 -                      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);
++                              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) */
-                       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_tab_highlight : theme_col_tab_highlight_inactive);
 -                      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,
++                              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 */
index ec9d8eead4389c4092270136fe7e2eff0e84c228,bd4bb032717daf1576cc58036b7176c97134fee6..e9ad2c7c88f764cdf81f2f55a0c020ade8c85deb
@@@ -380,9 -265,47 +380,9 @@@ static uiBlock *id_search_menu(bContex
                }
        }
  
 -      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_p,
 -                      &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_p,
 -                      &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_p, &template_ui, template_ID_set_property_cb, active_item_ptr.data,
-                      template_ui.prv_rows, template_ui.prv_cols);
++              C, ar, id_search_cb_p, &template_ui, template_ID_set_property_cb, active_item_ptr.data,
++              template_ui.prv_rows, template_ui.prv_cols);
  }
  
  /************************ ID Template ***************************/
@@@ -573,68 -474,6 +574,74 @@@ static const char *template_id_context(
  }
  #endif
  
-       BLT_I18N_MSGID_MULTI_CTXT("New", BLT_I18NCONTEXT_DEFAULT,
-                                        BLT_I18NCONTEXT_ID_SCENE,
-                                        BLT_I18NCONTEXT_ID_OBJECT,
-                                        BLT_I18NCONTEXT_ID_MESH,
-                                        BLT_I18NCONTEXT_ID_CURVE,
-                                        BLT_I18NCONTEXT_ID_METABALL,
-                                        BLT_I18NCONTEXT_ID_MATERIAL,
-                                        BLT_I18NCONTEXT_ID_TEXTURE,
-                                        BLT_I18NCONTEXT_ID_IMAGE,
-                                        BLT_I18NCONTEXT_ID_LATTICE,
-                                        BLT_I18NCONTEXT_ID_LAMP,
-                                        BLT_I18NCONTEXT_ID_CAMERA,
-                                        BLT_I18NCONTEXT_ID_WORLD,
-                                        BLT_I18NCONTEXT_ID_SCREEN,
-                                        BLT_I18NCONTEXT_ID_TEXT,
 +static uiBut *template_id_def_new_but(
 +        uiBlock *block, const ID *id, const TemplateID *template_ui, StructRNA *type,
 +        const char * const newop, const bool editable, const bool id_open, const bool use_tab_but,
 +        int but_height)
 +{
 +      ID *idfrom = template_ui->ptr.id.data;
 +      uiBut *but;
 +      const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
 +      const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT;
 +
 +      /* i18n markup, does nothing! */
-       BLT_I18N_MSGID_MULTI_CTXT("New", BLT_I18NCONTEXT_ID_SPEAKER,
-                                        BLT_I18NCONTEXT_ID_SOUND,
-                                        BLT_I18NCONTEXT_ID_ARMATURE,
-                                        BLT_I18NCONTEXT_ID_ACTION,
-                                        BLT_I18NCONTEXT_ID_NODETREE,
-                                        BLT_I18NCONTEXT_ID_BRUSH,
-                                        BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
-                                        BLT_I18NCONTEXT_ID_GPENCIL,
-                                        BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
-                                        BLT_I18NCONTEXT_ID_WORKSPACE,
-                                        BLT_I18NCONTEXT_ID_LIGHTPROBE,
++      BLT_I18N_MSGID_MULTI_CTXT(
++              "New",
++              BLT_I18NCONTEXT_DEFAULT,
++              BLT_I18NCONTEXT_ID_SCENE,
++              BLT_I18NCONTEXT_ID_OBJECT,
++              BLT_I18NCONTEXT_ID_MESH,
++              BLT_I18NCONTEXT_ID_CURVE,
++              BLT_I18NCONTEXT_ID_METABALL,
++              BLT_I18NCONTEXT_ID_MATERIAL,
++              BLT_I18NCONTEXT_ID_TEXTURE,
++              BLT_I18NCONTEXT_ID_IMAGE,
++              BLT_I18NCONTEXT_ID_LATTICE,
++              BLT_I18NCONTEXT_ID_LAMP,
++              BLT_I18NCONTEXT_ID_CAMERA,
++              BLT_I18NCONTEXT_ID_WORLD,
++              BLT_I18NCONTEXT_ID_SCREEN,
++              BLT_I18NCONTEXT_ID_TEXT,
 +      );
-               but = uiDefIconTextButO(block, but_type, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN,
-                                       (id) ? "" : CTX_IFACE_(template_id_context(type), "New"), 0, 0, w, but_height, NULL);
++      BLT_I18N_MSGID_MULTI_CTXT(
++              "New",
++              BLT_I18NCONTEXT_ID_SPEAKER,
++              BLT_I18NCONTEXT_ID_SOUND,
++              BLT_I18NCONTEXT_ID_ARMATURE,
++              BLT_I18NCONTEXT_ID_ACTION,
++              BLT_I18NCONTEXT_ID_NODETREE,
++              BLT_I18NCONTEXT_ID_BRUSH,
++              BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
++              BLT_I18NCONTEXT_ID_GPENCIL,
++              BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
++              BLT_I18NCONTEXT_ID_WORKSPACE,
++              BLT_I18NCONTEXT_ID_LIGHTPROBE,
 +      );
 +
 +      if (newop) {
-               but = uiDefIconTextBut(block, but_type, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
-                                      0, 0, w, but_height, NULL, 0, 0, 0, 0, NULL);
++              but = uiDefIconTextButO(
++                      block, but_type, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN,
++                      (id) ? "" : CTX_IFACE_(template_id_context(type), "New"), 0, 0, w, but_height, NULL);
 +              UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
 +      }
 +      else {
++              but = uiDefIconTextBut(
++                      block, but_type, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
++                      0, 0, w, but_height, NULL, 0, 0, 0, 0, NULL);
 +              UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
 +      }
 +
 +      if ((idfrom && idfrom->lib) || !editable) {
 +              UI_but_flag_enable(but, UI_BUT_DISABLED);
 +      }
 +
 +#ifndef WITH_INTERNATIONAL
 +      UNUSED_VARS(type);
 +#endif
 +
 +      return but;
 +}
 +
  static void template_ID(
          bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, int flag,
          const char *newop, const char *openop, const char *unlinkop)
                                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, "
-                                                       "Shift + Click to create a static override"));
++                              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))
++                                      NULL, 0, 0, 0, 0,
++                                      TIP_("Direct linked library data-block, click to make local, "
++                                           "Shift + Click to create a 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_LOCAL));
 +                              }
                        }
 -
 -                      UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL));
 +              }
 +              else if (ID_IS_STATIC_OVERRIDE(id)) {
-                       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_("Static override of linked library data-block, click to make fully 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_("Static override of linked library data-block, click to make fully local"));
 +                      UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_OVERRIDE));
                }
  
                if (id->us > 1) {
        UI_block_align_end(block);
  }
  
-               const unsigned int but_width = UI_fontstyle_string_width(&style->widgetlabel, id->name + 2) + UI_UNIT_X +
-                                              (is_active ? ICON_DEFAULT_WIDTH_SCALE : 0);
 +static void template_ID_tabs(
 +        bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag,
 +        const char *newop, const char *UNUSED(openop), const char *unlinkop)
 +{
 +      const ARegion *region = CTX_wm_region(C);
 +      const PointerRNA active_ptr = RNA_property_pointer_get(&template->ptr, template->prop);
 +      const int but_align = (region->alignment == RGN_ALIGN_TOP) ? UI_BUT_ALIGN_DOWN : UI_BUT_ALIGN_TOP;
 +      const int but_height = UI_UNIT_Y * 1.1;
 +
 +      uiBlock *block = uiLayoutGetBlock(layout);
 +      uiStyle *style = UI_style_get_dpi();
 +
 +
 +      for (ID *id = template->idlb->first; id; id = id->next) {
 +              wmOperatorType *unlink_ot = WM_operatortype_find(unlinkop, false);
 +              const bool is_active = active_ptr.data == id;
++              const unsigned int but_width = (
++                      UI_fontstyle_string_width(&style->widgetlabel, id->name + 2) + UI_UNIT_X +
++                      (is_active ? ICON_DEFAULT_WIDTH_SCALE : 0));
 +              uiButTab *tab;
 +
 +              tab = (uiButTab *)uiDefButR_prop(
 +                      block, UI_BTYPE_TAB, 0, "", 0, 0, but_width, UI_UNIT_Y * 1.1,
 +                      &template->ptr, template->prop, 0, 0.0f,
 +                      sizeof(id->name) - 2, 0.0f, 0.0f, "");
 +              UI_but_funcN_set(&tab->but, template_ID_set_property_cb, MEM_dupallocN(template), id);
 +              tab->but.custom_data = (void *)id;
 +              tab->unlink_ot = unlink_ot;
 +
 +              if (is_active) {
 +                      UI_but_flag_enable(&tab->but, UI_BUT_VALUE_CLEAR);
 +              }
 +              UI_but_drawflag_enable(&tab->but, but_align);
 +      }
 +
 +      if (flag & UI_ID_ADD_NEW) {
 +              const bool editable = RNA_property_editable(&template->ptr, template->prop);
 +              uiBut *but;
 +
 +              if (active_ptr.type) {
 +                      type = active_ptr.type;
 +              }
 +
 +              but = template_id_def_new_but(block, active_ptr.data, template, type, newop, editable, flag & UI_ID_OPEN, true, but_height);
 +              UI_but_drawflag_enable(but, but_align);
 +      }
 +}
 +
  static void ui_template_id(
 -        uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
 -        const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols, int filter)
 +        uiLayout *layout, bContext *C,
 +        PointerRNA *ptr, const char *propname,
 +        const char *newop, const char *openop, const char *unlinkop,
 +        int flag, int prv_rows, int prv_cols, int filter, bool use_tabs)
  {
        TemplateID *template_ui;
        PropertyRNA *prop;
@@@ -1019,208 -842,6 +1036,209 @@@ void uiTemplateAnyID
        uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE);
  }
  
-       active_ptr = RNA_property_pointer_get(&template_search.search_data.target_ptr,
-                                             template_search.search_data.target_prop);
 +/********************* 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);
-                      C, region, ui_rna_collection_search_cb, &template_search,
-                      template_search_handle_cb, active_ptr.data,
-                      template_search.preview_rows, template_search.preview_cols);
++      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 ********************/
  
  /* ---------- */
@@@ -1454,13 -1080,13 +1475,15 @@@ static uiLayout *draw_modifier
                        }
                        else {
                                uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
--                              uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
--                                          0, "apply_as", MODIFIER_APPLY_DATA);
++                              uiItemEnumO(
++                                      row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
++                                      0, "apply_as", MODIFIER_APPLY_DATA);
  
                                if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
--                                      uiItemEnumO(row, "OBJECT_OT_modifier_apply",
--                                                  CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
--                                                  0, "apply_as", MODIFIER_APPLY_SHAPE);
++                                      uiItemEnumO(
++                                              row, "OBJECT_OT_modifier_apply",
++                                              CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
++                                              0, "apply_as", MODIFIER_APPLY_SHAPE);
                                }
                        }
  
index b81825eba6e753a6c369f2855c6cf016243b1ee3,a7de70629d10fb0e44d20b048b222b1ae956dc59..dbd65ade307669da85ecd4bd9ab9e70869c1bac1
@@@ -1690,11 -1307,12 +1694,12 @@@ static void widget_draw_text_ime_underl
                        ofs_x = 0;
                }
  
-               width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
-                                 ime_data->composite_len + but->pos - but->ofs);
+               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) {
                                ofs_x = 0;
                        }
  
-                       width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
-                                         sel_end + sel_start - but->ofs);
+                       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);
                }
        }
  }
@@@ -2421,30 -2265,31 +2428,31 @@@ static void widget_menu_back(uiWidgetCo
        wtb.draw_emboss = false;
        widgetbase_draw(&wtb, wcol);
  
 -      glDisable(GL_BLEND);
 +      GPU_blend(false);
  }
  
 -
  static void ui_hsv_cursor(float x, float y)
  {
 -      glPushMatrix();
 -      glTranslatef(x, y, 0.0f);
 +      unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
  
 -      glColor3f(1.0f, 1.0f, 1.0f);
 -      glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 8);
 +      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);
 -      glDisable(GL_BLEND);
 -      glDisable(GL_LINE_SMOOTH);
 +      GPU_blend(true);
 +      GPU_line_smooth(true);
 +      immUniformColor3f(0.0f, 0.0f, 0.0f);
 +      imm_draw_circle_wire_2d(pos, x, y, 3.0f * U.pixelsize, 12);
 +      GPU_blend(false);
 +      GPU_line_smooth(false);
  
 -      glPopMatrix();
 +      immUnbindProgram();
  }
  
- void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect,
-                                 const float mx, const float my)
+ void ui_hsvcircle_vals_from_pos(
+         float *val_rad, float *val_dist, const rcti *rect,
+         const float mx, const float my)
  {
        /* duplication of code... well, simple is better now */
        const float centx = BLI_rcti_cent_x_fl(rect);
index 4e9d1fad6e09d1a0e0218b61b7b4ebb1dda1e5d8,299001d4e451ac17f1013429fecc9057c9c2e312..fc282e50ce2d9569dddb889bb3b3efb81f81a9fd
@@@ -2547,14 -2426,16 +2550,15 @@@ void UI_view2d_text_cache_draw(ARegion 
                }
  
                if (v2s->rect.xmin >= v2s->rect.xmax)
-                       BLF_draw_default((float)(v2s->mval[0] + xofs), (float)(v2s->mval[1] + yofs), 0.0,
-                                         v2s->str, BLF_DRAW_STR_DUMMY_MAX);
+                       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_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_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(font_id, BLF_CLIPPING);
                }
        }
        g_v2d_strings = NULL;