Blender  V2.93
interface_widgets.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <limits.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "DNA_brush_types.h"
29 #include "DNA_userdef_types.h"
30 
31 #include "BLI_listbase.h"
32 #include "BLI_math.h"
33 #include "BLI_rect.h"
34 #include "BLI_string.h"
35 #include "BLI_string_utf8.h"
36 #include "BLI_utildefines.h"
37 
38 #include "BKE_context.h"
39 
40 #include "RNA_access.h"
41 
42 #include "BLF_api.h"
43 
44 #include "ED_node.h"
45 
46 #include "UI_interface.h"
47 #include "UI_interface_icons.h"
48 
49 #include "interface_intern.h"
50 
51 #include "GPU_batch.h"
52 #include "GPU_batch_presets.h"
53 #include "GPU_immediate.h"
54 #include "GPU_immediate_util.h"
55 #include "GPU_matrix.h"
56 #include "GPU_platform.h"
57 #include "GPU_state.h"
58 
59 #ifdef WITH_INPUT_IME
60 # include "WM_types.h"
61 #endif
62 
63 /* -------------------------------------------------------------------- */
67 /* icons are 80% of height of button (16 pixels inside 20 height) */
68 #define ICON_SIZE_FROM_BUTRECT(rect) (0.8f * BLI_rcti_size_y(rect))
69 
70 /* visual types for drawing */
71 /* for time being separated from functional types */
72 typedef enum {
73  /* default */
75 
76  /* standard set */
87 
88  /* strings */
93 
94  /* menus */
99 
104 
105  /* specials */
117 
118 /* Button state argument shares bits with 'uiBut.flag'.
119  * reuse flags that aren't needed for drawing to avoid collision. */
120 enum {
121  /* Show that holding the button opens a menu. */
127 
130 };
131 /* Prevent accidental use. */
132 #define UI_BUT_UPDATE_DELAY ((void)0)
133 #define UI_BUT_UNDO ((void)0)
134 
137 /* -------------------------------------------------------------------- */
141 static void color_blend_v3_v3(uchar cp[3], const uchar cpstate[3], const float fac)
142 {
143  if (fac != 0.0f) {
144  cp[0] = (int)((1.0f - fac) * cp[0] + fac * cpstate[0]);
145  cp[1] = (int)((1.0f - fac) * cp[1] + fac * cpstate[1]);
146  cp[2] = (int)((1.0f - fac) * cp[2] + fac * cpstate[2]);
147  }
148 }
149 
150 static void color_blend_v4_v4v4(uchar r_col[4],
151  const uchar col1[4],
152  const uchar col2[4],
153  const float fac)
154 {
155  const int faci = unit_float_to_uchar_clamp(fac);
156  const int facm = 255 - faci;
157 
158  r_col[0] = (faci * col1[0] + facm * col2[0]) / 256;
159  r_col[1] = (faci * col1[1] + facm * col2[1]) / 256;
160  r_col[2] = (faci * col1[2] + facm * col2[2]) / 256;
161  r_col[3] = (faci * col1[3] + facm * col2[3]) / 256;
162 }
163 
164 static void color_add_v3_i(uchar cp[3], int tint)
165 {
166  cp[0] = clamp_i(cp[0] + tint, 0, 255);
167  cp[1] = clamp_i(cp[1] + tint, 0, 255);
168  cp[2] = clamp_i(cp[2] + tint, 0, 255);
169 }
170 
171 static void color_ensure_contrast_v3(uchar cp[3], const uchar cp_other[3], int contrast)
172 {
173  BLI_assert(contrast > 0);
174  const int item_value = rgb_to_grayscale_byte(cp);
175  const int inner_value = rgb_to_grayscale_byte(cp_other);
176  const int delta = item_value - inner_value;
177  if (delta >= 0) {
178  if (contrast > delta) {
179  color_add_v3_i(cp, contrast - delta);
180  }
181  }
182  else {
183  if (contrast > -delta) {
184  color_add_v3_i(cp, -contrast - delta);
185  }
186  }
187 }
188 
189 static void color_mul_hsl_v3(uchar ch[3], float h_factor, float s_factor, float l_factor)
190 {
191  float rgb[3], hsl[3];
192  rgb_uchar_to_float(rgb, ch);
193  rgb_to_hsl_v(rgb, hsl);
194  hsl[0] *= h_factor;
195  hsl[1] *= s_factor;
196  hsl[2] *= l_factor;
197  hsl_to_rgb_v(hsl, rgb);
198  rgb_float_to_uchar(ch, rgb);
199 }
200 
203 /* -------------------------------------------------------------------- */
220 /* fill this struct with polygon info to draw AA'ed */
221 /* it has outline, back, and two optional tria meshes */
222 
223 typedef struct uiWidgetTrias {
225  int type;
226  float size, center[2];
227 
228  float vec[16][2];
229  const uint (*index)[3];
230 
232 
233 /* max as used by round_box__edges */
234 /* Make sure to change widget_base_vert.glsl accordingly. */
235 #define WIDGET_CURVE_RESOLU 9
236 #define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4)
237 
238 typedef struct uiWidgetBase {
239  /* TODO remove these completely */
244 
246 
249 
250  /* Widget shader parameters, must match the shader layout. */
253 
258 typedef struct uiWidgetType {
259 
260  /* pointer to theme color definition */
263 
264  /* converted colors for state */
266 
267  void (*state)(struct uiWidgetType *, int state, int drawflag, eUIEmbossType emboss);
268  void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
269  void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
270  void (*text)(const uiFontStyle *, const uiWidgetColors *, uiBut *, rcti *);
271 
273 
276 /* -------------------------------------------------------------------- */
280 static const float cornervec[WIDGET_CURVE_RESOLU][2] = {
281  {0.0, 0.0},
282  {0.195, 0.02},
283  {0.383, 0.067},
284  {0.55, 0.169},
285  {0.707, 0.293},
286  {0.831, 0.45},
287  {0.924, 0.617},
288  {0.98, 0.805},
289  {1.0, 1.0},
290 };
291 
293  {0.468813, -0.481430},
294  {-0.155755, -0.352820},
295  {0.219306, -0.238501},
296  {-0.393286, -0.110949},
297  {-0.024699, 0.013908},
298  {0.343805, 0.147431},
299  {-0.272855, 0.269918},
300  {0.095909, 0.388710},
301 };
302 #define WIDGET_AA_JITTER UI_PIXEL_AA_JITTER
303 #define jit ui_pixel_jitter
304 
305 static const float g_shape_preset_number_arrow_vert[3][2] = {
306  {-0.352077, 0.532607},
307  {-0.352077, -0.549313},
308  {0.330000, -0.008353},
309 };
311  {0, 1, 2},
312 };
313 
314 static const float g_shape_preset_scroll_circle_vert[16][2] = {
315  {0.382684, 0.923879},
316  {0.000001, 1.000000},
317  {-0.382683, 0.923880},
318  {-0.707107, 0.707107},
319  {-0.923879, 0.382684},
320  {-1.000000, 0.000000},
321  {-0.923880, -0.382684},
322  {-0.707107, -0.707107},
323  {-0.382683, -0.923880},
324  {0.000000, -1.000000},
325  {0.382684, -0.923880},
326  {0.707107, -0.707107},
327  {0.923880, -0.382684},
328  {1.000000, -0.000000},
329  {0.923880, 0.382683},
330  {0.707107, 0.707107},
331 };
333  {0, 1, 2},
334  {2, 0, 3},
335  {3, 0, 15},
336  {3, 15, 4},
337  {4, 15, 14},
338  {4, 14, 5},
339  {5, 14, 13},
340  {5, 13, 6},
341  {6, 13, 12},
342  {6, 12, 7},
343  {7, 12, 11},
344  {7, 11, 8},
345  {8, 11, 10},
346  {8, 10, 9},
347 };
348 
349 static const float g_shape_preset_menu_arrow_vert[6][2] = {
350  {-0.33, 0.16},
351  {0.33, 0.16},
352  {0, 0.82},
353  {0, -0.82},
354  {-0.33, -0.16},
355  {0.33, -0.16},
356 };
357 static const uint g_shape_preset_menu_arrow_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
358 
359 static const float g_shape_preset_checkmark_vert[6][2] = {
360  {-0.578579, 0.253369},
361  {-0.392773, 0.412794},
362  {-0.004241, -0.328551},
363  {-0.003001, 0.034320},
364  {1.055313, 0.864744},
365  {0.866408, 1.026895},
366 };
367 
368 static const uint g_shape_preset_checkmark_face[4][3] = {
369  {3, 2, 4},
370  {3, 4, 5},
371  {1, 0, 3},
372  {0, 2, 3},
373 };
374 
375 #define OY (-0.2 / 2)
376 #define SC (0.35 * 2)
377 static const float g_shape_preset_hold_action_vert[6][2] = {
378  {-0.5 + SC, 1.0 + OY},
379  {0.5, 1.0 + OY},
380  {0.5, 0.0 + OY + SC},
381 };
382 static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
383 #undef OY
384 #undef SC
385 
388 /* -------------------------------------------------------------------- */
397 static struct {
400 
401  /* TODO remove */
405 
407 {
408  if (g_ui_batch_cache.format.attr_len == 0) {
411  format, "vflag", GPU_COMP_U32, 1, GPU_FETCH_INT);
412  }
413  return &g_ui_batch_cache.format;
414 }
415 
416 #define INNER 0
417 #define OUTLINE 1
418 #define EMBOSS 2
419 #define NO_AA 0
420 
422 {
423  uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
424  *data = d;
425 }
426 
428  int corner_id,
429  int corner_v,
430  int jit_v,
431  bool inner,
432  bool emboss,
433  int color)
434 {
435  uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
436  *data = corner_id;
437  *data |= corner_v << 2;
438  *data |= jit_v << 6;
439  *data |= color << 12;
440  *data |= (inner) ? (1 << 10) : 0; /* is inner vert */
441  *data |= (emboss) ? (1 << 11) : 0; /* is emboss vert */
442  return *data;
443 }
444 
446 {
447  if (g_ui_batch_cache.roundbox_widget == NULL) {
449 
450  GPU_vertbuf_data_alloc(vbo, 12);
451 
452  GPUIndexBufBuilder ibuf;
453  GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 6, 12);
454  /* Widget */
455  GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2);
456  GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3);
457  /* Trias */
458  GPU_indexbuf_add_tri_verts(&ibuf, 4, 5, 6);
459  GPU_indexbuf_add_tri_verts(&ibuf, 6, 5, 7);
460 
461  GPU_indexbuf_add_tri_verts(&ibuf, 8, 9, 10);
462  GPU_indexbuf_add_tri_verts(&ibuf, 10, 9, 11);
463 
464  g_ui_batch_cache.roundbox_widget = GPU_batch_create_ex(
467  }
468  return g_ui_batch_cache.roundbox_widget;
469 }
470 
472 {
473  if (g_ui_batch_cache.roundbox_shadow == NULL) {
474  uint32_t last_data;
475  GPUVertBufRaw vflag_step;
477  const int vcount = (WIDGET_SIZE_MAX + 1) * 2 + 2 + WIDGET_SIZE_MAX;
478  GPU_vertbuf_data_alloc(vbo, vcount);
479  GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
480 
481  for (int c = 0; c < 4; c++) {
482  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
483  set_roundbox_vertex(&vflag_step, c, a, NO_AA, true, false, INNER);
484  set_roundbox_vertex(&vflag_step, c, a, NO_AA, false, false, INNER);
485  }
486  }
487  /* close loop */
488  last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
489  last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, false, false, INNER);
490  /* restart */
491  set_roundbox_vertex_data(&vflag_step, last_data);
492  set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
493  /* filled */
494  for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
495  for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) {
496  set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
497  set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
498  }
499  }
500  g_ui_batch_cache.roundbox_shadow = GPU_batch_create_ex(
503  }
504  return g_ui_batch_cache.roundbox_shadow;
505 }
506 
507 #undef INNER
508 #undef OUTLINE
509 #undef EMBOSS
510 #undef NO_AA
511 
514 /* -------------------------------------------------------------------- */
519  float x1, float y1, float x2, float y2, float x3, float y3, const float color[4])
520 {
521  const float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}};
522 
523  float draw_color[4];
524  copy_v4_v4(draw_color, color);
525  /* Note: This won't give back the original color. */
526  draw_color[3] *= 1.0f / WIDGET_AA_JITTER;
527 
529 
533 
534  immUniformColor4fv(draw_color);
536 
537  /* for each AA step */
538  for (int j = 0; j < WIDGET_AA_JITTER; j++) {
539  immVertex2f(pos, tri_arr[0][0] + jit[j][0], tri_arr[0][1] + jit[j][1]);
540  immVertex2f(pos, tri_arr[1][0] + jit[j][0], tri_arr[1][1] + jit[j][1]);
541  immVertex2f(pos, tri_arr[2][0] + jit[j][0], tri_arr[2][1] + jit[j][1]);
542  }
543 
544  immEnd();
545 
547 
549 }
550 
551 /* Triangle 'icon' for panel header and other cases. */
552 void UI_draw_icon_tri(float x, float y, char dir, const float color[4])
553 {
554  const float f3 = 0.05 * U.widget_unit;
555  const float f5 = 0.15 * U.widget_unit;
556  const float f7 = 0.25 * U.widget_unit;
557 
558  if (dir == 'h') {
559  UI_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color);
560  }
561  else if (dir == 't') {
562  UI_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color);
563  }
564  else { /* 'v' = vertical, down. */
565  UI_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color);
566  }
567 }
568 
569 /* triangle 'icon' inside rect */
570 void ui_draw_anti_tria_rect(const rctf *rect, char dir, const float color[4])
571 {
572  if (dir == 'h') {
573  const float half = 0.5f * BLI_rctf_size_y(rect);
575  rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half, color);
576  }
577  else {
578  const float half = 0.5f * BLI_rctf_size_x(rect);
580  rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin, color);
581  }
582 }
583 
584 void UI_draw_anti_fan(float tri_array[][2], uint length, const float color[4])
585 {
586  float draw_color[4];
587 
588  copy_v4_v4(draw_color, color);
589  draw_color[3] *= 2.0f / WIDGET_AA_JITTER;
590 
592 
596 
597  immUniformColor4fv(draw_color);
598 
599  /* for each AA step */
600  for (int j = 0; j < WIDGET_AA_JITTER; j++) {
602  immVertex2f(pos, tri_array[0][0], tri_array[0][1]);
603  immVertex2f(pos, tri_array[1][0], tri_array[1][1]);
604 
605  /* We jitter only the middle of the fan, the extremes are pinned. */
606  for (int i = 2; i < length - 1; i++) {
607  immVertex2f(pos, tri_array[i][0] + jit[j][0], tri_array[i][1] + jit[j][1]);
608  }
609 
610  immVertex2f(pos, tri_array[length - 1][0], tri_array[length - 1][1]);
611  immEnd();
612  }
613 
615 
617 }
618 
619 static void widget_init(uiWidgetBase *wtb)
620 {
621  wtb->totvert = wtb->halfwayvert = 0;
622  wtb->tria1.tot = 0;
623  wtb->tria2.tot = 0;
625  wtb->tria1.size = 0;
626  wtb->tria2.size = 0;
627 
628  wtb->draw_inner = true;
629  wtb->draw_outline = true;
630  wtb->draw_emboss = true;
631 
632  wtb->uniform_params.shade_dir = 1.0f;
633  wtb->uniform_params.alpha_discard = 1.0f;
634 }
635 
638 /* -------------------------------------------------------------------- */
642 /* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
643 /* return tot */
645  float (*vert)[2], const rcti *rect, float rad, int roundboxalign, float step)
646 {
647  float vec[WIDGET_CURVE_RESOLU][2];
648  int tot = 0;
649 
650  rad += step;
651 
652  if (2.0f * rad > BLI_rcti_size_y(rect)) {
653  rad = 0.5f * BLI_rcti_size_y(rect);
654  }
655 
656  const float minx = rect->xmin - step;
657  const float miny = rect->ymin - step;
658  const float maxx = rect->xmax + step;
659  const float maxy = rect->ymax + step;
660 
661  /* Multiply. */
662  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
663  vec[a][0] = rad * cornervec[a][0];
664  vec[a][1] = rad * cornervec[a][1];
665  }
666 
667  /* start with left-top, anti clockwise */
668  if (roundboxalign & UI_CNR_TOP_LEFT) {
669  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
670  vert[tot][0] = minx + rad - vec[a][0];
671  vert[tot][1] = maxy - vec[a][1];
672  }
673  }
674  else {
675  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
676  vert[tot][0] = minx;
677  vert[tot][1] = maxy;
678  }
679  }
680 
681  if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
682  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
683  vert[tot][0] = minx + vec[a][1];
684  vert[tot][1] = miny + rad - vec[a][0];
685  }
686  }
687  else {
688  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
689  vert[tot][0] = minx;
690  vert[tot][1] = miny;
691  }
692  }
693 
694  if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
695  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
696  vert[tot][0] = maxx - rad + vec[a][0];
697  vert[tot][1] = miny + vec[a][1];
698  }
699  }
700  else {
701  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
702  vert[tot][0] = maxx;
703  vert[tot][1] = miny;
704  }
705  }
706 
707  if (roundboxalign & UI_CNR_TOP_RIGHT) {
708  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
709  vert[tot][0] = maxx - vec[a][1];
710  vert[tot][1] = maxy - rad + vec[a][0];
711  }
712  }
713  else {
714  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
715  vert[tot][0] = maxx;
716  vert[tot][1] = maxy;
717  }
718  }
719  return tot;
720 }
721 
722 /* this call has 1 extra arg to allow mask outline */
723 static void round_box__edges(
724  uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad, float radi)
725 {
726  float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2];
727  const float minx = rect->xmin, miny = rect->ymin, maxx = rect->xmax, maxy = rect->ymax;
728  const float minxi = minx + U.pixelsize; /* boundbox inner */
729  const float maxxi = maxx - U.pixelsize;
730  const float minyi = miny + U.pixelsize;
731  const float maxyi = maxy - U.pixelsize;
732  /* for uv, can divide by zero */
733  const float facxi = (maxxi != minxi) ? 1.0f / (maxxi - minxi) : 0.0f;
734  const float facyi = (maxyi != minyi) ? 1.0f / (maxyi - minyi) : 0.0f;
735  int tot = 0;
736  const int hnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT)) ==
738  (roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) ==
740  1 :
741  2;
742  const int vnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)) ==
744  (roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ==
746  1 :
747  2;
748 
749  const int minsize = min_ii(BLI_rcti_size_x(rect) * hnum, BLI_rcti_size_y(rect) * vnum);
750 
751  if (2.0f * rad > minsize) {
752  rad = 0.5f * minsize;
753  }
754 
755  if (2.0f * (radi + 1.0f) > minsize) {
756  radi = 0.5f * minsize - U.pixelsize;
757  }
758 
759  wt->uniform_params.rad = rad;
760  wt->uniform_params.radi = radi;
761  wt->uniform_params.facxi = facxi;
762  wt->uniform_params.facyi = facyi;
763  wt->uniform_params.round_corners[0] = (roundboxalign & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f;
764  wt->uniform_params.round_corners[1] = (roundboxalign & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f;
765  wt->uniform_params.round_corners[2] = (roundboxalign & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f;
766  wt->uniform_params.round_corners[3] = (roundboxalign & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f;
768  BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi);
769 
770  /* mult */
771  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
772  veci[a][0] = radi * cornervec[a][0];
773  veci[a][1] = radi * cornervec[a][1];
774  vec[a][0] = rad * cornervec[a][0];
775  vec[a][1] = rad * cornervec[a][1];
776  }
777 
778  /* corner left-bottom */
779  if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
780  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
781  wt->inner_v[tot][0] = minxi + veci[a][1];
782  wt->inner_v[tot][1] = minyi + radi - veci[a][0];
783 
784  wt->outer_v[tot][0] = minx + vec[a][1];
785  wt->outer_v[tot][1] = miny + rad - vec[a][0];
786 
787  wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
788  wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
789  }
790  }
791  else {
792  wt->inner_v[tot][0] = minxi;
793  wt->inner_v[tot][1] = minyi;
794 
795  wt->outer_v[tot][0] = minx;
796  wt->outer_v[tot][1] = miny;
797 
798  wt->inner_uv[tot][0] = 0.0f;
799  wt->inner_uv[tot][1] = 0.0f;
800 
801  tot++;
802  }
803 
804  /* corner right-bottom */
805  if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
806  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
807  wt->inner_v[tot][0] = maxxi - radi + veci[a][0];
808  wt->inner_v[tot][1] = minyi + veci[a][1];
809 
810  wt->outer_v[tot][0] = maxx - rad + vec[a][0];
811  wt->outer_v[tot][1] = miny + vec[a][1];
812 
813  wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
814  wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
815  }
816  }
817  else {
818  wt->inner_v[tot][0] = maxxi;
819  wt->inner_v[tot][1] = minyi;
820 
821  wt->outer_v[tot][0] = maxx;
822  wt->outer_v[tot][1] = miny;
823 
824  wt->inner_uv[tot][0] = 1.0f;
825  wt->inner_uv[tot][1] = 0.0f;
826 
827  tot++;
828  }
829 
830  wt->halfwayvert = tot;
831 
832  /* corner right-top */
833  if (roundboxalign & UI_CNR_TOP_RIGHT) {
834  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
835  wt->inner_v[tot][0] = maxxi - veci[a][1];
836  wt->inner_v[tot][1] = maxyi - radi + veci[a][0];
837 
838  wt->outer_v[tot][0] = maxx - vec[a][1];
839  wt->outer_v[tot][1] = maxy - rad + vec[a][0];
840 
841  wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
842  wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
843  }
844  }
845  else {
846  wt->inner_v[tot][0] = maxxi;
847  wt->inner_v[tot][1] = maxyi;
848 
849  wt->outer_v[tot][0] = maxx;
850  wt->outer_v[tot][1] = maxy;
851 
852  wt->inner_uv[tot][0] = 1.0f;
853  wt->inner_uv[tot][1] = 1.0f;
854 
855  tot++;
856  }
857 
858  /* corner left-top */
859  if (roundboxalign & UI_CNR_TOP_LEFT) {
860  for (int a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
861  wt->inner_v[tot][0] = minxi + radi - veci[a][0];
862  wt->inner_v[tot][1] = maxyi - veci[a][1];
863 
864  wt->outer_v[tot][0] = minx + rad - vec[a][0];
865  wt->outer_v[tot][1] = maxy - vec[a][1];
866 
867  wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
868  wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
869  }
870  }
871  else {
872  wt->inner_v[tot][0] = minxi;
873  wt->inner_v[tot][1] = maxyi;
874 
875  wt->outer_v[tot][0] = minx;
876  wt->outer_v[tot][1] = maxy;
877 
878  wt->inner_uv[tot][0] = 0.0f;
879  wt->inner_uv[tot][1] = 1.0f;
880 
881  tot++;
882  }
883 
884  BLI_assert(tot <= WIDGET_SIZE_MAX);
885 
886  wt->totvert = tot;
887 }
888 
889 static void round_box_edges(uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad)
890 {
891  round_box__edges(wt, roundboxalign, rect, rad, rad - U.pixelsize);
892 }
893 
896 /* -------------------------------------------------------------------- */
900 /* based on button rect, return scaled array of triangles */
902  const rcti *rect,
903  float triasize,
904  char where,
905  /* input data */
906  const float verts[][2],
907  const int verts_tot,
908  const uint tris[][3],
909  const int tris_tot)
910 {
911  float sizex, sizey;
912  int i1 = 0, i2 = 1;
913 
914  const float minsize = ELEM(where, 'r', 'l') ? BLI_rcti_size_y(rect) : BLI_rcti_size_x(rect);
915 
916  /* center position and size */
917  float centx = (float)rect->xmin + 0.4f * minsize;
918  float centy = (float)rect->ymin + 0.5f * minsize;
919  tria->size = sizex = sizey = -0.5f * triasize * minsize;
920 
921  if (where == 'r') {
922  centx = (float)rect->xmax - 0.4f * minsize;
923  sizex = -sizex;
924  }
925  else if (where == 't') {
926  centx = (float)rect->xmin + 0.5f * minsize;
927  centy = (float)rect->ymax - 0.5f * minsize;
928  sizey = -sizey;
929  i2 = 0;
930  i1 = 1;
931  }
932  else if (where == 'b') {
933  centx = (float)rect->xmin + 0.5f * minsize;
934  sizex = -sizex;
935  i2 = 0;
936  i1 = 1;
937  }
938 
939  for (int a = 0; a < verts_tot; a++) {
940  tria->vec[a][0] = sizex * verts[a][i1] + centx;
941  tria->vec[a][1] = sizey * verts[a][i2] + centy;
942  }
943 
944  tria->center[0] = centx;
945  tria->center[1] = centy;
946 
947  tria->tot = tris_tot;
948  tria->index = tris;
949 }
950 
952  const rcti *rect,
953  float triasize,
954  char where)
955 {
956  tria->type = ROUNDBOX_TRIA_ARROWS;
958  rect,
959  triasize,
960  where,
965 }
966 
968  const rcti *rect,
969  float triasize,
970  char where)
971 {
973  /* With the current changes to use batches for widget drawing, the code
974  * below is doing almost nothing effectively. 'where' doesn't work either,
975  * shader is currently hardcoded to work for the button triangle pointing
976  * at the lower right. The same limitation applies to other trias as well.
977  * XXX Should be addressed. */
979  rect,
980  triasize,
981  where,
986 }
987 
989  const rcti *rect,
990  float triasize,
991  char where)
992 {
993  tria->type = ROUNDBOX_TRIA_SCROLL;
995  rect,
996  triasize,
997  where,
1002 }
1003 
1005  uint col,
1006  int mode,
1007  const float quads_pos[WIDGET_SIZE_MAX][2],
1008  const uchar quads_col[WIDGET_SIZE_MAX][4],
1009  uint totvert)
1010 {
1011  immBegin(mode, totvert);
1012  for (int i = 0; i < totvert; i++) {
1013  if (quads_col) {
1014  immAttr4ubv(col, quads_col[i]);
1015  }
1016  immVertex2fv(pos, quads_pos[i]);
1017  }
1018  immEnd();
1019 }
1020 
1022 {
1023  const float width = BLI_rcti_size_x(rect);
1024  const float height = BLI_rcti_size_y(rect);
1025  float centx, centy, size;
1026 
1027  tria->type = ROUNDBOX_TRIA_MENU;
1028 
1029  /* Center position and size. */
1030  tria->center[0] = centx = rect->xmin + 0.52f * BLI_rcti_size_y(rect);
1031  tria->center[1] = centy = rect->ymin + 0.52f * BLI_rcti_size_y(rect);
1032  tria->size = size = 0.4f * height;
1033 
1034  if (width > height * 1.1f) {
1035  /* For wider buttons align tighter to the right. */
1036  tria->center[0] = centx = rect->xmax - 0.32f * height;
1037  }
1038 
1039  for (int a = 0; a < 6; a++) {
1040  tria->vec[a][0] = size * g_shape_preset_menu_arrow_vert[a][0] + centx;
1041  tria->vec[a][1] = size * g_shape_preset_menu_arrow_vert[a][1] + centy;
1042  }
1043 
1044  tria->tot = 2;
1046 }
1047 
1049 {
1050  float centx, centy, size;
1051 
1052  tria->type = ROUNDBOX_TRIA_CHECK;
1053 
1054  /* Center position and size. */
1055  tria->center[0] = centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
1056  tria->center[1] = centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
1057  tria->size = size = 0.5f * BLI_rcti_size_y(rect);
1058 
1059  for (int a = 0; a < 6; a++) {
1060  tria->vec[a][0] = size * g_shape_preset_checkmark_vert[a][0] + centx;
1061  tria->vec[a][1] = size * g_shape_preset_checkmark_vert[a][1] + centy;
1062  }
1063 
1064  tria->tot = 4;
1066 }
1067 
1070 /* -------------------------------------------------------------------- */
1074 /* prepares shade colors */
1075 static void shadecolors4(
1076  uchar coltop[4], uchar coldown[4], const uchar *color, short shadetop, short shadedown)
1077 {
1078  coltop[0] = CLAMPIS(color[0] + shadetop, 0, 255);
1079  coltop[1] = CLAMPIS(color[1] + shadetop, 0, 255);
1080  coltop[2] = CLAMPIS(color[2] + shadetop, 0, 255);
1081  coltop[3] = color[3];
1082 
1083  coldown[0] = CLAMPIS(color[0] + shadedown, 0, 255);
1084  coldown[1] = CLAMPIS(color[1] + shadedown, 0, 255);
1085  coldown[2] = CLAMPIS(color[2] + shadedown, 0, 255);
1086  coldown[3] = color[3];
1087 }
1088 
1090  const int totvert,
1091  float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2])
1092 {
1093  int a;
1094  for (a = 0; a < totvert; a++) {
1095  copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[a]);
1096  copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[a]);
1097  }
1098  copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[0]);
1099  copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]);
1100 }
1101 
1103 {
1104  float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
1105  widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
1106 
1108  pos, 0, GPU_PRIM_TRI_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
1109 }
1110 
1112  const bool alpha_check,
1113  const float discard_factor)
1114 {
1115  if (alpha_check) {
1116  wtb->uniform_params.alpha_discard = -discard_factor;
1117  }
1118  else {
1119  wtb->uniform_params.alpha_discard = discard_factor;
1120  }
1121 }
1122 
1123 static void widgetbase_set_uniform_alpha_check(uiWidgetBase *wtb, const bool alpha_check)
1124 {
1125  const float discard_factor = fabs(wtb->uniform_params.alpha_discard);
1126  widgetbase_set_uniform_alpha_discard(wtb, alpha_check, discard_factor);
1127 }
1128 
1129 static void widgetbase_set_uniform_discard_factor(uiWidgetBase *wtb, const float discard_factor)
1130 {
1131  const bool alpha_check = wtb->uniform_params.alpha_discard < 0.0f;
1132  widgetbase_set_uniform_alpha_discard(wtb, alpha_check, discard_factor);
1133 }
1134 
1136  const uchar *col1,
1137  const uchar *col2,
1138  const uchar *outline,
1139  const uchar *emboss,
1140  const uchar *tria,
1141  const bool alpha_check)
1142 {
1143  widgetbase_set_uniform_alpha_check(wtb, alpha_check);
1144  rgba_float_args_set_ch(wtb->uniform_params.color_inner1, col1[0], col1[1], col1[2], col1[3]);
1145  rgba_float_args_set_ch(wtb->uniform_params.color_inner2, col2[0], col2[1], col2[2], col2[3]);
1147  wtb->uniform_params.color_outline, outline[0], outline[1], outline[2], outline[3]);
1149  wtb->uniform_params.color_emboss, emboss[0], emboss[1], emboss[2], emboss[3]);
1150  rgba_float_args_set_ch(wtb->uniform_params.color_tria, tria[0], tria[1], tria[2], tria[3]);
1151 }
1152 
1155 /* -------------------------------------------------------------------- */
1159 /* keep in sync with shader */
1160 #define MAX_WIDGET_BASE_BATCH 6
1161 #define MAX_WIDGET_PARAMETERS 12
1162 
1163 static struct {
1165  int count;
1166  bool enabled;
1167 } g_widget_base_batch = {{{{0}}}};
1168 
1170 {
1171  const float checker_params[3] = {
1172  UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
1173 
1174  if (g_widget_base_batch.count == 0) {
1175  return;
1176  }
1177 
1179  if (g_widget_base_batch.count == 1) {
1180  /* draw single */
1183  batch, "parameters", MAX_WIDGET_PARAMETERS, (const float(*)[4])g_widget_base_batch.params);
1184  GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
1186  }
1187  else {
1190  "parameters",
1192  (float(*)[4])g_widget_base_batch.params);
1193  GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
1195  }
1196  g_widget_base_batch.count = 0;
1197 }
1198 
1200 {
1201  BLI_assert(g_widget_base_batch.enabled == false);
1202  g_widget_base_batch.enabled = true;
1203 }
1204 
1206 {
1207  BLI_assert(g_widget_base_batch.enabled == true);
1208  g_widget_base_batch.enabled = false;
1209 
1211 
1213 
1215 }
1216 
1217 /* Disable cached/instanced drawing and enforce single widget drawing pipeline.
1218  * Works around interface artifacts happening on certain driver and hardware
1219  * configurations. */
1221 {
1222  /* MacOS is known to have issues on Mac Mini and MacBook Pro with Intel Iris GPU.
1223  * For example, T78307. */
1225  return true;
1226  }
1227 
1228  return false;
1229 }
1230 
1232 {
1233  wtb->uniform_params.tria_type = wtb->tria1.type;
1234  wtb->uniform_params.tria1_size = wtb->tria1.size;
1235  wtb->uniform_params.tria2_size = wtb->tria2.size;
1238 
1241  g_widget_base_batch.count++;
1242 
1245  }
1246  }
1247  else {
1248  const float checker_params[3] = {
1249  UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
1250  /* draw single */
1254  batch, "parameters", MAX_WIDGET_PARAMETERS, (float(*)[4]) & wtb->uniform_params);
1255  GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
1257  }
1258 }
1259 
1261  const uiWidgetColors *wcol,
1262  bool show_alpha_checkers)
1263 {
1264  uchar inner_col1[4] = {0};
1265  uchar inner_col2[4] = {0};
1266  uchar emboss_col[4] = {0};
1267  uchar outline_col[4] = {0};
1268  uchar tria_col[4] = {0};
1269  /* For color widget. */
1270  if (wcol->shaded != 0) {
1271  show_alpha_checkers = false;
1272  }
1273 
1274  /* backdrop non AA */
1275  if (wtb->draw_inner) {
1276  if (wcol->shaded == 0) {
1277  /* simple fill */
1278  inner_col1[0] = inner_col2[0] = wcol->inner[0];
1279  inner_col1[1] = inner_col2[1] = wcol->inner[1];
1280  inner_col1[2] = inner_col2[2] = wcol->inner[2];
1281  inner_col1[3] = inner_col2[3] = wcol->inner[3];
1282  }
1283  else {
1284  /* gradient fill */
1285  shadecolors4(inner_col1, inner_col2, wcol->inner, wcol->shadetop, wcol->shadedown);
1286  }
1287  }
1288 
1289  if (wtb->draw_outline) {
1290  outline_col[0] = wcol->outline[0];
1291  outline_col[1] = wcol->outline[1];
1292  outline_col[2] = wcol->outline[2];
1293  outline_col[3] = wcol->outline[3];
1294 
1295  /* emboss bottom shadow */
1296  if (wtb->draw_emboss) {
1298  }
1299  }
1300 
1301  if (wtb->tria1.type != ROUNDBOX_TRIA_NONE) {
1302  tria_col[0] = wcol->item[0];
1303  tria_col[1] = wcol->item[1];
1304  tria_col[2] = wcol->item[2];
1305  tria_col[3] = wcol->item[3];
1306  }
1307 
1308  /* Draw everything in one draw-call. */
1309  if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] ||
1310  show_alpha_checkers) {
1312  wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, show_alpha_checkers);
1313 
1315  draw_widgetbase_batch(wtb);
1317  }
1318 }
1319 
1320 static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
1321 {
1322  widgetbase_draw_ex(wtb, wcol, false);
1323 }
1324 
1327 /* -------------------------------------------------------------------- */
1331 #define UI_TEXT_CLIP_MARGIN (0.25f * U.widget_unit / but->block->aspect)
1332 
1333 #define PREVIEW_PAD 4
1334 
1335 static float widget_alpha_factor(const int state)
1336 {
1339  return 0.25f;
1340  }
1341  return 0.5f;
1342  }
1343 
1345  return 0.5f;
1346  }
1347 
1348  return 1.0f;
1349 }
1350 
1351 static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
1352 {
1353  if (icon == ICON_NONE) {
1354  return;
1355  }
1356 
1357  const int w = BLI_rcti_size_x(rect);
1358  const int h = BLI_rcti_size_y(rect);
1359  const int size = MIN2(w, h) - PREVIEW_PAD * 2;
1360 
1361  if (size > 0) {
1362  const int x = rect->xmin + w / 2 - size / 2;
1363  const int y = rect->ymin + h / 2 - size / 2;
1364 
1365  UI_icon_draw_preview(x, y, icon, 1.0f, alpha, size);
1366  }
1367 }
1368 
1369 static int ui_but_draw_menu_icon(const uiBut *but)
1370 {
1371  return (but->flag & UI_BUT_ICON_SUBMENU) && (but->emboss == UI_EMBOSS_PULLDOWN);
1372 }
1373 
1374 /* icons have been standardized... and this call draws in untransformed coordinates */
1375 
1376 static void widget_draw_icon(
1377  const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const uchar mono_color[4])
1378 {
1379  float xs = 0.0f, ys = 0.0f;
1380 
1381  if (but->flag & UI_BUT_ICON_PREVIEW) {
1383  widget_draw_preview(icon, alpha, rect);
1385  return;
1386  }
1387 
1388  /* this icon doesn't need draw... */
1389  if (icon == ICON_BLANK1 && (but->flag & UI_BUT_ICON_SUBMENU) == 0) {
1390  return;
1391  }
1392 
1393  const float aspect = but->block->aspect * U.inv_dpi_fac;
1394  const float height = ICON_DEFAULT_HEIGHT / aspect;
1395 
1396  /* calculate blend color */
1398  if (but->flag & UI_SELECT) {
1399  /* pass */
1400  }
1401  else if (but->flag & UI_ACTIVE) {
1402  /* pass */
1403  }
1404  else {
1405  alpha = 0.75f;
1406  }
1407  }
1408  else if ((but->type == UI_BTYPE_LABEL)) {
1409  /* extra feature allows more alpha blending */
1410  if (but->a1 == 1.0f) {
1411  alpha *= but->a2;
1412  }
1413  }
1414  else if (ELEM(but->type, UI_BTYPE_BUT, UI_BTYPE_DECORATOR)) {
1415  alpha *= widget_alpha_factor(but->flag);
1416  }
1417 
1419 
1420  if (icon && icon != ICON_BLANK1) {
1421  const float ofs = 1.0f / aspect;
1422 
1423  if (but->drawflag & UI_BUT_ICON_LEFT) {
1424  /* special case - icon_only pie buttons */
1426  but->str && but->str[0] == '\0') {
1427  xs = rect->xmin + 2.0f * ofs;
1428  }
1429  else if (but->emboss == UI_EMBOSS_NONE || but->type == UI_BTYPE_LABEL) {
1430  xs = rect->xmin + 2.0f * ofs;
1431  }
1432  else {
1433  xs = rect->xmin + 4.0f * ofs;
1434  }
1435  }
1436  else {
1437  xs = (rect->xmin + rect->xmax - height) / 2.0f;
1438  }
1439  ys = (rect->ymin + rect->ymax - height) / 2.0f;
1440 
1441  /* force positions to integers, for zoom levels near 1. draws icons crisp. */
1442  if (aspect > 0.95f && aspect < 1.05f) {
1443  xs = (int)(xs + 0.1f);
1444  ys = (int)(ys + 0.1f);
1445  }
1446 
1447  /* Get theme color. */
1448  uchar color[4] = {mono_color[0], mono_color[1], mono_color[2], mono_color[3]};
1449  const bool has_theme = UI_icon_get_theme_color(icon, color);
1450 
1451  /* to indicate draggable */
1452  if (but->dragpoin && (but->flag & UI_ACTIVE)) {
1453  UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme);
1454  }
1455  else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW))) {
1456  UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
1457  }
1458  else if (!((but->icon != ICON_NONE) && UI_but_is_tool(but))) {
1459  if (has_theme) {
1460  alpha *= 0.8f;
1461  }
1462  UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
1463  }
1464  else {
1465  const bTheme *btheme = UI_GetTheme();
1466  const float desaturate = 1.0 - btheme->tui.icon_saturation;
1467  UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme);
1468  }
1469  }
1470 
1472 }
1473 
1474 static void widget_draw_submenu_tria(const uiBut *but,
1475  const rcti *rect,
1476  const uiWidgetColors *wcol)
1477 {
1478  const float aspect = but->block->aspect * U.inv_dpi_fac;
1479  const int tria_height = (int)(ICON_DEFAULT_HEIGHT / aspect);
1480  const int tria_width = (int)(ICON_DEFAULT_WIDTH / aspect) - 2 * U.pixelsize;
1481  const int xs = rect->xmax - tria_width;
1482  const int ys = (rect->ymin + rect->ymax - tria_height) / 2.0f;
1483 
1484  float col[4];
1485  rgba_uchar_to_float(col, wcol->text);
1486  col[3] *= 0.8f;
1487 
1488  rctf tria_rect;
1489  BLI_rctf_init(&tria_rect, xs, xs + tria_width, ys, ys + tria_height);
1490  BLI_rctf_scale(&tria_rect, 0.4f);
1491 
1495  ui_draw_anti_tria_rect(&tria_rect, 'h', col);
1496 }
1497 
1498 static void ui_text_clip_give_prev_off(uiBut *but, const char *str)
1499 {
1500  const char *prev_utf8 = BLI_str_find_prev_char_utf8(str, str + but->ofs);
1501  const int bytes = str + but->ofs - prev_utf8;
1502 
1503  but->ofs -= bytes;
1504 }
1505 
1506 static void ui_text_clip_give_next_off(uiBut *but, const char *str)
1507 {
1508  const char *next_utf8 = BLI_str_find_next_char_utf8(str + but->ofs, NULL);
1509  const int bytes = next_utf8 - (str + but->ofs);
1510 
1511  but->ofs += bytes;
1512 }
1513 
1519 static void ui_text_clip_right_ex(const uiFontStyle *fstyle,
1520  char *str,
1521  const size_t max_len,
1522  const float okwidth,
1523  const char *sep,
1524  const int sep_len,
1525  const float sep_strwidth,
1526  size_t *r_final_len)
1527 {
1528  BLI_assert(str[0]);
1529 
1530  /* How many BYTES (not characters) of this utf-8 string can fit, along with appended ellipsis. */
1531  int l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, NULL);
1532 
1533  if (l_end > 0) {
1534  /* At least one character, so clip and add the ellipsis. */
1535  memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */
1536  if (r_final_len) {
1537  *r_final_len = (size_t)(l_end) + sep_len;
1538  }
1539  }
1540  else {
1541  /* Otherwise fit as much as we can without adding an ellipsis. */
1542  l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, NULL);
1543  str[l_end] = '\0';
1544  if (r_final_len) {
1545  *r_final_len = (size_t)l_end;
1546  }
1547  }
1548 }
1549 
1562  char *str,
1563  float okwidth,
1564  const float minwidth,
1565  const size_t max_len,
1566  const char rpart_sep)
1567 {
1568  /* Add some epsilon to OK width, avoids 'ellipsing' text that nearly fits!
1569  * Better to have a small piece of the last char cut out,
1570  * than two remaining chars replaced by an ellipsis... */
1571  okwidth += 1.0f + UI_DPI_FAC;
1572 
1573  BLI_assert(str[0]);
1574 
1575  /* need to set this first */
1576  UI_fontstyle_set(fstyle);
1577 
1578  if (fstyle->kerning == 1) {
1579  /* for BLF_width */
1581  }
1582 
1583  float strwidth = BLF_width(fstyle->uifont_id, str, max_len);
1584 
1585  if ((okwidth > 0.0f) && (strwidth > okwidth)) {
1586  /* Ellipsis. Some compilers complain with real literal string. */
1587  const char sep[] = {0xe2, 0x80, 0xA6, 0x0};
1588  const int sep_len = sizeof(sep) - 1;
1589  const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1);
1590 
1591  char *rpart = NULL, rpart_buf[UI_MAX_DRAW_STR];
1592  float rpart_width = 0.0f;
1593  size_t rpart_len = 0;
1594  size_t final_lpart_len;
1595 
1596  if (rpart_sep) {
1597  rpart = strrchr(str, rpart_sep);
1598 
1599  if (rpart) {
1600  rpart_len = strlen(rpart);
1601  rpart_width = BLF_width(fstyle->uifont_id, rpart, rpart_len);
1602  okwidth -= rpart_width;
1603  strwidth -= rpart_width;
1604 
1605  if (okwidth < 0.0f) {
1606  /* Not enough place for actual label, just display protected right part.
1607  * Here just for safety, should never happen in real life! */
1608  memmove(str, rpart, rpart_len + 1);
1609  rpart = NULL;
1610  okwidth += rpart_width;
1611  strwidth = rpart_width;
1612  }
1613  }
1614  }
1615 
1616  const float parts_strwidth = (okwidth - sep_strwidth) / 2.0f;
1617 
1618  if (rpart) {
1619  strcpy(rpart_buf, rpart);
1620  *rpart = '\0';
1621  rpart = rpart_buf;
1622  }
1623 
1624  const size_t l_end = BLF_width_to_strlen(
1625  fstyle->uifont_id, str, max_len, parts_strwidth, NULL);
1626  if (l_end < 10 || min_ff(parts_strwidth, strwidth - okwidth) < minwidth) {
1627  /* If we really have no place, or we would clip a very small piece of string in the middle,
1628  * only show start of string.
1629  */
1631  fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
1632  }
1633  else {
1634  size_t r_offset, r_len;
1635 
1636  r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, NULL);
1637  r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'. */
1638 
1639  if (l_end + sep_len + r_len + rpart_len > max_len) {
1640  /* Corner case, the str already takes all available mem,
1641  * and the ellipsis chars would actually add more chars.
1642  * Better to just trim one or two letters to the right in this case...
1643  * Note: with a single-char ellipsis, this should never happen! But better be safe
1644  * here...
1645  */
1647  fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
1648  }
1649  else {
1650  memmove(str + l_end + sep_len, str + r_offset, r_len);
1651  memcpy(str + l_end, sep, sep_len);
1652  /* -1 to remove trailing '\0'! */
1653  final_lpart_len = (size_t)(l_end + sep_len + r_len - 1);
1654 
1655  while (BLF_width(fstyle->uifont_id, str, max_len) > okwidth) {
1656  /* This will happen because a lot of string width processing is done in integer pixels,
1657  * which can introduce a rather high error in the end (about 2 pixels or so).
1658  * Only one char removal shall ever be needed in real-life situation... */
1659  r_len--;
1660  final_lpart_len--;
1661  char *c = str + l_end + sep_len;
1662  memmove(c, c + 1, r_len);
1663  }
1664  }
1665  }
1666 
1667  if (rpart) {
1668  /* Add back preserved right part to our shorten str. */
1669  memcpy(str + final_lpart_len, rpart, rpart_len + 1); /* +1 for trailing '\0'. */
1670  okwidth += rpart_width;
1671  }
1672 
1673  strwidth = BLF_width(fstyle->uifont_id, str, max_len);
1674  }
1675 
1676  if (fstyle->kerning == 1) {
1678  }
1679 
1680  BLI_assert(strwidth <= okwidth);
1681 
1682  return strwidth;
1683 }
1684 
1688 static void ui_text_clip_middle(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
1689 {
1690  /* No margin for labels! */
1692  0 :
1693  (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
1694  const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
1695  const size_t max_len = sizeof(but->drawstr);
1696  const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
1697 
1698  but->ofs = 0;
1699  but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, '\0');
1700 }
1701 
1709  uiBut *but,
1710  const rcti *rect,
1711  const char rsep)
1712 {
1713  /* No margin for labels! */
1715  0 :
1716  (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
1717  const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
1718  const size_t max_len = sizeof(but->drawstr);
1719  const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
1720 
1721  but->ofs = 0;
1722  but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep);
1723 }
1724 
1728 static void ui_text_clip_cursor(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
1729 {
1730  const int border = (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
1731  const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
1732 
1733  BLI_assert(but->editstr && but->pos >= 0);
1734 
1735  /* need to set this first */
1736  UI_fontstyle_set(fstyle);
1737 
1738  if (fstyle->kerning == 1) {
1739  /* for BLF_width */
1741  }
1742 
1743  /* define ofs dynamically */
1744  if (but->ofs > but->pos) {
1745  but->ofs = but->pos;
1746  }
1747 
1748  if (BLF_width(fstyle->uifont_id, but->editstr, INT_MAX) <= okwidth) {
1749  but->ofs = 0;
1750  }
1751 
1752  but->strwidth = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, INT_MAX);
1753 
1754  if (but->strwidth > okwidth) {
1755  int len = strlen(but->editstr);
1756 
1757  while (but->strwidth > okwidth) {
1758  float width;
1759 
1760  /* string position of cursor */
1761  width = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, (but->pos - but->ofs));
1762 
1763  /* if cursor is at 20 pixels of right side button we clip left */
1764  if (width > okwidth - 20) {
1766  }
1767  else {
1768  int bytes;
1769  /* shift string to the left */
1770  if (width < 20 && but->ofs > 0) {
1772  }
1774  if (bytes == -1) {
1775  bytes = 1;
1776  }
1777  len -= bytes;
1778  }
1779 
1780  but->strwidth = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, len - but->ofs);
1781 
1782  if (but->strwidth < 10) {
1783  break;
1784  }
1785  }
1786  }
1787 
1788  if (fstyle->kerning == 1) {
1790  }
1791 }
1792 
1798 static void ui_text_clip_right_label(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
1799 {
1800  const int border = UI_TEXT_CLIP_MARGIN + 1;
1801  const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
1802  int drawstr_len = strlen(but->drawstr);
1803  const char *cpend = but->drawstr + drawstr_len;
1804 
1805  /* need to set this first */
1806  UI_fontstyle_set(fstyle);
1807 
1808  if (fstyle->kerning == 1) {
1809  /* for BLF_width */
1811  }
1812 
1813  but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr));
1814  but->ofs = 0;
1815 
1816  /* First shorten number-buttons eg,
1817  * Translucency: 0.000
1818  * becomes
1819  * Trans: 0.000
1820  */
1821 
1822  /* find the space after ':' separator */
1823  char *cpoin = strrchr(but->drawstr, ':');
1824 
1825  if (cpoin && (cpoin < cpend - 2)) {
1826  char *cp2 = cpoin;
1827 
1828  /* chop off the leading text, starting from the right */
1829  while (but->strwidth > okwidth && cp2 > but->drawstr) {
1830  const char *prev_utf8 = BLI_str_find_prev_char_utf8(but->drawstr, cp2);
1831  const int bytes = cp2 - prev_utf8;
1832 
1833  /* shift the text after and including cp2 back by 1 char,
1834  * +1 to include null terminator */
1835  memmove(cp2 - bytes, cp2, drawstr_len + 1);
1836  cp2 -= bytes;
1837 
1838  drawstr_len -= bytes;
1839  // BLI_assert(strlen(but->drawstr) == drawstr_len);
1840 
1841  but->strwidth = BLF_width(
1842  fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
1843  if (but->strwidth < 10) {
1844  break;
1845  }
1846  }
1847 
1848  /* after the leading text is gone, chop off the : and following space, with ofs */
1849  while ((but->strwidth > okwidth) && (but->ofs < 2)) {
1851  but->strwidth = BLF_width(
1852  fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
1853  if (but->strwidth < 10) {
1854  break;
1855  }
1856  }
1857  }
1858 
1859  /* Now just remove trailing chars */
1860  /* once the label's gone, chop off the least significant digits */
1861  if (but->strwidth > okwidth) {
1862  float strwidth;
1863  drawstr_len = BLF_width_to_strlen(fstyle->uifont_id,
1864  but->drawstr + but->ofs,
1865  drawstr_len - but->ofs,
1866  okwidth,
1867  &strwidth) +
1868  but->ofs;
1869  but->strwidth = strwidth;
1870  but->drawstr[drawstr_len] = 0;
1871  }
1872 
1873  if (fstyle->kerning == 1) {
1875  }
1876 }
1877 
1878 #ifdef WITH_INPUT_IME
1879 static void widget_draw_text_ime_underline(const uiFontStyle *fstyle,
1880  const uiWidgetColors *wcol,
1881  const uiBut *but,
1882  const rcti *rect,
1883  const wmIMEData *ime_data,
1884  const char *drawstr)
1885 {
1886  int ofs_x, width;
1887  int rect_x = BLI_rcti_size_x(rect);
1888  int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end;
1889  float fcol[4];
1890 
1891  if (drawstr[0] != 0) {
1892  if (but->pos >= but->ofs) {
1893  ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->pos - but->ofs);
1894  }
1895  else {
1896  ofs_x = 0;
1897  }
1898 
1899  width = BLF_width(
1900  fstyle->uifont_id, drawstr + but->ofs, ime_data->composite_len + but->pos - but->ofs);
1901 
1902  rgba_uchar_to_float(fcol, wcol->text);
1903  UI_draw_text_underline(rect->xmin + ofs_x,
1904  rect->ymin + 6 * U.pixelsize,
1905  min_ii(width, rect_x - 2) - ofs_x,
1906  1,
1907  fcol);
1908 
1909  /* draw the thick line */
1910  if (sel_start != -1 && sel_end != -1) {
1911  sel_end -= sel_start;
1912  sel_start += but->pos;
1913 
1914  if (sel_start >= but->ofs) {
1915  ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_start - but->ofs);
1916  }
1917  else {
1918  ofs_x = 0;
1919  }
1920 
1921  width = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_end + sel_start - but->ofs);
1922 
1923  UI_draw_text_underline(rect->xmin + ofs_x,
1924  rect->ymin + 6 * U.pixelsize,
1925  min_ii(width, rect_x - 2) - ofs_x,
1926  2,
1927  fcol);
1928  }
1929  }
1930 }
1931 #endif /* WITH_INPUT_IME */
1932 
1934  const size_t str_step_ofs,
1935  const rcti *glyph_step_bounds,
1936  const int UNUSED(glyph_advance_x),
1937  const rctf *glyph_bounds,
1938  const int glyph_bearing[2],
1939  void *user_data)
1940 {
1941  /* The index of the character to get, set to the x-position. */
1942  int *ul_data = user_data;
1943  if (ul_data[0] == (int)str_step_ofs) {
1944  ul_data[1] = glyph_step_bounds->xmin + glyph_bearing[0] +
1945  (BLI_rctf_size_x(glyph_bounds) / 2.0f);
1946  /* Early exit. */
1947  return false;
1948  }
1949  return true;
1950 }
1951 
1952 static void widget_draw_text(const uiFontStyle *fstyle,
1953  const uiWidgetColors *wcol,
1954  uiBut *but,
1955  rcti *rect)
1956 {
1957  int drawstr_left_len = UI_MAX_DRAW_STR;
1958  const char *drawstr = but->drawstr;
1959  const char *drawstr_right = NULL;
1960  bool use_right_only = false;
1961 
1962 #ifdef WITH_INPUT_IME
1963  const wmIMEData *ime_data;
1964 #endif
1965 
1966  UI_fontstyle_set(fstyle);
1967 
1968  eFontStyle_Align align;
1969  if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
1970  align = UI_STYLE_TEXT_LEFT;
1971  }
1972  else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
1973  align = UI_STYLE_TEXT_RIGHT;
1974  }
1975  else {
1976  align = UI_STYLE_TEXT_CENTER;
1977  }
1978 
1979  if (fstyle->kerning == 1) {
1980  /* for BLF_width */
1982  }
1983 
1984  /* Special case: when we're entering text for multiple buttons,
1985  * don't draw the text for any of the multi-editing buttons */
1986  if (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI)) {
1987  uiBut *but_edit = ui_but_drag_multi_edit_get(but);
1988  if (but_edit) {
1989  drawstr = but_edit->editstr;
1990  align = UI_STYLE_TEXT_LEFT;
1991  }
1992  }
1993  else {
1994  if (but->editstr) {
1995  /* max length isn't used in this case,
1996  * we rely on string being NULL terminated. */
1997  drawstr_left_len = INT_MAX;
1998 
1999 #ifdef WITH_INPUT_IME
2000  /* FIXME, IME is modifying 'const char *drawstr! */
2001  ime_data = ui_but_ime_data_get(but);
2002 
2003  if (ime_data && ime_data->composite_len) {
2004  /* insert composite string into cursor pos */
2005  BLI_snprintf((char *)drawstr,
2007  "%s%s%s",
2008  but->editstr,
2009  ime_data->str_composite,
2010  but->editstr + but->pos);
2011  }
2012  else
2013 #endif
2014  {
2015  drawstr = but->editstr;
2016  }
2017  }
2018  }
2019 
2020  /* text button selection, cursor, composite underline */
2021  if (but->editstr && but->pos != -1) {
2022  int but_pos_ofs;
2023  /* Shape of the cursor for drawing. */
2024  rcti but_cursor_shape;
2025 
2026  /* text button selection */
2027  if ((but->selend - but->selsta) > 0) {
2028  int selsta_draw, selwidth_draw;
2029 
2030  if (drawstr[0] != 0) {
2031  /* We are drawing on top of widget bases. Flush cache. */
2035 
2036  if (but->selsta >= but->ofs) {
2037  selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selsta - but->ofs);
2038  }
2039  else {
2040  selsta_draw = 0;
2041  }
2042 
2043  selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs);
2044 
2048 
2049  immUniformColor4ubv(wcol->item);
2050  immRecti(pos,
2051  rect->xmin + selsta_draw,
2052  rect->ymin + U.pixelsize,
2053  min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
2054  rect->ymax - U.pixelsize);
2055 
2056  immUnbindProgram();
2057  }
2058  }
2059 
2060  /* text cursor */
2061  but_pos_ofs = but->pos;
2062 
2063 #ifdef WITH_INPUT_IME
2064  /* if is ime compositing, move the cursor */
2065  if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) {
2066  but_pos_ofs += ime_data->cursor_pos;
2067  }
2068 #endif
2069 
2070  if (but->pos >= but->ofs) {
2071  int t;
2072  if (drawstr[0] != 0) {
2073  t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but_pos_ofs - but->ofs);
2074  }
2075  else {
2076  t = 0;
2077  }
2078  /* We are drawing on top of widget bases. Flush cache. */
2082 
2086 
2088 
2089  but_cursor_shape.xmin = (rect->xmin + t) - U.pixelsize;
2090  but_cursor_shape.ymin = rect->ymin + U.pixelsize;
2091  but_cursor_shape.xmax = (rect->xmin + t) + U.pixelsize;
2092  but_cursor_shape.ymax = rect->ymax - U.pixelsize;
2093 
2094  /* draw cursor */
2095  immRecti(pos,
2096  but_cursor_shape.xmin,
2097  but_cursor_shape.ymin,
2098  but_cursor_shape.xmax,
2099  but_cursor_shape.ymax);
2100 
2101  immUnbindProgram();
2102  }
2103 
2104 #ifdef WITH_INPUT_IME
2105  if (ime_data && ime_data->composite_len) {
2106  /* ime cursor following */
2107  if (but->pos >= but->ofs) {
2108  ui_but_ime_reposition(but, but_cursor_shape.xmax + 5, but_cursor_shape.ymin + 3, false);
2109  }
2110 
2111  /* composite underline */
2112  widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr);
2113  }
2114 #endif
2115  }
2116 
2117  if (fstyle->kerning == 1) {
2119  }
2120 
2121 #if 0
2122  ui_rasterpos_safe(x, y, but->aspect);
2123  transopts = ui_translate_buttons();
2124 #endif
2125 
2126  /* cut string in 2 parts - only for menu entries */
2127  if ((but->drawflag & UI_BUT_HAS_SHORTCUT) && (but->editstr == NULL)) {
2128  if (but->flag & UI_BUT_HAS_SEP_CHAR) {
2129  drawstr_right = strrchr(drawstr, UI_SEP_CHAR);
2130  if (drawstr_right) {
2131  drawstr_left_len = (drawstr_right - drawstr);
2132  drawstr_right++;
2133  }
2134  }
2135  }
2136 
2137 #ifdef USE_NUMBUTS_LR_ALIGN
2138  if (!drawstr_right && (but->drawflag & UI_BUT_TEXT_LEFT) &&
2140  /* if we're editing or multi-drag (fake editing), then use left alignment */
2141  (but->editstr == NULL) && (drawstr == but->drawstr)) {
2142  drawstr_right = strrchr(drawstr + but->ofs, ':');
2143  if (drawstr_right) {
2144  drawstr_right++;
2145  drawstr_left_len = (drawstr_right - drawstr - 1);
2146 
2147  while (*drawstr_right == ' ') {
2148  drawstr_right++;
2149  }
2150  }
2151  else {
2152  /* no prefix, even so use only cpoin */
2153  drawstr_right = drawstr + but->ofs;
2154  use_right_only = true;
2155  }
2156  }
2157 #endif
2158 
2159  if (!use_right_only) {
2160  /* for underline drawing */
2161  int font_xofs, font_yofs;
2162 
2163  int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) :
2164  (drawstr_left_len - but->ofs);
2165 
2166  if (drawlen > 0) {
2167  UI_fontstyle_draw_ex(fstyle,
2168  rect,
2169  drawstr + but->ofs,
2170  wcol->text,
2171  &(struct uiFontStyleDraw_Params){
2172  .align = align,
2173  },
2174  drawlen,
2175  &font_xofs,
2176  &font_yofs,
2177  NULL);
2178 
2179  if (but->menu_key != '\0') {
2180  const char *drawstr_ofs = drawstr + but->ofs;
2181  int ul_index = -1;
2182 
2183  {
2184  /* Find upper case, fallback to lower case. */
2185  const char *drawstr_end = drawstr_ofs + drawlen;
2186  const char keys[] = {but->menu_key - 32, but->menu_key};
2187  for (int i = 0; i < ARRAY_SIZE(keys); i++) {
2188  const char *drawstr_menu = strchr(drawstr_ofs, keys[i]);
2189  if (drawstr_menu != NULL && drawstr_menu < drawstr_end) {
2190  ul_index = (int)(drawstr_menu - drawstr_ofs);
2191  break;
2192  }
2193  }
2194  }
2195 
2196  if (ul_index != -1) {
2197  if (fstyle->kerning == 1) {
2199  }
2200 
2201  int ul_data[2] = {
2202  ul_index, /* Character index to test. */
2203  0, /* Write the x-offset here. */
2204  };
2206  drawstr_ofs,
2207  ul_index + 1,
2209  ul_data);
2210  ul_data[1] -= BLF_width(fstyle->uifont_id, "_", 2) / 2.0f;
2211 
2212  BLF_position(fstyle->uifont_id,
2213  rect->xmin + font_xofs + ul_data[1],
2214  rect->ymin + font_yofs,
2215  0.0f);
2216  BLF_color4ubv(fstyle->uifont_id, wcol->text);
2217  BLF_draw(fstyle->uifont_id, "_", 2);
2218 
2219  if (fstyle->kerning == 1) {
2221  }
2222  }
2223  }
2224  }
2225  }
2226 
2227  /* part text right aligned */
2228  if (drawstr_right) {
2229  uchar col[4];
2230  copy_v4_v4_uchar(col, wcol->text);
2231  if (but->drawflag & UI_BUT_HAS_SHORTCUT) {
2232  col[3] *= 0.5f;
2233  }
2234 
2235  rect->xmax -= UI_TEXT_CLIP_MARGIN;
2236  UI_fontstyle_draw(fstyle,
2237  rect,
2238  drawstr_right,
2239  col,
2240  &(struct uiFontStyleDraw_Params){
2241  .align = UI_STYLE_TEXT_RIGHT,
2242  });
2243  }
2244 }
2245 
2246 static void widget_draw_extra_icons(const uiWidgetColors *wcol,
2247  uiBut *but,
2248  rcti *rect,
2249  float alpha)
2250 {
2251  const float icon_size = ICON_SIZE_FROM_BUTRECT(rect);
2252 
2253  /* Offset of icons from the right edge. Keep in sync
2254  with 'ui_but_extra_operator_icon_mouse_over_get'. */
2255  if (!BLI_listbase_is_empty(&but->extra_op_icons)) {
2256  /* Eyeballed. */
2257  rect->xmax -= 0.2 * icon_size;
2258  }
2259 
2260  /* Inverse order, from right to left. */
2262  rcti temp = *rect;
2263  float alpha_this = alpha;
2264 
2265  temp.xmin = temp.xmax - icon_size;
2266 
2267  if (!op_icon->highlighted) {
2268  alpha_this *= 0.75f;
2269  }
2270 
2271  /* Draw the icon at the center, and restore the flags after. */
2272  const int old_drawflags = but->drawflag;
2274  widget_draw_icon(but, op_icon->icon, alpha_this, &temp, wcol->text);
2275  but->drawflag = old_drawflags;
2276 
2277  rect->xmax -= icon_size;
2278  }
2279 }
2280 
2282  const rcti *rect,
2283  uiBut *but,
2284  float alpha)
2285 {
2286  /* Node socket pointer can be passed as custom_data, see UI_but_node_link_set(). */
2287  if (but->custom_data) {
2288  const float scale = 0.9f / but->block->aspect;
2289 
2290  float col[4];
2291  rgba_uchar_to_float(col, but->col);
2292  col[3] *= alpha;
2293 
2297 
2298  ED_node_socket_draw(but->custom_data, rect, col, scale);
2299  }
2300  else {
2301  widget_draw_icon(but, ICON_LAYER_USED, alpha, rect, wcol->text);
2302  }
2303 }
2304 
2305 /* draws text and icons for buttons */
2306 static void widget_draw_text_icon(const uiFontStyle *fstyle,
2307  const uiWidgetColors *wcol,
2308  uiBut *but,
2309  rcti *rect)
2310 {
2311  const bool show_menu_icon = ui_but_draw_menu_icon(but);
2312  const float alpha = (float)wcol->text[3] / 255.0f;
2313  char password_str[UI_MAX_DRAW_STR];
2314  bool no_text_padding = but->drawflag & UI_BUT_NO_TEXT_PADDING;
2315 
2316  ui_but_text_password_hide(password_str, but, false);
2317 
2318  /* check for button text label */
2319  if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && (but->flag & UI_BUT_NODE_LINK)) {
2320  rcti temp = *rect;
2321  const int size = BLI_rcti_size_y(rect) + 1; /* Not the icon size! */
2322 
2323  if (but->drawflag & UI_BUT_ICON_LEFT) {
2324  temp.xmax = rect->xmin + size;
2325  rect->xmin = temp.xmax;
2326  /* Further padding looks off. */
2327  no_text_padding = true;
2328  }
2329  else {
2330  temp.xmin = rect->xmax - size;
2331  rect->xmax = temp.xmin;
2332  }
2333 
2334  widget_draw_node_link_socket(wcol, &temp, but, alpha);
2335  }
2336 
2337  /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
2338  * and offset the text label to accommodate it */
2339 
2340  /* Big previews with optional text label below */
2341  if (but->flag & UI_BUT_ICON_PREVIEW && ui_block_is_menu(but->block)) {
2342  const BIFIconID icon = ui_but_icon(but);
2343  int icon_size = BLI_rcti_size_y(rect);
2344  int text_size = 0;
2345 
2346  /* This is a bit brittle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */
2347  if (icon_size > BLI_rcti_size_x(rect)) {
2348  /* button is not square, it has extra height for label */
2349  text_size = UI_UNIT_Y;
2350  icon_size -= text_size;
2351  }
2352 
2353  /* draw icon in rect above the space reserved for the label */
2354  rect->ymin += text_size;
2356  widget_draw_preview(icon, alpha, rect);
2358 
2359  /* offset rect to draw label in */
2360  rect->ymin -= text_size;
2361  rect->ymax -= icon_size;
2362 
2363  /* vertically centering text */
2364  rect->ymin += UI_UNIT_Y / 2;
2365  }
2366  /* Icons on the left with optional text label on the right */
2367  else if (but->flag & UI_HAS_ICON || show_menu_icon) {
2368  const bool is_tool = ((but->icon != ICON_NONE) & UI_but_is_tool(but));
2369 
2370  /* XXX add way to draw icons at a different size!
2371  * Use small icons for popup. */
2372 #ifdef USE_UI_TOOLBAR_HACK
2373  const float aspect_orig = but->block->aspect;
2374  if (is_tool && (but->block->flag & UI_BLOCK_POPOVER)) {
2375  but->block->aspect *= 2.0f;
2376  }
2377 #endif
2378 
2379  const BIFIconID icon = ui_but_icon(but);
2380  const int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT;
2381  const float icon_size = icon_size_init / (but->block->aspect * U.inv_dpi_fac);
2382  const float icon_padding = 2 * UI_DPI_FAC;
2383 
2384 #ifdef USE_UI_TOOLBAR_HACK
2385  if (is_tool) {
2386  /* pass (even if its a menu toolbar) */
2387  but->drawflag |= UI_BUT_TEXT_LEFT;
2388  but->drawflag |= UI_BUT_ICON_LEFT;
2389  }
2390 #endif
2391 
2392  /* menu item - add some more padding so menus don't feel cramped. it must
2393  * be part of the button so that this area is still clickable */
2394  if (is_tool) {
2395  /* pass (even if its a menu toolbar) */
2396  }
2397  else if (ui_block_is_pie_menu(but->block)) {
2398  if (but->emboss == UI_EMBOSS_RADIAL) {
2399  rect->xmin += 0.3f * U.widget_unit;
2400  }
2401  }
2402  /* Menu items, but only if they are not icon-only (rare). */
2403  else if (ui_block_is_menu(but->block) && but->drawstr[0]) {
2404  rect->xmin += 0.2f * U.widget_unit;
2405  }
2406 
2407  /* By default icon is the color of text, but can optionally override with but->col. */
2408  widget_draw_icon(but, icon, alpha, rect, (but->col[3] != 0) ? but->col : wcol->text);
2409 
2410  if (show_menu_icon) {
2412  widget_draw_submenu_tria(but, rect, wcol);
2413  }
2414 
2415 #ifdef USE_UI_TOOLBAR_HACK
2416  but->block->aspect = aspect_orig;
2417 #endif
2418 
2419  rect->xmin += round_fl_to_int(icon_size + icon_padding);
2420  }
2421 
2422  if (!no_text_padding) {
2423  const int text_padding = round_fl_to_int((UI_TEXT_MARGIN_X * U.widget_unit) /
2424  but->block->aspect);
2425  if (but->editstr) {
2426  rect->xmin += text_padding;
2427  }
2428  else if (but->flag & UI_BUT_DRAG_MULTI) {
2429  const bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL;
2430  if (text_is_edited || (but->drawflag & UI_BUT_TEXT_LEFT)) {
2431  rect->xmin += text_padding;
2432  }
2433  }
2434  else if (but->drawflag & UI_BUT_TEXT_LEFT) {
2435  rect->xmin += text_padding;
2436  }
2437  else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
2438  rect->xmax -= text_padding;
2439  }
2440  }
2441  else {
2442  /* In case a separate text label and some other button are placed under each other,
2443  and the outline of the button does not contrast with the background.
2444  Add an offset (thickness of the outline) so that the text does not stick out visually. */
2445  if (but->drawflag & UI_BUT_TEXT_LEFT) {
2446  rect->xmin += U.pixelsize;
2447  }
2448  else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
2449  rect->xmax -= U.pixelsize;
2450  }
2451  }
2452 
2453  /* Menu contains sub-menu items with triangle icon on their right. Shortcut
2454  * strings should be drawn with some padding to the right then. */
2455  if (ui_block_is_menu(but->block) &&
2457  rect->xmax -= UI_MENU_SUBMENU_PADDING;
2458  }
2459 
2460  /* extra icons, e.g. 'x' icon to clear text or icon for eyedropper */
2461  widget_draw_extra_icons(wcol, but, rect, alpha);
2462 
2463  /* clip but->drawstr to fit in available space */
2464  if (but->editstr && but->pos >= 0) {
2465  ui_text_clip_cursor(fstyle, but, rect);
2466  }
2467  else if (but->drawstr[0] == '\0') {
2468  /* bypass text clipping on icon buttons */
2469  but->ofs = 0;
2470  but->strwidth = 0;
2471  }
2472  else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
2473  ui_text_clip_right_label(fstyle, but, rect);
2474  }
2475  else if (but->flag & UI_BUT_HAS_SEP_CHAR) {
2476  /* Clip middle, but protect in all case right part containing the shortcut, if any. */
2477  ui_text_clip_middle_protect_right(fstyle, but, rect, UI_SEP_CHAR);
2478  }
2479  else {
2480  ui_text_clip_middle(fstyle, but, rect);
2481  }
2482 
2483  /* always draw text for textbutton cursor */
2484  widget_draw_text(fstyle, wcol, but, rect);
2485 
2486  ui_but_text_password_hide(password_str, but, true);
2487 
2488  /* if a widget uses font shadow it has to be deactivated now */
2489  BLF_disable(fstyle->uifont_id, BLF_SHADOW);
2490 }
2491 
2492 #undef UI_TEXT_CLIP_MARGIN
2493 
2496 /* -------------------------------------------------------------------- */
2502 /* put all widget colors on half alpha, use local storage */
2503 static void ui_widget_color_disabled(uiWidgetType *wt, const int state)
2504 {
2505  static uiWidgetColors wcol_theme_s;
2506 
2507  wcol_theme_s = *wt->wcol_theme;
2508 
2509  const float factor = widget_alpha_factor(state);
2510 
2511  wcol_theme_s.outline[3] *= factor;
2512  wcol_theme_s.inner[3] *= factor;
2513  wcol_theme_s.inner_sel[3] *= factor;
2514  wcol_theme_s.item[3] *= factor;
2515  wcol_theme_s.text[3] *= factor;
2516  wcol_theme_s.text_sel[3] *= factor;
2517 
2518  wt->wcol_theme = &wcol_theme_s;
2519 }
2520 
2522 {
2523  const bool dark = (rgb_to_grayscale_byte(wcol->text) > rgb_to_grayscale_byte(wcol->inner));
2524  color_mul_hsl_v3(wcol->inner, 1.0f, 1.15f, dark ? 1.2f : 1.1f);
2525  color_mul_hsl_v3(wcol->outline, 1.0f, 1.15f, 1.15f);
2526  color_mul_hsl_v3(wcol->text, 1.0f, 1.15f, dark ? 1.25f : 0.8f);
2527 }
2528 
2530  int state,
2531  int drawflag,
2532  const eUIEmbossType emboss)
2533 {
2534  /* Explicitly require #UI_EMBOSS_NONE_OR_STATUS for color blending with no emboss. */
2535  if (emboss == UI_EMBOSS_NONE) {
2536  return NULL;
2537  }
2538 
2539  if (drawflag & UI_BUT_ANIMATED_CHANGED) {
2540  return wcol_state->inner_changed_sel;
2541  }
2542  if (state & UI_BUT_ANIMATED_KEY) {
2543  return wcol_state->inner_key_sel;
2544  }
2545  if (state & UI_BUT_ANIMATED) {
2546  return wcol_state->inner_anim_sel;
2547  }
2548  if (state & UI_BUT_DRIVEN) {
2549  return wcol_state->inner_driven_sel;
2550  }
2551  if (state & UI_BUT_OVERRIDDEN) {
2552  return wcol_state->inner_overridden_sel;
2553  }
2554  return NULL;
2555 }
2556 
2557 /* copy colors from theme, and set changes in it based on state */
2558 static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
2559 {
2560  uiWidgetStateColors *wcol_state = wt->wcol_state;
2561 
2562  if ((state & UI_BUT_LIST_ITEM) && !(state & UI_STATE_TEXT_INPUT)) {
2563  /* Override default widget's colors. */
2564  bTheme *btheme = UI_GetTheme();
2565  wt->wcol_theme = &btheme->tui.wcol_list_item;
2566 
2569  }
2570  }
2571 
2572  wt->wcol = *(wt->wcol_theme);
2573 
2574  const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag, emboss);
2575 
2576  if (state & UI_SELECT) {
2578  if (color_blend != NULL) {
2579  color_blend_v3_v3(wt->wcol.inner, color_blend, wcol_state->blend);
2580  }
2581 
2583 
2584  if (state & UI_SELECT) {
2585  SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
2586  }
2587  }
2588  else {
2589  if (state & UI_BUT_ACTIVE_DEFAULT) {
2592  }
2593  if (color_blend != NULL) {
2594  color_blend_v3_v3(wt->wcol.inner, color_blend, wcol_state->blend);
2595  }
2596 
2597  /* Add "hover" highlight. Ideally this could apply in all cases,
2598  * even if UI_SELECT. But currently this causes some flickering
2599  * as buttons can be created and updated without respect to mouse
2600  * position and so can draw without UI_ACTIVE set. See D6503. */
2601  if (state & UI_ACTIVE) {
2602  widget_active_color(&wt->wcol);
2603  }
2604  }
2605 
2606  if (state & UI_BUT_REDALERT) {
2607  const uchar red[4] = {255, 0, 0};
2608  if (wt->draw && emboss != UI_EMBOSS_NONE) {
2609  color_blend_v3_v3(wt->wcol.inner, red, 0.4f);
2610  }
2611  else {
2612  color_blend_v3_v3(wt->wcol.text, red, 0.4f);
2613  }
2614  }
2615 
2616  if (state & UI_BUT_DRAG_MULTI) {
2617  /* the button isn't SELECT but we're editing this so draw with sel color */
2619  SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
2620  color_blend_v3_v3(wt->wcol.text, wt->wcol.text_sel, 0.85f);
2621  }
2622 
2623  if (state & UI_BUT_NODE_ACTIVE) {
2624  const uchar blue[4] = {86, 128, 194};
2625  color_blend_v3_v3(wt->wcol.inner, blue, 0.3f);
2626  }
2627 }
2628 
2631 /* -------------------------------------------------------------------- */
2635 /* sliders use special hack which sets 'item' as inner when drawing filling */
2636 static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
2637 {
2638  uiWidgetStateColors *wcol_state = wt->wcol_state;
2639 
2640  /* call this for option button */
2641  widget_state(wt, state, drawflag, emboss);
2642 
2643  const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag, emboss);
2644  if (color_blend != NULL) {
2645  /* Set the slider 'item' so that it reflects state settings too.
2646  * De-saturate so the color of the slider doesn't conflict with the blend color,
2647  * which can make the color hard to see when the slider is set to full (see T66102). */
2648  wt->wcol.item[0] = wt->wcol.item[1] = wt->wcol.item[2] = rgb_to_grayscale_byte(wt->wcol.item);
2649  color_blend_v3_v3(wt->wcol.item, color_blend, wcol_state->blend);
2651  }
2652 
2653  if (state & UI_SELECT) {
2654  SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
2655  }
2656 }
2657 
2658 /* labels use theme colors for text */
2660  int state,
2661  int drawflag,
2662  eUIEmbossType emboss)
2663 {
2664  const bTheme *btheme = UI_GetTheme();
2665 
2666  const uiWidgetColors *old_wcol = wt->wcol_theme;
2667  uiWidgetColors wcol_menu_option = *wt->wcol_theme;
2668 
2669  /* Override the checkbox theme colors to use the menu-back text colors. */
2670  copy_v3_v3_uchar(wcol_menu_option.text, btheme->tui.wcol_menu_back.text);
2671  copy_v3_v3_uchar(wcol_menu_option.text_sel, btheme->tui.wcol_menu_back.text_sel);
2672  wt->wcol_theme = &wcol_menu_option;
2673 
2674  widget_state(wt, state, drawflag, emboss);
2675 
2676  wt->wcol_theme = old_wcol;
2677 }
2678 
2680  int UNUSED(state),
2681  int UNUSED(drawflag),
2682  eUIEmbossType UNUSED(emboss))
2683 {
2684  wt->wcol = *(wt->wcol_theme);
2685 }
2686 
2687 /* special case, button that calls pulldown */
2689  int UNUSED(state),
2690  int UNUSED(drawflag),
2691  eUIEmbossType UNUSED(emboss))
2692 {
2693  wt->wcol = *(wt->wcol_theme);
2694 }
2695 
2696 /* special case, pie menu items */
2698  int state,
2699  int UNUSED(drawflag),
2700  eUIEmbossType UNUSED(emboss))
2701 {
2702  wt->wcol = *(wt->wcol_theme);
2703 
2704  /* active and disabled (not so common) */
2705  if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
2706  color_blend_v3_v3(wt->wcol.text, wt->wcol.text_sel, 0.5f);
2707  /* draw the backdrop at low alpha, helps navigating with keys
2708  * when disabled items are active */
2709  copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.item);
2710  wt->wcol.inner[3] = 64;
2711  }
2712  else {
2713  /* regular active */
2714  if (state & (UI_SELECT | UI_ACTIVE)) {
2716  }
2717  else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
2718  /* regular disabled */
2719  color_blend_v3_v3(wt->wcol.text, wt->wcol.inner, 0.5f);
2720  }
2721 
2722  if (state & UI_SELECT) {
2724  }
2725  else if (state & UI_ACTIVE) {
2726  copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.item);
2727  }
2728  }
2729 }
2730 
2731 /* special case, menu items */
2733  int state,
2734  int UNUSED(drawflag),
2735  eUIEmbossType UNUSED(emboss))
2736 {
2737  wt->wcol = *(wt->wcol_theme);
2738 
2739  /* active and disabled (not so common) */
2740  if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
2741  /* draw the backdrop at low alpha, helps navigating with keys
2742  * when disabled items are active */
2743  wt->wcol.text[3] = 128;
2744  color_blend_v3_v3(wt->wcol.inner, wt->wcol.text, 0.5f);
2745  wt->wcol.inner[3] = 64;
2746  }
2747  else {
2748  /* regular active */
2749  if (state & UI_ACTIVE) {
2751  }
2752  else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
2753  /* regular disabled */
2754  color_blend_v3_v3(wt->wcol.text, wt->wcol.inner, 0.5f);
2755  }
2756 
2757  if (state & UI_ACTIVE) {
2759  }
2760  }
2761 }
2762 
2765 /* -------------------------------------------------------------------- */
2769 /* outside of rect, rad to left/bottom/right */
2770 static void widget_softshadow(const rcti *rect, int roundboxalign, const float radin)
2771 {
2772  bTheme *btheme = UI_GetTheme();
2773  uiWidgetBase wtb;
2774  rcti rect1 = *rect;
2775  float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2];
2776  const float radout = UI_ThemeMenuShadowWidth();
2777 
2778  /* disabled shadow */
2779  if (radout == 0.0f) {
2780  return;
2781  }
2782 
2783  /* prevent tooltips to not show round shadow */
2784  if (radout > 0.2f * BLI_rcti_size_y(&rect1)) {
2785  rect1.ymax -= 0.2f * BLI_rcti_size_y(&rect1);
2786  }
2787  else {
2788  rect1.ymax -= radout;
2789  }
2790 
2791  /* inner part */
2792  const int totvert = round_box_shadow_edges(wtb.inner_v,
2793  &rect1,
2794  radin,
2795  roundboxalign &
2797  0.0f);
2798 
2799  /* we draw a number of increasing size alpha quad strips */
2800  const float alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout;
2801 
2804 
2806 
2807  for (int step = 1; step <= (int)radout; step++) {
2808  const float expfac = sqrtf(step / radout);
2809 
2810  round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
2811 
2812  immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
2813 
2814  widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
2815 
2816  widget_draw_vertex_buffer(pos, 0, GPU_PRIM_TRI_STRIP, triangle_strip, NULL, totvert * 2);
2817  }
2818 
2819  immUnbindProgram();
2820 }
2821 
2822 static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
2823 {
2824  uiWidgetBase wtb;
2825  int roundboxalign = UI_CNR_ALL;
2826 
2827  widget_init(&wtb);
2828 
2829  /* menu is 2nd level or deeper */
2830  if (flag & UI_BLOCK_POPUP) {
2831  // rect->ymin -= 4.0;
2832  // rect->ymax += 4.0;
2833  }
2834  else if (direction == UI_DIR_DOWN) {
2835  roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
2836  rect->ymin -= 0.1f * U.widget_unit;
2837  }
2838  else if (direction == UI_DIR_UP) {
2839  roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
2840  rect->ymax += 0.1f * U.widget_unit;
2841  }
2842 
2844  widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
2845 
2846  round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
2847  wtb.draw_emboss = false;
2848  widgetbase_draw(&wtb, wcol);
2849 
2851 }
2852 
2853 static void ui_hsv_cursor(float x, float y)
2854 {
2857 
2859 
2860  immUniformColor3f(1.0f, 1.0f, 1.0f);
2861  imm_draw_circle_fill_2d(pos, x, y, 3.0f * U.pixelsize, 8);
2862 
2864  GPU_line_smooth(true);
2865  immUniformColor3f(0.0f, 0.0f, 0.0f);
2866  imm_draw_circle_wire_2d(pos, x, y, 3.0f * U.pixelsize, 12);
2868  GPU_line_smooth(false);
2869 
2870  immUnbindProgram();
2871 }
2872 
2874  const rcti *rect, const float mx, const float my, float *r_val_rad, float *r_val_dist)
2875 {
2876  /* duplication of code... well, simple is better now */
2877  const float centx = BLI_rcti_cent_x_fl(rect);
2878  const float centy = BLI_rcti_cent_y_fl(rect);
2879  const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
2880  const float m_delta[2] = {mx - centx, my - centy};
2881  const float dist_sq = len_squared_v2(m_delta);
2882 
2883  *r_val_dist = (dist_sq < (radius * radius)) ? sqrtf(dist_sq) / radius : 1.0f;
2884  *r_val_rad = atan2f(m_delta[0], m_delta[1]) / (2.0f * (float)M_PI) + 0.5f;
2885 }
2886 
2887 /* cursor in hsv circle, in float units -1 to 1, to map on radius */
2889  const ColorPicker *cpicker, const rcti *rect, const float *hsv, float *r_xpos, float *r_ypos)
2890 {
2891  /* duplication of code... well, simple is better now */
2892  const float centx = BLI_rcti_cent_x_fl(rect);
2893  const float centy = BLI_rcti_cent_y_fl(rect);
2894  const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
2895 
2896  const float ang = 2.0f * (float)M_PI * hsv[0] + (float)M_PI_2;
2897 
2898  float radius_t;
2899  if (cpicker->use_color_cubic && (U.color_picker_type == USER_CP_CIRCLE_HSV)) {
2900  radius_t = (1.0f - pow3f(1.0f - hsv[1]));
2901  }
2902  else {
2903  radius_t = hsv[1];
2904  }
2905 
2906  const float rad = clamp_f(radius_t, 0.0f, 1.0f) * radius;
2907  *r_xpos = centx + cosf(-ang) * rad;
2908  *r_ypos = centy + sinf(-ang) * rad;
2909 }
2910 
2911 static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
2912 {
2913  /* TODO(merwin): reimplement as shader for pixel-perfect colors */
2914 
2915  const int tot = 64;
2916  const float radstep = 2.0f * (float)M_PI / (float)tot;
2917  const float centx = BLI_rcti_cent_x_fl(rect);
2918  const float centy = BLI_rcti_cent_y_fl(rect);
2919  const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
2920 
2921  ColorPicker *cpicker = but->custom_data;
2922  float rgb[3], hsv[3], rgb_center[3];
2923  const bool is_color_gamma = ui_but_is_color_gamma(but);
2924 
2925  /* Initialize for compatibility. */
2926  copy_v3_v3(hsv, cpicker->hsv_perceptual);
2927 
2928  /* Compute current hue. */
2929  ui_but_v3_get(but, rgb);
2932 
2933  CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */
2934 
2935  /* exception: if 'lock' is set
2936  * lock the value of the color wheel to 1.
2937  * Useful for color correction tools where you're only interested in hue. */
2938  if (cpicker->use_color_lock) {
2939  if (U.color_picker_type == USER_CP_CIRCLE_HSV) {
2940  hsv[2] = 1.0f;
2941  }
2942  else {
2943  hsv[2] = 0.5f;
2944  }
2945  }
2946 
2947  const float hsv_center[3] = {0.0f, 0.0f, hsv[2]};
2948  ui_color_picker_hsv_to_rgb(hsv_center, rgb_center);
2949  ui_perceptual_to_scene_linear_space(but, rgb_center);
2950 
2951  if (!is_color_gamma) {
2952  ui_block_cm_to_display_space_v3(but->block, rgb_center);
2953  }
2954 
2957  const uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2958 
2960 
2961  immBegin(GPU_PRIM_TRI_FAN, tot + 2);
2962  immAttr3fv(color, rgb_center);
2963  immVertex2f(pos, centx, centy);
2964 
2965  float ang = 0.0f;
2966  for (int a = 0; a <= tot; a++, ang += radstep) {
2967  const float si = sinf(ang);
2968  const float co = cosf(ang);
2969  float hsv_ang[3];
2970  float rgb_ang[3];
2971 
2973  rect, centx + co * radius, centy + si * radius, hsv_ang, hsv_ang + 1);
2974  hsv_ang[2] = hsv[2];
2975 
2976  ui_color_picker_hsv_to_rgb(hsv_ang, rgb_ang);
2978 
2979  if (!is_color_gamma) {
2980  ui_block_cm_to_display_space_v3(but->block, rgb_ang);
2981  }
2982 
2983  immAttr3fv(color, rgb_ang);
2984  immVertex2f(pos, centx + co * radius, centy + si * radius);
2985  }
2986  immEnd();
2987  immUnbindProgram();
2988 
2989  /* fully rounded outline */
2990  format = immVertexFormat();
2992 
2994 
2996  GPU_line_smooth(true);
2997 
2999  imm_draw_circle_wire_2d(pos, centx, centy, radius, tot);
3000 
3001  immUnbindProgram();
3002 
3004  GPU_line_smooth(false);
3005 
3006  /* cursor */
3007  copy_v3_v3(hsv, cpicker->hsv_perceptual);
3008  ui_but_v3_get(but, rgb);
3011 
3012  float xpos, ypos;
3013  ui_hsvcircle_pos_from_vals(cpicker, rect, hsv, &xpos, &ypos);
3014  ui_hsv_cursor(xpos, ypos);
3015 }
3016 
3019 /* -------------------------------------------------------------------- */
3023 /* draws in resolution of 48x4 colors */
3024 void ui_draw_gradient(const rcti *rect,
3025  const float hsv[3],
3026  const eButGradientType type,
3027  const float alpha)
3028 {
3029  /* allows for 4 steps (red->yellow) */
3030  const int steps = 48;
3031  const float color_step = 1.0f / steps;
3032  int a;
3033  const float h = hsv[0], s = hsv[1], v = hsv[2];
3034  float dx, dy, sx1, sx2, sy;
3035  float col0[4][3]; /* left half, rect bottom to top */
3036  float col1[4][3]; /* right half, rect bottom to top */
3037 
3038  /* draw series of gouraud rects */
3039 
3040  switch (type) {
3041  case UI_GRAD_SV:
3042  hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
3043  hsv_to_rgb(h, 0.0, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
3044  hsv_to_rgb(h, 0.0, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
3045  hsv_to_rgb(h, 0.0, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
3046  break;
3047  case UI_GRAD_HV:
3048  hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
3049  hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
3050  hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
3051  hsv_to_rgb(0.0, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
3052  break;
3053  case UI_GRAD_HS:
3054  hsv_to_rgb(0.0, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]);
3055  hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
3056  hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
3057  hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
3058  break;
3059  case UI_GRAD_H:
3060  hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
3061  copy_v3_v3(col1[1], col1[0]);
3062  copy_v3_v3(col1[2], col1[0]);
3063  copy_v3_v3(col1[3], col1[0]);
3064  break;
3065  case UI_GRAD_S:
3066  hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
3067  copy_v3_v3(col1[0], col1[1]);
3068  copy_v3_v3(col1[2], col1[1]);
3069  copy_v3_v3(col1[3], col1[1]);
3070  break;
3071  case UI_GRAD_V:
3072  hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
3073  copy_v3_v3(col1[0], col1[2]);
3074  copy_v3_v3(col1[1], col1[2]);
3075  copy_v3_v3(col1[3], col1[2]);
3076  break;
3077  default:
3078  BLI_assert(!"invalid 'type' argument");
3079  hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]);
3080  copy_v3_v3(col1[0], col1[2]);
3081  copy_v3_v3(col1[1], col1[2]);
3082  copy_v3_v3(col1[3], col1[2]);
3083  break;
3084  }
3085 
3086  /* old below */
3091 
3092  immBegin(GPU_PRIM_TRIS, steps * 3 * 6);
3093 
3094  /* 0.999 = prevent float inaccuracy for steps */
3095  for (dx = 0.0f; dx < 0.999f; dx += color_step) {
3096  const float dx_next = dx + color_step;
3097 
3098  /* previous color */
3099  copy_v3_v3(col0[0], col1[0]);
3100  copy_v3_v3(col0[1], col1[1]);
3101  copy_v3_v3(col0[2], col1[2]);
3102  copy_v3_v3(col0[3], col1[3]);
3103 
3104  /* new color */
3105  switch (type) {
3106  case UI_GRAD_SV:
3107  hsv_to_rgb(h, dx, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
3108  hsv_to_rgb(h, dx, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
3109  hsv_to_rgb(h, dx, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
3110  hsv_to_rgb(h, dx, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
3111  break;
3112  case UI_GRAD_HV:
3113  hsv_to_rgb(dx_next, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
3114  hsv_to_rgb(dx_next, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
3115  hsv_to_rgb(dx_next, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
3116  hsv_to_rgb(dx_next, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
3117  break;
3118  case UI_GRAD_HS:
3119  hsv_to_rgb(dx_next, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]);
3120  hsv_to_rgb(dx_next, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
3121  hsv_to_rgb(dx_next, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
3122  hsv_to_rgb(dx_next, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
3123  break;
3124  case UI_GRAD_H:
3125  /* annoying but without this the color shifts - could be solved some other way
3126  * - campbell */
3127  hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
3128  copy_v3_v3(col1[1], col1[0]);
3129  copy_v3_v3(col1[2], col1[0]);
3130  copy_v3_v3(col1[3], col1[0]);
3131  break;
3132  case UI_GRAD_S:
3133  hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
3134  copy_v3_v3(col1[0], col1[1]);
3135  copy_v3_v3(col1[2], col1[1]);
3136  copy_v3_v3(col1[3], col1[1]);
3137  break;
3138  case UI_GRAD_V:
3139  hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
3140  copy_v3_v3(col1[0], col1[2]);
3141  copy_v3_v3(col1[1], col1[2]);
3142  copy_v3_v3(col1[3], col1[2]);
3143  break;
3144  default:
3145  break;
3146  }
3147 
3148  /* rect */
3149  sx1 = rect->xmin + dx * BLI_rcti_size_x(rect);
3150  sx2 = rect->xmin + dx_next * BLI_rcti_size_x(rect);
3151  sy = rect->ymin;
3152  dy = (float)BLI_rcti_size_y(rect) / 3.0f;
3153 
3154  for (a = 0; a < 3; a++, sy += dy) {
3155  immAttr4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
3156  immVertex2f(pos, sx1, sy);
3157 
3158  immAttr4f(col, col1[a][0], col1[a][1], col1[a][2], alpha);
3159  immVertex2f(pos, sx2, sy);
3160 
3161  immAttr4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
3162  immVertex2f(pos, sx2, sy + dy);
3163 
3164  immAttr4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
3165  immVertex2f(pos, sx1, sy);
3166 
3167  immAttr4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
3168  immVertex2f(pos, sx2, sy + dy);
3169 
3170  immAttr4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
3171  immVertex2f(pos, sx1, sy + dy);
3172  }
3173  }
3174  immEnd();
3175 
3176  immUnbindProgram();
3177 }
3178 
3180  const uiButHSVCube *hsv_but, const rcti *rect, const float *hsv, float *r_xp, float *r_yp)
3181 {
3182  float x = 0.0f, y = 0.0f;
3183 
3184  switch (hsv_but->gradient_type) {
3185  case UI_GRAD_SV:
3186  x = hsv[1];
3187  y = hsv[2];
3188  break;
3189  case UI_GRAD_HV:
3190  x = hsv[0];
3191  y = hsv[2];
3192  break;
3193  case UI_GRAD_HS:
3194  x = hsv[0];
3195  y = hsv[1];
3196  break;
3197  case UI_GRAD_H:
3198  x = hsv[0];
3199  y = 0.5;
3200  break;
3201  case UI_GRAD_S:
3202  x = hsv[1];
3203  y = 0.5;
3204  break;
3205  case UI_GRAD_V:
3206  x = hsv[2];
3207  y = 0.5;
3208  break;
3209  case UI_GRAD_L_ALT:
3210  x = 0.5f;
3211  /* exception only for value strip - use the range set in but->min/max */
3212  y = hsv[2];
3213  break;
3214  case UI_GRAD_V_ALT:
3215  x = 0.5f;
3216  /* exception only for value strip - use the range set in but->min/max */
3217  y = (hsv[2] - hsv_but->but.softmin) / (hsv_but->but.softmax - hsv_but->but.softmin);
3218  break;
3219  }
3220 
3221  /* cursor */
3222  *r_xp = rect->xmin + x * BLI_rcti_size_x(rect);
3223  *r_yp = rect->ymin + y * BLI_rcti_size_y(rect);
3224 }
3225 
3226 static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
3227 {
3228  const uiButHSVCube *hsv_but = (uiButHSVCube *)but;
3229  float rgb[3];
3230  float x = 0.0f, y = 0.0f;
3231  ColorPicker *cpicker = but->custom_data;
3232  float *hsv = cpicker->hsv_perceptual;
3233  float hsv_n[3];
3234 
3235  /* Initialize for compatibility. */
3236  copy_v3_v3(hsv_n, hsv);
3237 
3238  ui_but_v3_get(but, rgb);
3240  rgb_to_hsv_compat_v(rgb, hsv_n);
3241 
3242  ui_draw_gradient(rect, hsv_n, hsv_but->gradient_type, 1.0f);
3243 
3244  ui_hsvcube_pos_from_vals(hsv_but, rect, hsv_n, &x, &y);
3245  CLAMP(x, rect->xmin + 3.0f, rect->xmax - 3.0f);
3246  CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
3247 
3248  ui_hsv_cursor(x, y);
3249 
3250  /* outline */
3254  immUniformColor3ub(0, 0, 0);
3255  imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
3256  immUnbindProgram();
3257 }
3258 
3259 /* vertical 'value' slider, using new widget code */
3260 static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
3261 {
3262  const uiButHSVCube *hsv_but = (uiButHSVCube *)but;
3263  bTheme *btheme = UI_GetTheme();
3264  uiWidgetColors *wcol = &btheme->tui.wcol_numslider;
3265  uiWidgetBase wtb;
3266  const float rad = wcol->roundness * BLI_rcti_size_x(rect);
3267  float x, y;
3268  float rgb[3], hsv[3], v;
3269 
3270  ui_but_v3_get(but, rgb);
3272 
3273  if (hsv_but->gradient_type == UI_GRAD_L_ALT) {
3274  rgb_to_hsl_v(rgb, hsv);
3275  }
3276  else {
3277  rgb_to_hsv_v(rgb, hsv);
3278  }
3279  v = hsv[2];
3280 
3281  /* map v from property range to [0,1] */
3282  if (hsv_but->gradient_type == UI_GRAD_V_ALT) {
3283  const float min = but->softmin, max = but->softmax;
3284  v = (v - min) / (max - min);
3285  }
3286 
3287  widget_init(&wtb);
3288 
3289  /* fully rounded */
3290  round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
3291 
3292  /* setup temp colors */
3293  widgetbase_draw(&wtb,
3294  &((uiWidgetColors){
3295  .outline = {0, 0, 0, 255},
3296  .inner = {128, 128, 128, 255},
3297  .shadetop = 127,
3298  .shadedown = -128,
3299  .shaded = 1,
3300  }));
3301 
3302  /* We are drawing on top of widget bases. Flush cache. */
3306 
3307  /* cursor */
3308  x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
3309  y = rect->ymin + v * BLI_rcti_size_y(rect);
3310  CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
3311 
3312  ui_hsv_cursor(x, y);
3313 }
3314 
3316 static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol)
3317 {
3318  const int y = rect->ymin + BLI_rcti_size_y(rect) / 2 - 1;
3319  const uchar col[4] = {
3320  wcol->text[0],
3321  wcol->text[1],
3322  wcol->text[2],
3323  30,
3324  };
3325 
3329 
3332  GPU_line_width(1.0f);
3333 
3335  immVertex2f(pos, rect->xmin, y);
3336  immVertex2f(pos, rect->xmax, y);
3337  immEnd();
3338 
3340 
3341  immUnbindProgram();
3342 }
3343 
3346 /* -------------------------------------------------------------------- */
3351  uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, bool emboss)
3352 {
3353  const float rad = wcol->roundness * BLI_rcti_size_y(rect);
3354  const int handle_width = min_ii(BLI_rcti_size_x(rect) / 3, BLI_rcti_size_y(rect) * 0.7f);
3355 
3356  if (state & UI_SELECT) {
3357  SWAP(short, wcol->shadetop, wcol->shadedown);
3358  }
3359 
3360  uiWidgetBase wtb;
3361  widget_init(&wtb);
3362 
3363  if (!emboss) {
3364  round_box_edges(&wtb, roundboxalign, rect, rad);
3365  }
3366  else {
3367  wtb.draw_inner = false;
3368  wtb.draw_outline = false;
3369  }
3370 
3371  /* decoration */
3372  if ((state & UI_ACTIVE) && !(state & UI_STATE_TEXT_INPUT)) {
3373  uiWidgetColors wcol_zone;
3374  uiWidgetBase wtb_zone;
3375  rcti rect_zone;
3376  int roundboxalign_zone;
3377 
3378  /* left arrow zone */
3379  widget_init(&wtb_zone);
3380  wtb_zone.draw_outline = false;
3381  wtb_zone.draw_emboss = false;
3382 
3383  wcol_zone = *wcol;
3384  copy_v3_v3_uchar(wcol_zone.item, wcol->text);
3385  if (state & UI_STATE_ACTIVE_LEFT) {
3386  widget_active_color(&wcol_zone);
3387  }
3388 
3389  rect_zone = *rect;
3390  rect_zone.xmax = rect->xmin + handle_width + U.pixelsize;
3391  roundboxalign_zone = roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
3392  round_box_edges(&wtb_zone, roundboxalign_zone, &rect_zone, rad);
3393 
3394  shape_preset_init_number_arrows(&wtb_zone.tria1, &rect_zone, 0.6f, 'l');
3395  widgetbase_draw(&wtb_zone, &wcol_zone);
3396 
3397  /* right arrow zone */
3398  widget_init(&wtb_zone);
3399  wtb_zone.draw_outline = false;
3400  wtb_zone.draw_emboss = false;
3401  wtb_zone.tria1.type = ROUNDBOX_TRIA_ARROWS;
3402 
3403  wcol_zone = *wcol;
3404  copy_v3_v3_uchar(wcol_zone.item, wcol->text);
3405  if (state & UI_STATE_ACTIVE_RIGHT) {
3406  widget_active_color(&wcol_zone);
3407  }
3408 
3409  rect_zone = *rect;
3410  rect_zone.xmin = rect->xmax - handle_width - U.pixelsize;
3411  roundboxalign_zone = roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
3412  round_box_edges(&wtb_zone, roundboxalign_zone, &rect_zone, rad);
3413 
3414  shape_preset_init_number_arrows(&wtb_zone.tria2, &rect_zone, 0.6f, 'r');
3415  widgetbase_draw(&wtb_zone, &wcol_zone);
3416 
3417  /* middle highlight zone */
3418  widget_init(&wtb_zone);
3419  wtb_zone.draw_outline = false;
3420  wtb_zone.draw_emboss = false;
3421 
3422  wcol_zone = *wcol;
3423  copy_v3_v3_uchar(wcol_zone.item, wcol->text);
3425  widget_active_color(&wcol_zone);
3426  }
3427 
3428  rect_zone = *rect;
3429  rect_zone.xmin = rect->xmin + handle_width - U.pixelsize;
3430  rect_zone.xmax = rect->xmax - handle_width + U.pixelsize;
3431  round_box_edges(&wtb_zone, 0, &rect_zone, 0);
3432  widgetbase_draw(&wtb_zone, &wcol_zone);
3433 
3434  /* outline */
3435  wtb.draw_inner = false;
3436  widgetbase_draw(&wtb, wcol);
3437  }
3438  else {
3439  /* inner and outline */
3440  widgetbase_draw(&wtb, wcol);
3441  }
3442 
3443  if (!(state & UI_STATE_TEXT_INPUT)) {
3444  const float textofs = 0.425f * BLI_rcti_size_y(rect);
3445 
3446  /* text space */
3447  rect->xmin += textofs;
3448  rect->xmax -= textofs;
3449  }
3450 }
3451 
3452 static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
3453 {
3454  widget_numbut_draw(wcol, rect, state, roundboxalign, false);
3455 }
3456 
3457 static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
3458 {
3459  uiWidgetBase wtb;
3460  widget_init(&wtb);
3461 
3462  const float rad = wcol->roundness * U.widget_unit;
3463  round_box_edges(&wtb, roundboxalign, rect, rad);
3464 
3465  /* decoration */
3467  /* copy size and center to 2nd tria */
3468  wtb.tria2 = wtb.tria1;
3469 
3470  widgetbase_draw(&wtb, wcol);
3471 
3472  /* text space, arrows are about 0.6 height of button */
3473  rect->xmax -= (6 * BLI_rcti_size_y(rect)) / 10;
3474 }
3475 
3480  uiWidgetColors *wcol,
3481  rcti *rect,
3482  int UNUSED(state),
3483  int UNUSED(roundboxalign))
3484 {
3485  uiWidgetBase wtb;
3486  widget_init(&wtb);
3487  wtb.draw_inner = false;
3488  wtb.draw_outline = false;
3489 
3490  /* decoration */
3492  /* copy size and center to 2nd tria */
3493  wtb.tria2 = wtb.tria1;
3494 
3495  widgetbase_draw(&wtb, wcol);
3496 }
3497 
3502  uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
3503 {
3504  widget_numbut_draw(wcol, rect, state, roundboxalign, true);
3505 }
3506 
3507 /* function in use for buttons and for view2d sliders */
3508 void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *slider, int state)
3509 {
3510  uiWidgetBase wtb;
3511  bool outline = false;
3512 
3513  widget_init(&wtb);
3514 
3515  /* determine horizontal/vertical */
3516  const bool horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
3517 
3518  const float rad = (horizontal) ? wcol->roundness * BLI_rcti_size_y(rect) :
3519  wcol->roundness * BLI_rcti_size_x(rect);
3520 
3521  wtb.uniform_params.shade_dir = (horizontal) ? 1.0f : 0.0;
3522 
3523  /* draw back part, colors swapped and shading inverted */
3524  if (horizontal) {
3525  SWAP(short, wcol->shadetop, wcol->shadedown);
3526  }
3527 
3528  round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
3529  widgetbase_draw(&wtb, wcol);
3530 
3531  /* slider */
3532  if ((BLI_rcti_size_x(slider) < 2) || (BLI_rcti_size_y(slider) < 2)) {
3533  /* pass */
3534  }
3535  else {
3536  SWAP(short, wcol->shadetop, wcol->shadedown);
3537 
3538  copy_v4_v4_uchar(wcol->inner, wcol->item);
3539 
3540  if (wcol->shadetop > wcol->shadedown) {
3541  wcol->shadetop += 20; /* XXX violates themes... */
3542  }
3543  else {
3544  wcol->shadedown += 20;
3545  }
3546 
3547  if (state & UI_SCROLL_PRESSED) {
3548  wcol->inner[0] = wcol->inner[0] >= 250 ? 255 : wcol->inner[0] + 5;
3549  wcol->inner[1] = wcol->inner[1] >= 250 ? 255 : wcol->inner[1] + 5;
3550  wcol->inner[2] = wcol->inner[2] >= 250 ? 255 : wcol->inner[2] + 5;
3551  }
3552 
3553  /* draw */
3554  wtb.draw_emboss = false; /* only emboss once */
3555 
3556  /* exception for progress bar */
3557  if (state & UI_SCROLL_NO_OUTLINE) {
3558  SWAP(bool, outline, wtb.draw_outline);
3559  }
3560 
3561  round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
3562 
3563  if (state & UI_SCROLL_ARROWS) {
3564  if (wcol->item[0] > 48) {
3565  wcol->item[0] -= 48;
3566  }
3567  if (wcol->item[1] > 48) {
3568  wcol->item[1] -= 48;
3569  }
3570  if (wcol->item[2] > 48) {
3571  wcol->item[2] -= 48;
3572  }
3573  wcol->item[3] = 255;
3574 
3575  if (horizontal) {
3576  rcti slider_inset = *slider;
3577  slider_inset.xmin += 0.05 * U.widget_unit;
3578  slider_inset.xmax -= 0.05 * U.widget_unit;
3579  shape_preset_init_scroll_circle(&wtb.tria1, &slider_inset, 0.6f, 'l');
3580  shape_preset_init_scroll_circle(&wtb.tria2, &slider_inset, 0.6f, 'r');
3581  }
3582  else {
3583  shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
3584  shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
3585  }
3586  }
3587  widgetbase_draw(&wtb, wcol);
3588 
3589  if (state & UI_SCROLL_NO_OUTLINE) {
3590  SWAP(bool, outline, wtb.draw_outline);
3591  }
3592  }
3593 }
3594 
3595 static void widget_scroll(
3596  uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
3597 {
3598  /* calculate slider part */
3599  const float value = (float)ui_but_value_get(but);
3600 
3601  const float size = max_ff((but->softmax + but->a1 - but->softmin), 2.0f);
3602 
3603  /* position */
3604  rcti rect1 = *rect;
3605 
3606  /* determine horizontal/vertical */
3607  const bool horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
3608 
3609  if (horizontal) {
3610  const float fac = BLI_rcti_size_x(rect) / size;
3611  rect1.xmin = rect1.xmin + ceilf(fac * (value - but->softmin));
3612  rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin));
3613 
3614  /* Ensure minimum size. */
3615  const float min = BLI_rcti_size_y(rect);
3616 
3617  if (BLI_rcti_size_x(&rect1) < min) {
3618  rect1.xmax = rect1.xmin + min;
3619 
3620  if (rect1.xmax > rect->xmax) {
3621  rect1.xmax = rect->xmax;
3622  rect1.xmin = max_ii(rect1.xmax - min, rect->xmin);
3623  }
3624  }
3625  }
3626  else {
3627  const float fac = BLI_rcti_size_y(rect) / size;
3628  rect1.ymax = rect1.ymax - ceilf(fac * (value - but->softmin));
3629  rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin));
3630 
3631  /* Ensure minimum size. */
3632  const float min = BLI_rcti_size_x(rect);
3633 
3634  if (BLI_rcti_size_y(&rect1) < min) {
3635  rect1.ymax = rect1.ymin + min;
3636 
3637  if (rect1.ymax > rect->ymax) {
3638  rect1.ymax = rect->ymax;
3639  rect1.ymin = max_ii(rect1.ymax - min, rect->ymin);
3640  }
3641  }
3642  }
3643 
3644  if (state & UI_SELECT) {
3646  }
3647  else {
3648  state = 0;
3649  }
3650  UI_draw_widget_scroll(wcol, rect, &rect1, state);
3651 }
3652 
3654  uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
3655 {
3656  uiButProgressbar *but_progressbar = (uiButProgressbar *)but;
3657  rcti rect_prog = *rect, rect_bar = *rect;
3658 
3659  uiWidgetBase wtb, wtb_bar;
3660  widget_init(&wtb);
3661  widget_init(&wtb_bar);
3662 
3663  /* round corners */
3664  const float value = but_progressbar->progress;
3665  const float ofs = wcol->roundness * BLI_rcti_size_y(&rect_prog);
3666  float w = value * BLI_rcti_size_x(&rect_prog);
3667 
3668  /* Ensure minimum size. */
3669  w = MAX2(w, ofs);
3670 
3671  rect_bar.xmax = rect_bar.xmin + w;
3672 
3673  round_box_edges(&wtb, roundboxalign, &rect_prog, ofs);
3674  round_box_edges(&wtb_bar, roundboxalign, &rect_bar, ofs);
3675 
3676  wtb.draw_outline = true;
3677  widgetbase_draw(&wtb, wcol);
3678 
3679  /* "slider" bar color */
3680  copy_v3_v3_uchar(wcol->inner, wcol->item);
3681  widgetbase_draw(&wtb_bar, wcol);
3682 
3683  /* raise text a bit */
3684  rect->xmin += (BLI_rcti_size_x(&rect_prog) / 2);
3685  rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2);
3686 }
3687 
3688 static void widget_nodesocket(
3689  uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
3690 {
3691  const int radi = 5;
3692 
3693  uiWidgetBase wtb;
3694  widget_init(&wtb);
3695 
3696  uchar old_inner[3], old_outline[3];
3697  copy_v3_v3_uchar(old_inner, wcol->inner);
3698  copy_v3_v3_uchar(old_outline, wcol->outline);
3699 
3700  wcol->inner[0] = but->col[0];
3701  wcol->inner[1] = but->col[1];
3702  wcol->inner[2] = but->col[2];
3703  wcol->outline[0] = 0;
3704  wcol->outline[1] = 0;
3705  wcol->outline[2] = 0;
3706  wcol->outline[3] = 150;
3707 
3708  const int cent_x = BLI_rcti_cent_x(rect);
3709  const int cent_y = BLI_rcti_cent_y(rect);
3710  rect->xmin = cent_x - radi;
3711  rect->xmax = cent_x + radi;
3712  rect->ymin = cent_y - radi;
3713  rect->ymax = cent_y + radi;
3714 
3715  wtb.draw_outline = true;
3716  round_box_edges(&wtb, UI_CNR_ALL, rect, (float)radi);
3717  widgetbase_draw(&wtb, wcol);
3718 
3719  copy_v3_v3_uchar(wcol->inner, old_inner);
3720  copy_v3_v3_uchar(wcol->outline, old_outline);
3721 }
3722 
3723 static void widget_numslider(
3724  uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
3725 {
3726  uiWidgetBase wtb, wtb1;
3727  widget_init(&wtb);
3728  widget_init(&wtb1);
3729 
3730  /* Backdrop first. */
3731  const float ofs = wcol->roundness * BLI_rcti_size_y(rect);
3732  const float toffs = ofs * 0.75f;
3733  round_box_edges(&wtb, roundboxalign, rect, ofs);
3734 
3735  wtb.draw_outline = false;
3736  widgetbase_draw(&wtb, wcol);
3737 
3738  /* Draw slider part only when not in text editing. */
3739  if (!(state & UI_STATE_TEXT_INPUT)) {
3740  int roundboxalign_slider = roundboxalign;
3741 
3742  uchar outline[3];
3743  copy_v3_v3_uchar(outline, wcol->outline);
3744  copy_v3_v3_uchar(wcol->outline, wcol->item);
3745  copy_v3_v3_uchar(wcol->inner, wcol->item);
3746 
3747  if (!(state & UI_SELECT)) {
3748  SWAP(short, wcol->shadetop, wcol->shadedown);
3749  }
3750 
3751  rcti rect1 = *rect;
3752  float factor, factor_ui;
3753  float factor_discard = 1.0f; /* No discard. */
3754  const float value = (float)ui_but_value_get(but);
3755 
3756  if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PERCENTAGE)) {
3757  factor = value / but->softmax;
3758  }
3759  else {
3760  factor = (value - but->softmin) / (but->softmax - but->softmin);
3761  }
3762 
3763  const float width = (float)BLI_rcti_size_x(rect);
3764  factor_ui = factor * width;
3765 
3766  if (factor_ui <= ofs) {
3767  /* Left part only. */
3768  roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
3769  rect1.xmax = rect1.xmin + ofs;
3770  factor_discard = factor_ui / ofs;
3771  }
3772  else if (factor_ui <= width - ofs) {
3773  /* Left part + middle part. */
3774  roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
3775  rect1.xmax = rect1.xmin + factor_ui;
3776  }
3777  else {
3778  /* Left part + middle part + right part. */
3779  factor_discard = factor;
3780  }
3781 
3782  round_box_edges(&wtb1, roundboxalign_slider, &rect1, ofs);
3783  wtb1.draw_outline = false;
3784  widgetbase_set_uniform_discard_factor(&wtb1, factor_discard);
3785  widgetbase_draw(&wtb1, wcol);
3786 
3787  copy_v3_v3_uchar(wcol->outline, outline);
3788 
3789  if (!(state & UI_SELECT)) {
3790  SWAP(short, wcol->shadetop, wcol->shadedown);
3791  }
3792  }
3793 
3794  /* Outline. */
3795  wtb.draw_outline = true;
3796  wtb.draw_inner = false;
3797  widgetbase_draw(&wtb, wcol);
3798 
3799  /* Add space at either side of the button so text aligns with number-buttons
3800  * (which have arrow icons). */
3801  if (!(state & UI_STATE_TEXT_INPUT)) {
3802  rect->xmax -= toffs;
3803  rect->xmin += toffs;
3804  }
3805 }
3806 
3807 /* I think 3 is sufficient border to indicate keyed status */
3808 #define SWATCH_KEYED_BORDER 3
3809 
3810 static void widget_swatch(
3811  uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
3812 {
3813  BLI_assert(but->type == UI_BTYPE_COLOR);
3814  uiButColor *color_but = (uiButColor *)but;
3815  float col[4];
3816 
3817  col[3] = 1.0f;
3818 
3819  if (but->rnaprop) {
3820  BLI_assert(but->rnaindex == -1);
3821 
3822  if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) {
3823  col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
3824  }
3825  }
3826 
3827  uiWidgetBase wtb;
3828  widget_init(&wtb);
3829 
3830  const float rad = wcol->roundness * U.widget_unit;
3831  round_box_edges(&wtb, roundboxalign, rect, rad);
3832 
3833  ui_but_v3_get(but, col);
3834 
3836  UI_BUT_REDALERT)) ||
3837  (but->drawflag & UI_BUT_ANIMATED_CHANGED)) {
3838  /* draw based on state - color for keyed etc */
3839  widgetbase_draw(&wtb, wcol);
3840 
3841  /* inset to draw swatch color */
3842  rect->xmin += SWATCH_KEYED_BORDER;
3843  rect->xmax -= SWATCH_KEYED_BORDER;
3844  rect->ymin += SWATCH_KEYED_BORDER;
3845  rect->ymax -= SWATCH_KEYED_BORDER;
3846 
3847  round_box_edges(&wtb, roundboxalign, rect, rad);
3848  }
3849 
3850  if (!ui_but_is_color_gamma(but)) {
3852  }
3853 
3854  rgba_float_to_uchar(wcol->inner, col);
3855  const bool show_alpha_checkers = (wcol->inner[3] < 255);
3856 
3857  wcol->shaded = 0;
3858 
3859  /* Now we reduce alpha of the inner color (i.e. the color shown)
3860  * so that this setting can look grayed out, while retaining
3861  * the checkerboard (for transparent values). This is needed
3862  * here as the effects of ui_widget_color_disabled() are overwritten. */
3863  wcol->inner[3] *= widget_alpha_factor(state);
3864 
3865  widgetbase_draw_ex(&wtb, wcol, show_alpha_checkers);
3866  if (color_but->is_pallete_color &&
3867  ((Palette *)but->rnapoin.owner_id)->active_color == color_but->palette_color_index) {
3868  const float width = rect->xmax - rect->xmin;
3869  const float height = rect->ymax - rect->ymin;
3870  /* find color luminance and change it slightly */
3871  float bw = rgb_to_grayscale(col);
3872 
3873  bw += (bw < 0.5f) ? 0.5f : -0.5f;
3874 
3875  /* We are drawing on top of widget bases. Flush cache. */
3879 
3883 
3884  immUniformColor3f(bw, bw, bw);
3885  immBegin(GPU_PRIM_TRIS, 3);
3886  immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
3887  immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
3888  immVertex2f(pos, rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
3889  immEnd();
3890 
3891  immUnbindProgram();
3892  }
3893 }
3894 
3895 static void widget_unitvec(
3896  uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
3897 {
3898  ui_draw_but_UNITVEC(but, wcol, rect);
3899 }
3900 
3902  uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
3903 {
3905  but->emboss != UI_EMBOSS_NONE) {
3906  uiWidgetBase wtb;
3907  widget_init(&wtb);
3908  wtb.draw_outline = false;
3909 
3910  const float rad = wcol->roundness * BLI_rcti_size_y(rect);
3911  round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
3912  widgetbase_draw(&wtb, wcol);
3913  }
3914  else if (but->type == UI_BTYPE_NUM) {
3915  /* Draw number buttons still with left/right
3916  * triangles when field is not embossed */
3917  widget_numbut_embossn(but, wcol, rect, state, roundboxalign);
3918  }
3919  else if (but->type == UI_BTYPE_MENU) {
3920  /* Draw menu buttons still with down arrow. */
3921  widget_menubut_embossn(but, wcol, rect, state, roundboxalign);
3922  }
3923 }
3924 
3925 static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
3926 {
3927  if (state & UI_SELECT) {
3928  SWAP(short, wcol->shadetop, wcol->shadedown);
3929  }
3930 
3931  uiWidgetBase wtb;
3932  widget_init(&wtb);
3933 
3934  const float rad = wcol->roundness * U.widget_unit;
3935  round_box_edges(&wtb, roundboxalign, rect, rad);
3936 
3937  widgetbase_draw(&wtb, wcol);
3938 }
3939 
3941  rcti *rect,
3942  int UNUSED(state),
3943  int roundboxalign)
3944 {
3945  uiWidgetBase wtb;
3946  widget_init(&wtb);
3947 
3948  const float rad = wcol->roundness * U.widget_unit;
3949  round_box_edges(&wtb, roundboxalign, rect, rad);
3950 
3951  /* decoration */
3952  widgetbase_draw(&wtb, wcol);
3953 }
3954 
3955 static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
3956 {
3957  float back[4];
3959 
3960  if ((state & UI_ACTIVE) || (back[3] < 1.0f)) {
3961  uiWidgetBase wtb;
3962  const float rad = wcol->roundness * U.widget_unit;
3963 
3964  if (state & UI_ACTIVE) {
3965  copy_v4_v4_uchar(wcol->inner, wcol->inner_sel);
3966  copy_v3_v3_uchar(wcol->text, wcol->text_sel);
3967  copy_v3_v3_uchar(wcol->outline, wcol->inner);
3968  }
3969  else {
3970  wcol->inner[3] *= 1.0f - back[3];
3971  wcol->outline[3] = 0.0f;
3972  }
3973 
3974  widget_init(&wtb);
3975 
3976  /* half rounded */
3977  round_box_edges(&wtb, roundboxalign, rect, rad);
3978 
3979  widgetbase_draw(&wtb, wcol);
3980  }
3981 }
3982 
3984  rcti *rect,
3985  int UNUSED(state),
3986  int UNUSED(roundboxalign))
3987 {
3988  uiWidgetBase wtb;
3989  widget_init(&wtb);
3990 
3991  /* not rounded, no outline */
3992  wtb.draw_outline = false;
3993  round_box_edges(&wtb, 0, rect, 0.0f);
3994 
3995  widgetbase_draw(&wtb, wcol);
3996 }
3997 
3999  uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
4000 {
4001  const float fac = but->block->pie_data.alphafac;
4002 
4003  uiWidgetBase wtb;
4004  widget_init(&wtb);
4005 
4006  wtb.draw_emboss = false;
4007 
4008  const float rad = wcol->roundness * BLI_rcti_size_y(rect);
4009  round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
4010 
4011  wcol->inner[3] *= fac;
4012  wcol->inner_sel[3] *= fac;
4013  wcol->item[3] *= fac;
4014  wcol->text[3] *= fac;
4015  wcol->text_sel[3] *= fac;
4016  wcol->outline[3] *= fac;
4017 
4018  widgetbase_draw(&wtb, wcol);
4019 }
4020 
4022  rcti *rect,
4023  int UNUSED(state),
4024  int UNUSED(roundboxalign))
4025 {
4026  uiWidgetBase wtb;
4027  widget_init(&wtb);
4028 
4029  /* no outline */
4030  wtb.draw_outline = false;
4031  const float rad = wcol->roundness * U.widget_unit;
4032  round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
4033 
4034  widgetbase_draw(&wtb, wcol);
4035 }
4036 
4038  rcti *rect,
4039  int state,
4040  int UNUSED(roundboxalign))
4041 {
4042  const bool text_before_widget = (state & UI_STATE_TEXT_BEFORE_WIDGET);
4043  rcti recttemp = *rect;
4044 
4045  uiWidgetBase wtb;
4046  widget_init(&wtb);
4047 
4048  /* square */
4049  if (text_before_widget) {
4050  recttemp.xmin = recttemp.xmax - BLI_rcti_size_y(&recttemp);
4051  }
4052  else {
4053  recttemp.xmax = recttemp.xmin + BLI_rcti_size_y(&recttemp);
4054  }
4055 
4056  /* smaller */
4057  const int delta = (BLI_rcti_size_y(&recttemp) - 2 * U.pixelsize) / 6;
4059  &recttemp, BLI_rcti_size_x(&recttemp) - delta * 2, BLI_rcti_size_y(&recttemp) - delta * 2);
4060  /* Keep one edge in place. */
4061  BLI_rcti_translate(&recttemp, text_before_widget ? delta : -delta, 0);
4062 
4063  const float rad = wcol->roundness * BLI_rcti_size_y(&recttemp);
4064  round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
4065 
4066  /* decoration */
4067  if (state & UI_SELECT) {
4069  }
4070 
4071  widgetbase_draw(&wtb, wcol);
4072 
4073  /* Text space - factor is really just eyeballed. */
4074  const float offset = delta * 0.9;
4075  if (text_before_widget) {
4076  rect->xmax = recttemp.xmin - offset;
4077  }
4078  else {
4079  rect->xmin = recttemp.xmax + offset;
4080  }
4081 }
4082 
4083 /* labels use Editor theme colors for text */
4084 static void widget_state_label(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
4085 {
4086  if (state & UI_BUT_LIST_ITEM) {
4087  /* Override default label theme's colors. */
4088  bTheme *btheme = UI_GetTheme();
4089  wt->wcol_theme = &btheme->tui.wcol_list_item;
4090  /* call this for option button */
4091  widget_state(wt, state, drawflag, emboss);
4092  }
4093  else {
4094  /* call this for option button */
4095  widget_state(wt, state, drawflag, emboss);
4096  if (state & UI_SELECT) {
4098  }
4099  else {
4101  }
4102  }
4103 
4104  if (state & UI_BUT_REDALERT) {
4105  const uchar red[4] = {255, 0, 0};
4106  color_blend_v3_v3(wt->wcol.text, red, 0.4f);
4107  }
4108 }
4109 
4110 static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
4111 {
4112  uiWidgetBase wtb;
4113  widget_init(&wtb);
4114 
4115  const float rad = wcol->roundness * U.widget_unit;
4116  round_box_edges(&wtb, roundboxalign, rect, rad);
4117 
4118  widgetbase_draw(&wtb, wcol);
4119 }
4120 
4121 static void widget_box(
4122  uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
4123 {
4124  uiWidgetBase wtb;
4125  widget_init(&wtb);
4126 
4127  uchar old_col[3];
4128  copy_v3_v3_uchar(old_col, wcol->inner);
4129 
4130  /* abuse but->hsv - if it's non-zero, use this color as the box's background */
4131  if (but != NULL && but->col[3]) {
4132  wcol->inner[0] = but->col[0];
4133  wcol->inner[1] = but->col[1];
4134  wcol->inner[2] = but->col[2];
4135  wcol->inner[3] = but->col[3];
4136  }
4137 
4138  const float rad = wcol->roundness * U.widget_unit;
4139  round_box_edges(&wtb, roundboxalign, rect, rad);
4140 
4141  widgetbase_draw(&wtb, wcol);
4142 
4143  copy_v3_v3_uchar(wcol->inner, old_col);
4144 }
4145 
4146 static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
4147 {
4148  uiWidgetBase wtb;
4149  widget_init(&wtb);
4150 
4151  const float rad = wcol->roundness * U.widget_unit;
4152  round_box_edges(&wtb, roundboxalign, rect, rad);
4153 
4154  widgetbase_draw(&wtb, wcol);
4155 }
4156 
4157 #if 0
4158 static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
4159 {
4160  uiWidgetBase wtb;
4161  const float rad = wcol->roundness * U.widget_unit;
4162 
4163  widget_init(&wtb);
4164 
4165  /* half rounded */
4166  round_box_edges(&wtb, roundboxalign, rect, rad);
4167 
4168  widgetbase_draw(&wtb, wcol);
4169 }
4170 #endif
4171 
4172 static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
4173 {
4174  const float rad = wcol->roundness * U.widget_unit;
4175 
4176  uiWidgetBase wtb;
4177  widget_init(&wtb);
4178 
4179  if (state & UI_STATE_HOLD_ACTION) {
4180  /* Show that keeping pressed performs another action (typically a menu). */
4181  shape_preset_init_hold_action(&wtb.tria1, rect, 0.75f, 'r');
4182  }
4183 
4184  /* half rounded */
4185  round_box_edges(&wtb, roundboxalign, rect, rad);
4186 
4187  widgetbase_draw(&wtb, wcol);
4188 }
4189 
4190 static void widget_tab(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
4191 {
4192  const float rad = wcol->roundness * U.widget_unit;
4193  const bool is_active = (state & UI_SELECT);
4194 
4195  /* Draw shaded outline - Disabled for now,
4196  * seems incorrect and also looks nicer without it imho ;) */
4197  // #define USE_TAB_SHADED_HIGHLIGHT
4198 
4199  uchar theme_col_tab_highlight[3];
4200 
4201 #ifdef USE_TAB_SHADED_HIGHLIGHT
4202  /* create outline highlight colors */
4203  if (is_active) {
4204  interp_v3_v3v3_uchar(theme_col_tab_highlight, wcol->inner_sel, wcol->outline, 0.2f);
4205  }
4206  else {
4207  interp_v3_v3v3_uchar(theme_col_tab_highlight, wcol->inner, wcol->outline, 0.12f);
4208  }
4209 #endif
4210 
4211  uiWidgetBase wtb;
4212  widget_init(&wtb);
4213 
4214  /* half rounded */
4215  round_box_edges(&wtb, roundboxalign, rect, rad);
4216 
4217  /* draw inner */
4218 #ifdef USE_TAB_SHADED_HIGHLIGHT
4219  wtb.draw_outline = 0;
4220 #endif
4221  widgetbase_draw(&wtb, wcol);
4222 
4223  /* We are drawing on top of widget bases. Flush cache. */
4227 
4228 #ifdef USE_TAB_SHADED_HIGHLIGHT
4229  /* draw outline (3d look) */
4230  ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, wcol->inner);
4231 #endif
4232 
4233 #ifndef USE_TAB_SHADED_HIGHLIGHT
4234  UNUSED_VARS(is_active, theme_col_tab_highlight);
4235 #endif
4236 }
4237 
4238 static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
4239 {
4240  bTheme *btheme = UI_GetTheme();
4241  uiWidgetColors *wcol = &btheme->tui.wcol_radio;
4242  const float rad = wcol->roundness * U.widget_unit;
4243 
4244  /* state copy! */
4245  wt->wcol = *(wt->wcol_theme);
4246 
4247  uiWidgetBase wtb;
4248  widget_init(&wtb);
4249 
4250  if (but->block->drawextra) {
4251  /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
4252  but->block->drawextra(
4253  C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
4254 
4258 
4259  /* make mask to draw over image */
4260  uchar col[4];
4263 
4264  round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad);
4265  widgetbase_outline(&wtb, pos);
4266 
4267  immUnbindProgram();
4268  }
4269 
4270  /* outline */
4271  round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
4272  wtb.draw_outline = true;
4273  wtb.draw_inner = false;
4274  widgetbase_draw(&wtb, &wt->wcol);
4275 }
4276 
4278 {
4279  bTheme *btheme = UI_GetTheme();
4280 
4281  /* defaults */
4282  static uiWidgetType wt;
4283  wt.wcol_theme = &btheme->tui.wcol_regular;
4284  wt.wcol_state = &btheme->tui.wcol_state;
4285  wt.state = widget_state;
4286  wt.draw = widget_but;
4287  wt.custom = NULL;
4289 
4290  switch (type) {
4291  case UI_WTYPE_REGULAR:
4292  break;
4293 
4294  case UI_WTYPE_LABEL:
4295  wt.draw = NULL;
4297  break;
4298 
4299  case UI_WTYPE_TOGGLE:
4300  wt.wcol_theme = &btheme->tui.wcol_toggle;
4301  break;
4302 
4303  case UI_WTYPE_CHECKBOX:
4304  wt.wcol_theme = &btheme->tui.wcol_option;
4305  wt.draw = widget_optionbut;
4306  break;
4307 
4308  case UI_WTYPE_RADIO:
4309  wt.wcol_theme = &btheme->tui.wcol_radio;
4310  wt.draw = widget_radiobut;
4311  break;
4312 
4313  case UI_WTYPE_NUMBER:
4314  wt.wcol_theme = &btheme->tui.wcol_num;
4315  wt.draw = widget_numbut;
4316  break;
4317 
4318  case UI_WTYPE_SLIDER:
4319  wt.wcol_theme = &btheme->tui.wcol_numslider;
4320  wt.custom = widget_numslider;
4322  break;
4323 
4324  case UI_WTYPE_EXEC:
4325  wt.wcol_theme = &btheme->tui.wcol_tool;
4327  break;
4328 
4329  case UI_WTYPE_TOOLBAR_ITEM:
4330  wt.wcol_theme = &btheme->tui.wcol_toolbar_item;
4332  break;
4333 
4334  case UI_WTYPE_TAB:
4335  wt.wcol_theme = &btheme->tui.wcol_tab;
4336  wt.draw = widget_tab;
4337  break;
4338 
4339  case UI_WTYPE_TOOLTIP:
4340  wt.wcol_theme = &btheme->tui.wcol_tooltip;
4341  wt.draw = widget_menu_back;
4342  break;
4343 
4344  /* strings */
4345  case UI_WTYPE_NAME:
4346  wt.wcol_theme = &btheme->tui.wcol_text;
4347  wt.draw = widget_textbut;
4348  break;
4349 
4350  case UI_WTYPE_NAME_LINK:
4351  break;
4352 
4353  case UI_WTYPE_POINTER_LINK:
4354  break;
4355 
4356  case UI_WTYPE_FILENAME:
4357  break;
4358 
4359  /* start menus */
4360  case UI_WTYPE_MENU_RADIO:
4361  wt.wcol_theme = &btheme->tui.wcol_menu;
4362  wt.draw = widget_menubut;
4363  break;
4364 
4367  wt.wcol_theme = &btheme->tui.wcol_menu;
4368  wt.draw = widget_menuiconbut;
4369  break;
4370 
4372  wt.wcol_theme = &btheme->tui.wcol_menu;
4373  wt.draw = widget_menubut;
4374  break;
4375 
4376  case UI_WTYPE_PULLDOWN:
4377  wt.wcol_theme = &btheme->tui.wcol_pulldown;
4378  wt.draw = widget_pulldownbut;
4380  break;
4381 
4382  /* in menus */
4383  case UI_WTYPE_MENU_ITEM:
4384  wt.wcol_theme = &btheme->tui.wcol_menu_item;
4387  break;
4388 
4389  case UI_WTYPE_MENU_BACK:
4390  wt.wcol_theme = &btheme->tui.wcol_menu_back;
4391  wt.draw = widget_menu_back;
4392  break;
4393 
4394  /* specials */
4395  case UI_WTYPE_ICON:
4397  break;
4398 
4399  case UI_WTYPE_ICON_LABEL:
4400  /* behave like regular labels (this is simply a label with an icon) */
4403  break;
4404 
4405  case UI_WTYPE_SWATCH:
4406  wt.custom = widget_swatch;
4407  break;
4408 
4409  case UI_WTYPE_BOX:
4410  wt.custom = widget_box;
4411  wt.wcol_theme = &btheme->tui.wcol_box;
4412  break;
4413 
4414  case UI_WTYPE_RGB_PICKER:
4415  break;
4416 
4417  case UI_WTYPE_UNITVEC:
4418  wt.custom = widget_unitvec;
4419  break;
4420 
4421  case UI_WTYPE_SCROLL:
4422  wt.wcol_theme = &btheme->tui.wcol_scroll;
4424  wt.custom = widget_scroll;
4425  break;
4426 
4427  case UI_WTYPE_LISTITEM:
4428  wt.wcol_theme = &btheme->tui.wcol_list_item;
4430  break;
4431 
4432  case UI_WTYPE_PROGRESSBAR:
4433  wt.wcol_theme = &btheme->tui.wcol_progress;
4435  break;
4436 
4437  case UI_WTYPE_NODESOCKET:
4439  break;
4440 
4442  wt.wcol_theme = &btheme->tui.wcol_pie_menu;
4445  break;
4446  }
4447 
4448  return &wt;
4449 }
4450 
4451 static int widget_roundbox_set(uiBut *but, rcti *rect)
4452 {
4453  int roundbox = UI_CNR_ALL;
4454 
4455  /* alignment */
4456  if ((but->drawflag & UI_BUT_ALIGN) && but->type != UI_BTYPE_PULLDOWN) {
4457 
4458  /* ui_popup_block_position has this correction too, keep in sync */
4460  rect->ymax += U.pixelsize;
4461  }
4463  rect->xmin -= U.pixelsize;
4464  }
4465 
4466  switch (but->drawflag & UI_BUT_ALIGN) {
4467  case UI_BUT_ALIGN_TOP:
4469  break;
4470  case UI_BUT_ALIGN_DOWN:
4471  roundbox = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
4472  break;
4473  case UI_BUT_ALIGN_LEFT:
4475  break;
4476  case UI_BUT_ALIGN_RIGHT:
4477  roundbox = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
4478  break;
4480  roundbox = UI_CNR_TOP_LEFT;
4481  break;
4483  roundbox = UI_CNR_TOP_RIGHT;
4484  break;
4486  roundbox = UI_CNR_BOTTOM_LEFT;
4487  break;
4489  roundbox = UI_CNR_BOTTOM_RIGHT;
4490  break;
4491  default:
4492  roundbox = 0;
4493  break;
4494  }
4495  }
4496 
4497  /* align with open menu */
4498  if (but->active && (but->type != UI_BTYPE_POPOVER) && !ui_but_menu_draw_as_popover(but)) {
4499  const int direction = ui_but_menu_direction(but);
4500 
4501  if (direction == UI_DIR_UP) {
4502  roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT);
4503  }
4504  else if (direction == UI_DIR_DOWN) {
4505  roundbox &= ~(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
4506  }
4507  else if (direction == UI_DIR_LEFT) {
4508  roundbox &= ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
4509  }
4510  else if (direction == UI_DIR_RIGHT) {
4511  roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
4512  }
4513  }
4514 
4515  return roundbox;
4516 }
4517 
4518 /* -------------------------------------------------------------------- */
4522 /* conversion from old to new buttons, so still messy */
4523 void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBut *but, rcti *rect)
4524 {
4525  bTheme *btheme = UI_GetTheme();
4526  const ThemeUI *tui = &btheme->tui;
4527  const uiFontStyle *fstyle = &style->widget;
4528  uiWidgetType *wt = NULL;
4529 
4530  /* handle menus separately */
4531  if (but->emboss == UI_EMBOSS_PULLDOWN) {
4532  switch (but->type) {
4533  case UI_BTYPE_LABEL:
4534  widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
4535  break;
4536  case UI_BTYPE_SEPR_LINE:
4537  ui_draw_separator(rect, &tui->wcol_menu_item);
4538  break;
4539  default:
4541  break;
4542  }
4543  }
4545  /* Use the same widget types for both no emboss types. Later on,
4546  * #UI_EMBOSS_NONE_OR_STATUS will blend state colors if they apply. */
4547  switch (but->type) {
4548  case UI_BTYPE_LABEL:
4550  break;
4551  default:
4552  wt = widget_type(UI_WTYPE_ICON);
4553  break;
4554  }
4555  }
4556  else if (but->emboss == UI_EMBOSS_RADIAL) {
4558  }
4559  else {
4560  BLI_assert(but->emboss == UI_EMBOSS);
4561 
4562  switch (but->type) {
4563  case UI_BTYPE_LABEL:
4565  fstyle = &style->widgetlabel;
4566  if (but->drawflag & UI_BUT_BOX_ITEM) {
4567  wt->wcol_theme = &tui->wcol_box;
4568  wt->state = widget_state;
4569  }
4570  else if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
4571  wt->wcol_theme = &tui->wcol_menu_back;
4572  wt->state = widget_state;
4573  }
4574  if (!(but->flag & UI_HAS_ICON)) {
4576  }
4577  break;
4578 
4579  case UI_BTYPE_SEPR:
4580  case UI_BTYPE_SEPR_LINE:
4581  case UI_BTYPE_SEPR_SPACER:
4582  break;
4583 
4584  case UI_BTYPE_BUT:
4585  case UI_BTYPE_DECORATOR:
4586 #ifdef USE_UI_TOOLBAR_HACK
4587  if ((but->icon != ICON_NONE) && UI_but_is_tool(but)) {
4589  }
4590  else {
4591  wt = widget_type(UI_WTYPE_EXEC);
4592  }
4593 #else
4594  wt = widget_type(UI_WTYPE_EXEC);
4595 #endif
4596  break;
4597 
4598  case UI_BTYPE_NUM:
4600  break;
4601 
4602  case UI_BTYPE_NUM_SLIDER:
4604  break;
4605 
4606  case UI_BTYPE_ROW:
4608  break;
4609 
4610  case UI_BTYPE_LISTROW:
4612  break;
4613 
4614  case UI_BTYPE_TEXT:
4615  wt = widget_type(UI_WTYPE_NAME);
4616  break;
4617 
4618  case UI_BTYPE_SEARCH_MENU:
4619  wt = widget_type(UI_WTYPE_NAME);
4620  break;
4621 
4622  case UI_BTYPE_TAB:
4623  wt = widget_type(UI_WTYPE_TAB);
4624  break;
4625 
4626  case UI_BTYPE_BUT_TOGGLE:
4627  case UI_BTYPE_TOGGLE:
4628  case UI_BTYPE_TOGGLE_N:
4630  break;
4631 
4632  case UI_BTYPE_CHECKBOX:
4633  case UI_BTYPE_CHECKBOX_N:
4634  if (!(but->flag & UI_HAS_ICON)) {
4636 
4637  if ((but->drawflag & (UI_BUT_TEXT_LEFT | UI_BUT_TEXT_RIGHT)) == 0) {
4638  but->drawflag |= UI_BUT_TEXT_LEFT;
4639  }
4640  /* #widget_optionbut() carefully sets the text rectangle for fine tuned paddings. If the
4641  * text drawing were to add its own padding, DPI and zoom factor would be applied twice
4642  * in the final padding, so it's difficult to control it. */
4644  }
4645  else {
4647  }
4648 
4649  /* option buttons have strings outside, on menus use different colors */
4652  }
4653  break;
4654 
4655  case UI_BTYPE_MENU:
4656  case UI_BTYPE_BLOCK:
4657  case UI_BTYPE_POPOVER:
4658  if (but->flag & UI_BUT_NODE_LINK) {
4659  /* new node-link button, not active yet XXX */
4661  }
4662  else {
4663  /* with menu arrows */
4664 
4665  /* We could use a flag for this, but for now just check size,
4666  * add up/down arrows if there is room. */
4667  if ((!but->str[0] && but->icon && (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect) + 2)) ||
4668  /* disable for brushes also */
4669  (but->flag & UI_BUT_ICON_PREVIEW)) {
4670  /* no arrows */
4672  }
4673  else {
4675  }
4676  }
4677  break;
4678 
4679  case UI_BTYPE_PULLDOWN:
4681  break;
4682 
4683  case UI_BTYPE_BUT_MENU:
4685  break;
4686 
4687  case UI_BTYPE_COLOR:
4689  break;
4690 
4691  case UI_BTYPE_ROUNDBOX:
4692  case UI_BTYPE_LISTBOX:
4693  wt = widget_type(UI_WTYPE_BOX);
4694  break;
4695 
4696  case UI_BTYPE_EXTRA:
4698  break;
4699 
4700  case UI_BTYPE_HSVCUBE: {
4701  const uiButHSVCube *hsv_but = (uiButHSVCube *)but;
4702 
4703  if (ELEM(hsv_but->gradient_type, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) {
4704  /* vertical V slider, uses new widget draw now */
4705  ui_draw_but_HSV_v(but, rect);
4706  }
4707  else { /* other HSV pickers... */
4708  ui_draw_but_HSVCUBE(but, rect);
4709  }
4710  break;
4711  }
4712 
4713  case UI_BTYPE_HSVCIRCLE:
4714  ui_draw_but_HSVCIRCLE(but, &tui->wcol_regular, rect);
4715  break;
4716 
4717  case UI_BTYPE_COLORBAND:
4718  /* do not draw right to edge of rect */
4719  rect->xmin += (0.25f * UI_UNIT_X);
4720  rect->xmax -= (0.3f * UI_UNIT_X);
4721  ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
4722  break;
4723 
4724  case UI_BTYPE_UNITVEC:
4726  break;
4727 
4728  case UI_BTYPE_IMAGE:
4729  ui_draw_but_IMAGE(region, but, &tui->wcol_regular, rect);
4730  break;
4731 
4732  case UI_BTYPE_HISTOGRAM:
4733  ui_draw_but_HISTOGRAM(region, but, &tui->wcol_regular, rect);
4734  break;
4735 
4736  case UI_BTYPE_WAVEFORM:
4737  ui_draw_but_WAVEFORM(region, but, &tui->wcol_regular, rect);
4738  break;
4739 
4740  case UI_BTYPE_VECTORSCOPE:
4741  ui_draw_but_VECTORSCOPE(region, but, &tui->wcol_regular, rect);
4742  break;
4743 
4744  case UI_BTYPE_CURVE:
4745  /* do not draw right to edge of rect */
4746  rect->xmin += (0.2f * UI_UNIT_X);
4747  rect->xmax -= (0.2f * UI_UNIT_X);
4748  ui_draw_but_CURVE(region, but, &tui->wcol_regular, rect);
4749  break;
4750 
4751  case UI_BTYPE_CURVEPROFILE:
4752  ui_draw_but_CURVEPROFILE(region, but, &tui->wcol_regular, rect);
4753  break;
4754 
4755  case UI_BTYPE_PROGRESS_BAR:
4757  fstyle = &style->widgetlabel;
4758  break;
4759 
4760  case UI_BTYPE_SCROLL:
4762  break;
4763 
4764  case UI_BTYPE_GRIP:
4765  wt = widget_type(UI_WTYPE_ICON);
4766  break;
4767 
4769  ui_draw_but_TRACKPREVIEW(region, but, &tui->wcol_regular, rect);
4770  break;
4771 
4772  case UI_BTYPE_NODE_SOCKET:
4774  break;
4775 
4776  default:
4778  break;
4779  }
4780  }
4781 
4782  if (wt == NULL) {
4783  return;
4784  }
4785 
4786  // rcti disablerect = *rect; /* rect gets clipped smaller for text */
4787 
4788  const int roundboxalign = widget_roundbox_set(but, rect);
4789 
4790  /* Mask out flags re-used for local state. */
4791  int state = but->flag & ~UI_STATE_FLAGS_ALL;
4792  const int drawflag = but->drawflag;
4793 
4794  if (state & UI_SELECT_DRAW) {
4795  state |= UI_SELECT;
4796  }
4797 
4798  if ((but->editstr) ||
4801  }
4802 
4803  if (but->hold_func) {
4805  }
4806 
4807  if (state & UI_ACTIVE) {
4808  if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
4810  }
4811  else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
4813  }
4814  }
4815 
4816  bool use_alpha_blend = false;
4817  if (but->emboss != UI_EMBOSS_PULLDOWN) {
4819  use_alpha_blend = true;
4821  }
4822  }
4823 
4824  if (drawflag & UI_BUT_TEXT_RIGHT) {
4826  }
4827 
4828 #ifdef USE_UI_POPOVER_ONCE
4829  if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
4830  if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
4832  }
4833  }
4834 #endif
4835 
4836  wt->state(wt, state, drawflag, but->emboss);
4837  if (wt->custom) {
4838  wt->custom(but, &wt->wcol, rect, state, roundboxalign);
4839  }
4840  else if (wt->draw) {
4841  wt->draw(&wt->wcol, rect, state, roundboxalign);
4842  }
4843 
4844  if (use_alpha_blend) {
4846  }
4847 
4848  wt->text(fstyle, &wt->wcol, but, rect);
4849  if (use_alpha_blend) {
4851  }
4852 }
4853 
4854 static void ui_draw_clip_tri(uiBlock *block, rcti *rect, uiWidgetType *wt)
4855 {
4856  if (block) {
4857  float draw_color[4];
4858  const uchar *color = wt->wcol.text;
4859 
4860  draw_color[0] = ((float)color[0]) / 255.0f;
4861  draw_color[1] = ((float)color[1]) / 255.0f;
4862  draw_color[2] = ((float)color[2]) / 255.0f;
4863  draw_color[3] = 1.0f;
4864 
4865  if (block->flag & UI_BLOCK_CLIPTOP) {
4866  /* XXX no scaling for UI here yet */
4867  UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 6 * U.dpi_fac, 't', draw_color);
4868  }
4869  if (block->flag & UI_BLOCK_CLIPBOTTOM) {
4870  /* XXX no scaling for UI here yet */
4871  UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10 * U.dpi_fac, 'v', draw_color);
4872  }
4873  }
4874 }
4875 
4876 void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
4877 {
4879 
4880  wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
4881  if (block) {
4882  wt->draw(&wt->wcol, rect, block->flag, block->direction);
4883  }
4884  else {
4885  wt->draw(&wt->wcol, rect, 0, 0);
4886  }
4887 
4888  ui_draw_clip_tri(block, rect, wt);
4889 }
4890 
4895 void ui_draw_box_opaque(rcti *rect, int roundboxalign)
4896 {
4898 
4899  /* Alpha blend with the region's background color to force an opaque background. */
4900  uiWidgetColors *wcol = &wt->wcol;
4901  wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
4902  float background[4];
4903  UI_GetThemeColor4fv(TH_BACK, background);
4904  float new_inner[4];
4905  rgba_uchar_to_float(new_inner, wcol->inner);
4906  new_inner[0] = (new_inner[0] * new_inner[3]) + (background[0] * (1.0f - new_inner[3]));
4907  new_inner[1] = (new_inner[1] * new_inner[3]) + (background[1] * (1.0f - new_inner[3]));
4908  new_inner[2] = (new_inner[2] * new_inner[3]) + (background[2] * (1.0f - new_inner[3]));
4909  new_inner[3] = 1.0f;
4910  rgba_float_to_uchar(wcol->inner, new_inner);
4911 
4912  wt->custom(NULL, wcol, rect, 0, roundboxalign);
4913 }
4914 
4920  rcti *rect,
4921  int direction,
4922  const float unit_size,
4923  const float mval_origin[2])
4924 {
4925  /* tsk, this isn't nice. */
4926  const float unit_half = unit_size / 2;
4927  const float cent_x = mval_origin ? CLAMPIS(mval_origin[0],
4928  rect->xmin + unit_size,
4929  rect->xmax - unit_size) :
4930  BLI_rcti_cent_x(rect);
4931 
4933 
4934  /* Extracted from 'widget_menu_back', keep separate to avoid menu changes breaking popovers */
4935  {
4936  uiWidgetBase wtb;
4937  widget_init(&wtb);
4938 
4939  const int roundboxalign = UI_CNR_ALL;
4940  widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
4941 
4942  round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
4943  wtb.draw_emboss = false;
4944  widgetbase_draw(&wtb, wcol);
4945  }
4946 
4947  /* Draw popover arrow (top/bottom) */
4948  if (ELEM(direction, UI_DIR_UP, UI_DIR_DOWN)) {
4952 
4953  const bool is_down = (direction == UI_DIR_DOWN);
4954  const int sign = is_down ? 1 : -1;
4955  float y = is_down ? rect->ymax : rect->ymin;
4956 
4958  immBegin(GPU_PRIM_TRIS, 3);
4960  immVertex2f(pos, cent_x - unit_half, y);
4961  immVertex2f(pos, cent_x + unit_half, y);
4962  immVertex2f(pos, cent_x, y + sign * unit_half);
4963  immEnd();
4964 
4965  y = y - sign * round(U.pixelsize * 1.41);
4966 
4968  immBegin(GPU_PRIM_TRIS, 3);
4969  immUniformColor4ub(0, 0, 0, 0);
4970  immVertex2f(pos, cent_x - unit_half, y);
4971  immVertex2f(pos, cent_x + unit_half, y);
4972  immVertex2f(pos, cent_x, y + sign * unit_half);
4973  immEnd();
4974 
4976  immBegin(GPU_PRIM_TRIS, 3);
4977  immUniformColor4ubv(wcol->inner);
4978  immVertex2f(pos, cent_x - unit_half, y);
4979  immVertex2f(pos, cent_x + unit_half, y);
4980  immVertex2f(pos, cent_x, y + sign * unit_half);
4981  immEnd();
4982 
4983  immUnbindProgram();
4984  }
4985 
4987 }
4988 
4989 void ui_draw_popover_back(struct ARegion *region,
4990  uiStyle *UNUSED(style),
4991  uiBlock *block,
4992  rcti *rect)
4993 {
4995 
4996  if (block) {
4997  float mval_origin[2] = {UNPACK2(block->bounds_offset)};
4998  ui_window_to_block_fl(region, block, &mval_origin[0], &mval_origin[1]);
5000  wt->wcol_theme, rect, block->direction, U.widget_unit / block->aspect, mval_origin);
5001  }
5002  else {
5003  wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
5004  wt->draw(&wt->wcol, rect, 0, 0);
5005  }
5006 
5007  ui_draw_clip_tri(block, rect, wt);
5008 }
5009 
5010 static void draw_disk_shaded(float start,
5011  float angle,
5012  float radius_int,
5013  float radius_ext,
5014  int subd,
5015  const uchar col1[4],
5016  const uchar col2[4],
5017  bool shaded)
5018 {
5019  const float radius_ext_scale = (0.5f / radius_ext); /* 1 / (2 * radius_ext) */
5020 
5021  uint col;
5024  if (shaded) {
5027  }
5028  else {
5030  immUniformColor4ubv(col1);
5031  }
5032 
5033  immBegin(GPU_PRIM_TRI_STRIP, subd * 2);
5034  for (int i = 0; i < subd; i++) {
5035  const float a = start + ((i) / (float)(subd - 1)) * angle;
5036  const float s = sinf(a);
5037  const float c = cosf(a);
5038  const float y1 = s * radius_int;
5039  const float y2 = s * radius_ext;
5040 
5041  if (shaded) {
5042  uchar r_col[4];
5043  const float fac = (y1 + radius_ext) * radius_ext_scale;
5044  color_blend_v4_v4v4(r_col, col1, col2, fac);
5045  immAttr4ubv(col, r_col);
5046  }
5047  immVertex2f(pos, c * radius_int, s * radius_int);
5048 
5049  if (shaded) {
5050  uchar r_col[4];
5051  const float fac = (y2 + radius_ext) * radius_ext_scale;
5052  color_blend_v4_v4v4(r_col, col1, col2, fac);
5053  immAttr4ubv(col, r_col);
5054  }
5055  immVertex2f(pos, c * radius_ext, s * radius_ext);
5056  }
5057  immEnd();
5058 
5059  immUnbindProgram();
5060 }
5061 
5063 {
5064  bTheme *btheme = UI_GetTheme();
5065  const float cx = block->pie_data.pie_center_spawned[0];
5066  const float cy = block->pie_data.pie_center_spawned[1];
5067 
5068  float *pie_dir = block->pie_data.pie_dir;
5069 
5070  const float pie_radius_internal = U.dpi_fac * U.pie_menu_threshold;
5071  const float pie_radius_external = U.dpi_fac * (U.pie_menu_threshold + 7.0f);
5072 
5073  const int subd = 40;
5074 
5075  const float angle = atan2f(pie_dir[1], pie_dir[0]);
5076  const float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
5077 
5078  GPU_matrix_push();
5079  GPU_matrix_translate_2f(cx, cy);
5080 
5082  if (btheme->tui.wcol_pie_menu.shaded) {
5083  uchar col1[4], col2[4];
5084  shadecolors4(col1,
5085  col2,
5086  btheme->tui.wcol_pie_menu.inner,
5087  btheme->tui.wcol_pie_menu.shadetop,
5088  btheme->tui.wcol_pie_menu.shadedown);
5089  draw_disk_shaded(0.0f,
5090  (float)(M_PI * 2.0),
5091  pie_radius_internal,
5092  pie_radius_external,
5093  subd,
5094  col1,
5095  col2,
5096  true);
5097  }
5098  else {
5099  draw_disk_shaded(0.0f,
5100  (float)(M_PI * 2.0),
5101  pie_radius_internal,
5102  pie_radius_external,
5103  subd,
5104  btheme->tui.wcol_pie_menu.inner,
5105  NULL,
5106  false);
5107  }
5108 
5109  if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) {
5110  if (btheme->tui.wcol_pie_menu.shaded) {
5111  uchar col1[4], col2[4];
5112  shadecolors4(col1,
5113  col2,
5114  btheme->tui.wcol_pie_menu.inner_sel,
5115  btheme->tui.wcol_pie_menu.shadetop,
5116  btheme->tui.wcol_pie_menu.shadedown);
5117  draw_disk_shaded(angle - range / 2.0f,
5118  range,
5119  pie_radius_internal,
5120  pie_radius_external,
5121  subd,
5122  col1,
5123  col2,
5124  true);
5125  }
5126  else {
5127  draw_disk_shaded(angle - range / 2.0f,
5128  range,
5129  pie_radius_internal,
5130  pie_radius_external,
5131  subd,
5132  btheme->tui.wcol_pie_menu.inner_sel,
5133  NULL,
5134  false);
5135  }
5136  }
5137 
5142 
5143  imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_internal, subd);
5144  imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_external, subd);
5145 
5146  immUnbindProgram();
5147 
5148  if (U.pie_menu_confirm > 0 &&
5150  const float pie_confirm_radius = U.dpi_fac * (pie_radius_internal + U.pie_menu_confirm);
5151  const float pie_confirm_external = U.dpi_fac *
5152  (pie_radius_internal + U.pie_menu_confirm + 7.0f);
5153 
5154  const uchar col[4] = {UNPACK3(btheme->tui.wcol_pie_menu.text_sel), 64};
5155  draw_disk_shaded(angle - range / 2.0f,
5156  range,
5157  pie_confirm_radius,
5158  pie_confirm_external,
5159  subd,
5160  col,
5161  NULL,
5162  false);
5163  }
5164 
5166  GPU_matrix_pop();
5167 }
5168 
5170 {
5172  return wt->wcol_theme;
5173 }
5174 
5179  bool use_shadow,
5180  const rcti *rect,
5181  const float color[4])
5182 {
5183  uiWidgetType *wt = widget_type(type);
5184 
5185  if (use_shadow) {
5187  widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
5189  }
5190 
5191  rcti rect_copy = *rect;
5192  wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
5193  if (color) {
5194  rgba_float_to_uchar(wt->wcol.inner, color);
5195  }
5196  wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL);
5197 }
5198 void ui_draw_widget_menu_back_color(const rcti *rect, bool use_shadow, const float color[4])
5199 {
5200  ui_draw_widget_back_color(UI_WTYPE_MENU_BACK, use_shadow, rect, color);
5201 }
5202 
5203 void ui_draw_widget_menu_back(const rcti *rect, bool use_shadow)
5204 {
5206 }
5207 
5208 void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
5209 {
5211  wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
5212  /* wt->draw ends up using same function to draw the tooltip as menu_back */
5213  wt->draw(&wt->wcol, rect, 0, 0);
5214 }
5215 
5225 void ui_draw_menu_item(const uiFontStyle *fstyle,
5226  rcti *rect,
5227  const char *name,
5228  int iconid,
5229  int state,
5230  uiMenuItemSeparatorType separator_type,
5231  int *r_xmax)
5232 {
5234  const rcti _rect = *rect;
5235  const int row_height = BLI_rcti_size_y(rect);
5236  int max_hint_width = INT_MAX;
5237  int padding = 0.25f * row_height;
5238  char *cpoin = NULL;
5239 
5240  wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED);
5241  wt->draw(&wt->wcol, rect, 0, 0);
5242 
5243  UI_fontstyle_set(fstyle);
5244 
5245  /* text location offset */
5246  rect->xmin += padding;
5247  if (iconid) {
5248  rect->xmin += row_height; /* Use square area for icon. */
5249  }
5250 
5251  /* cut string in 2 parts? */
5252  if (separator_type != UI_MENU_ITEM_SEPARATOR_NONE) {
5253  cpoin = strrchr(name, UI_SEP_CHAR);
5254  if (cpoin) {
5255  *cpoin = 0;
5256 
5257  /* need to set this first */
5258  UI_fontstyle_set(fstyle);
5259 
5260  if (fstyle->kerning == 1) {
5261  /* for BLF_width */
5263  }
5264 
5265  if (separator_type == UI_MENU_ITEM_SEPARATOR_SHORTCUT) {
5266  /* Shrink rect to exclude the shortcut string. */
5267  rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_DPI_ICON_SIZE;
5268  }
5269  else if (separator_type == UI_MENU_ITEM_SEPARATOR_HINT) {
5270  /* Determine max-width for the hint string to leave the name string un-clipped (if there's
5271  * enough space to display it). */
5272 
5273  const int available_width = BLI_rcti_size_x(rect) - padding;
5274  const int name_width = BLF_width(fstyle->uifont_id, name, INT_MAX);
5275  const int hint_width = BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + padding;
5276 
5277  if ((name_width + hint_width) > available_width) {
5278  /* Clipping width for hint string. */
5279  max_hint_width = available_width * 0.40f;
5280  /* Clipping xmax for clipping of item name. */
5281  rect->xmax = (hint_width < max_hint_width) ?
5282  (rect->xmax - hint_width) :
5283  (rect->xmin + (available_width - max_hint_width));
5284  }
5285  }
5286  else {
5287  BLI_assert(!"Unknwon menu item separator type");
5288  }
5289 
5290  if (fstyle->kerning == 1) {
5292  }
5293  }
5294  }
5295 
5296  {
5297  char drawstr[UI_MAX_DRAW_STR];
5298  const float okwidth = (float)BLI_rcti_size_x(rect);
5299  const size_t max_len = sizeof(drawstr);
5300  const float minwidth = (float)(UI_DPI_ICON_SIZE);
5301 
5302  BLI_strncpy(drawstr, name, sizeof(drawstr));
5303  if (drawstr[0]) {
5304  UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
5305  }
5306 
5307  int xofs = 0, yofs = 0;
5308  struct ResultBLF info;
5309  UI_fontstyle_draw_ex(fstyle,
5310  rect,
5311  drawstr,
5312  wt->wcol.text,
5313  &(struct uiFontStyleDraw_Params){
5314  .align = UI_STYLE_TEXT_LEFT,
5315  },
5317  &xofs,
5318  &yofs,
5319  &info);
5320  if (r_xmax != NULL) {
5321  *r_xmax = xofs + info.width;
5322  }
5323  }
5324 
5325  /* restore rect, was messed with */
5326  *rect = _rect;
5327 
5328  if (iconid) {
5329  float height, aspect;
5330  const int xs = rect->xmin + 0.2f * UI_UNIT_X;
5331  const int ys = rect->ymin + 0.1f * BLI_rcti_size_y(rect);
5332 
5334  aspect = ICON_DEFAULT_HEIGHT / height;
5335 
5337  /* XXX scale weak get from fstyle? */
5338  UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false);
5340  }
5341 
5342  /* part text right aligned */
5343  if (separator_type != UI_MENU_ITEM_SEPARATOR_NONE) {
5344  if (cpoin) {
5345  /* Set inactive state for grayed out text. */
5347 
5348  char hint_drawstr[UI_MAX_DRAW_STR];
5349  {
5350  const size_t max_len = sizeof(hint_drawstr);
5351  const float minwidth = (float)(UI_DPI_ICON_SIZE);
5352 
5353  BLI_strncpy(hint_drawstr, cpoin + 1, sizeof(hint_drawstr));
5354  if (hint_drawstr[0] && (max_hint_width < INT_MAX)) {
5355  UI_text_clip_middle_ex(fstyle, hint_drawstr, max_hint_width, minwidth, max_len, '\0');
5356  }
5357  }
5358 
5359  rect->xmax = _rect.xmax - 5;
5360  UI_fontstyle_draw(fstyle,
5361  rect,
5362  hint_drawstr,
5363  wt->wcol.text,
5364  &(struct uiFontStyleDraw_Params){
5365  .align = UI_STYLE_TEXT_RIGHT,
5366  });
5367  *cpoin = UI_SEP_CHAR;
5368  }
5369  }
5370 }
5371 
5373  const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
5374 {
5375  rcti trect = *rect;
5376  const float text_size = UI_UNIT_Y;
5377  float font_dims[2] = {0.0f, 0.0f};
5379 
5380  /* drawing button background */
5381  wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED);
5382  wt->draw(&wt->wcol, rect, 0, 0);
5383 
5384  /* draw icon in rect above the space reserved for the label */
5385  rect->ymin += text_size;
5387  widget_draw_preview(iconid, 1.0f, rect);
5389 
5391  fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
5392 
5393  /* text rect */
5394  trect.xmin += 0;
5395  trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2;
5396  trect.ymin += U.widget_unit / 2;
5397  trect.ymax = trect.ymin + font_dims[1];
5398  if (trect.xmax > rect->xmax - PREVIEW_PAD) {
5399  trect.xmax = rect->xmax - PREVIEW_PAD;
5400  }
5401 
5402  {
5403  char drawstr[UI_MAX_DRAW_STR];
5404  const float okwidth = (float)BLI_rcti_size_x(&trect);
5405  const size_t max_len = sizeof(drawstr);
5406  const float minwidth = (float)(UI_DPI_ICON_SIZE);
5407 
5408  BLI_strncpy(drawstr, name, sizeof(drawstr));
5409  UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
5410 
5411  UI_fontstyle_draw(fstyle,
5412  &trect,
5413  drawstr,
5414  wt->wcol.text,
5415  &(struct uiFontStyleDraw_Params){
5416  .align = UI_STYLE_TEXT_CENTER,
5417  });
5418  }
5419 }
5420 
typedef float(TangentPoint)[2]
#define BLF_KERNING_DEFAULT
Definition: BLF_api.h:272
float BLF_width(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: blf.c:723
void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height) ATTR_NONNULL()
Definition: blf.c:698
void BLF_draw(int fontid, const char *str, size_t len) ATTR_NONNULL(2)
Definition: blf.c:542
#define BLF_DRAW_STR_DUMMY_MAX
Definition: BLF_api.h:283
size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width) ATTR_NONNULL(2)
Definition: blf.c:636
void BLF_disable(int fontid, int option)
Definition: blf.c:283
void BLF_boundbox_foreach_glyph(int fontid, const char *str, size_t len, BLF_GlyphBoundsFn user_fn, void *user_data) ATTR_NONNULL(2)
Definition: blf.c:630
void BLF_enable(int fontid, int option)
Definition: blf.c:274
#define BLF_SHADOW
Definition: BLF_api.h:271
size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width) ATTR_NONNULL(2)
Definition: blf.c:656
void BLF_color4ubv(int fontid, const unsigned char rgba[4])
Definition: blf.c:387
void BLF_position(int fontid, float x, float y, float z)
Definition: blf.c:312
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
Definition: BLI_listbase.h:184
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
#define M_PI_2
Definition: BLI_math_base.h:41
MINLINE float pow3f(float x)
MINLINE int clamp_i(int value, int min, int max)
#define M_PI
Definition: BLI_math_base.h:38
#define M_PI_4
Definition: BLI_math_base.h:44
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:254
#define rgba_float_args_set_ch(col, r, g, b, a)
void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:342
MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3])
MINLINE float rgb_to_grayscale(const float rgb[3])
void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
Definition: math_color.c:74
void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
Definition: math_color.c:31
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
Definition: math_color.c:414
void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
Definition: math_color.c:427
void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
Definition: math_color.c:315
void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
Definition: math_color.c:407
void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
Definition: math_color.c:422
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_squared_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4])
MINLINE void copy_v3_v3_uchar(unsigned char r[3], const unsigned char a[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3_uchar(unsigned char target[3], const unsigned char a[3], const unsigned char b[3], const float t)
Definition: math_vector.c:243
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
BLI_INLINE float BLI_rcti_cent_x_fl(const struct rcti *rct)
Definition: BLI_rect.h:128
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition: rct.c:597
void BLI_rcti_resize(struct rcti *rect, int x, int y)
Definition: rct.c:638
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition: rct.c:436
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:153
BLI_INLINE float BLI_rcti_cent_y_fl(const struct rcti *rct)
Definition: BLI_rect.h:132
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition: BLI_rect.h:140
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
void BLI_rctf_scale(rctf *rect, const float scale)
Definition: rct.c:694
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:161
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:165
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition: BLI_rect.h:136
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
int BLI_str_utf8_size(const char *p) ATTR_NONNULL()
Definition: string_utf8.c:495
char * BLI_str_find_prev_char_utf8(const char *str, const char *p) ATTR_NONNULL()
Definition: string_utf8.c:782
char * BLI_str_find_next_char_utf8(const char *p, const char *end) ATTR_NONNULL(1)
Definition: string_utf8.c:807
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNPACK2(a)
#define ARRAY_SIZE(arr)
#define UNUSED_VARS(...)
#define CLAMPIS(a, b, c)
#define SWAP(type, a, b)
#define UNUSED(x)
#define UNPACK3(a)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define MIN2(a, b)
void rect_copy(int dst[2][2], int src[2][2])
Definition: Basic.c:48
@ USER_CP_CIRCLE_HSV
void ED_node_socket_draw(struct bNodeSocket *sock, const struct rcti *rect, const float color[4], float scale)
GPUBatch
Definition: GPU_batch.h:93
void GPU_batch_draw_instanced(GPUBatch *batch, int i_count)
Definition: gpu_batch.cc:247
#define GPU_batch_uniform_4fv_array(batch, name, len, val)
Definition: GPU_batch.h:145
void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id)
Definition: gpu_batch.cc:299
GPUBatch * GPU_batch_create_ex(GPUPrimType prim, GPUVertBuf *vert, GPUIndexBuf *elem, eGPUBatchFlag owns_flag)
Definition: gpu_batch.cc:60
void GPU_batch_draw(GPUBatch *batch)
Definition: gpu_batch.cc:234
#define GPU_batch_uniform_3fv(batch, name, val)
Definition: GPU_batch.h:141
@ GPU_BATCH_OWNS_INDEX
Definition: GPU_batch.h:54
@ GPU_BATCH_OWNS_VBO
Definition: GPU_batch.h:45
void gpu_batch_presets_register(struct GPUBatch *preset_batch)
void immUniformColor4ubv(const unsigned char rgba[4])
void immAttr4ubv(uint attr_id, const unsigned char data[4])
void immUniformColor4f(float r, float g, float b, float a)
void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immUniformThemeColor(int color_id)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex2fv(uint attr_id, const float data[2])
void immUniformColor3ubv(const unsigned char rgb[3])
void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
void immAttr4f(uint attr_id, float x, float y, float z, float w)
void immUniformColor4fv(const float rgba[4])
GPUVertFormat * immVertexFormat(void)
void immUniformColor3f(float r, float g, float b)
void immAttr3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)
void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
void immRecti(uint pos, int x1, int y1, int x2, int y2)
void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
GPUIndexBuf * GPU_indexbuf_build(GPUIndexBufBuilder *)
void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint i1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte blue
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:142
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:135
void GPU_matrix_translate_2f(float x, float y)
Definition: gpu_matrix.cc:190
@ GPU_DRIVER_ANY
Definition: GPU_platform.h:56
@ GPU_OS_MAC
Definition: GPU_platform.h:47
@ GPU_DEVICE_INTEL
Definition: GPU_platform.h:35
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
@ GPU_PRIM_TRI_FAN
Definition: GPU_primitive.h:41
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_PRIM_TRI_STRIP
Definition: GPU_primitive.h:40
@ GPU_PRIM_TRIS
Definition: GPU_primitive.h:37
@ GPU_SHADER_2D_SMOOTH_COLOR
Definition: GPU_shader.h:185
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:171
@ GPU_SHADER_2D_WIDGET_BASE_INST
Definition: GPU_shader.h:374
@ GPU_SHADER_2D_WIDGET_BASE
Definition: GPU_shader.h:373
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_line_width(float width)
Definition: gpu_state.cc:173
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:85
#define GPU_vertbuf_create_with_format(format)
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
GPU_INLINE void * GPU_vertbuf_raw_step(GPUVertBufRaw *a)
void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *, uint a_idx, GPUVertBufRaw *access)
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
@ GPU_FETCH_INT_TO_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_I32
@ GPU_COMP_U32
@ GPU_COMP_U8
Group RGB to Bright Vector Camera CLAMP
@ PROP_PERCENTAGE
Definition: RNA_types.h:130
#define C
Definition: RandGen.cpp:39
#define UI_ALPHA_CHECKER_LIGHT
#define UI_UNIT_Y
@ UI_BUT_TEXT_RIGHT
Definition: UI_interface.h:261
@ UI_BUT_ACTIVE_RIGHT
Definition: UI_interface.h:291
@ UI_BUT_HAS_SHORTCUT
Definition: UI_interface.h:295
@ UI_BUT_ICON_LEFT
Definition: UI_interface.h:260
@ UI_BUT_ALIGN_DOWN
Definition: UI_interface.h:272
@ UI_BUT_ALIGN_TOP
Definition: UI_interface.h:269
@ UI_BUT_ALIGN
Definition: UI_interface.h:273
@ UI_BUT_NO_TEXT_PADDING
Definition: UI_interface.h:265
@ UI_BUT_ALIGN_STITCH_TOP
Definition: UI_interface.h:281
@ UI_BUT_ANIMATED_CHANGED
Definition: UI_interface.h:301
@ UI_BUT_TEXT_LEFT
Definition: UI_interface.h:259
@ UI_BUT_ACTIVE_LEFT
Definition: UI_interface.h:289
@ UI_BUT_BOX_ITEM
Definition: UI_interface.h:286
@ UI_BUT_ALIGN_STITCH_LEFT
Definition: UI_interface.h:282
@ UI_BUT_ALIGN_RIGHT
Definition: UI_interface.h:271
@ UI_BUT_ALIGN_LEFT
Definition: UI_interface.h:270
eUIEmbossType
Definition: UI_interface.h:106
@ UI_EMBOSS_UNDEFINED
Definition: UI_interface.h:117
@ UI_EMBOSS_NONE
Definition: UI_interface.h:108
@ UI_EMBOSS
Definition: UI_interface.h:107
@ UI_EMBOSS_RADIAL
Definition: UI_interface.h:110
@ UI_EMBOSS_PULLDOWN
Definition: UI_interface.h:109
@ UI_EMBOSS_NONE_OR_STATUS
Definition: UI_interface.h:115
void UI_fontstyle_set(const struct uiFontStyle *fs)
void UI_fontstyle_draw_ex(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, const uchar col[4], const struct uiFontStyleDraw_Params *fs_params, size_t len, int *r_xofs, int *r_yofs, struct ResultBLF *r_info)
@ UI_BUT_LIST_ITEM
Definition: UI_interface.h:218
@ UI_BUT_REDALERT
Definition: UI_interface.h:204
@ UI_BUT_ACTIVE_DEFAULT
Definition: UI_interface.h:215
@ UI_BUT_IMMEDIATE
Definition: UI_interface.h:209
@ UI_BUT_ANIMATED
Definition: UI_interface.h:201
@ UI_BUT_DISABLED
Definition: UI_interface.h:199
@ UI_BUT_INACTIVE
Definition: UI_interface.h:206
@ UI_BUT_OVERRIDDEN
Definition: UI_interface.h:234
@ UI_BUT_HAS_SEP_CHAR
Definition: UI_interface.h:225
@ UI_BUT_NODE_LINK
Definition: UI_interface.h:195
@ UI_BUT_ICON_PREVIEW
Definition: UI_interface.h:193
@ UI_BUT_NODE_ACTIVE
Definition: UI_interface.h:196
@ UI_BUT_DRIVEN
Definition: UI_interface.h:203
@ UI_BUT_DRAG_MULTI
Definition: UI_interface.h:220
@ UI_BUT_ICON_SUBMENU
Definition: UI_interface.h:192
@ UI_BUT_VALUE_CLEAR
Definition: UI_interface.h:231
@ UI_BUT_TEXTEDIT_UPDATE
Definition: UI_interface.h:229
@ UI_BUT_ANIMATED_KEY
Definition: UI_interface.h:202
@ UI_CNR_BOTTOM_LEFT
@ UI_CNR_BOTTOM_RIGHT
@ UI_CNR_ALL
@ UI_CNR_TOP_LEFT
@ UI_CNR_TOP_RIGHT
#define UI_SEP_CHAR
Definition: UI_interface.h:86
void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4])
#define UI_ALPHA_CHECKER_DARK
eFontStyle_Align
@ UI_STYLE_TEXT_LEFT
@ UI_STYLE_TEXT_CENTER
@ UI_STYLE_TEXT_RIGHT
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:90
#define UI_DPI_ICON_SIZE
Definition: UI_interface.h:311
#define UI_DPI_FAC
Definition: UI_interface.h:309
void UI_but_drawflag_disable(uiBut *but, int flag)
Definition: interface.c:6097
@ UI_BLOCK_CLIPBOTTOM
Definition: UI_interface.h:146
@ UI_BLOCK_POPOVER_ONCE
Definition: UI_interface.h:163
@ UI_BLOCK_POPUP
Definition: UI_interface.h:150
@ UI_BLOCK_CLIPTOP
Definition: UI_interface.h:147
@ UI_BLOCK_POPOVER
Definition: UI_interface.h:162
eButGradientType
Definition: UI_interface.h:398
@ UI_GRAD_L_ALT
Definition: UI_interface.h:407
@ UI_GRAD_SV
Definition: UI_interface.h:399
@ UI_GRAD_V_ALT
Definition: UI_interface.h:406
@ UI_GRAD_S
Definition: UI_interface.h:403
@ UI_GRAD_HV
Definition: UI_interface.h:400
@ UI_GRAD_HS
Definition: UI_interface.h:401
@ UI_GRAD_V
Definition: UI_interface.h:404
@ UI_GRAD_H
Definition: UI_interface.h:402
void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, const uchar col[4], const struct uiFontStyleDraw_Params *fs_params)
@ UI_SCROLL_NO_OUTLINE
Definition: UI_interface.h:459
@ UI_SCROLL_PRESSED
Definition: UI_interface.h:457
@ UI_SCROLL_ARROWS
Definition: UI_interface.h:458
@ UI_DIR_DOWN
Definition: UI_interface.h:123
@ UI_DIR_RIGHT
Definition: UI_interface.h:125
@ UI_DIR_LEFT
Definition: UI_interface.h:124
@ UI_DIR_UP
Definition: UI_interface.h:122
#define UI_UNIT_X
@ UI_BTYPE_BUT
Definition: UI_interface.h:334
@ UI_BTYPE_TOGGLE
Definition: UI_interface.h:344
@ UI_BTYPE_EXTRA
Definition: UI_interface.h:377
@ UI_BTYPE_TAB
Definition: UI_interface.h:354
@ UI_BTYPE_LISTBOX
Definition: UI_interface.h:370
@ UI_BTYPE_VECTORSCOPE
Definition: UI_interface.h:383
@ UI_BTYPE_SEPR_SPACER
Definition: UI_interface.h:389
@ UI_BTYPE_NODE_SOCKET
Definition: UI_interface.h:385
@ UI_BTYPE_ROUNDBOX
Definition: UI_interface.h:363
@ UI_BTYPE_COLORBAND
Definition: UI_interface.h:364
@ UI_BTYPE_BUT_MENU
Definition: UI_interface.h:339
@ UI_BTYPE_TOGGLE_N
Definition: UI_interface.h:345
@ UI_BTYPE_HISTOGRAM
Definition: UI_interface.h:381
@ UI_BTYPE_WAVEFORM
Definition: UI_interface.h:382
@ UI_BTYPE_BLOCK
Definition: UI_interface.h:357
@ UI_BTYPE_NUM_SLIDER
Definition: UI_interface.h:343
@ UI_BTYPE_HSVCIRCLE
Definition: UI_interface.h:372
@ UI_BTYPE_LISTROW
Definition: UI_interface.h:371
@ UI_BTYPE_TEXT
Definition: UI_interface.h:336
@ UI_BTYPE_BUT_TOGGLE
Definition: UI_interface.h:349
@ UI_BTYPE_HSVCUBE
Definition: UI_interface.h:360
@ UI_BTYPE_LABEL
Definition: UI_interface.h:358
@ UI_BTYPE_CURVE
Definition: UI_interface.h:367
@ UI_BTYPE_DECORATOR
Definition: UI_interface.h:392
@ UI_BTYPE_ROW
Definition: UI_interface.h:335
@ UI_BTYPE_SEARCH_MENU
Definition: UI_interface.h:376
@ UI_BTYPE_UNITVEC
Definition: UI_interface.h:366
@ UI_BTYPE_SEPR_LINE
Definition: UI_interface.h:387
@ UI_BTYPE_PROGRESS_BAR
Definition: UI_interface.h:384
@ UI_BTYPE_POPOVER
Definition: UI_interface.h:355
@ UI_BTYPE_CHECKBOX_N
Definition: UI_interface.h:352
@ UI_BTYPE_SEPR
Definition: UI_interface.h:386
@ UI_BTYPE_NUM
Definition: UI_interface.h:341
@ UI_BTYPE_PULLDOWN
Definition: UI_interface.h:362
@ UI_BTYPE_CURVEPROFILE
Definition: UI_interface.h:369
@ UI_BTYPE_TRACK_PREVIEW
Definition: UI_interface.h:373
@ UI_BTYPE_COLOR
Definition: UI_interface.h:353
@ UI_BTYPE_CHECKBOX
Definition: UI_interface.h:351
@ UI_BTYPE_GRIP
Definition: UI_interface.h:391
@ UI_BTYPE_MENU
Definition: UI_interface.h:338
@ UI_BTYPE_IMAGE
Definition: UI_interface.h:380
@ UI_BTYPE_SCROLL
Definition: UI_interface.h:356
@ UI_BLOCK_THEME_STYLE_POPUP
Definition: UI_interface.h:671
bool UI_but_is_tool(const uiBut *but)
#define ICON_DEFAULT_HEIGHT
#define ICON_DEFAULT_HEIGHT_TOOLBAR
bool UI_icon_get_theme_color(int icon_id, unsigned char color[4])
void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size)
#define ICON_DEFAULT_WIDTH
void UI_icon_draw_ex(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const uchar mono_color[4], const bool mono_border)
BIFIconID
Definition: UI_resources.h:34
@ TH_BACK
Definition: UI_resources.h:55
@ TH_WIDGET_EMBOSS
Definition: UI_resources.h:308
@ TH_WIDGET_TEXT_CURSOR
Definition: UI_resources.h:309
@ TH_TEXT
Definition: UI_resources.h:58
@ TH_TEXT_HI
Definition: UI_resources.h:59
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
Definition: resources.c:1350
int UI_ThemeMenuShadowWidth(void)
Definition: resources.c:1486
struct bTheme * UI_GetTheme(void)
Definition: resources.c:1086
void UI_GetThemeColor4fv(int colorid, float col[4])
Definition: resources.c:1199
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
Definition: resources.c:1381
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
btVector3 m_delta
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
Definition: util_half.h:41
void * user_data
static CCL_NAMESPACE_BEGIN const double alpha
GPUBatch * batch
Definition: drawnode.c:3779
static float color_step
Definition: effects.c:747
#define str(s)
static float verts[][3]
uint pos
uint col
uint padding(uint offset, uint alignment)
uiBut * ui_but_drag_multi_edit_get(uiBut *but)
Definition: interface.c:2600
double ui_but_value_get(uiBut *but)
Definition: interface.c:2431
void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3])
Definition: interface.c:3844
void ui_window_to_block_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
Definition: interface.c:190
bool ui_but_menu_draw_as_popover(const uiBut *but)
Definition: interface.c:4376
void ui_but_v3_get(uiBut *but, float vec[3])
Definition: interface.c:2230
void ui_draw_but_WAVEFORM(ARegion *UNUSED(region), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
void ui_draw_but_IMAGE(ARegion *UNUSED(region), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *rect)
void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
void ui_draw_but_COLORBAND(uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *rect)
void ui_draw_but_CURVEPROFILE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
void ui_draw_but_HISTOGRAM(ARegion *UNUSED(region), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
void ui_draw_but_TAB_outline(const rcti *rect, float rad, uchar highlight[3], uchar highlight_fade[3])
void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(region), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
int ui_but_menu_direction(uiBut *but)
void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *but, const bool restore)
IconTextureDrawCall border
@ ROUNDBOX_TRIA_CHECK
@ ROUNDBOX_TRIA_SCROLL
@ ROUNDBOX_TRIA_MENU
@ ROUNDBOX_TRIA_ARROWS
@ ROUNDBOX_TRIA_NONE
@ ROUNDBOX_TRIA_HOLD_ACTION_ARROW
void ui_perceptual_to_scene_linear_space(uiBut *but, float rgb[3])
void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3])
#define UI_MENU_SUBMENU_PADDING
bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT
@ UI_PIE_DEGREES_RANGE_LARGE
@ UI_PIE_INVALID_DIR
@ UI_PIE_CLICK_STYLE
void ui_scene_linear_to_perceptual_space(uiBut *but, float rgb[3])
#define UI_TEXT_MARGIN_X
bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT
void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3])
@ UI_BLOCK_CONTAINS_SUBMENU_BUT
int ui_but_icon(const uiBut *but)
bool ui_but_is_popover_once_compat(const uiBut *but) ATTR_WARN_UNUSED_RESULT
bool ui_but_is_color_gamma(uiBut *but)
@ UI_ACTIVE
@ UI_SELECT_DRAW
@ UI_HAS_ICON
@ UI_SELECT
@ UI_SEARCH_FILTER_NO_MATCH
#define UI_PIXEL_AA_JITTER
uiMenuItemSeparatorType
@ UI_MENU_ITEM_SEPARATOR_NONE
@ UI_MENU_ITEM_SEPARATOR_HINT
@ UI_MENU_ITEM_SEPARATOR_SHORTCUT
const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2]
static void widget_state_pie_menu_item(uiWidgetType *wt, int state, int UNUSED(drawflag), eUIEmbossType UNUSED(emboss))
static void color_blend_v3_v3(uchar cp[3], const uchar cpstate[3], const float fac)
void UI_widgetbase_draw_cache_begin(void)
static void widget_state_nothing(uiWidgetType *wt, int UNUSED(state), int UNUSED(drawflag), eUIEmbossType UNUSED(emboss))
static const float g_shape_preset_hold_action_vert[6][2]
struct uiWidgetType uiWidgetType
static const uint g_shape_preset_scroll_circle_face[14][3]
GPUVertFormat format
static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
static const float g_shape_preset_number_arrow_vert[3][2]
void ui_draw_popover_back(struct ARegion *region, uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
static int ui_but_draw_menu_icon(const uiBut *but)
static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
static void widget_unitvec(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
static void widgetbase_set_uniform_discard_factor(uiWidgetBase *wtb, const float discard_factor)
static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
void ui_draw_widget_menu_back_color(const rcti *rect, bool use_shadow, const float color[4])
static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol)
static void ui_draw_clip_tri(uiBlock *block, rcti *rect, uiWidgetType *wt)
static float widget_alpha_factor(const int state)
GPUBatch * roundbox_widget
static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
static void widget_softshadow(const rcti *rect, int roundboxalign, const float radin)
static void ui_hsv_cursor(float x, float y)
#define INNER
static void widget_state_menu_item(uiWidgetType *wt, int state, int UNUSED(drawflag), eUIEmbossType UNUSED(emboss))
static const float cornervec[WIDGET_CURVE_RESOLU][2]
static void widget_numbut_embossn(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
static void ui_text_clip_give_next_off(uiBut *but, const char *str)
static void ui_text_clip_right_ex(const uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth, const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define UI_BUT_UNDO
static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
static const uint g_shape_preset_checkmark_face[4][3]
static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
static void widgetbase_set_uniform_alpha_discard(uiWidgetBase *wtb, const bool alpha_check, const float discard_factor)
struct uiWidgetBase uiWidgetBase
static void ui_text_clip_right_label(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
void ui_hsvcircle_pos_from_vals(const ColorPicker *cpicker, const rcti *rect, const float *hsv, float *r_xpos, float *r_ypos)
static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
static void widget_draw_extra_icons(const uiWidgetColors *wcol, uiBut *but, rcti *rect, float alpha)
static void widgetbase_outline(uiWidgetBase *wtb, uint pos)
#define UI_TEXT_CLIP_MARGIN
static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX *2+2][2])
static void color_mul_hsl_v3(uchar ch[3], float h_factor, float s_factor, float l_factor)
#define PREVIEW_PAD
static void ui_widget_color_disabled(uiWidgetType *wt, const int state)
static void widget_state_pulldown(uiWidgetType *wt, int UNUSED(state), int UNUSED(drawflag), eUIEmbossType UNUSED(emboss))
void ui_draw_gradient(const rcti *rect, const float hsv[3], const eButGradientType type, const float alpha)
static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
void ui_draw_widget_menu_back(const rcti *rect, bool use_shadow)
static void draw_disk_shaded(float start, float angle, float radius_int, float radius_ext, int subd, const uchar col1[4], const uchar col2[4], bool shaded)
static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
static void widget_draw_text_icon(const uiFontStyle *fstyle, const uiWidgetColors *wcol, uiBut *but, rcti *rect)
uint vflag_id
#define MAX_WIDGET_BASE_BATCH
static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
void ui_hsvcube_pos_from_vals(const uiButHSVCube *hsv_but, const rcti *rect, const float *hsv, float *r_xp, float *r_yp)
static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad, float radi)
void ui_draw_anti_tria_rect(const rctf *rect, char dir, const float color[4])
static void shadecolors4(uchar coltop[4], uchar coldown[4], const uchar *color, short shadetop, short shadedown)
static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
GPUBatch * ui_batch_roundbox_shadow_get(void)
static void widget_tab(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
#define SC
uiWidgetTypeEnum
@ UI_WTYPE_SLIDER
@ UI_WTYPE_RGB_PICKER
@ UI_WTYPE_POINTER_LINK
@ UI_WTYPE_BOX
@ UI_WTYPE_MENU_ICON_RADIO
@ UI_WTYPE_SWATCH
@ UI_WTYPE_ICON_LABEL
@ UI_WTYPE_FILENAME
@ UI_WTYPE_LABEL
@ UI_WTYPE_TOGGLE
@ UI_WTYPE_LISTITEM
@ UI_WTYPE_ICON
@ UI_WTYPE_NAME
@ UI_WTYPE_EXEC
@ UI_WTYPE_PULLDOWN
@ UI_WTYPE_NUMBER
@ UI_WTYPE_MENU_ITEM
@ UI_WTYPE_MENU_ITEM_RADIAL
@ UI_WTYPE_NAME_LINK
@ UI_WTYPE_TOOLTIP
@ UI_WTYPE_UNITVEC
@ UI_WTYPE_TOOLBAR_ITEM
@ UI_WTYPE_CHECKBOX
@ UI_WTYPE_RADIO
@ UI_WTYPE_MENU_BACK
@ UI_WTYPE_TAB
@ UI_WTYPE_REGULAR
@ UI_WTYPE_MENU_POINTER_LINK
@ UI_WTYPE_SCROLL
@ UI_WTYPE_MENU_RADIO
@ UI_WTYPE_MENU_NODE_LINK
@ UI_WTYPE_NODESOCKET
@ UI_WTYPE_PROGRESSBAR
static int round_box_shadow_edges(float(*vert)[2], const rcti *rect, float rad, int roundboxalign, float step)
static void color_blend_v4_v4v4(uchar r_col[4], const uchar col1[4], const uchar col2[4], const float fac)
void UI_widgetbase_draw_cache_end(void)
static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
static void shape_preset_init_number_arrows(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
#define OY
static void shape_preset_init_hold_action(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
void ui_draw_preview_item(const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
static void widget_draw_node_link_socket(const uiWidgetColors *wcol, const rcti *rect, uiBut *but, float alpha)
static const uint g_shape_preset_hold_action_face[2][3]
static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *rect)
static const uchar * widget_color_blend_from_flags(const uiWidgetStateColors *wcol_state, int state, int drawflag, const eUIEmbossType emboss)
bool enabled
GPUBatch * roundbox_shadow
GPUBatch * ui_batch_roundbox_widget_get(void)
static void widget_state_option_menu(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
struct uiWidgetTrias uiWidgetTrias
static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
static void widget_draw_vertex_buffer(uint pos, uint col, int mode, const float quads_pos[WIDGET_SIZE_MAX][2], const uchar quads_col[WIDGET_SIZE_MAX][4], uint totvert)
void UI_draw_anti_fan(float tri_array[][2], uint length, const float color[4])
static void set_roundbox_vertex_data(GPUVertBufRaw *vflag_step, uint32_t d)
static void ui_text_clip_middle_protect_right(const uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char rsep)
#define UI_BUT_UPDATE_DELAY
static void draw_widgetbase_batch(uiWidgetBase *wtb)
static bool draw_widgetbase_batch_skip_draw_cache(void)
static void widget_draw_submenu_tria(const uiBut *but, const rcti *rect, const uiWidgetColors *wcol)
static const float g_shape_preset_menu_arrow_vert[6][2]
const uiWidgetColors * ui_tooltip_get_theme(void)
#define jit
static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
static const float g_shape_preset_checkmark_vert[6][2]
static GPUVertFormat * vflag_format(void)
static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rcti *rect)
#define WIDGET_SIZE_MAX
static const uint g_shape_preset_number_arrow_face[1][3]
static void ui_text_clip_give_prev_off(uiBut *but, const char *str)
void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
static struct @421 g_ui_batch_cache
static void shape_preset_init_trias_ex(uiWidgetTrias *tria, const rcti *rect, float triasize, char where, const float verts[][2], const int verts_tot, const uint tris[][3], const int tris_tot)
static void ui_draw_widget_back_color(uiWidgetTypeEnum type, bool use_shadow, const rcti *rect, const float color[4])
static void widgetbase_set_uniform_alpha_check(uiWidgetBase *wtb, const bool alpha_check)
#define ICON_SIZE_FROM_BUTRECT(rect)
static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, bool emboss)
void ui_hsvcircle_vals_from_pos(const rcti *rect, const float mx, const float my, float *r_val_rad, float *r_val_dist)
static void ui_text_clip_cursor(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *slider, int state)
static void widgetbase_set_uniform_colors_ubv(uiWidgetBase *wtb, const uchar *col1, const uchar *col2, const uchar *outline, const uchar *emboss, const uchar *tria, const bool alpha_check)
static void widget_init(uiWidgetBase *wtb)
static void widget_menubut_embossn(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
void ui_draw_menu_item(const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, uiMenuItemSeparatorType separator_type, int *r_xmax)
void UI_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4])
float UI_text_clip_middle_ex(const uiFontStyle *fstyle, char *str, float okwidth, const float minwidth, const size_t max_len, const char rpart_sep)
void ui_draw_box_opaque(rcti *rect, int roundboxalign)
static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
static void widget_nodesocket(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
static void ui_draw_popover_back_impl(const uiWidgetColors *wcol, rcti *rect, int direction, const float unit_size, const float mval_origin[2])
static void widget_state_label(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
static void round_box_edges(uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad)
static int widget_roundbox_set(uiBut *but, rcti *rect)
#define WIDGET_CURVE_RESOLU
static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
int count
static void widgetbase_draw_ex(uiWidgetBase *wtb, const uiWidgetColors *wcol, bool show_alpha_checkers)
void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
#define MAX_WIDGET_PARAMETERS
static struct @422 g_widget_base_batch
#define NO_AA
static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
void UI_widgetbase_draw_cache_flush(void)
@ UI_STATE_FLAGS_ALL
@ UI_STATE_ACTIVE_RIGHT
@ UI_STATE_TEXT_INPUT
@ UI_STATE_TEXT_BEFORE_WIDGET
@ UI_STATE_HOLD_ACTION
@ UI_STATE_ACTIVE_LEFT
#define WIDGET_AA_JITTER
static uiWidgetType * widget_type(uiWidgetTypeEnum type)
static void widget_draw_text(const uiFontStyle *fstyle, const uiWidgetColors *wcol, uiBut *but, rcti *rect)
static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const uchar mono_color[4])
static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
static bool widget_draw_text_underline_calc_center_x(const char *UNUSED(str), const size_t str_step_ofs, const rcti *glyph_step_bounds, const int UNUSED(glyph_advance_x), const rctf *glyph_bounds, const int glyph_bearing[2], void *user_data)
void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBut *but, rcti *rect)
static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
static void color_ensure_contrast_v3(uchar cp[3], const uchar cp_other[3], int contrast)
void UI_draw_icon_tri(float x, float y, char dir, const float color[4])
static const float g_shape_preset_scroll_circle_vert[16][2]
static void color_add_v3_i(uchar cp[3], int tint)
static void widget_active_color(uiWidgetColors *wcol)
static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
static uint32_t set_roundbox_vertex(GPUVertBufRaw *vflag_step, int corner_id, int corner_v, int jit_v, bool inner, bool emboss, int color)
static const uint g_shape_preset_menu_arrow_face[2][3]
#define SWATCH_KEYED_BORDER
void ui_draw_pie_center(uiBlock *block)
static void ui_text_clip_middle(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
#define sinf(x)
#define cosf(x)
#define atan2f(x, y)
#define ceilf(x)
#define sqrtf(x)
format
Definition: logImageCore.h:47
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
static ulong state[N]
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
double sign(double arg)
Definition: utility.h:250
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:3108
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1218
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1160
static const int steps
Definition: sky_nishita.cpp:28
#define min(a, b)
Definition: sort.c:51
unsigned int uint32_t
Definition: stdint.h:83
float hsv_perceptual[3]
float pie_center_spawned[2]
float pie_dir[2]
struct ID * owner_id
Definition: RNA_types.h:50
int width
Definition: BLF_api.h:300
float menu_shadow_fac
uiWidgetColors wcol_pulldown
uiWidgetColors wcol_numslider
uiWidgetColors wcol_list_item
uiWidgetColors wcol_menu
uiWidgetColors wcol_progress
uiWidgetColors wcol_menu_back
uiWidgetColors wcol_num
uiWidgetColors wcol_menu_item
uiWidgetColors wcol_toggle
uiWidgetColors wcol_regular
uiWidgetColors wcol_tooltip
uiWidgetColors wcol_option
uiWidgetColors wcol_text
uiWidgetColors wcol_tab
uiWidgetStateColors wcol_state
uiWidgetColors wcol_radio
uiWidgetColors wcol_scroll
uiWidgetColors wcol_pie_menu
uiWidgetColors wcol_toolbar_item
uiWidgetColors wcol_tool
float icon_saturation
uiWidgetColors wcol_box
ThemeUI tui
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79
void * drawextra_arg2
void * drawextra_arg1
struct PieMenuData pie_data
int bounds_offset[2]
char theme_style
short content_hints
void(* drawextra)(const struct bContext *C, void *idv, void *arg1, void *arg2, rcti *rect)
eButGradientType gradient_type
short selend
ListBase extra_op_icons
void * custom_data
struct uiHandleButtonData * active
void * dragpoin
char * editstr
eButType type
uchar menu_key
float softmin
short strwidth
uiBlock * block
eUIEmbossType emboss
char * poin
short selsta
uiButHandleHoldFunc hold_func
BIFIconID icon
float softmax
char drawstr[UI_MAX_DRAW_STR]
struct PropertyRNA * rnaprop
char * str
uchar col[4]
struct PointerRNA rnapoin
uiFontStyle widget
uiFontStyle widgetlabel
uiWidgetTrias tria2
float inner_v[WIDGET_SIZE_MAX][2]
float outer_v[WIDGET_SIZE_MAX][2]
uiWidgetTrias tria1
float inner_uv[WIDGET_SIZE_MAX][2]
uiWidgetBaseParameters uniform_params
unsigned char inner_sel[4]
unsigned char inner[4]
unsigned char outline[4]
unsigned char text[4]
unsigned char item[4]
unsigned char text_sel[4]
unsigned char shaded
unsigned char inner_key_sel[4]
unsigned char inner_changed_sel[4]
unsigned char inner_anim_sel[4]
unsigned char inner_driven_sel[4]
unsigned char inner_overridden_sel[4]
float vec[16][2]
const uint(* index)[3]
void(* custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign)
uiWidgetColors wcol
void(* state)(struct uiWidgetType *, int state, int drawflag, eUIEmbossType emboss)
const uiWidgetColors * wcol_theme
void(* text)(const uiFontStyle *, const uiWidgetColors *, uiBut *, rcti *)
uiWidgetStateColors * wcol_state
void(* draw)(uiWidgetColors *, rcti *, int state, int roundboxalign)
float max
ccl_device_inline float2 fabs(const float2 &a)
uint len