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