Blender  V2.93
interface_layout.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <limits.h>
22 #include <math.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_armature_types.h"
29 #include "DNA_screen_types.h"
30 #include "DNA_userdef_types.h"
31 
32 #include "BLI_alloca.h"
33 #include "BLI_dynstr.h"
34 #include "BLI_listbase.h"
35 #include "BLI_math.h"
36 #include "BLI_rect.h"
37 #include "BLI_string.h"
38 #include "BLI_utildefines.h"
39 
40 #include "BLT_translation.h"
41 
42 #include "BKE_anim_data.h"
43 #include "BKE_armature.h"
44 #include "BKE_context.h"
45 #include "BKE_global.h"
46 #include "BKE_idprop.h"
47 #include "BKE_screen.h"
48 
49 #include "RNA_access.h"
50 
51 #include "UI_interface.h"
52 
53 #include "WM_api.h"
54 #include "WM_types.h"
55 
56 #include "interface_intern.h"
57 
58 /* Show an icon button after each RNA button to use to quickly set keyframes,
59  * this is a way to display animation/driven/override status, see T54951. */
60 #define UI_PROP_DECORATE
61 /* Alternate draw mode where some buttons can use single icon width,
62  * giving more room for the text at the expense of nicely aligned text. */
63 #define UI_PROP_SEP_ICON_WIDTH_EXCEPTION
64 
65 /* -------------------------------------------------------------------- */
69 #define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \
70  if (ot == NULL) { \
71  ui_item_disabled(layout, _opname); \
72  RNA_warning("'%s' unknown operator", _opname); \
73  return_statement; \
74  } \
75  (void)0
76 
77 #define UI_ITEM_PROP_SEP_DIVIDE 0.4f
78 
79 /* uiLayoutRoot */
80 
81 typedef struct uiLayoutRoot {
82  struct uiLayoutRoot *next, *prev;
83 
84  int type;
85  int opcontext;
86 
87  int emw, emh;
88  int padding;
89 
91  void *argv;
92 
93  const uiStyle *style;
97 
98 /* Item */
99 
100 typedef enum uiItemType {
102 
113 
115 #if 0
116  TEMPLATE_COLUMN_FLOW,
117  TEMPLATE_SPLIT,
118  TEMPLATE_BOX,
119 
120  TEMPLATE_HEADER,
121  TEMPLATE_HEADER_ID,
122 #endif
124 
125 typedef struct uiItem {
126  void *next, *prev;
128  int flag;
130 
131 enum {
134 
135  UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
138  /* Show an icon button next to each property (to set keyframes, show status).
139  * Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */
142 };
143 
144 typedef struct uiButtonItem {
148 
149 struct uiLayout {
151 
156 
158 
161 
162  int x, y, w, h;
163  float scale[2];
164  short space;
165  bool align;
166  bool active;
169  bool enabled;
170  bool redalert;
174  char alignment;
177  float units[2];
178 };
179 
180 typedef struct uiLayoutItemFlow {
182  int number;
183  int totcol;
185 
186 typedef struct uiLayoutItemGridFlow {
188 
189  /* Extra parameters */
190  bool row_major; /* Fill first row first, instead of filling first column first. */
191  bool even_columns; /* Same width for all columns. */
192  bool even_rows; /* Same height for all rows. */
200 
201  /* Pure internal runtime storage. */
204 
205 typedef struct uiLayoutItemBx {
209 
210 typedef struct uiLayoutItemSplit {
212  float percentage;
214 
215 typedef struct uiLayoutItemRoot {
218 
221 /* -------------------------------------------------------------------- */
225 static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_NAME_STR])
226 {
227  const int len = strlen(name);
228 
229  if (len != 0 && len + 1 < UI_MAX_NAME_STR) {
230  memcpy(namestr, name, len);
231  namestr[len] = ':';
232  namestr[len + 1] = '\0';
233  return namestr;
234  }
235 
236  return name;
237 }
238 
239 static int ui_item_fit(
240  int item, int pos, int all, int available, bool is_last, int alignment, float *extra_pixel)
241 {
242  /* available == 0 is unlimited */
243  if (ELEM(0, available, all)) {
244  return item;
245  }
246 
247  if (all > available) {
248  /* contents is bigger than available space */
249  if (is_last) {
250  return available - pos;
251  }
252 
253  const float width = *extra_pixel + (item * available) / (float)all;
254  *extra_pixel = width - (int)width;
255  return (int)width;
256  }
257 
258  /* contents is smaller or equal to available space */
259  if (alignment == UI_LAYOUT_ALIGN_EXPAND) {
260  if (is_last) {
261  return available - pos;
262  }
263 
264  const float width = *extra_pixel + (item * available) / (float)all;
265  *extra_pixel = width - (int)width;
266  return (int)width;
267  }
268  return item;
269 }
270 
271 /* variable button size in which direction? */
272 #define UI_ITEM_VARY_X 1
273 #define UI_ITEM_VARY_Y 2
274 
276 {
277  return ((ELEM(layout->root->type, UI_LAYOUT_HEADER, UI_LAYOUT_PIEMENU) ||
278  (layout->alignment != UI_LAYOUT_ALIGN_EXPAND)) ?
281 }
282 
283 static bool ui_layout_variable_size(uiLayout *layout)
284 {
285  /* Note that this code is probably a bit flakey, we'd probably want to know whether it's
286  * variable in X and/or Y, etc. But for now it mimics previous one,
287  * with addition of variable flag set for children of grid-flow layouts. */
288  return ui_layout_vary_direction(layout) == UI_ITEM_VARY_X || layout->variable_size;
289 }
290 
291 /* estimated size of text + icon */
292 static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool compact)
293 {
294  const int unit_x = UI_UNIT_X * (layout->scale[0] ? layout->scale[0] : 1.0f);
295 
296  if (icon && !name[0]) {
297  return unit_x; /* icon only */
298  }
299 
300  if (ui_layout_variable_size(layout)) {
301  if (!icon && !name[0]) {
302  return unit_x; /* No icon or name. */
303  }
304  if (layout->alignment != UI_LAYOUT_ALIGN_EXPAND) {
305  layout->item.flag |= UI_ITEM_FIXED_SIZE;
306  }
307  const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
308  float margin = compact ? 1.25 : 1.50;
309  if (icon) {
310  /* It may seem odd that the icon only adds (unit_x / 4)
311  * but taking margins into account its fine, except
312  * in compact mode a bit more margin is required. */
313  margin += compact ? 0.35 : 0.25;
314  }
315  return UI_fontstyle_string_width(fstyle, name) + (unit_x * margin);
316  }
317  return unit_x * 10;
318 }
319 
320 static void ui_item_size(uiItem *item, int *r_w, int *r_h)
321 {
322  if (item->type == ITEM_BUTTON) {
323  uiButtonItem *bitem = (uiButtonItem *)item;
324 
325  if (r_w) {
326  *r_w = BLI_rctf_size_x(&bitem->but->rect);
327  }
328  if (r_h) {
329  *r_h = BLI_rctf_size_y(&bitem->but->rect);
330  }
331  }
332  else {
333  uiLayout *litem = (uiLayout *)item;
334 
335  if (r_w) {
336  *r_w = litem->w;
337  }
338  if (r_h) {
339  *r_h = litem->h;
340  }
341  }
342 }
343 
344 static void ui_item_offset(uiItem *item, int *r_x, int *r_y)
345 {
346  if (item->type == ITEM_BUTTON) {
347  uiButtonItem *bitem = (uiButtonItem *)item;
348 
349  if (r_x) {
350  *r_x = bitem->but->rect.xmin;
351  }
352  if (r_y) {
353  *r_y = bitem->but->rect.ymin;
354  }
355  }
356  else {
357  if (r_x) {
358  *r_x = 0;
359  }
360  if (r_y) {
361  *r_y = 0;
362  }
363  }
364 }
365 
366 static void ui_item_position(uiItem *item, int x, int y, int w, int h)
367 {
368  if (item->type == ITEM_BUTTON) {
369  uiButtonItem *bitem = (uiButtonItem *)item;
370 
371  bitem->but->rect.xmin = x;
372  bitem->but->rect.ymin = y;
373  bitem->but->rect.xmax = x + w;
374  bitem->but->rect.ymax = y + h;
375 
376  ui_but_update(bitem->but); /* for strlen */
377  }
378  else {
379  uiLayout *litem = (uiLayout *)item;
380 
381  litem->x = x;
382  litem->y = y + h;
383  litem->w = w;
384  litem->h = h;
385  }
386 }
387 
388 static void ui_item_move(uiItem *item, int delta_xmin, int delta_xmax)
389 {
390  if (item->type == ITEM_BUTTON) {
391  uiButtonItem *bitem = (uiButtonItem *)item;
392 
393  bitem->but->rect.xmin += delta_xmin;
394  bitem->but->rect.xmax += delta_xmax;
395 
396  ui_but_update(bitem->but); /* for strlen */
397  }
398  else {
399  uiLayout *litem = (uiLayout *)item;
400 
401  if (delta_xmin > 0) {
402  litem->x += delta_xmin;
403  }
404  else {
405  litem->w += delta_xmax;
406  }
407  }
408 }
409 
412 /* -------------------------------------------------------------------- */
416 int uiLayoutGetLocalDir(const uiLayout *layout)
417 {
418  switch (layout->item.type) {
419  case ITEM_LAYOUT_ROW:
420  case ITEM_LAYOUT_ROOT:
421  case ITEM_LAYOUT_OVERLAP:
422  return UI_LAYOUT_HORIZONTAL;
423  case ITEM_LAYOUT_COLUMN:
426  case ITEM_LAYOUT_SPLIT:
428  case ITEM_LAYOUT_BOX:
429  default:
430  return UI_LAYOUT_VERTICAL;
431  }
432 }
433 
434 static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, bool align)
435 {
436  uiLayout *sub;
438  sub = uiLayoutRow(layout, align);
439  }
440  else {
441  sub = uiLayoutColumn(layout, align);
442  }
443 
444  sub->space = 0;
445  return sub;
446 }
447 
448 static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
449 {
450  wmWindow *win = CTX_wm_window(C);
451  uiBut *but = arg_but;
452  PointerRNA *ptr = &but->rnapoin;
453  PropertyRNA *prop = but->rnaprop;
454  const int index = POINTER_AS_INT(arg_index);
455  const int shift = win->eventstate->shift;
456  const int len = RNA_property_array_length(ptr, prop);
457 
458  if (!shift) {
459  RNA_property_boolean_set_index(ptr, prop, index, true);
460 
461  for (int i = 0; i < len; i++) {
462  if (i != index) {
463  RNA_property_boolean_set_index(ptr, prop, i, 0);
464  }
465  }
466 
467  RNA_property_update(C, ptr, prop);
468 
469  LISTBASE_FOREACH (uiBut *, cbut, &but->block->buttons) {
470  ui_but_update(cbut);
471  }
472  }
473 }
474 
475 /* create buttons for an item with an RNA array */
476 static void ui_item_array(uiLayout *layout,
477  uiBlock *block,
478  const char *name,
479  int icon,
480  PointerRNA *ptr,
481  PropertyRNA *prop,
482  int len,
483  int x,
484  int y,
485  int w,
486  int UNUSED(h),
487  bool expand,
488  bool slider,
489  int toggle,
490  bool icon_only,
491  bool compact,
492  bool show_text)
493 {
494  const uiStyle *style = layout->root->style;
495 
496  /* retrieve type and subtype */
497  const PropertyType type = RNA_property_type(prop);
498  const PropertySubType subtype = RNA_property_subtype(prop);
499 
500  uiLayout *sub = ui_item_local_sublayout(layout, layout, 1);
501  UI_block_layout_set_current(block, sub);
502 
503  /* create label */
504  if (name[0] && show_text) {
505  uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
506  }
507 
508  /* create buttons */
509  if (type == PROP_BOOLEAN && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
510  /* special check for layer layout */
511  const int cols = (len >= 20) ? 2 : 1;
512  const int colbuts = len / (2 * cols);
513  uint layer_used = 0;
514  uint layer_active = 0;
515 
516  UI_block_layout_set_current(block, uiLayoutAbsolute(layout, false));
517 
518  const int butw = UI_UNIT_X * 0.75;
519  const int buth = UI_UNIT_X * 0.75;
520 
521  if (ptr->type == &RNA_Armature) {
522  bArmature *arm = ptr->data;
523 
524  layer_used = arm->layer_used;
525 
526  if (arm->edbo) {
527  if (arm->act_edbone) {
528  layer_active |= arm->act_edbone->layer;
529  }
530  }
531  else {
532  if (arm->act_bone) {
533  layer_active |= arm->act_bone->layer;
534  }
535  }
536  }
537 
538  for (int b = 0; b < cols; b++) {
539  UI_block_align_begin(block);
540 
541  for (int a = 0; a < colbuts; a++) {
542  const int layer_num = a + b * colbuts;
543  const uint layer_flag = (1u << layer_num);
544 
545  if (layer_used & layer_flag) {
546  if (layer_active & layer_flag) {
547  icon = ICON_LAYER_ACTIVE;
548  }
549  else {
550  icon = ICON_LAYER_USED;
551  }
552  }
553  else {
554  icon = ICON_BLANK1;
555  }
556 
557  uiBut *but = uiDefAutoButR(
558  block, ptr, prop, layer_num, "", icon, x + butw * a, y + buth, butw, buth);
559  if (subtype == PROP_LAYER_MEMBER) {
560  UI_but_func_set(but, ui_layer_but_cb, but, POINTER_FROM_INT(layer_num));
561  }
562  }
563  for (int a = 0; a < colbuts; a++) {
564  const int layer_num = a + len / 2 + b * colbuts;
565  const uint layer_flag = (1u << layer_num);
566 
567  if (layer_used & layer_flag) {
568  if (layer_active & layer_flag) {
569  icon = ICON_LAYER_ACTIVE;
570  }
571  else {
572  icon = ICON_LAYER_USED;
573  }
574  }
575  else {
576  icon = ICON_BLANK1;
577  }
578 
579  uiBut *but = uiDefAutoButR(
580  block, ptr, prop, layer_num, "", icon, x + butw * a, y, butw, buth);
581  if (subtype == PROP_LAYER_MEMBER) {
582  UI_but_func_set(but, ui_layer_but_cb, but, POINTER_FROM_INT(layer_num));
583  }
584  }
585  UI_block_align_end(block);
586 
587  x += colbuts * butw + style->buttonspacex;
588  }
589  }
590  else if (subtype == PROP_MATRIX) {
591  int totdim, dim_size[3]; /* 3 == RNA_MAX_ARRAY_DIMENSION */
592  int row, col;
593 
594  UI_block_layout_set_current(block, uiLayoutAbsolute(layout, true));
595 
596  totdim = RNA_property_array_dimension(ptr, prop, dim_size);
597  if (totdim != 2) {
598  /* Only 2D matrices supported in UI so far. */
599  return;
600  }
601 
602  w /= dim_size[0];
603  /* h /= dim_size[1]; */ /* UNUSED */
604 
605  for (int a = 0; a < len; a++) {
606  col = a % dim_size[0];
607  row = a / dim_size[0];
608 
609  uiBut *but = uiDefAutoButR(block,
610  ptr,
611  prop,
612  a,
613  "",
614  ICON_NONE,
615  x + w * col,
616  y + (dim_size[1] * UI_UNIT_Y) - (row * UI_UNIT_Y),
617  w,
618  UI_UNIT_Y);
619  if (slider && but->type == UI_BTYPE_NUM) {
620  uiButNumber *number_but = (uiButNumber *)but;
621 
622  but->a1 = number_but->step_size;
624  }
625  }
626  }
627  else if (subtype == PROP_DIRECTION && !expand) {
628  uiDefButR_prop(block,
630  0,
631  name,
632  x,
633  y,
634  UI_UNIT_X * 3,
635  UI_UNIT_Y * 3,
636  ptr,
637  prop,
638  -1,
639  0,
640  0,
641  -1,
642  -1,
643  NULL);
644  }
645  else {
646  /* note, this block of code is a bit arbitrary and has just been made
647  * to work with common cases, but may need to be re-worked */
648 
649  /* special case, boolean array in a menu, this could be used in a more generic way too */
650  if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && !expand && ELEM(len, 3, 4)) {
651  uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y);
652  }
653  else {
654  /* Even if 'expand' is false, we expand anyway. */
655 
656  /* layout for known array subtypes */
657  char str[3] = {'\0'};
658 
659  if (!icon_only && show_text) {
660  if (type != PROP_BOOLEAN) {
661  str[1] = ':';
662  }
663  }
664 
665  /* show checkboxes for rna on a non-emboss block (menu for eg) */
666  bool *boolarr = NULL;
667  if (type == PROP_BOOLEAN &&
669  boolarr = MEM_callocN(sizeof(bool) * len, __func__);
670  RNA_property_boolean_get_array(ptr, prop, boolarr);
671  }
672 
673  const char *str_buf = show_text ? str : "";
674  for (int a = 0; a < len; a++) {
675  if (!icon_only && show_text) {
676  str[0] = RNA_property_array_item_char(prop, a);
677  }
678  if (boolarr) {
679  icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
680  }
681 
682  const int width_item = ((compact && type == PROP_BOOLEAN) ?
683  min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) :
684  w);
685 
686  uiBut *but = uiDefAutoButR(
687  block, ptr, prop, a, str_buf, icon, 0, 0, width_item, UI_UNIT_Y);
688  if (slider && but->type == UI_BTYPE_NUM) {
689  uiButNumber *number_but = (uiButNumber *)but;
690 
691  but->a1 = number_but->step_size;
693  }
694  if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) {
695  but->type = UI_BTYPE_TOGGLE;
696  }
697  if ((a == 0) && (subtype == PROP_AXISANGLE)) {
699  }
700  }
701 
702  if (boolarr) {
703  MEM_freeN(boolarr);
704  }
705  }
706  }
707 
708  UI_block_layout_set_current(block, layout);
709 }
710 
711 static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2)
712 {
713  wmWindow *win = CTX_wm_window(C);
714 
715  if (!win->eventstate->shift) {
716  uiBut *but = (uiBut *)arg1;
717  const int enum_value = POINTER_AS_INT(arg2);
718 
719  int current_value = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
720  if (!(current_value & enum_value)) {
721  current_value = enum_value;
722  }
723  else {
724  current_value &= enum_value;
725  }
726  RNA_property_enum_set(&but->rnapoin, but->rnaprop, current_value);
727  }
728 }
729 
734  uiBlock *block,
735  PointerRNA *ptr,
736  PropertyRNA *prop,
737  const char *uiname,
738  const int h,
739  const eButType but_type,
740  const bool icon_only,
741  const EnumPropertyItem *item,
742  const bool is_first)
743 {
744  const char *name = (!uiname || uiname[0]) ? item->name : "";
745  const int icon = item->icon;
746  const int value = item->value;
747  const int itemw = ui_text_icon_width(block->curlayout, icon_only ? "" : name, icon, 0);
748 
749  uiBut *but;
750  if (icon && name[0] && !icon_only) {
752  block, but_type, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
753  }
754  else if (icon) {
755  const int w = (is_first) ? itemw : ceilf(itemw - U.pixelsize);
756  but = uiDefIconButR_prop(
757  block, but_type, 0, icon, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
758  }
759  else {
760  but = uiDefButR_prop(
761  block, but_type, 0, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
762  }
763 
764  if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
765  /* If this is set, assert since we're clobbering someone elses callback. */
766  /* Buttons get their block's func by default, so we cannot assert in that case either. */
767  BLI_assert(ELEM(but->func, NULL, block->func));
769  }
770 
771  if (uiLayoutGetLocalDir(layout) != UI_LAYOUT_HORIZONTAL) {
772  but->drawflag |= UI_BUT_TEXT_LEFT;
773  }
774 
775  /* Allow quick, inaccurate swipe motions to switch tabs
776  * (no need to keep cursor over them). */
777  if (but_type == UI_BTYPE_TAB) {
778  but->flag |= UI_BUT_DRAG_LOCK;
779  }
780 }
781 
782 static void ui_item_enum_expand_exec(uiLayout *layout,
783  uiBlock *block,
784  PointerRNA *ptr,
785  PropertyRNA *prop,
786  const char *uiname,
787  const int h,
788  const eButType but_type,
789  const bool icon_only)
790 {
791  /* XXX: The way this function currently handles uiname parameter
792  * is insane and inconsistent with general UI API:
793  *
794  * - uiname is the *enum property* label.
795  * - when it is NULL or empty, we do not draw *enum items* labels,
796  * this doubles the icon_only parameter.
797  * - we *never* draw (i.e. really use) the enum label uiname, it is just used as a mere flag!
798  *
799  * Unfortunately, fixing this implies an API "soft break", so better to defer it for later... :/
800  * - mont29
801  */
802 
804 
805  const bool radial = (layout->root->type == UI_LAYOUT_PIEMENU);
806 
807  bool free;
808  const EnumPropertyItem *item_array;
809  if (radial) {
810  RNA_property_enum_items_gettexted_all(block->evil_C, ptr, prop, &item_array, NULL, &free);
811  }
812  else {
813  RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item_array, NULL, &free);
814  }
815 
816  /* We don't want nested rows, cols in menus. */
817  uiLayout *layout_radial = NULL;
818  if (radial) {
819  if (layout->root->layout == layout) {
820  layout_radial = uiLayoutRadial(layout);
821  UI_block_layout_set_current(block, layout_radial);
822  }
823  else {
824  if (layout->item.type == ITEM_LAYOUT_RADIAL) {
825  layout_radial = layout;
826  }
827  UI_block_layout_set_current(block, layout);
828  }
829  }
831  layout->root->type == UI_LAYOUT_MENU) {
832  UI_block_layout_set_current(block, layout);
833  }
834  else {
835  UI_block_layout_set_current(block, ui_item_local_sublayout(layout, layout, 1));
836  }
837 
838  for (const EnumPropertyItem *item = item_array; item->identifier; item++) {
839  const bool is_first = item == item_array;
840 
841  if (!item->identifier[0]) {
842  const EnumPropertyItem *next_item = item + 1;
843 
844  /* Separate items, potentially with a label. */
845  if (next_item->identifier) {
846  /* Item without identifier but with name:
847  * Add group label for the following items. */
848  if (item->name) {
849  if (!is_first) {
850  uiItemS(block->curlayout);
851  }
852  uiItemL(block->curlayout, item->name, item->icon);
853  }
854  else if (radial && layout_radial) {
855  uiItemS(layout_radial);
856  }
857  else {
858  uiItemS(block->curlayout);
859  }
860  }
861  continue;
862  }
863 
865  layout, block, ptr, prop, uiname, h, but_type, icon_only, item, is_first);
866  }
867 
868  UI_block_layout_set_current(block, layout);
869 
870  if (free) {
871  MEM_freeN((void *)item_array);
872  }
873 }
874 static void ui_item_enum_expand(uiLayout *layout,
875  uiBlock *block,
876  PointerRNA *ptr,
877  PropertyRNA *prop,
878  const char *uiname,
879  const int h,
880  const bool icon_only)
881 {
882  ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_ROW, icon_only);
883 }
884 static void ui_item_enum_expand_tabs(uiLayout *layout,
885  bContext *C,
886  uiBlock *block,
887  PointerRNA *ptr,
888  PropertyRNA *prop,
889  PointerRNA *ptr_highlight,
890  PropertyRNA *prop_highlight,
891  const char *uiname,
892  const int h,
893  const bool icon_only)
894 {
895  uiBut *last = block->buttons.last;
896 
897  ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_TAB, icon_only);
898  BLI_assert(last != block->buttons.last);
899 
900  for (uiBut *tab = last ? last->next : block->buttons.first; tab; tab = tab->next) {
902  }
903 
904  const bool use_custom_highlight = (prop_highlight != NULL);
905 
906  if (use_custom_highlight) {
907  const int highlight_array_len = RNA_property_array_length(ptr_highlight, prop_highlight);
908  bool *highlight_array = alloca(sizeof(bool) * highlight_array_len);
909  RNA_property_boolean_get_array(ptr_highlight, prop_highlight, highlight_array);
910  int i = 0;
911  for (uiBut *tab_but = last ? last->next : block->buttons.first;
912  (tab_but != NULL) && (i < highlight_array_len);
913  tab_but = tab_but->next, i++) {
914  SET_FLAG_FROM_TEST(tab_but->flag, !highlight_array[i], UI_BUT_INACTIVE);
915  }
916  }
917 }
918 
919 /* callback for keymap item change button */
920 static void ui_keymap_but_cb(bContext *UNUSED(C), void *but_v, void *UNUSED(key_v))
921 {
922  uiBut *but = but_v;
923 
924  RNA_boolean_set(&but->rnapoin, "shift", (but->modifier_key & KM_SHIFT) != 0);
925  RNA_boolean_set(&but->rnapoin, "ctrl", (but->modifier_key & KM_CTRL) != 0);
926  RNA_boolean_set(&but->rnapoin, "alt", (but->modifier_key & KM_ALT) != 0);
927  RNA_boolean_set(&but->rnapoin, "oskey", (but->modifier_key & KM_OSKEY) != 0);
928 }
929 
937  uiBlock *block,
938  const char *name,
939  int icon,
940  PointerRNA *ptr,
941  PropertyRNA *prop,
942  int index,
943  int x,
944  int y,
945  int w_hint,
946  int h,
947  int flag)
948 {
949  uiLayout *sub = layout;
950  int prop_but_width = w_hint;
951 #ifdef UI_PROP_DECORATE
952  uiLayout *layout_prop_decorate = NULL;
953  const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
954  const bool use_prop_decorate = use_prop_sep && (layout->item.flag & UI_ITEM_PROP_DECORATE) &&
955  (layout->item.flag & UI_ITEM_PROP_DECORATE_NO_PAD) == 0;
956 #endif
957 
958  const bool is_keymapitem_ptr = RNA_struct_is_a(ptr->type, &RNA_KeyMapItem);
959  if ((flag & UI_ITEM_R_FULL_EVENT) && !is_keymapitem_ptr) {
960  RNA_warning("Data is not a keymap item struct: %s. Ignoring 'full_event' option.",
962  }
963 
964  UI_block_layout_set_current(block, layout);
965 
966  /* Only add new row if more than 1 item will be added. */
967  if (name[0]
968 #ifdef UI_PROP_DECORATE
969  || use_prop_decorate
970 #endif
971  ) {
972  /* Also avoid setting 'align' if possible. Set the space to zero instead as aligning a large
973  * number of labels can end up aligning thousands of buttons when displaying key-map search (a
974  * heavy operation), see: T78636. */
975  sub = uiLayoutRow(layout, layout->align);
976  sub->space = 0;
977  }
978 
979  if (name[0]) {
980 #ifdef UI_PROP_DECORATE
981  if (use_prop_sep) {
982  layout_prop_decorate = uiItemL_respect_property_split(layout, name, 0);
983  }
984  else
985 #endif
986  {
987  int w_label;
988  if (ui_layout_variable_size(layout)) {
989  /* w_hint is width for label in this case.
990  * Use a default width for property button(s) */
991  prop_but_width = UI_UNIT_X * 5;
992  w_label = w_hint;
993  }
994  else {
995  w_label = w_hint / 3;
996  }
997  uiDefBut(block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, "");
998  }
999  }
1000 
1001  const PropertyType type = RNA_property_type(prop);
1002  const PropertySubType subtype = RNA_property_subtype(prop);
1003 
1004  uiBut *but;
1005  if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) {
1006  UI_block_layout_set_current(block, uiLayoutRow(sub, true));
1007  but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, prop_but_width - UI_UNIT_X, h);
1008 
1009  /* BUTTONS_OT_file_browse calls UI_context_active_but_prop_get_filebrowser */
1010  uiDefIconButO(block,
1011  UI_BTYPE_BUT,
1012  subtype == PROP_DIRPATH ? "BUTTONS_OT_directory_browse" :
1013  "BUTTONS_OT_file_browse",
1015  ICON_FILEBROWSER,
1016  x,
1017  y,
1018  UI_UNIT_X,
1019  h,
1020  NULL);
1021  }
1022  else if (flag & UI_ITEM_R_EVENT) {
1023  but = uiDefButR_prop(block,
1025  0,
1026  name,
1027  x,
1028  y,
1029  prop_but_width,
1030  h,
1031  ptr,
1032  prop,
1033  index,
1034  0,
1035  0,
1036  -1,
1037  -1,
1038  NULL);
1039  }
1040  else if ((flag & UI_ITEM_R_FULL_EVENT) && is_keymapitem_ptr) {
1041  char buf[128];
1042 
1043  WM_keymap_item_to_string(ptr->data, false, buf, sizeof(buf));
1044 
1045  but = uiDefButR_prop(block,
1047  0,
1048  buf,
1049  x,
1050  y,
1051  prop_but_width,
1052  h,
1053  ptr,
1054  prop,
1055  0,
1056  0,
1057  0,
1058  -1,
1059  -1,
1060  NULL);
1062  if (flag & UI_ITEM_R_IMMEDIATE) {
1064  }
1065  }
1066  else {
1067  const char *str = (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY)) ? NULL : "";
1068  but = uiDefAutoButR(block, ptr, prop, index, str, icon, x, y, prop_but_width, h);
1069  }
1070 
1071 #ifdef UI_PROP_DECORATE
1072  /* Only for alignment. */
1073  if (use_prop_decorate) { /* Note that sep flag may have been unset meanwhile. */
1074  uiItemL(layout_prop_decorate ? layout_prop_decorate : sub, NULL, ICON_BLANK1);
1075  }
1076 #endif /* UI_PROP_DECORATE */
1077 
1078  UI_block_layout_set_current(block, layout);
1079  return but;
1080 }
1081 
1083  PointerRNA *r_ptr,
1084  PropertyRNA **r_prop,
1085  bool *r_is_undo,
1086  bool *r_is_userdef)
1087 {
1088  ARegion *region = CTX_wm_menu(C) ? CTX_wm_menu(C) : CTX_wm_region(C);
1089  uiBut *prevbut = NULL;
1090 
1091  memset(r_ptr, 0, sizeof(*r_ptr));
1092  *r_prop = NULL;
1093  *r_is_undo = false;
1094  *r_is_userdef = false;
1095 
1096  if (!region) {
1097  return;
1098  }
1099 
1100  LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
1101  LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
1102  if (but && but->rnapoin.data) {
1103  if (RNA_property_type(but->rnaprop) == PROP_STRING) {
1104  prevbut = but;
1105  }
1106  }
1107 
1108  /* find the button before the active one */
1109  if ((but->flag & UI_BUT_LAST_ACTIVE) && prevbut) {
1110  *r_ptr = prevbut->rnapoin;
1111  *r_prop = prevbut->rnaprop;
1112  *r_is_undo = (prevbut->flag & UI_BUT_UNDO) != 0;
1113  *r_is_userdef = UI_but_is_userdef(prevbut);
1114  return;
1115  }
1116  }
1117  }
1118 }
1119 
1122 /* -------------------------------------------------------------------- */
1129 static void ui_but_tip_from_enum_item(uiBut *but, const EnumPropertyItem *item)
1130 {
1131  if (but->tip == NULL || but->tip[0] == '\0') {
1132  if (item->description && item->description[0] &&
1133  !(but->optype && but->optype->get_description)) {
1134  but->tip = item->description;
1135  }
1136  }
1137 }
1138 
1139 /* disabled item */
1140 static void ui_item_disabled(uiLayout *layout, const char *name)
1141 {
1142  uiBlock *block = layout->root->block;
1143 
1144  UI_block_layout_set_current(block, layout);
1145 
1146  if (!name) {
1147  name = "";
1148  }
1149 
1150  const int w = ui_text_icon_width(layout, name, 0, 0);
1151 
1152  uiBut *but = uiDefBut(
1153  block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1154  UI_but_disable(but, "");
1155 }
1156 
1163  wmOperatorType *ot,
1164  const char *name,
1165  int icon,
1166  IDProperty *properties,
1167  int context,
1168  int flag,
1169  PointerRNA *r_opptr)
1170 {
1171  /* Take care to fill 'r_opptr' whatever happens. */
1172  uiBlock *block = layout->root->block;
1173 
1174  if (!name) {
1175  if (ot && ot->srna && (flag & UI_ITEM_R_ICON_ONLY) == 0) {
1176  name = WM_operatortype_name(ot, NULL);
1177  }
1178  else {
1179  name = "";
1180  }
1181  }
1182 
1183  if (layout->root->type == UI_LAYOUT_MENU && !icon) {
1184  icon = ICON_BLANK1;
1185  }
1186 
1187  UI_block_layout_set_current(block, layout);
1188  ui_block_new_button_group(block, 0);
1189 
1190  const int w = ui_text_icon_width(layout, name, icon, 0);
1191 
1192  const eUIEmbossType prev_emboss = layout->emboss;
1193  if (flag & UI_ITEM_R_NO_BG) {
1194  layout->emboss = UI_EMBOSS_NONE_OR_STATUS;
1195  }
1196 
1197  /* create the button */
1198  uiBut *but;
1199  if (icon) {
1200  if (name[0]) {
1201  but = uiDefIconTextButO_ptr(
1202  block, UI_BTYPE_BUT, ot, context, icon, name, 0, 0, w, UI_UNIT_Y, NULL);
1203  }
1204  else {
1205  but = uiDefIconButO_ptr(block, UI_BTYPE_BUT, ot, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
1206  }
1207  }
1208  else {
1209  but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, context, name, 0, 0, w, UI_UNIT_Y, NULL);
1210  }
1211 
1212  BLI_assert(but->optype != NULL);
1213 
1214  if (flag & UI_ITEM_R_NO_BG) {
1215  layout->emboss = prev_emboss;
1216  }
1217 
1218  if (flag & UI_ITEM_O_DEPRESS) {
1219  but->flag |= UI_SELECT_DRAW;
1220  }
1221 
1222  if (flag & UI_ITEM_R_ICON_ONLY) {
1224  }
1225 
1226  if (layout->redalert) {
1228  }
1229 
1230  if (layout->active_default) {
1232  }
1233 
1234  /* assign properties */
1235  if (properties || r_opptr) {
1236  PointerRNA *opptr = UI_but_operator_ptr_get(but);
1237  if (properties) {
1238  opptr->data = properties;
1239  }
1240  else {
1241  const IDPropertyTemplate val = {0};
1242  opptr->data = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
1243  }
1244  if (r_opptr) {
1245  *r_opptr = *opptr;
1246  }
1247  }
1248 
1249  return but;
1250 }
1251 
1252 static void ui_item_menu_hold(struct bContext *C, ARegion *butregion, uiBut *but)
1253 {
1254  uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
1255  uiLayout *layout = UI_popup_menu_layout(pup);
1256  uiBlock *block = layout->root->block;
1257  UI_popup_menu_but_set(pup, butregion, but);
1258 
1259  block->flag |= UI_BLOCK_POPUP_HOLD;
1260  block->flag |= UI_BLOCK_IS_FLIP;
1261 
1262  char direction = UI_DIR_DOWN;
1263  if (!but->drawstr[0]) {
1264  switch (RGN_ALIGN_ENUM_FROM_MASK(butregion->alignment)) {
1265  case RGN_ALIGN_LEFT:
1266  direction = UI_DIR_RIGHT;
1267  break;
1268  case RGN_ALIGN_RIGHT:
1269  direction = UI_DIR_LEFT;
1270  break;
1271  case RGN_ALIGN_BOTTOM:
1272  direction = UI_DIR_UP;
1273  break;
1274  default:
1275  direction = UI_DIR_DOWN;
1276  break;
1277  }
1278  }
1279  UI_block_direction_set(block, direction);
1280 
1281  const char *menu_id = but->hold_argN;
1282  MenuType *mt = WM_menutype_find(menu_id, true);
1283  if (mt) {
1284  uiLayoutSetContextFromBut(layout, but);
1285  UI_menutype_draw(C, mt, layout);
1286  }
1287  else {
1288  uiItemL(layout, "Menu Missing:", ICON_NONE);
1289  uiItemL(layout, menu_id, ICON_NONE);
1290  }
1291  UI_popup_menu_end(C, pup);
1292 }
1293 
1295  wmOperatorType *ot,
1296  const char *name,
1297  int icon,
1298  IDProperty *properties,
1299  int context,
1300  int flag,
1301  PointerRNA *r_opptr)
1302 {
1303  uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
1304 }
1305 
1307  wmOperatorType *ot,
1308  const char *name,
1309  int icon,
1310  IDProperty *properties,
1311  int context,
1312  int flag,
1313  const char *menu_id,
1314  PointerRNA *r_opptr)
1315 {
1316  uiBut *but = uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
1318 }
1319 
1320 void uiItemFullO(uiLayout *layout,
1321  const char *opname,
1322  const char *name,
1323  int icon,
1324  IDProperty *properties,
1325  int context,
1326  int flag,
1327  PointerRNA *r_opptr)
1328 {
1329  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1330 
1331  UI_OPERATOR_ERROR_RET(ot, opname, {
1332  if (r_opptr) {
1333  *r_opptr = PointerRNA_NULL;
1334  }
1335  return;
1336  });
1337 
1338  uiItemFullO_ptr(layout, ot, name, icon, properties, context, flag, r_opptr);
1339 }
1340 
1341 static const char *ui_menu_enumpropname(uiLayout *layout,
1342  PointerRNA *ptr,
1343  PropertyRNA *prop,
1344  int retval)
1345 {
1346  bool free;
1347  const EnumPropertyItem *item;
1348  RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
1349 
1350  const char *name;
1351  if (RNA_enum_name(item, retval, &name)) {
1352  name = CTX_IFACE_(RNA_property_translation_context(prop), name);
1353  }
1354  else {
1355  name = "";
1356  }
1357 
1358  if (free) {
1359  MEM_freeN((void *)item);
1360  }
1361 
1362  return name;
1363 }
1364 
1366  wmOperatorType *ot,
1367  const char *name,
1368  int icon,
1369  const char *propname,
1370  int value)
1371 {
1372  PointerRNA ptr;
1374 
1375  PropertyRNA *prop = RNA_struct_find_property(&ptr, propname);
1376  if (prop == NULL) {
1377  RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
1378  return;
1379  }
1380 
1381  RNA_property_enum_set(&ptr, prop, value);
1382 
1383  if (!name) {
1384  name = ui_menu_enumpropname(layout, &ptr, prop, value);
1385  }
1386 
1387  uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
1388 }
1389 void uiItemEnumO(uiLayout *layout,
1390  const char *opname,
1391  const char *name,
1392  int icon,
1393  const char *propname,
1394  int value)
1395 {
1396  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1397 
1398  if (ot) {
1399  uiItemEnumO_ptr(layout, ot, name, icon, propname, value);
1400  }
1401  else {
1402  ui_item_disabled(layout, opname);
1403  RNA_warning("unknown operator '%s'", opname);
1404  }
1405 }
1406 
1408 {
1409  return (layout->item.type == ITEM_LAYOUT_RADIAL) ||
1410  ((layout->item.type == ITEM_LAYOUT_ROOT) && (layout->root->type == UI_LAYOUT_PIEMENU));
1411 }
1412 
1419  wmOperatorType *ot,
1420  PointerRNA ptr,
1421  PropertyRNA *prop,
1422  IDProperty *properties,
1423  int context,
1424  int flag,
1425  const EnumPropertyItem *item_array,
1426  int totitem)
1427 {
1428  const char *propname = RNA_property_identifier(prop);
1429  if (RNA_property_type(prop) != PROP_ENUM) {
1430  RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
1431  return;
1432  }
1433 
1434  uiLayout *target, *split = NULL;
1435  uiBlock *block = layout->root->block;
1436  const bool radial = ui_layout_is_radial(layout);
1437 
1438  if (radial) {
1439  target = uiLayoutRadial(layout);
1440  }
1441  else if ((uiLayoutGetLocalDir(layout) == UI_LAYOUT_HORIZONTAL) && (flag & UI_ITEM_R_ICON_ONLY)) {
1442  target = layout;
1443  UI_block_layout_set_current(block, target);
1444 
1445  /* Add a blank button to the beginning of the row. */
1446  uiDefIconBut(block,
1448  0,
1449  ICON_BLANK1,
1450  0,
1451  0,
1452  1.25f * UI_UNIT_X,
1453  UI_UNIT_Y,
1454  NULL,
1455  0,
1456  0,
1457  0,
1458  0,
1459  NULL);
1460  }
1461  else {
1462  split = uiLayoutSplit(layout, 0.0f, false);
1463  target = uiLayoutColumn(split, layout->align);
1464  }
1465 
1466  bool last_iter = false;
1467  const EnumPropertyItem *item = item_array;
1468  for (int i = 1; item->identifier && !last_iter; i++, item++) {
1469  /* handle oversized pies */
1470  if (radial && (totitem > PIE_MAX_ITEMS) && (i >= PIE_MAX_ITEMS)) {
1471  if (item->name) { /* only visible items */
1472  const EnumPropertyItem *tmp;
1473 
1474  /* Check if there are more visible items for the next level. If not, we don't
1475  * add a new level and add the remaining item instead of the 'more' button. */
1476  for (tmp = item + 1; tmp->identifier; tmp++) {
1477  if (tmp->name) {
1478  break;
1479  }
1480  }
1481 
1482  if (tmp->identifier) { /* only true if loop above found item and did early-exit */
1484  block, ot, propname, properties, item_array, totitem, context, flag);
1485  /* break since rest of items is handled in new pie level */
1486  break;
1487  }
1488  last_iter = true;
1489  }
1490  else {
1491  continue;
1492  }
1493  }
1494 
1495  if (item->identifier[0]) {
1496  PointerRNA tptr;
1498  if (properties) {
1499  if (tptr.data) {
1500  IDP_FreeProperty(tptr.data);
1501  }
1502  tptr.data = IDP_CopyProperty(properties);
1503  }
1504  RNA_property_enum_set(&tptr, prop, item->value);
1505 
1506  uiItemFullO_ptr(target,
1507  ot,
1508  (flag & UI_ITEM_R_ICON_ONLY) ? NULL : item->name,
1509  item->icon,
1510  tptr.data,
1511  context,
1512  flag,
1513  NULL);
1514 
1515  ui_but_tip_from_enum_item(block->buttons.last, item);
1516  }
1517  else {
1518  if (item->name) {
1519  if (item != item_array && !radial && split != NULL) {
1520  target = uiLayoutColumn(split, layout->align);
1521 
1522  /* inconsistent, but menus with labels do not look good flipped */
1523  block->flag |= UI_BLOCK_NO_FLIP;
1524  }
1525 
1526  uiBut *but;
1527  if (item->icon || radial) {
1528  uiItemL(target, item->name, item->icon);
1529 
1530  but = block->buttons.last;
1531  }
1532  else {
1533  /* Do not use uiItemL here, as our root layout is a menu one,
1534  * it will add a fake blank icon! */
1535  but = uiDefBut(block,
1537  0,
1538  item->name,
1539  0,
1540  0,
1541  UI_UNIT_X * 5,
1542  UI_UNIT_Y,
1543  NULL,
1544  0.0,
1545  0.0,
1546  0,
1547  0,
1548  "");
1549  uiItemS(target);
1550  }
1551  ui_but_tip_from_enum_item(but, item);
1552  }
1553  else {
1554  if (radial) {
1555  /* invisible dummy button to ensure all items are
1556  * always at the same position */
1557  uiItemS(target);
1558  }
1559  else {
1560  /* XXX bug here, columns draw bottom item badly */
1561  uiItemS(target);
1562  }
1563  }
1564  }
1565  }
1566 }
1567 
1569  const char *opname,
1570  const char *propname,
1571  IDProperty *properties,
1572  int context,
1573  int flag)
1574 {
1575  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1576 
1577  if (!ot || !ot->srna) {
1578  ui_item_disabled(layout, opname);
1579  RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
1580  return;
1581  }
1582 
1583  PointerRNA ptr;
1585  /* so the context is passed to itemf functions (some need it) */
1587  PropertyRNA *prop = RNA_struct_find_property(&ptr, propname);
1588 
1589  /* don't let bad properties slip through */
1590  BLI_assert((prop == NULL) || (RNA_property_type(prop) == PROP_ENUM));
1591 
1592  uiBlock *block = layout->root->block;
1593  if (prop && RNA_property_type(prop) == PROP_ENUM) {
1594  const EnumPropertyItem *item_array = NULL;
1595  int totitem;
1596  bool free;
1597 
1598  if (ui_layout_is_radial(layout)) {
1599  /* XXX: While "_all()" guarantees spatial stability,
1600  * it's bad when an enum has > 8 items total,
1601  * but only a small subset will ever be shown at once
1602  * (e.g. Mode Switch menu, after the introduction of GP editing modes).
1603  */
1604 #if 0
1606  block->evil_C, &ptr, prop, &item_array, &totitem, &free);
1607 #else
1608  RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
1609 #endif
1610  }
1611  else {
1612  RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
1613  }
1614 
1615  /* add items */
1616  uiItemsFullEnumO_items(layout, ot, ptr, prop, properties, context, flag, item_array, totitem);
1617 
1618  if (free) {
1619  MEM_freeN((void *)item_array);
1620  }
1621 
1622  /* intentionally don't touch UI_BLOCK_IS_FLIP here,
1623  * we don't know the context this is called in */
1624  }
1625  else if (prop && RNA_property_type(prop) != PROP_ENUM) {
1626  RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
1627  return;
1628  }
1629  else {
1630  RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
1631  return;
1632  }
1633 }
1634 
1635 void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname)
1636 {
1637  uiItemsFullEnumO(layout, opname, propname, NULL, layout->root->opcontext, 0);
1638 }
1639 
1640 /* for use in cases where we have */
1642  const char *name,
1643  int icon,
1644  const char *opname,
1645  const char *propname,
1646  int value)
1647 {
1648  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1649  UI_OPERATOR_ERROR_RET(ot, opname, return );
1650 
1651  PointerRNA ptr;
1653 
1654  /* enum lookup */
1655  PropertyRNA *prop = RNA_struct_find_property(&ptr, propname);
1656  if (prop == NULL) {
1657  RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
1658  return;
1659  }
1660 
1661  RNA_property_enum_set(&ptr, prop, value);
1662 
1663  /* same as uiItemEnumO */
1664  if (!name) {
1665  name = ui_menu_enumpropname(layout, &ptr, prop, value);
1666  }
1667 
1668  uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
1669 }
1670 
1672  const char *name,
1673  int icon,
1674  const char *opname,
1675  const char *propname,
1676  const char *value_str)
1677 {
1678  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1679  UI_OPERATOR_ERROR_RET(ot, opname, return );
1680 
1681  PointerRNA ptr;
1683 
1684  PropertyRNA *prop = RNA_struct_find_property(&ptr, propname);
1685  if (prop == NULL) {
1686  RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
1687  return;
1688  }
1689 
1690  /* enum lookup */
1691  /* no need for translations here */
1692  const EnumPropertyItem *item;
1693  bool free;
1694  RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
1695 
1696  int value;
1697  if (item == NULL || RNA_enum_value_from_id(item, value_str, &value) == 0) {
1698  if (free) {
1699  MEM_freeN((void *)item);
1700  }
1701  RNA_warning("%s.%s, enum %s not found", RNA_struct_identifier(ptr.type), propname, value_str);
1702  return;
1703  }
1704 
1705  if (free) {
1706  MEM_freeN((void *)item);
1707  }
1708 
1709  RNA_property_enum_set(&ptr, prop, value);
1710 
1711  /* same as uiItemEnumO */
1712  if (!name) {
1713  name = ui_menu_enumpropname(layout, &ptr, prop, value);
1714  }
1715 
1716  uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
1717 }
1718 
1720  const char *name,
1721  int icon,
1722  const char *opname,
1723  const char *propname,
1724  int value)
1725 {
1726  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1727  UI_OPERATOR_ERROR_RET(ot, opname, return );
1728 
1729  PointerRNA ptr;
1731  RNA_boolean_set(&ptr, propname, value);
1732 
1733  uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
1734 }
1735 
1736 void uiItemIntO(uiLayout *layout,
1737  const char *name,
1738  int icon,
1739  const char *opname,
1740  const char *propname,
1741  int value)
1742 {
1743  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1744  UI_OPERATOR_ERROR_RET(ot, opname, return );
1745 
1746  PointerRNA ptr;
1748  RNA_int_set(&ptr, propname, value);
1749 
1750  uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
1751 }
1752 
1753 void uiItemFloatO(uiLayout *layout,
1754  const char *name,
1755  int icon,
1756  const char *opname,
1757  const char *propname,
1758  float value)
1759 {
1760  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1761 
1762  UI_OPERATOR_ERROR_RET(ot, opname, return );
1763 
1764  PointerRNA ptr;
1766  RNA_float_set(&ptr, propname, value);
1767 
1768  uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
1769 }
1770 
1772  const char *name,
1773  int icon,
1774  const char *opname,
1775  const char *propname,
1776  const char *value)
1777 {
1778  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
1779 
1780  UI_OPERATOR_ERROR_RET(ot, opname, return );
1781 
1782  PointerRNA ptr;
1784  RNA_string_set(&ptr, propname, value);
1785 
1786  uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
1787 }
1788 
1789 void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
1790 {
1791  uiItemFullO(layout, opname, name, icon, NULL, layout->root->opcontext, 0, NULL);
1792 }
1793 
1794 /* RNA property items */
1795 
1796 static void ui_item_rna_size(uiLayout *layout,
1797  const char *name,
1798  int icon,
1799  PointerRNA *ptr,
1800  PropertyRNA *prop,
1801  int index,
1802  bool icon_only,
1803  bool compact,
1804  int *r_w,
1805  int *r_h)
1806 {
1807  int w = 0, h;
1808 
1809  /* arbitrary extended width by type */
1810  const PropertyType type = RNA_property_type(prop);
1811  const PropertySubType subtype = RNA_property_subtype(prop);
1812  const int len = RNA_property_array_length(ptr, prop);
1813 
1814  bool is_checkbox_only = false;
1815  if (!name[0] && !icon_only) {
1816  if (ELEM(type, PROP_STRING, PROP_POINTER)) {
1817  name = "non-empty text";
1818  }
1819  else if (type == PROP_BOOLEAN) {
1820  if (icon == ICON_NONE) {
1821  /* Exception for checkboxes, they need a little less space to align nicely. */
1822  is_checkbox_only = true;
1823  }
1824  icon = ICON_DOT;
1825  }
1826  else if (type == PROP_ENUM) {
1827  /* Find the longest enum item name, instead of using a dummy text! */
1828  const EnumPropertyItem *item_array;
1829  bool free;
1831  layout->root->block->evil_C, ptr, prop, &item_array, NULL, &free);
1832 
1833  for (const EnumPropertyItem *item = item_array; item->identifier; item++) {
1834  if (item->identifier[0]) {
1835  w = max_ii(w, ui_text_icon_width(layout, item->name, item->icon, compact));
1836  }
1837  }
1838  if (free) {
1839  MEM_freeN((void *)item_array);
1840  }
1841  }
1842  }
1843 
1844  if (!w) {
1845  if (type == PROP_ENUM && icon_only) {
1846  w = ui_text_icon_width(layout, "", ICON_BLANK1, compact);
1847  if (index != RNA_ENUM_VALUE) {
1848  w += 0.6f * UI_UNIT_X;
1849  }
1850  }
1851  else {
1852  /* not compact for float/int buttons, looks too squashed */
1854  layout, name, icon, ELEM(type, PROP_FLOAT, PROP_INT) ? false : compact);
1855  }
1856  }
1857  h = UI_UNIT_Y;
1858 
1859  /* increase height for arrays */
1860  if (index == RNA_NO_INDEX && len > 0) {
1861  if (!name[0] && icon == ICON_NONE) {
1862  h = 0;
1863  }
1864  if (layout->item.flag & UI_ITEM_PROP_SEP) {
1865  h = 0;
1866  }
1867  if (ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
1868  h += 2 * UI_UNIT_Y;
1869  }
1870  else if (subtype == PROP_MATRIX) {
1871  h += ceilf(sqrtf(len)) * UI_UNIT_Y;
1872  }
1873  else {
1874  h += len * UI_UNIT_Y;
1875  }
1876  }
1877 
1878  /* Increase width requirement if in a variable size layout. */
1879  if (ui_layout_variable_size(layout)) {
1880  if (type == PROP_BOOLEAN && name[0]) {
1881  w += UI_UNIT_X / 5;
1882  }
1883  else if (is_checkbox_only) {
1884  w -= UI_UNIT_X / 4;
1885  }
1886  else if (type == PROP_ENUM && !icon_only) {
1887  w += UI_UNIT_X / 4;
1888  }
1889  else if (ELEM(type, PROP_FLOAT, PROP_INT)) {
1890  w += UI_UNIT_X * 3;
1891  }
1892  }
1893 
1894  *r_w = w;
1895  *r_h = h;
1896 }
1897 
1898 static bool ui_item_rna_is_expand(PropertyRNA *prop, int index, int item_flag)
1899 {
1900  const bool is_array = RNA_property_array_check(prop);
1901  const int subtype = RNA_property_subtype(prop);
1902  return is_array && (index == RNA_NO_INDEX) &&
1903  ((item_flag & UI_ITEM_R_EXPAND) ||
1905 }
1906 
1915 {
1916  for (uiLayout *parent = cur_layout; parent; parent = parent->parent) {
1917  if (parent->heading[0]) {
1918  return parent;
1919  }
1920  }
1921 
1922  return NULL;
1923 }
1924 
1926  uiLayout *heading_layout,
1927  bool right_align,
1928  bool respect_prop_split)
1929 {
1930  const int prev_alignment = layout->alignment;
1931 
1932  if (right_align) {
1934  }
1935 
1936  if (respect_prop_split) {
1937  uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE);
1938  }
1939  else {
1940  uiItemL(layout, heading_layout->heading, ICON_NONE);
1941  }
1942  /* After adding the heading label, we have to mark it somehow as added, so it's not added again
1943  * for other items in this layout. For now just clear it. */
1944  heading_layout->heading[0] = '\0';
1945 
1946  layout->alignment = prev_alignment;
1947 }
1948 
1954 static uiLayout *ui_item_prop_split_layout_hack(uiLayout *layout_parent, uiLayout *layout_split)
1955 {
1956  /* Tag item as using property split layout, this is inherited to children so they can get special
1957  * treatment if needed. */
1958  layout_parent->item.flag |= UI_ITEM_INSIDE_PROP_SEP;
1959 
1960  if (layout_parent->item.type == ITEM_LAYOUT_ROW) {
1961  /* Prevent further splits within the row. */
1962  uiLayoutSetPropSep(layout_parent, false);
1963 
1964  layout_parent->child_items_layout = uiLayoutRow(layout_split, true);
1965  return layout_parent->child_items_layout;
1966  }
1967  return layout_split;
1968 }
1969 
1970 void uiItemFullR(uiLayout *layout,
1971  PointerRNA *ptr,
1972  PropertyRNA *prop,
1973  int index,
1974  int value,
1975  int flag,
1976  const char *name,
1977  int icon)
1978 {
1979  uiBlock *block = layout->root->block;
1980  char namestr[UI_MAX_NAME_STR];
1981  const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
1982  const bool inside_prop_sep = ((layout->item.flag & UI_ITEM_INSIDE_PROP_SEP) != 0);
1983  /* Columns can define a heading to insert. If the first item added to a split layout doesn't have
1984  * a label to display in the first column, the heading is inserted there. Otherwise it's inserted
1985  * as a new row before the first item. */
1986  uiLayout *heading_layout = ui_layout_heading_find(layout);
1987  /* Although checkboxes use the split layout, they are an exception and should only place their
1988  * label in the second column, to not make that almost empty.
1989  *
1990  * Keep using 'use_prop_sep' instead of disabling it entirely because
1991  * we need the ability to have decorators still. */
1992  bool use_prop_sep_split_label = use_prop_sep;
1993  bool use_split_empty_name = (flag & UI_ITEM_R_SPLIT_EMPTY_NAME);
1994 
1995 #ifdef UI_PROP_DECORATE
1996  struct {
1997  bool use_prop_decorate;
1998  int len;
1999  uiLayout *layout;
2000  uiBut *but;
2001  } ui_decorate = {
2002  .use_prop_decorate = (((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) && use_prop_sep),
2003  };
2004 #endif /* UI_PROP_DECORATE */
2005 
2006  UI_block_layout_set_current(block, layout);
2007  ui_block_new_button_group(block, 0);
2008 
2009  /* retrieve info */
2010  const PropertyType type = RNA_property_type(prop);
2011  const bool is_array = RNA_property_array_check(prop);
2012  const int len = (is_array) ? RNA_property_array_length(ptr, prop) : 0;
2013 
2014  const bool icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0;
2015 
2016  /* Boolean with -1 to signify that the value depends on the presence of an icon. */
2017  const int toggle = ((flag & UI_ITEM_R_TOGGLE) ? 1 : ((flag & UI_ITEM_R_ICON_NEVER) ? 0 : -1));
2018  const bool no_icon = (toggle == 0);
2019 
2020  /* set name and icon */
2021  if (!name) {
2022  if (!icon_only) {
2023  name = RNA_property_ui_name(prop);
2024  }
2025  else {
2026  name = "";
2027  }
2028  }
2029 
2030  if (type != PROP_BOOLEAN) {
2031  flag &= ~UI_ITEM_R_CHECKBOX_INVERT;
2032  }
2033 
2034  if (flag & UI_ITEM_R_ICON_ONLY) {
2035  /* pass */
2036  }
2038  if (use_prop_sep == false) {
2039  name = ui_item_name_add_colon(name, namestr);
2040  }
2041  }
2042  else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) {
2043  if (use_prop_sep == false) {
2044  name = ui_item_name_add_colon(name, namestr);
2045  }
2046  }
2047  else if (type == PROP_ENUM && index != RNA_ENUM_VALUE) {
2048  if (flag & UI_ITEM_R_COMPACT) {
2049  name = "";
2050  }
2051  else {
2052  if (use_prop_sep == false) {
2053  name = ui_item_name_add_colon(name, namestr);
2054  }
2055  }
2056  }
2057 
2058  if (no_icon == false) {
2059  if (icon == ICON_NONE) {
2060  icon = RNA_property_ui_icon(prop);
2061  }
2062 
2063  /* Menus and pie-menus don't show checkbox without this. */
2064  if ((layout->root->type == UI_LAYOUT_MENU) ||
2065  /* Use checkboxes only as a fallback in pie-menu's, when no icon is defined. */
2066  ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) {
2067  const int prop_flag = RNA_property_flag(prop);
2068  if (type == PROP_BOOLEAN) {
2069  if ((is_array == false) || (index != RNA_NO_INDEX)) {
2070  if (prop_flag & PROP_ICONS_CONSECUTIVE) {
2071  icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
2072  }
2073  else if (is_array) {
2074  icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT :
2075  ICON_CHECKBOX_DEHLT;
2076  }
2077  else {
2078  icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
2079  }
2080  }
2081  }
2082  else if (type == PROP_ENUM) {
2083  if (index == RNA_ENUM_VALUE) {
2084  const int enum_value = RNA_property_enum_get(ptr, prop);
2085  if (prop_flag & PROP_ICONS_CONSECUTIVE) {
2086  icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
2087  }
2088  else if (prop_flag & PROP_ENUM_FLAG) {
2089  icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
2090  }
2091  else {
2092  icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
2093  }
2094  }
2095  }
2096  }
2097  }
2098 
2099 #ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION
2100  if (use_prop_sep) {
2101  if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
2102  use_prop_sep_split_label = false;
2103  /* For check-boxes we make an exception: We allow showing them in a split row even without
2104  * label. It typically relates to its neighbor items, so no need for an extra label. */
2105  use_split_empty_name = true;
2106  }
2107  }
2108 #endif
2109 
2110  if ((type == PROP_ENUM) && (RNA_property_flag(prop) & PROP_ENUM_FLAG)) {
2111  flag |= UI_ITEM_R_EXPAND;
2112  }
2113 
2114  const bool slider = (flag & UI_ITEM_R_SLIDER) != 0;
2115  const bool expand = (flag & UI_ITEM_R_EXPAND) != 0;
2116  const bool no_bg = (flag & UI_ITEM_R_NO_BG) != 0;
2117  const bool compact = (flag & UI_ITEM_R_COMPACT) != 0;
2118 
2119  /* get size */
2120  int w, h;
2121  ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h);
2122 
2123  const eUIEmbossType prev_emboss = layout->emboss;
2124  if (no_bg) {
2125  layout->emboss = UI_EMBOSS_NONE_OR_STATUS;
2126  }
2127 
2128  uiBut *but = NULL;
2129 
2130  /* Split the label / property. */
2131  uiLayout *layout_parent = layout;
2132 
2133  if (use_prop_sep) {
2134  uiLayout *layout_row = NULL;
2135 #ifdef UI_PROP_DECORATE
2136  if (ui_decorate.use_prop_decorate) {
2137  layout_row = uiLayoutRow(layout, true);
2138  layout_row->space = 0;
2139  ui_decorate.len = max_ii(1, len);
2140  }
2141 #endif /* UI_PROP_DECORATE */
2142 
2143  if ((name[0] == '\0') && !use_split_empty_name) {
2144  /* Ensure we get a column when text is not set. */
2145  layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
2146  layout->space = 0;
2147  if (heading_layout) {
2148  ui_layout_heading_label_add(layout, heading_layout, false, false);
2149  }
2150  }
2151  else {
2152  uiLayout *layout_split = uiLayoutSplit(
2153  layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true);
2154  bool label_added = false;
2155  uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
2156  layout_sub->space = 0;
2157 
2158  if (!use_prop_sep_split_label) {
2159  /* Pass */
2160  }
2161  else if (ui_item_rna_is_expand(prop, index, flag)) {
2162  char name_with_suffix[UI_MAX_DRAW_STR + 2];
2163  char str[2] = {'\0'};
2164  for (int a = 0; a < len; a++) {
2165  str[0] = RNA_property_array_item_char(prop, a);
2166  const bool use_prefix = (a == 0 && name && name[0]);
2167  if (use_prefix) {
2168  char *s = name_with_suffix;
2169  s += STRNCPY_RLEN(name_with_suffix, name);
2170  *s++ = ' ';
2171  *s++ = str[0];
2172  *s++ = '\0';
2173  }
2174  but = uiDefBut(block,
2176  0,
2177  use_prefix ? name_with_suffix : str,
2178  0,
2179  0,
2180  w,
2181  UI_UNIT_Y,
2182  NULL,
2183  0.0,
2184  0.0,
2185  0,
2186  0,
2187  "");
2188  but->drawflag |= UI_BUT_TEXT_RIGHT;
2189  but->drawflag &= ~UI_BUT_TEXT_LEFT;
2190 
2191  label_added = true;
2192  }
2193  }
2194  else {
2195  if (name) {
2196  but = uiDefBut(
2197  block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
2198  but->drawflag |= UI_BUT_TEXT_RIGHT;
2199  but->drawflag &= ~UI_BUT_TEXT_LEFT;
2200 
2201  label_added = true;
2202  }
2203  }
2204 
2205  if (!label_added && heading_layout) {
2206  ui_layout_heading_label_add(layout_sub, heading_layout, true, false);
2207  }
2208 
2209  layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split);
2210 
2211  /* Watch out! We can only write into the new layout now. */
2212  if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) {
2213  /* Expanded enums each have their own name. */
2214 
2215  /* Often expanded enum's are better arranged into a row,
2216  * so check the existing layout. */
2217  if (uiLayoutGetLocalDir(layout) == UI_LAYOUT_HORIZONTAL) {
2218  layout = uiLayoutRow(layout_split, true);
2219  }
2220  else {
2221  layout = uiLayoutColumn(layout_split, true);
2222  }
2223  }
2224  else {
2225  if (use_prop_sep_split_label) {
2226  name = "";
2227  }
2228  layout = uiLayoutColumn(layout_split, true);
2229  }
2230  layout->space = 0;
2231  }
2232 
2233 #ifdef UI_PROP_DECORATE
2234  if (ui_decorate.use_prop_decorate) {
2235  ui_decorate.layout = uiLayoutColumn(layout_row, true);
2236  ui_decorate.layout->space = 0;
2237  UI_block_layout_set_current(block, layout);
2238  ui_decorate.but = block->buttons.last;
2239 
2240  /* Clear after. */
2242  }
2243 #endif /* UI_PROP_DECORATE */
2244  }
2245  /* End split. */
2246  else if (heading_layout) {
2247  /* Could not add heading to split layout, fallback to inserting it to the layout with the
2248  * heading itself. */
2249  ui_layout_heading_label_add(heading_layout, heading_layout, false, false);
2250  }
2251 
2252  /* array property */
2253  if (index == RNA_NO_INDEX && is_array) {
2254  if (inside_prop_sep) {
2255  /* Within a split row, add array items to a column so they match the column layout of
2256  * previous items (e.g. transform vector with lock icon for each item). */
2257  layout = uiLayoutColumn(layout, true);
2258  }
2259 
2260  ui_item_array(layout,
2261  block,
2262  name,
2263  icon,
2264  ptr,
2265  prop,
2266  len,
2267  0,
2268  0,
2269  w,
2270  h,
2271  expand,
2272  slider,
2273  toggle,
2274  icon_only,
2275  compact,
2276  !use_prop_sep_split_label);
2277  }
2278  /* enum item */
2279  else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
2280  if (icon && name[0] && !icon_only) {
2282  block, UI_BTYPE_ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
2283  }
2284  else if (icon) {
2286  block, UI_BTYPE_ROW, 0, icon, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
2287  }
2288  else {
2290  block, UI_BTYPE_ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
2291  }
2292  }
2293  /* expanded enum */
2294  else if (type == PROP_ENUM && expand) {
2295  ui_item_enum_expand(layout, block, ptr, prop, name, h, icon_only);
2296  }
2297  /* property with separate label */
2298  else if (ELEM(type, PROP_ENUM, PROP_STRING, PROP_POINTER)) {
2299  but = ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h, flag);
2300  but = ui_but_add_search(but, ptr, prop, NULL, NULL);
2301 
2302  if (layout->redalert) {
2304  }
2305 
2306  if (layout->activate_init) {
2308  }
2309  }
2310  /* single button */
2311  else {
2312  but = uiDefAutoButR(block, ptr, prop, index, name, icon, 0, 0, w, h);
2313 
2314  if (slider && but->type == UI_BTYPE_NUM) {
2315  uiButNumber *num_but = (uiButNumber *)but;
2316 
2317  but->a1 = num_but->step_size;
2319  }
2320 
2321  if (flag & UI_ITEM_R_CHECKBOX_INVERT) {
2322  if (ELEM(but->type,
2328  }
2329  }
2330 
2331  if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) {
2332  but->type = UI_BTYPE_TOGGLE;
2333  }
2334 
2335  if (layout->redalert) {
2337  }
2338 
2339  if (layout->activate_init) {
2341  }
2342  }
2343 
2344  /* The resulting button may have the icon set since boolean button drawing
2345  * is being 'helpful' and adding an icon for us.
2346  * In this case we want the ability not to have an icon.
2347  *
2348  * We could pass an argument not to set the icon to begin with however this is the one case
2349  * the functionality is needed. */
2350  if (but && no_icon) {
2351  if ((icon == ICON_NONE) && (but->icon != ICON_NONE)) {
2352  ui_def_but_icon_clear(but);
2353  }
2354  }
2355 
2356  /* Mark non-embossed textfields inside a listbox. */
2357  if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) &&
2360  }
2361 
2362 #ifdef UI_PROP_DECORATE
2363  if (ui_decorate.use_prop_decorate) {
2364  uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first;
2365  const bool use_blank_decorator = (flag & UI_ITEM_R_FORCE_BLANK_DECORATE);
2366  uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false);
2367  layout_col->space = 0;
2368  layout_col->emboss = UI_EMBOSS_NONE;
2369 
2370  int i;
2371  for (i = 0; i < ui_decorate.len && but_decorate; i++) {
2372  PointerRNA *ptr_dec = use_blank_decorator ? NULL : &but_decorate->rnapoin;
2373  PropertyRNA *prop_dec = use_blank_decorator ? NULL : but_decorate->rnaprop;
2374 
2375  /* The icons are set in 'ui_but_anim_flag' */
2376  uiItemDecoratorR_prop(layout_col, ptr_dec, prop_dec, but_decorate->rnaindex);
2377  but = block->buttons.last;
2378 
2379  /* Order the decorator after the button we decorate, this is used so we can always
2380  * do a quick lookup. */
2381  BLI_remlink(&block->buttons, but);
2382  BLI_insertlinkafter(&block->buttons, but_decorate, but);
2383  but_decorate = but->next;
2384  }
2385  BLI_assert(ELEM(i, 1, ui_decorate.len));
2386 
2388  }
2389 #endif /* UI_PROP_DECORATE */
2390 
2391  if (no_bg) {
2392  layout->emboss = prev_emboss;
2393  }
2394 
2395  /* ensure text isn't added to icon_only buttons */
2396  if (but && icon_only) {
2397  BLI_assert(but->str[0] == '\0');
2398  }
2399 }
2400 
2401 void uiItemR(
2402  uiLayout *layout, PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
2403 {
2404  PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
2405 
2406  if (!prop) {
2407  ui_item_disabled(layout, propname);
2408  RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
2409  return;
2410  }
2411 
2412  uiItemFullR(layout, ptr, prop, RNA_NO_INDEX, 0, flag, name, icon);
2413 }
2414 
2419  PointerRNA *ptr,
2420  PropertyRNA *prop,
2421  int index,
2422  int value,
2423  int flag,
2424  const char *name,
2425  int icon,
2426  const char *panel_type)
2427 {
2428  uiBlock *block = layout->root->block;
2429  uiBut *but = block->buttons.last;
2430  uiItemFullR(layout, ptr, prop, index, value, flag, name, icon);
2431  but = but->next;
2432  while (but) {
2433  if (but->rnaprop == prop && ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_COLOR)) {
2434  ui_but_rna_menu_convert_to_panel_type(but, panel_type);
2435  break;
2436  }
2437  but = but->next;
2438  }
2439  if (but == NULL) {
2440  const char *propname = RNA_property_identifier(prop);
2441  ui_item_disabled(layout, panel_type);
2442  RNA_warning("property could not use a popover: %s.%s (%s)",
2444  propname,
2445  panel_type);
2446  }
2447 }
2448 
2450  PointerRNA *ptr,
2451  PropertyRNA *prop,
2452  int index,
2453  int value,
2454  int flag,
2455  const char *name,
2456  int icon,
2457  const char *menu_type)
2458 {
2459  uiBlock *block = layout->root->block;
2460  uiBut *but = block->buttons.last;
2461  uiItemFullR(layout, ptr, prop, index, value, flag, name, icon);
2462  but = but->next;
2463  while (but) {
2464  if (but->rnaprop == prop && but->type == UI_BTYPE_MENU) {
2465  ui_but_rna_menu_convert_to_menu_type(but, menu_type);
2466  break;
2467  }
2468  but = but->next;
2469  }
2470  if (but == NULL) {
2471  const char *propname = RNA_property_identifier(prop);
2472  ui_item_disabled(layout, menu_type);
2473  RNA_warning("property could not use a menu: %s.%s (%s)",
2475  propname,
2476  menu_type);
2477  }
2478 }
2479 
2481  const char *name,
2482  int icon,
2483  struct PointerRNA *ptr,
2484  PropertyRNA *prop,
2485  int value)
2486 {
2487  if (RNA_property_type(prop) != PROP_ENUM) {
2488  const char *propname = RNA_property_identifier(prop);
2489  ui_item_disabled(layout, propname);
2490  RNA_warning("property not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
2491  return;
2492  }
2493 
2494  uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, value, 0, name, icon);
2495 }
2496 
2497 void uiItemEnumR(uiLayout *layout,
2498  const char *name,
2499  int icon,
2500  struct PointerRNA *ptr,
2501  const char *propname,
2502  int value)
2503 {
2504  PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
2505 
2506  if (prop == NULL) {
2507  ui_item_disabled(layout, propname);
2508  RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
2509  return;
2510  }
2511 
2512  uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, value, 0, name, icon);
2513 }
2514 
2516  struct PointerRNA *ptr,
2517  PropertyRNA *prop,
2518  const char *value,
2519  const char *name,
2520  int icon)
2521 {
2522  if (UNLIKELY(RNA_property_type(prop) != PROP_ENUM)) {
2523  const char *propname = RNA_property_identifier(prop);
2524  ui_item_disabled(layout, propname);
2525  RNA_warning("not an enum property: %s.%s", RNA_struct_identifier(ptr->type), propname);
2526  return;
2527  }
2528 
2529  const EnumPropertyItem *item;
2530  bool free;
2531  RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
2532 
2533  int ivalue;
2534  if (!RNA_enum_value_from_id(item, value, &ivalue)) {
2535  const char *propname = RNA_property_identifier(prop);
2536  if (free) {
2537  MEM_freeN((void *)item);
2538  }
2539  ui_item_disabled(layout, propname);
2540  RNA_warning("enum property value not found: %s", value);
2541  return;
2542  }
2543 
2544  for (int a = 0; item[a].identifier; a++) {
2545  if (item[a].identifier[0] == '\0') {
2546  /* Skip enum item separators. */
2547  continue;
2548  }
2549  if (item[a].value == ivalue) {
2550  const char *item_name = name ?
2551  name :
2552  CTX_IFACE_(RNA_property_translation_context(prop), item[a].name);
2553  const int flag = item_name[0] ? 0 : UI_ITEM_R_ICON_ONLY;
2554 
2555  uiItemFullR(
2556  layout, ptr, prop, RNA_ENUM_VALUE, ivalue, flag, item_name, icon ? icon : item[a].icon);
2557  break;
2558  }
2559  }
2560 
2561  if (free) {
2562  MEM_freeN((void *)item);
2563  }
2564 }
2565 
2567  struct PointerRNA *ptr,
2568  const char *propname,
2569  const char *value,
2570  const char *name,
2571  int icon)
2572 {
2573  PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
2574  if (UNLIKELY(prop == NULL)) {
2575  ui_item_disabled(layout, propname);
2576  RNA_warning("enum property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
2577  return;
2578  }
2579  uiItemEnumR_string_prop(layout, ptr, prop, value, name, icon);
2580 }
2581 
2582 void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname)
2583 {
2584  uiBlock *block = layout->root->block;
2585 
2586  PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
2587 
2588  if (!prop) {
2589  ui_item_disabled(layout, propname);
2590  RNA_warning("enum property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
2591  return;
2592  }
2593 
2594  if (RNA_property_type(prop) != PROP_ENUM) {
2595  RNA_warning("not an enum property: %s.%s", RNA_struct_identifier(ptr->type), propname);
2596  return;
2597  }
2598 
2599  uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
2600  uiLayout *column = uiLayoutColumn(split, false);
2601 
2602  int totitem;
2603  const EnumPropertyItem *item;
2604  bool free;
2605  RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free);
2606 
2607  for (int i = 0; i < totitem; i++) {
2608  if (item[i].identifier[0]) {
2609  uiItemEnumR_prop(column, item[i].name, item[i].icon, ptr, prop, item[i].value);
2610  ui_but_tip_from_enum_item(block->buttons.last, &item[i]);
2611  }
2612  else {
2613  if (item[i].name) {
2614  if (i != 0) {
2615  column = uiLayoutColumn(split, false);
2616  /* inconsistent, but menus with labels do not look good flipped */
2617  block->flag |= UI_BLOCK_NO_FLIP;
2618  }
2619 
2620  uiItemL(column, item[i].name, ICON_NONE);
2621  uiBut *bt = block->buttons.last;
2622  bt->drawflag = UI_BUT_TEXT_LEFT;
2623 
2624  ui_but_tip_from_enum_item(bt, &item[i]);
2625  }
2626  else {
2627  uiItemS(column);
2628  }
2629  }
2630  }
2631 
2632  if (free) {
2633  MEM_freeN((void *)item);
2634  }
2635 
2636  /* intentionally don't touch UI_BLOCK_IS_FLIP here,
2637  * we don't know the context this is called in */
2638 }
2639 
2640 /* Pointer RNA button with search */
2641 
2642 static void search_id_collection(StructRNA *ptype, PointerRNA *r_ptr, PropertyRNA **r_prop)
2643 {
2644  /* look for collection property in Main */
2645  /* NOTE: using global Main is OK-ish here, UI shall not access other Mains anyway. */
2647 
2648  *r_prop = NULL;
2649 
2650  RNA_STRUCT_BEGIN (r_ptr, iprop) {
2651  /* if it's a collection and has same pointer type, we've got it */
2652  if (RNA_property_type(iprop) == PROP_COLLECTION) {
2653  StructRNA *srna = RNA_property_pointer_type(r_ptr, iprop);
2654 
2655  if (ptype == srna) {
2656  *r_prop = iprop;
2657  break;
2658  }
2659  }
2660  }
2662 }
2663 
2665 {
2666  uiRNACollectionSearch *coll_search = ptr;
2667  UI_butstore_free(coll_search->butstore_block, coll_search->butstore);
2668  MEM_freeN(ptr);
2669 }
2670 
2675  uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
2676 {
2677  /* for ID's we do automatic lookup */
2678  PointerRNA sptr;
2679  if (!searchprop) {
2680  if (RNA_property_type(prop) == PROP_POINTER) {
2681  StructRNA *ptype = RNA_property_pointer_type(ptr, prop);
2682  search_id_collection(ptype, &sptr, &searchprop);
2683  searchptr = &sptr;
2684  }
2685  }
2686 
2687  /* turn button into search button */
2688  if (searchprop) {
2689  uiRNACollectionSearch *coll_search = MEM_mallocN(sizeof(*coll_search), __func__);
2690  uiButSearch *search_but;
2691 
2693  search_but = (uiButSearch *)but;
2694  search_but->rnasearchpoin = *searchptr;
2695  search_but->rnasearchprop = searchprop;
2696  but->hardmax = MAX2(but->hardmax, 256.0f);
2698  if (RNA_property_is_unlink(prop)) {
2699  but->flag |= UI_BUT_VALUE_CLEAR;
2700  }
2701 
2702  coll_search->target_ptr = *ptr;
2703  coll_search->target_prop = prop;
2704  coll_search->search_ptr = *searchptr;
2705  coll_search->search_prop = searchprop;
2706  coll_search->search_but = but;
2707  coll_search->butstore_block = but->block;
2708  coll_search->butstore = UI_butstore_create(coll_search->butstore_block);
2709  UI_butstore_register(coll_search->butstore, &coll_search->search_but);
2710 
2711  if (RNA_property_type(prop) == PROP_ENUM) {
2712  /* XXX, this will have a menu string,
2713  * but in this case we just want the text */
2714  but->str[0] = 0;
2715  }
2716 
2720  coll_search,
2721  false,
2723  NULL,
2724  NULL);
2725  }
2726  else if (but->type == UI_BTYPE_SEARCH_MENU) {
2727  /* In case we fail to find proper searchprop,
2728  * so other code might have already set but->type to search menu... */
2729  but->flag |= UI_BUT_DISABLED;
2730  }
2731 
2732  return but;
2733 }
2734 
2736  PointerRNA *ptr,
2737  PropertyRNA *prop,
2738  PointerRNA *searchptr,
2739  PropertyRNA *searchprop,
2740  const char *name,
2741  int icon)
2742 {
2743  const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
2744 
2746 
2747  const PropertyType type = RNA_property_type(prop);
2749  RNA_warning("Property %s.%s must be a pointer, string or enum",
2751  RNA_property_identifier(prop));
2752  return;
2753  }
2754  if (RNA_property_type(searchprop) != PROP_COLLECTION) {
2755  RNA_warning("search collection property is not a collection type: %s.%s",
2756  RNA_struct_identifier(searchptr->type),
2757  RNA_property_identifier(searchprop));
2758  return;
2759  }
2760 
2761  /* get icon & name */
2762  if (icon == ICON_NONE) {
2763  StructRNA *icontype;
2764  if (type == PROP_POINTER) {
2765  icontype = RNA_property_pointer_type(ptr, prop);
2766  }
2767  else {
2768  icontype = RNA_property_pointer_type(searchptr, searchprop);
2769  }
2770 
2771  icon = RNA_struct_ui_icon(icontype);
2772  }
2773  if (!name) {
2774  name = RNA_property_ui_name(prop);
2775  }
2776 
2777  char namestr[UI_MAX_NAME_STR];
2778  if (use_prop_sep == false) {
2779  name = ui_item_name_add_colon(name, namestr);
2780  }
2781 
2782  /* create button */
2783  uiBlock *block = uiLayoutGetBlock(layout);
2784 
2785  int w, h;
2786  ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, false, &w, &h);
2787  w += UI_UNIT_X; /* X icon needs more space */
2788  uiBut *but = ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0);
2789 
2790  ui_but_add_search(but, ptr, prop, searchptr, searchprop);
2791 }
2792 
2794  PointerRNA *ptr,
2795  const char *propname,
2796  PointerRNA *searchptr,
2797  const char *searchpropname,
2798  const char *name,
2799  int icon)
2800 {
2801  /* validate arguments */
2802  PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
2803  if (!prop) {
2804  RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
2805  return;
2806  }
2807  PropertyRNA *searchprop = RNA_struct_find_property(searchptr, searchpropname);
2808  if (!searchprop) {
2809  RNA_warning("search collection property not found: %s.%s",
2810  RNA_struct_identifier(searchptr->type),
2811  searchpropname);
2812  return;
2813  }
2814 
2815  uiItemPointerR_prop(layout, ptr, prop, searchptr, searchprop, name, icon);
2816 }
2817 
2818 /* menu item */
2819 void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
2820 {
2821  MenuType *mt = (MenuType *)arg_mt;
2822 
2823  UI_menutype_draw(C, mt, layout);
2824 
2825  /* Menus are created flipped (from event handling point of view). */
2826  layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
2827 }
2828 
2829 void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt)
2830 {
2831  PanelType *pt = (PanelType *)arg_pt;
2832  UI_paneltype_draw(C, pt, layout);
2833 
2834  /* panels are created flipped (from event handling pov) */
2835  layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
2836 }
2837 
2838 static uiBut *ui_item_menu(uiLayout *layout,
2839  const char *name,
2840  int icon,
2841  uiMenuCreateFunc func,
2842  void *arg,
2843  void *argN,
2844  const char *tip,
2845  bool force_menu)
2846 {
2847  uiBlock *block = layout->root->block;
2848  uiLayout *heading_layout = ui_layout_heading_find(layout);
2849 
2850  UI_block_layout_set_current(block, layout);
2851  ui_block_new_button_group(block, 0);
2852 
2853  if (!name) {
2854  name = "";
2855  }
2856  if (layout->root->type == UI_LAYOUT_MENU && !icon) {
2857  icon = ICON_BLANK1;
2858  }
2859 
2860  int w = ui_text_icon_width(layout, name, icon, 1);
2861  const int h = UI_UNIT_Y;
2862 
2863  if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */
2864  if (icon == ICON_NONE && force_menu) {
2865  /* pass */
2866  }
2867  else if (force_menu) {
2868  w += 0.6f * UI_UNIT_X;
2869  }
2870  else {
2871  if (name[0]) {
2872  w -= UI_UNIT_X / 2;
2873  }
2874  }
2875  }
2876 
2877  if (heading_layout) {
2878  ui_layout_heading_label_add(layout, heading_layout, true, true);
2879  }
2880 
2881  uiBut *but;
2882  if (name[0] && icon) {
2883  but = uiDefIconTextMenuBut(block, func, arg, icon, name, 0, 0, w, h, tip);
2884  }
2885  else if (icon) {
2886  but = uiDefIconMenuBut(block, func, arg, icon, 0, 0, w, h, tip);
2887  if (force_menu && name[0]) {
2889  }
2890  }
2891  else {
2892  but = uiDefMenuBut(block, func, arg, name, 0, 0, w, h, tip);
2893  }
2894 
2895  if (argN) {
2896  /* ugly .. */
2897  if (arg != argN) {
2898  but->poin = (char *)but;
2899  }
2900  but->func_argN = argN;
2901  }
2902 
2903  if (ELEM(layout->root->type, UI_LAYOUT_PANEL, UI_LAYOUT_TOOLBAR) ||
2904  /* We never want a drop-down in menu! */
2905  (force_menu && layout->root->type != UI_LAYOUT_MENU)) {
2907  }
2908 
2909  return but;
2910 }
2911 
2912 void uiItemM_ptr(uiLayout *layout, MenuType *mt, const char *name, int icon)
2913 {
2914  if (!name) {
2915  name = CTX_IFACE_(mt->translation_context, mt->label);
2916  }
2917 
2918  if (layout->root->type == UI_LAYOUT_MENU && !icon) {
2919  icon = ICON_BLANK1;
2920  }
2921 
2922  ui_item_menu(layout,
2923  name,
2924  icon,
2926  mt,
2927  NULL,
2928  mt->description ? TIP_(mt->description) : "",
2929  false);
2930 }
2931 
2932 void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
2933 {
2934  MenuType *mt = WM_menutype_find(menuname, false);
2935  if (mt == NULL) {
2936  RNA_warning("not found %s", menuname);
2937  return;
2938  }
2939  uiItemM_ptr(layout, mt, name, icon);
2940 }
2941 
2942 void uiItemMContents(uiLayout *layout, const char *menuname)
2943 {
2944  MenuType *mt = WM_menutype_find(menuname, false);
2945  if (mt == NULL) {
2946  RNA_warning("not found %s", menuname);
2947  return;
2948  }
2949 
2950  uiBlock *block = layout->root->block;
2951  bContext *C = block->evil_C;
2952  UI_menutype_draw(C, mt, layout);
2953 }
2954 
2959 void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index)
2960 {
2961  uiBlock *block = layout->root->block;
2962 
2963  UI_block_layout_set_current(block, layout);
2964  uiLayout *col = uiLayoutColumn(layout, false);
2965  col->space = 0;
2966  col->emboss = UI_EMBOSS_NONE;
2967 
2968  if (ELEM(NULL, ptr, prop) || !RNA_property_animateable(ptr, prop)) {
2969  uiBut *but = uiDefIconBut(block,
2971  0,
2972  ICON_BLANK1,
2973  0,
2974  0,
2975  UI_UNIT_X,
2976  UI_UNIT_Y,
2977  NULL,
2978  0.0,
2979  0.0,
2980  0.0,
2981  0.0,
2982  "");
2983  but->flag |= UI_BUT_DISABLED;
2984  return;
2985  }
2986 
2987  const bool is_expand = ui_item_rna_is_expand(prop, index, 0);
2988  const bool is_array = RNA_property_array_check(prop);
2989 
2990  /* Loop for the array-case, but only do in case of an expanded array. */
2991  for (int i = 0; i < (is_expand ? RNA_property_array_length(ptr, prop) : 1); i++) {
2992  uiButDecorator *decorator_but = (uiButDecorator *)uiDefIconBut(block,
2994  0,
2995  ICON_DOT,
2996  0,
2997  0,
2998  UI_UNIT_X,
2999  UI_UNIT_Y,
3000  NULL,
3001  0.0,
3002  0.0,
3003  0.0,
3004  0.0,
3005  TIP_("Animate property"));
3006 
3007  UI_but_func_set(&decorator_but->but, ui_but_anim_decorate_cb, decorator_but, NULL);
3008  decorator_but->but.flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
3009  /* Reusing RNA search members, setting actual RNA data has many side-effects. */
3010  decorator_but->rnapoin = *ptr;
3011  decorator_but->rnaprop = prop;
3012  /* ui_def_but_rna() sets non-array buttons to have a RNA index of 0. */
3013  decorator_but->rnaindex = (!is_array || is_expand) ? i : index;
3014  }
3015 }
3016 
3021 void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index)
3022 {
3023  PropertyRNA *prop = NULL;
3024 
3025  if (ptr && propname) {
3026  /* validate arguments */
3027  prop = RNA_struct_find_property(ptr, propname);
3028  if (!prop) {
3029  ui_item_disabled(layout, propname);
3030  RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
3031  return;
3032  }
3033  }
3034 
3035  /* ptr and prop are allowed to be NULL here. */
3036  uiItemDecoratorR_prop(layout, ptr, prop, index);
3037 }
3038 
3039 /* popover */
3041  uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon)
3042 {
3043  if (!name) {
3044  name = CTX_IFACE_(pt->translation_context, pt->label);
3045  }
3046 
3047  if (layout->root->type == UI_LAYOUT_MENU && !icon) {
3048  icon = ICON_BLANK1;
3049  }
3050 
3051  const bool ok = (pt->poll == NULL) || pt->poll(C, pt);
3052  if (ok && (pt->draw_header != NULL)) {
3053  layout = uiLayoutRow(layout, true);
3054  Panel panel = {
3055  .type = pt,
3056  .layout = layout,
3057  .flag = PNL_POPOVER,
3058  };
3059  pt->draw_header(C, &panel);
3060  }
3061  uiBut *but = ui_item_menu(
3062  layout, name, icon, ui_item_paneltype_func, pt, NULL, pt->description, true);
3063  but->type = UI_BTYPE_POPOVER;
3064  if (!ok) {
3065  but->flag |= UI_BUT_DISABLED;
3066  }
3067 }
3068 
3070  uiLayout *layout, bContext *C, const char *panel_type, const char *name, int icon)
3071 {
3072  PanelType *pt = WM_paneltype_find(panel_type, true);
3073  if (pt == NULL) {
3074  RNA_warning("Panel type not found '%s'", panel_type);
3075  return;
3076  }
3077  uiItemPopoverPanel_ptr(layout, C, pt, name, icon);
3078 }
3079 
3081  bContext *C,
3082  int space_id,
3083  int region_id,
3084  const char *context,
3085  const char *category)
3086 {
3087  SpaceType *st = BKE_spacetype_from_id(space_id);
3088  if (st == NULL) {
3089  RNA_warning("space type not found %d", space_id);
3090  return;
3091  }
3092  ARegionType *art = BKE_regiontype_from_id(st, region_id);
3093  if (art == NULL) {
3094  RNA_warning("region type not found %d", region_id);
3095  return;
3096  }
3097 
3098  LISTBASE_FOREACH (PanelType *, pt, &art->paneltypes) {
3099  /* Causes too many panels, check context. */
3100  if (pt->parent_id[0] == '\0') {
3101  if (/* (*context == '\0') || */ STREQ(pt->context, context)) {
3102  if ((*category == '\0') || STREQ(pt->category, category)) {
3103  if (pt->poll == NULL || pt->poll(C, pt)) {
3104  uiItemPopoverPanel_ptr(layout, C, pt, NULL, ICON_NONE);
3105  }
3106  }
3107  }
3108  }
3109  }
3110 }
3111 
3112 /* label item */
3113 static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
3114 {
3115  uiBlock *block = layout->root->block;
3116 
3117  UI_block_layout_set_current(block, layout);
3118  ui_block_new_button_group(block, 0);
3119 
3120  if (!name) {
3121  name = "";
3122  }
3123  if (layout->root->type == UI_LAYOUT_MENU && !icon) {
3124  icon = ICON_BLANK1;
3125  }
3126 
3127  const int w = ui_text_icon_width(layout, name, icon, 0);
3128 
3129  uiBut *but;
3130  if (icon && name[0]) {
3131  but = uiDefIconTextBut(
3132  block, UI_BTYPE_LABEL, 0, icon, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
3133  }
3134  else if (icon) {
3135  but = uiDefIconBut(
3136  block, UI_BTYPE_LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
3137  }
3138  else {
3139  but = uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
3140  }
3141 
3142  /* to compensate for string size padding in ui_text_icon_width,
3143  * make text aligned right if the layout is aligned right.
3144  */
3146  but->drawflag &= ~UI_BUT_TEXT_LEFT; /* default, needs to be unset */
3147  but->drawflag |= UI_BUT_TEXT_RIGHT;
3148  }
3149 
3150  /* Mark as a label inside a listbox. */
3151  if (block->flag & UI_BLOCK_LIST_ITEM) {
3152  but->flag |= UI_BUT_LIST_ITEM;
3153  }
3154 
3155  if (layout->redalert) {
3157  }
3158 
3159  return but;
3160 }
3161 
3163  uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert)
3164 {
3165  uiBut *but = uiItemL_(layout, name, icon);
3166 
3167  if (highlight) {
3168  /* TODO: add another flag for this. */
3170  }
3171 
3172  if (redalert) {
3174  }
3175 }
3176 
3177 void uiItemL(uiLayout *layout, const char *name, int icon)
3178 {
3179  uiItemL_(layout, name, icon);
3180 }
3181 
3188 {
3189  uiPropertySplitWrapper split_wrapper = {NULL};
3190 
3191  uiLayout *layout_row = uiLayoutRow(parent_layout, true);
3192  uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true);
3193 
3194  split_wrapper.label_column = uiLayoutColumn(layout_split, true);
3195  split_wrapper.label_column->alignment = UI_LAYOUT_ALIGN_RIGHT;
3196  split_wrapper.property_row = ui_item_prop_split_layout_hack(parent_layout, layout_split);
3197  split_wrapper.decorate_column = uiLayoutColumn(layout_row, true);
3198 
3199  return split_wrapper;
3200 }
3201 
3202 /*
3203  * Helper to add a label and creates a property split layout if needed.
3204  */
3205 uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon)
3206 {
3207  if (layout->item.flag & UI_ITEM_PROP_SEP) {
3208  uiBlock *block = uiLayoutGetBlock(layout);
3209  const uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(layout);
3210  /* Further items added to 'layout' will automatically be added to split_wrapper.property_row */
3211 
3212  uiItemL_(split_wrapper.label_column, text, icon);
3213  UI_block_layout_set_current(block, split_wrapper.property_row);
3214 
3215  return split_wrapper.decorate_column;
3216  }
3217 
3218  char namestr[UI_MAX_NAME_STR];
3219  if (text) {
3220  text = ui_item_name_add_colon(text, namestr);
3221  }
3222  uiItemL_(layout, text, icon);
3223 
3224  return layout;
3225 }
3226 
3227 void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon)
3228 {
3229  uiBut *but = uiItemL_(layout, name, icon);
3230 
3231  if (ptr && ptr->type) {
3232  if (RNA_struct_is_ID(ptr->type)) {
3234  }
3235  }
3236 }
3237 
3238 /* value item */
3239 void uiItemV(uiLayout *layout, const char *name, int icon, int argval)
3240 {
3241  /* label */
3242  uiBlock *block = layout->root->block;
3243  int *retvalue = (block->handle) ? &block->handle->retvalue : NULL;
3244 
3245  UI_block_layout_set_current(block, layout);
3246 
3247  if (!name) {
3248  name = "";
3249  }
3250  if (layout->root->type == UI_LAYOUT_MENU && !icon) {
3251  icon = ICON_BLANK1;
3252  }
3253 
3254  const int w = ui_text_icon_width(layout, name, icon, 0);
3255 
3256  if (icon && name[0]) {
3257  uiDefIconTextButI(block,
3258  UI_BTYPE_BUT,
3259  argval,
3260  icon,
3261  name,
3262  0,
3263  0,
3264  w,
3265  UI_UNIT_Y,
3266  retvalue,
3267  0.0,
3268  0.0,
3269  0,
3270  -1,
3271  "");
3272  }
3273  else if (icon) {
3274  uiDefIconButI(
3275  block, UI_BTYPE_BUT, argval, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
3276  }
3277  else {
3278  uiDefButI(
3279  block, UI_BTYPE_BUT, argval, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
3280  }
3281 }
3282 
3283 /* separator item */
3284 void uiItemS_ex(uiLayout *layout, float factor)
3285 {
3286  uiBlock *block = layout->root->block;
3287  const bool is_menu = ui_block_is_menu(block);
3288  if (is_menu && !UI_block_can_add_separator(block)) {
3289  return;
3290  }
3291  int space = (is_menu) ? 0.45f * UI_UNIT_X : 0.3f * UI_UNIT_X;
3292  space *= factor;
3293 
3294  UI_block_layout_set_current(block, layout);
3295  uiDefBut(block,
3296  (is_menu) ? UI_BTYPE_SEPR_LINE : UI_BTYPE_SEPR,
3297  0,
3298  "",
3299  0,
3300  0,
3301  space,
3302  space,
3303  NULL,
3304  0.0,
3305  0.0,
3306  0,
3307  0,
3308  "");
3309 }
3310 
3311 /* separator item */
3312 void uiItemS(uiLayout *layout)
3313 {
3314  uiItemS_ex(layout, 1.0f);
3315 }
3316 
3317 /* Flexible spacing. */
3318 void uiItemSpacer(uiLayout *layout)
3319 {
3320  uiBlock *block = layout->root->block;
3321  const bool is_popup = ui_block_is_popup_any(block);
3322 
3323  if (is_popup) {
3324  printf("Error: separator_spacer() not supported in popups.\n");
3325  return;
3326  }
3327 
3328  if (block->direction & UI_DIR_RIGHT) {
3329  printf("Error: separator_spacer() only supported in horizontal blocks.\n");
3330  return;
3331  }
3332 
3333  UI_block_layout_set_current(block, layout);
3334  uiDefBut(block,
3336  0,
3337  "",
3338  0,
3339  0,
3340  0.3f * UI_UNIT_X,
3341  UI_UNIT_Y,
3342  NULL,
3343  0.0,
3344  0.0,
3345  0,
3346  0,
3347  "");
3348 }
3349 
3350 /* level items */
3351 void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg)
3352 {
3353  if (!func) {
3354  return;
3355  }
3356 
3357  ui_item_menu(layout, name, icon, func, arg, NULL, "", false);
3358 }
3359 
3363 void uiItemMenuFN(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *argN)
3364 {
3365  if (!func) {
3366  return;
3367  }
3368 
3369  /* Second 'argN' only ensures it gets freed. */
3370  ui_item_menu(layout, name, icon, func, argN, argN, "", false);
3371 }
3372 
3373 typedef struct MenuItemLevel {
3375  /* don't use pointers to the strings because python can dynamically
3376  * allocate strings and free before the menu draws, see T27304. */
3381 
3382 static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
3383 {
3384  MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN);
3385 
3386  uiLayoutSetOperatorContext(layout, lvl->opcontext);
3387  uiItemsEnumO(layout, lvl->opname, lvl->propname);
3388 
3389  layout->root->block->flag |= UI_BLOCK_IS_FLIP;
3390 
3391  /* override default, needed since this was assumed pre 2.70 */
3393 }
3394 
3396  bContext *C,
3397  wmOperatorType *ot,
3398  const char *propname,
3399  const char *name,
3400  int icon)
3401 {
3402  /* Caller must check */
3403  BLI_assert(ot->srna != NULL);
3404 
3405  if (name == NULL) {
3406  name = WM_operatortype_name(ot, NULL);
3407  }
3408 
3409  if (layout->root->type == UI_LAYOUT_MENU && !icon) {
3410  icon = ICON_BLANK1;
3411  }
3412 
3413  MenuItemLevel *lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
3414  BLI_strncpy(lvl->opname, ot->idname, sizeof(lvl->opname));
3415  BLI_strncpy(lvl->propname, propname, sizeof(lvl->propname));
3416  lvl->opcontext = layout->root->opcontext;
3417 
3418  uiBut *but = ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl, NULL, true);
3419 
3420  /* add hotkey here, lower UI code can't detect it */
3421  if ((layout->root->block->flag & UI_BLOCK_LOOP) && (ot->prop && ot->invoke)) {
3422  char keybuf[128];
3424  C, ot->idname, layout->root->opcontext, NULL, false, keybuf, sizeof(keybuf))) {
3425  ui_but_add_shortcut(but, keybuf, false);
3426  }
3427  }
3428 }
3429 
3431  bContext *C,
3432  const char *opname,
3433  const char *propname,
3434  const char *name,
3435  int icon)
3436 {
3437  wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
3438 
3439  UI_OPERATOR_ERROR_RET(ot, opname, return );
3440 
3441  if (!ot->srna) {
3442  ui_item_disabled(layout, opname);
3443  RNA_warning("operator missing srna '%s'", opname);
3444  return;
3445  }
3446 
3447  uiItemMenuEnumO_ptr(layout, C, ot, propname, name, icon);
3448 }
3449 
3450 static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
3451 {
3452  MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN);
3453 
3454  uiLayoutSetOperatorContext(layout, lvl->opcontext);
3455  uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
3456  layout->root->block->flag |= UI_BLOCK_IS_FLIP;
3457 }
3458 
3460  uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon)
3461 {
3462  if (!name) {
3463  name = RNA_property_ui_name(prop);
3464  }
3465  if (layout->root->type == UI_LAYOUT_MENU && !icon) {
3466  icon = ICON_BLANK1;
3467  }
3468 
3469  MenuItemLevel *lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
3470  lvl->rnapoin = *ptr;
3471  BLI_strncpy(lvl->propname, RNA_property_identifier(prop), sizeof(lvl->propname));
3472  lvl->opcontext = layout->root->opcontext;
3473 
3474  ui_item_menu(layout,
3475  name,
3476  icon,
3478  NULL,
3479  lvl,
3481  false);
3482 }
3483 
3485  uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
3486 {
3487  PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
3488  if (!prop) {
3489  ui_item_disabled(layout, propname);
3490  RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
3491  return;
3492  }
3493 
3494  uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
3495 }
3496 
3498  bContext *C,
3499  PointerRNA *ptr,
3500  PropertyRNA *prop,
3501  PointerRNA *ptr_highlight,
3502  PropertyRNA *prop_highlight,
3503  bool icon_only)
3504 {
3505  uiBlock *block = layout->root->block;
3506 
3507  UI_block_layout_set_current(block, layout);
3509  layout, C, block, ptr, prop, ptr_highlight, prop_highlight, NULL, UI_UNIT_Y, icon_only);
3510 }
3511 
3514 /* -------------------------------------------------------------------- */
3518 /* single-row layout */
3519 static void ui_litem_estimate_row(uiLayout *litem)
3520 {
3521  int itemw, itemh;
3522  bool min_size_flag = true;
3523 
3524  litem->w = 0;
3525  litem->h = 0;
3526 
3527  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3528  ui_item_size(item, &itemw, &itemh);
3529 
3530  min_size_flag = min_size_flag && (item->flag & UI_ITEM_FIXED_SIZE);
3531 
3532  litem->w += itemw;
3533  litem->h = MAX2(itemh, litem->h);
3534 
3535  if (item->next) {
3536  litem->w += litem->space;
3537  }
3538  }
3539 
3540  if (min_size_flag) {
3541  litem->item.flag |= UI_ITEM_FIXED_SIZE;
3542  }
3543 }
3544 
3545 static int ui_litem_min_width(int itemw)
3546 {
3547  return MIN2(2 * UI_UNIT_X, itemw);
3548 }
3549 
3550 static void ui_litem_layout_row(uiLayout *litem)
3551 {
3552  uiItem *last_free_item = NULL;
3553  int x, neww, newtotw, itemw, minw, itemh, offset;
3554  int freew, fixedx, freex, flag = 0, lastw = 0;
3555  float extra_pixel;
3556 
3557  /* x = litem->x; */ /* UNUSED */
3558  const int y = litem->y;
3559  int w = litem->w;
3560  int totw = 0;
3561  int tot = 0;
3562 
3563  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3564  ui_item_size(item, &itemw, &itemh);
3565  totw += itemw;
3566  tot++;
3567  }
3568 
3569  if (totw == 0) {
3570  return;
3571  }
3572 
3573  if (w != 0) {
3574  w -= (tot - 1) * litem->space;
3575  }
3576  int fixedw = 0;
3577 
3578  /* keep clamping items to fixed minimum size until all are done */
3579  do {
3580  freew = 0;
3581  x = 0;
3582  flag = 0;
3583  newtotw = totw;
3584  extra_pixel = 0.0f;
3585 
3586  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3587  if (item->flag & UI_ITEM_AUTO_FIXED_SIZE) {
3588  continue;
3589  }
3590 
3591  ui_item_size(item, &itemw, &itemh);
3592  minw = ui_litem_min_width(itemw);
3593 
3594  if (w - lastw > 0) {
3595  neww = ui_item_fit(itemw, x, totw, w - lastw, !item->next, litem->alignment, &extra_pixel);
3596  }
3597  else {
3598  neww = 0; /* no space left, all will need clamping to minimum size */
3599  }
3600 
3601  x += neww;
3602 
3603  bool min_flag = item->flag & UI_ITEM_FIXED_SIZE;
3604  /* ignore min flag for rows with right or center alignment */
3605  if (item->type != ITEM_BUTTON &&
3606  ELEM(((uiLayout *)item)->alignment, UI_LAYOUT_ALIGN_RIGHT, UI_LAYOUT_ALIGN_CENTER) &&
3607  litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
3608  ((uiItem *)litem)->flag & UI_ITEM_FIXED_SIZE) {
3609  min_flag = false;
3610  }
3611 
3612  if ((neww < minw || min_flag) && w != 0) {
3613  /* fixed size */
3614  item->flag |= UI_ITEM_AUTO_FIXED_SIZE;
3615  if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_FIXED_SIZE) {
3616  minw = itemw;
3617  }
3618  fixedw += minw;
3619  flag = 1;
3620  newtotw -= itemw;
3621  }
3622  else {
3623  /* keep free size */
3624  item->flag &= ~UI_ITEM_AUTO_FIXED_SIZE;
3625  freew += itemw;
3626  }
3627  }
3628 
3629  totw = newtotw;
3630  lastw = fixedw;
3631  } while (flag);
3632 
3633  freex = 0;
3634  fixedx = 0;
3635  extra_pixel = 0.0f;
3636  x = litem->x;
3637 
3638  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3639  ui_item_size(item, &itemw, &itemh);
3640  minw = ui_litem_min_width(itemw);
3641 
3642  if (item->flag & UI_ITEM_AUTO_FIXED_SIZE) {
3643  /* fixed minimum size items */
3644  if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_FIXED_SIZE) {
3645  minw = itemw;
3646  }
3647  itemw = ui_item_fit(
3648  minw, fixedx, fixedw, min_ii(w, fixedw), !item->next, litem->alignment, &extra_pixel);
3649  fixedx += itemw;
3650  }
3651  else {
3652  /* free size item */
3653  itemw = ui_item_fit(
3654  itemw, freex, freew, w - fixedw, !item->next, litem->alignment, &extra_pixel);
3655  freex += itemw;
3656  last_free_item = item;
3657  }
3658 
3659  /* align right/center */
3660  offset = 0;
3661  if (litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
3662  if (freew + fixedw > 0 && freew + fixedw < w) {
3663  offset = w - (fixedw + freew);
3664  }
3665  }
3666  else if (litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
3667  if (freew + fixedw > 0 && freew + fixedw < w) {
3668  offset = (w - (fixedw + freew)) / 2;
3669  }
3670  }
3671 
3672  /* position item */
3673  ui_item_position(item, x + offset, y - itemh, itemw, itemh);
3674 
3675  x += itemw;
3676  if (item->next) {
3677  x += litem->space;
3678  }
3679  }
3680 
3681  /* add extra pixel */
3682  uiItem *last_item = litem->items.last;
3683  extra_pixel = litem->w - (x - litem->x);
3684  if (extra_pixel > 0 && litem->alignment == UI_LAYOUT_ALIGN_EXPAND && last_free_item &&
3685  last_item && last_item->flag & UI_ITEM_AUTO_FIXED_SIZE) {
3686  ui_item_move(last_free_item, 0, extra_pixel);
3687  for (uiItem *item = last_free_item->next; item; item = item->next) {
3688  ui_item_move(item, extra_pixel, extra_pixel);
3689  }
3690  }
3691 
3692  litem->w = x - litem->x;
3693  litem->h = litem->y - y;
3694  litem->x = x;
3695  litem->y = y;
3696 }
3697 
3698 /* single-column layout */
3699 static void ui_litem_estimate_column(uiLayout *litem, bool is_box)
3700 {
3701  int itemw, itemh;
3702  bool min_size_flag = true;
3703 
3704  litem->w = 0;
3705  litem->h = 0;
3706 
3707  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3708  ui_item_size(item, &itemw, &itemh);
3709 
3710  min_size_flag = min_size_flag && (item->flag & UI_ITEM_FIXED_SIZE);
3711 
3712  litem->w = MAX2(litem->w, itemw);
3713  litem->h += itemh;
3714 
3715  if (item->next && (!is_box || item != litem->items.first)) {
3716  litem->h += litem->space;
3717  }
3718  }
3719 
3720  if (min_size_flag) {
3721  litem->item.flag |= UI_ITEM_FIXED_SIZE;
3722  }
3723 }
3724 
3725 static void ui_litem_layout_column(uiLayout *litem, bool is_box, bool is_menu)
3726 {
3727  const int x = litem->x;
3728  int y = litem->y;
3729 
3730  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3731  int itemw, itemh;
3732  ui_item_size(item, &itemw, &itemh);
3733 
3734  y -= itemh;
3735  ui_item_position(item, x, y, is_menu ? itemw : litem->w, itemh);
3736 
3737  if (item->next && (!is_box || item != litem->items.first)) {
3738  y -= litem->space;
3739  }
3740 
3741  if (is_box) {
3742  item->flag |= UI_ITEM_BOX_ITEM;
3743  }
3744  }
3745 
3746  litem->h = litem->y - y;
3747  litem->x = x;
3748  litem->y = y;
3749 }
3750 
3751 /* calculates the angle of a specified button in a radial menu,
3752  * stores a float vector in unit circle */
3753 static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
3754 {
3755  if (itemnum >= PIE_MAX_ITEMS) {
3756  itemnum %= PIE_MAX_ITEMS;
3757  printf("Warning: Pie menus with more than %i items are currently unsupported\n",
3758  PIE_MAX_ITEMS);
3759  }
3760 
3761  const RadialDirection dir = ui_radial_dir_order[itemnum];
3762  ui_but_pie_dir(dir, vec);
3763 
3764  return dir;
3765 }
3766 
3768 {
3769 
3770  if ((item->type == ITEM_BUTTON) && (((uiButtonItem *)item)->but->type == UI_BTYPE_LABEL)) {
3771  return false;
3772  }
3773 
3774  return true;
3775 }
3776 
3778 {
3779 
3781  return false;
3782  }
3783 
3784  return true;
3785 }
3786 
3788 {
3789  int itemh, itemw;
3790  int itemnum = 0;
3791  int totitems = 0;
3792 
3793  /* For the radial layout we will use Matt Ebb's design
3794  * for radiation, see http://mattebb.com/weblog/radiation/
3795  * also the old code at http://developer.blender.org/T5103
3796  */
3797 
3798  const int pie_radius = U.pie_menu_radius * UI_DPI_FAC;
3799 
3800  const int x = litem->x;
3801  const int y = litem->y;
3802 
3803  int minx = x, miny = y, maxx = x, maxy = y;
3804 
3805  /* first count total items */
3806  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3807  totitems++;
3808  }
3809 
3810  if (totitems < 5) {
3812  }
3813 
3814  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3815  /* not all button types are drawn in a radial menu, do filtering here */
3816  if (ui_item_is_radial_displayable(item)) {
3817  RadialDirection dir;
3818  float vec[2];
3819  float factor[2];
3820 
3821  dir = ui_get_radialbut_vec(vec, itemnum);
3822  factor[0] = (vec[0] > 0.01f) ? 0.0f : ((vec[0] < -0.01f) ? -1.0f : -0.5f);
3823  factor[1] = (vec[1] > 0.99f) ? 0.0f : ((vec[1] < -0.99f) ? -1.0f : -0.5f);
3824 
3825  itemnum++;
3826 
3827  if (item->type == ITEM_BUTTON) {
3828  uiButtonItem *bitem = (uiButtonItem *)item;
3829 
3830  bitem->but->pie_dir = dir;
3831  /* scale the buttons */
3832  bitem->but->rect.ymax *= 1.5f;
3833  /* add a little bit more here to include number */
3834  bitem->but->rect.xmax += 1.5f * UI_UNIT_X;
3835  /* enable drawing as pie item if supported by widget */
3836  if (ui_item_is_radial_drawable(bitem)) {
3837  bitem->but->emboss = UI_EMBOSS_RADIAL;
3838  bitem->but->drawflag |= UI_BUT_ICON_LEFT;
3839  }
3840  }
3841 
3842  ui_item_size(item, &itemw, &itemh);
3843 
3844  ui_item_position(item,
3845  x + vec[0] * pie_radius + factor[0] * itemw,
3846  y + vec[1] * pie_radius + factor[1] * itemh,
3847  itemw,
3848  itemh);
3849 
3850  minx = min_ii(minx, x + vec[0] * pie_radius - itemw / 2);
3851  maxx = max_ii(maxx, x + vec[0] * pie_radius + itemw / 2);
3852  miny = min_ii(miny, y + vec[1] * pie_radius - itemh / 2);
3853  maxy = max_ii(maxy, y + vec[1] * pie_radius + itemh / 2);
3854  }
3855  }
3856 
3857  litem->x = minx;
3858  litem->y = miny;
3859  litem->w = maxx - minx;
3860  litem->h = maxy - miny;
3861 }
3862 
3863 /* root layout */
3865 {
3866  /* nothing to do */
3867 }
3868 
3870 {
3871  /* first item is pie menu title, align on center of menu */
3872  uiItem *item = litem->items.first;
3873 
3874  if (item->type == ITEM_BUTTON) {
3875  int itemh, itemw, x, y;
3876  x = litem->x;
3877  y = litem->y;
3878 
3879  ui_item_size(item, &itemw, &itemh);
3880 
3882  item, x - itemw / 2, y + U.dpi_fac * (U.pie_menu_threshold + 9.0f), itemw, itemh);
3883  }
3884 }
3885 
3886 static void ui_litem_layout_root(uiLayout *litem)
3887 {
3888  if (litem->root->type == UI_LAYOUT_HEADER) {
3889  ui_litem_layout_row(litem);
3890  }
3891  else if (litem->root->type == UI_LAYOUT_PIEMENU) {
3893  }
3894  else if (litem->root->type == UI_LAYOUT_MENU) {
3895  ui_litem_layout_column(litem, false, true);
3896  }
3897  else {
3898  ui_litem_layout_column(litem, false, false);
3899  }
3900 }
3901 
3902 /* box layout */
3903 static void ui_litem_estimate_box(uiLayout *litem)
3904 {
3905  const uiStyle *style = litem->root->style;
3906 
3907  ui_litem_estimate_column(litem, true);
3908 
3909  int boxspace = style->boxspace;
3910  if (litem->root->type == UI_LAYOUT_HEADER) {
3911  boxspace = 0;
3912  }
3913  litem->w += 2 * boxspace;
3914  litem->h += 2 * boxspace;
3915 }
3916 
3917 static void ui_litem_layout_box(uiLayout *litem)
3918 {
3919  uiLayoutItemBx *box = (uiLayoutItemBx *)litem;
3920  const uiStyle *style = litem->root->style;
3921 
3922  int boxspace = style->boxspace;
3923  if (litem->root->type == UI_LAYOUT_HEADER) {
3924  boxspace = 0;
3925  }
3926 
3927  const int w = litem->w;
3928  const int h = litem->h;
3929 
3930  litem->x += boxspace;
3931  litem->y -= boxspace;
3932 
3933  if (w != 0) {
3934  litem->w -= 2 * boxspace;
3935  }
3936  if (h != 0) {
3937  litem->h -= 2 * boxspace;
3938  }
3939 
3940  ui_litem_layout_column(litem, true, false);
3941 
3942  litem->x -= boxspace;
3943  litem->y -= boxspace;
3944 
3945  if (w != 0) {
3946  litem->w += 2 * boxspace;
3947  }
3948  if (h != 0) {
3949  litem->h += 2 * boxspace;
3950  }
3951 
3952  /* roundbox around the sublayout */
3953  uiBut *but = box->roundbox;
3954  but->rect.xmin = litem->x;
3955  but->rect.ymin = litem->y;
3956  but->rect.xmax = litem->x + litem->w;
3957  but->rect.ymax = litem->y + litem->h;
3958 }
3959 
3960 /* multi-column layout, automatically flowing to the next */
3962 {
3963  const uiStyle *style = litem->root->style;
3964  uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
3965  int itemw, itemh, maxw = 0;
3966 
3967  /* compute max needed width and total height */
3968  int toth = 0;
3969  int totitem = 0;
3970  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
3971  ui_item_size(item, &itemw, &itemh);
3972  maxw = MAX2(maxw, itemw);
3973  toth += itemh;
3974  totitem++;
3975  }
3976 
3977  if (flow->number <= 0) {
3978  /* auto compute number of columns, not very good */
3979  if (maxw == 0) {
3980  flow->totcol = 1;
3981  return;
3982  }
3983 
3984  flow->totcol = max_ii(litem->root->emw / maxw, 1);
3985  flow->totcol = min_ii(flow->totcol, totitem);
3986  }
3987  else {
3988  flow->totcol = flow->number;
3989  }
3990 
3991  /* compute sizes */
3992  int x = 0;
3993  int y = 0;
3994  int emy = 0;
3995  int miny = 0;
3996 
3997  maxw = 0;
3998  const int emh = toth / flow->totcol;
3999 
4000  /* create column per column */
4001  int col = 0;
4002  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4003  ui_item_size(item, &itemw, &itemh);
4004 
4005  y -= itemh + style->buttonspacey;
4006  miny = min_ii(miny, y);
4007  emy -= itemh;
4008  maxw = max_ii(itemw, maxw);
4009 
4010  /* decide to go to next one */
4011  if (col < flow->totcol - 1 && emy <= -emh) {
4012  x += maxw + litem->space;
4013  maxw = 0;
4014  y = 0;
4015  emy = 0; /* need to reset height again for next column */
4016  col++;
4017  }
4018  }
4019 
4020  litem->w = x;
4021  litem->h = litem->y - miny;
4022 }
4023 
4025 {
4026  const uiStyle *style = litem->root->style;
4027  uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
4028  int col, emh, itemw, itemh;
4029 
4030  /* compute max needed width and total height */
4031  int toth = 0;
4032  int totitem = 0;
4033  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4034  ui_item_size(item, &itemw, &itemh);
4035  toth += itemh;
4036  totitem++;
4037  }
4038 
4039  /* compute sizes */
4040  int x = litem->x;
4041  int y = litem->y;
4042  int emy = 0;
4043  int miny = 0;
4044 
4045  int w = litem->w - (flow->totcol - 1) * style->columnspace;
4046  emh = toth / flow->totcol;
4047 
4048  /* create column per column */
4049  col = 0;
4050  w = (litem->w - (flow->totcol - 1) * style->columnspace) / flow->totcol;
4051  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4052  ui_item_size(item, &itemw, &itemh);
4053 
4054  itemw = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? w : min_ii(w, itemw);
4055 
4056  y -= itemh;
4057  emy -= itemh;
4058  ui_item_position(item, x, y, itemw, itemh);
4059  y -= style->buttonspacey;
4060  miny = min_ii(miny, y);
4061 
4062  /* decide to go to next one */
4063  if (col < flow->totcol - 1 && emy <= -emh) {
4064  x += w + style->columnspace;
4065  y = litem->y;
4066  emy = 0; /* need to reset height again for next column */
4067  col++;
4068 
4069  const int remaining_width = litem->w - (x - litem->x);
4070  const int remaining_width_between_columns = (flow->totcol - col - 1) * style->columnspace;
4071  const int remaining_columns = flow->totcol - col;
4072  w = (remaining_width - remaining_width_between_columns) / remaining_columns;
4073  }
4074  }
4075 
4076  litem->h = litem->y - miny;
4077  litem->x = x;
4078  litem->y = miny;
4079 }
4080 
4081 /* multi-column and multi-row layout. */
4082 typedef struct UILayoutGridFlowInput {
4083  /* General layout control settings. */
4084  const bool row_major : 1; /* Fill rows before columns */
4085  const bool even_columns : 1; /* All columns will have same width. */
4086  const bool even_rows : 1; /* All rows will have same height. */
4087  const int space_x; /* Space between columns. */
4088  const int space_y; /* Space between rows. */
4089  /* Real data about current position and size of this layout item
4090  * (either estimated, or final values). */
4091  const int litem_w; /* Layout item width. */
4092  const int litem_x; /* Layout item X position. */
4093  const int litem_y; /* Layout item Y position. */
4094  /* Actual number of columns and rows to generate (computed from first pass usually). */
4095  const int tot_columns; /* Number of columns. */
4096  const int tot_rows; /* Number of rows. */
4098 
4099 typedef struct UILayoutGridFlowOutput {
4100  int *tot_items; /* Total number of items in this grid layout. */
4101  /* Width / X pos data. */
4102  float *global_avg_w; /* Computed average width of the columns. */
4103  int *cos_x_array; /* Computed X coordinate of each column. */
4104  int *widths_array; /* Computed width of each column. */
4105  int *tot_w; /* Computed total width. */
4106  /* Height / Y pos data. */
4107  int *global_max_h; /* Computed height of the tallest item in the grid. */
4108  int *cos_y_array; /* Computed Y coordinate of each column. */
4109  int *heights_array; /* Computed height of each column. */
4110  int *tot_h; /* Computed total height. */
4112 
4115  UILayoutGridFlowOutput *results)
4116 {
4117  float tot_w = 0.0f, tot_h = 0.0f;
4118  float global_avg_w = 0.0f, global_totweight_w = 0.0f;
4119  int global_max_h = 0;
4120 
4121  float *avg_w = NULL, *totweight_w = NULL;
4122  int *max_h = NULL;
4123 
4124  BLI_assert(
4125  parameters->tot_columns != 0 ||
4126  (results->cos_x_array == NULL && results->widths_array == NULL && results->tot_w == NULL));
4127  BLI_assert(
4128  parameters->tot_rows != 0 ||
4129  (results->cos_y_array == NULL && results->heights_array == NULL && results->tot_h == NULL));
4130 
4131  if (results->tot_items) {
4132  *results->tot_items = 0;
4133  }
4134 
4135  if (items->first == NULL) {
4136  if (results->global_avg_w) {
4137  *results->global_avg_w = 0.0f;
4138  }
4139  if (results->global_max_h) {
4140  *results->global_max_h = 0;
4141  }
4142  return;
4143  }
4144 
4145  if (parameters->tot_columns != 0) {
4146  avg_w = BLI_array_alloca(avg_w, parameters->tot_columns);
4147  totweight_w = BLI_array_alloca(totweight_w, parameters->tot_columns);
4148  memset(avg_w, 0, sizeof(*avg_w) * parameters->tot_columns);
4149  memset(totweight_w, 0, sizeof(*totweight_w) * parameters->tot_columns);
4150  }
4151  if (parameters->tot_rows != 0) {
4152  max_h = BLI_array_alloca(max_h, parameters->tot_rows);
4153  memset(max_h, 0, sizeof(*max_h) * parameters->tot_rows);
4154  }
4155 
4156  int i = 0;
4157  LISTBASE_FOREACH (uiItem *, item, items) {
4158  int item_w, item_h;
4159  ui_item_size(item, &item_w, &item_h);
4160 
4161  global_avg_w += (float)(item_w * item_w);
4162  global_totweight_w += (float)item_w;
4163  global_max_h = max_ii(global_max_h, item_h);
4164 
4165  if (parameters->tot_rows != 0 && parameters->tot_columns != 0) {
4166  const int index_col = parameters->row_major ? i % parameters->tot_columns :
4167  i / parameters->tot_rows;
4168  const int index_row = parameters->row_major ? i / parameters->tot_columns :
4169  i % parameters->tot_rows;
4170 
4171  avg_w[index_col] += (float)(item_w * item_w);
4172  totweight_w[index_col] += (float)item_w;
4173 
4174  max_h[index_row] = max_ii(max_h[index_row], item_h);
4175  }
4176 
4177  if (results->tot_items) {
4178  (*results->tot_items)++;
4179  }
4180  i++;
4181  }
4182 
4183  /* Finalize computing of column average sizes */
4184  global_avg_w /= global_totweight_w;
4185  if (parameters->tot_columns != 0) {
4186  for (i = 0; i < parameters->tot_columns; i++) {
4187  avg_w[i] /= totweight_w[i];
4188  tot_w += avg_w[i];
4189  }
4190  if (parameters->even_columns) {
4191  tot_w = ceilf(global_avg_w) * parameters->tot_columns;
4192  }
4193  }
4194  /* Finalize computing of rows max sizes */
4195  if (parameters->tot_rows != 0) {
4196  for (i = 0; i < parameters->tot_rows; i++) {
4197  tot_h += max_h[i];
4198  }
4199  if (parameters->even_rows) {
4200  tot_h = global_max_h * parameters->tot_columns;
4201  }
4202  }
4203 
4204  /* Compute positions and sizes of all cells. */
4205  if (results->cos_x_array != NULL && results->widths_array != NULL) {
4206  /* We enlarge/narrow columns evenly to match available width. */
4207  const float wfac = (float)(parameters->litem_w -
4208  (parameters->tot_columns - 1) * parameters->space_x) /
4209  tot_w;
4210 
4211  for (int col = 0; col < parameters->tot_columns; col++) {
4212  results->cos_x_array[col] = (col ? results->cos_x_array[col - 1] +
4213  results->widths_array[col - 1] + parameters->space_x :
4214  parameters->litem_x);
4215  if (parameters->even_columns) {
4216  /* (< remaining width > - < space between remaining columns >) / < remaining columns > */
4217  results->widths_array[col] = (((parameters->litem_w -
4218  (results->cos_x_array[col] - parameters->litem_x)) -
4219  (parameters->tot_columns - col - 1) * parameters->space_x) /
4220  (parameters->tot_columns - col));
4221  }
4222  else if (col == parameters->tot_columns - 1) {
4223  /* Last column copes width rounding errors... */
4224  results->widths_array[col] = parameters->litem_w -
4225  (results->cos_x_array[col] - parameters->litem_x);
4226  }
4227  else {
4228  results->widths_array[col] = (int)(avg_w[col] * wfac);
4229  }
4230  }
4231  }
4232  if (results->cos_y_array != NULL && results->heights_array != NULL) {
4233  for (int row = 0; row < parameters->tot_rows; row++) {
4234  if (parameters->even_rows) {
4235  results->heights_array[row] = global_max_h;
4236  }
4237  else {
4238  results->heights_array[row] = max_h[row];
4239  }
4240  results->cos_y_array[row] = (row ? results->cos_y_array[row - 1] - parameters->space_y -
4241  results->heights_array[row] :
4242  parameters->litem_y - results->heights_array[row]);
4243  }
4244  }
4245 
4246  if (results->global_avg_w) {
4247  *results->global_avg_w = global_avg_w;
4248  }
4249  if (results->global_max_h) {
4250  *results->global_max_h = global_max_h;
4251  }
4252  if (results->tot_w) {
4253  *results->tot_w = (int)tot_w + parameters->space_x * (parameters->tot_columns - 1);
4254  }
4255  if (results->tot_h) {
4256  *results->tot_h = tot_h + parameters->space_y * (parameters->tot_rows - 1);
4257  }
4258 }
4259 
4261 {
4262  const uiStyle *style = litem->root->style;
4263  uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
4264 
4265  const int space_x = style->columnspace;
4266  const int space_y = style->buttonspacey;
4267 
4268  /* Estimate average needed width and height per item. */
4269  {
4270  float avg_w;
4271  int max_h;
4272 
4275  .row_major = gflow->row_major,
4276  .even_columns = gflow->even_columns,
4277  .even_rows = gflow->even_rows,
4278  .litem_w = litem->w,
4279  .litem_x = litem->x,
4280  .litem_y = litem->y,
4281  .space_x = space_x,
4282  .space_y = space_y,
4283  }),
4285  .tot_items = &gflow->tot_items,
4286  .global_avg_w = &avg_w,
4287  .global_max_h = &max_h,
4288  }));
4289 
4290  if (gflow->tot_items == 0) {
4291  litem->w = litem->h = 0;
4292  gflow->tot_columns = gflow->tot_rows = 0;
4293  return;
4294  }
4295 
4296  /* Even in varying column width case,
4297  * we fix our columns number from weighted average width of items,
4298  * a proper solving of required width would be too costly,
4299  * and this should give reasonably good results in all reasonable cases. */
4300  if (gflow->columns_len > 0) {
4301  gflow->tot_columns = gflow->columns_len;
4302  }
4303  else {
4304  if (avg_w == 0.0f) {
4305  gflow->tot_columns = 1;
4306  }
4307  else {
4308  gflow->tot_columns = min_ii(max_ii((int)(litem->w / avg_w), 1), gflow->tot_items);
4309  }
4310  }
4311  gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
4312 
4313  /* Try to tweak number of columns and rows to get better filling of last column or row,
4314  * and apply 'modulo' value to number of columns or rows.
4315  * Note that modulo does not prevent ending with fewer columns/rows than modulo, if mandatory
4316  * to avoid empty column/row. */
4317  {
4318  const int modulo = (gflow->columns_len < -1) ? -gflow->columns_len : 0;
4319  const int step = modulo ? modulo : 1;
4320 
4321  if (gflow->row_major) {
4322  /* Adjust number of columns to be multiple of given modulo. */
4323  if (modulo && gflow->tot_columns % modulo != 0 && gflow->tot_columns > modulo) {
4324  gflow->tot_columns = gflow->tot_columns - (gflow->tot_columns % modulo);
4325  }
4326  /* Find smallest number of columns conserving computed optimal number of rows. */
4327  for (gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
4328  (gflow->tot_columns - step) > 0 &&
4329  (int)ceilf((float)gflow->tot_items / (gflow->tot_columns - step)) <= gflow->tot_rows;
4330  gflow->tot_columns -= step) {
4331  /* pass */
4332  }
4333  }
4334  else {
4335  /* Adjust number of rows to be multiple of given modulo. */
4336  if (modulo && gflow->tot_rows % modulo != 0) {
4337  gflow->tot_rows = min_ii(gflow->tot_rows + modulo - (gflow->tot_rows % modulo),
4338  gflow->tot_items);
4339  }
4340  /* Find smallest number of rows conserving computed optimal number of columns. */
4341  for (gflow->tot_columns = (int)ceilf((float)gflow->tot_items / gflow->tot_rows);
4342  (gflow->tot_rows - step) > 0 &&
4343  (int)ceilf((float)gflow->tot_items / (gflow->tot_rows - step)) <= gflow->tot_columns;
4344  gflow->tot_rows -= step) {
4345  /* pass */
4346  }
4347  }
4348  }
4349 
4350  /* Set evenly-spaced axes size
4351  * (quick optimization in case we have even columns and rows). */
4352  if (gflow->even_columns && gflow->even_rows) {
4353  litem->w = (int)(gflow->tot_columns * avg_w) + space_x * (gflow->tot_columns - 1);
4354  litem->h = (int)(gflow->tot_rows * max_h) + space_y * (gflow->tot_rows - 1);
4355  return;
4356  }
4357  }
4358 
4359  /* Now that we have our final number of columns and rows,
4360  * we can compute actual needed space for non-evenly sized axes. */
4361  {
4362  int tot_w, tot_h;
4363 
4366  .row_major = gflow->row_major,
4367  .even_columns = gflow->even_columns,
4368  .even_rows = gflow->even_rows,
4369  .litem_w = litem->w,
4370  .litem_x = litem->x,
4371  .litem_y = litem->y,
4372  .space_x = space_x,
4373  .space_y = space_y,
4374  .tot_columns = gflow->tot_columns,
4375  .tot_rows = gflow->tot_rows,
4376  }),
4378  .tot_w = &tot_w,
4379  .tot_h = &tot_h,
4380  }));
4381 
4382  litem->w = tot_w;
4383  litem->h = tot_h;
4384  }
4385 }
4386 
4388 {
4389  const uiStyle *style = litem->root->style;
4390  uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
4391 
4392  if (gflow->tot_items == 0) {
4393  litem->w = litem->h = 0;
4394  return;
4395  }
4396 
4397  BLI_assert(gflow->tot_columns > 0);
4398  BLI_assert(gflow->tot_rows > 0);
4399 
4400  const int space_x = style->columnspace;
4401  const int space_y = style->buttonspacey;
4402 
4403  int *widths = BLI_array_alloca(widths, gflow->tot_columns);
4404  int *heights = BLI_array_alloca(heights, gflow->tot_rows);
4405  int *cos_x = BLI_array_alloca(cos_x, gflow->tot_columns);
4406  int *cos_y = BLI_array_alloca(cos_y, gflow->tot_rows);
4407 
4408  /* This time we directly compute coordinates and sizes of all cells. */
4411  .row_major = gflow->row_major,
4412  .even_columns = gflow->even_columns,
4413  .even_rows = gflow->even_rows,
4414  .litem_w = litem->w,
4415  .litem_x = litem->x,
4416  .litem_y = litem->y,
4417  .space_x = space_x,
4418  .space_y = space_y,
4419  .tot_columns = gflow->tot_columns,
4420  .tot_rows = gflow->tot_rows,
4421  }),
4423  .cos_x_array = cos_x,
4424  .cos_y_array = cos_y,
4425  .widths_array = widths,
4426  .heights_array = heights,
4427  }));
4428 
4429  int i;
4430  LISTBASE_FOREACH_INDEX (uiItem *, item, &litem->items, i) {
4431  const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows;
4432  const int row = gflow->row_major ? i / gflow->tot_columns : i % gflow->tot_rows;
4433  int item_w, item_h;
4434  ui_item_size(item, &item_w, &item_h);
4435 
4436  const int w = widths[col];
4437  const int h = heights[row];
4438 
4439  item_w = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? w : min_ii(w, item_w);
4440  item_h = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? h : min_ii(h, item_h);
4441 
4442  ui_item_position(item, cos_x[col], cos_y[row], item_w, item_h);
4443  }
4444 
4445  litem->h = litem->y - cos_y[gflow->tot_rows - 1];
4446  litem->x = (cos_x[gflow->tot_columns - 1] - litem->x) + widths[gflow->tot_columns - 1];
4447  litem->y = litem->y - litem->h;
4448 }
4449 
4450 /* free layout */
4452 {
4453  int minx = 1e6;
4454  int miny = 1e6;
4455  litem->w = 0;
4456  litem->h = 0;
4457 
4458  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4459  int itemx, itemy, itemw, itemh;
4460  ui_item_offset(item, &itemx, &itemy);
4461  ui_item_size(item, &itemw, &itemh);
4462 
4463  minx = min_ii(minx, itemx);
4464  miny = min_ii(miny, itemy);
4465 
4466  litem->w = MAX2(litem->w, itemx + itemw);
4467  litem->h = MAX2(litem->h, itemy + itemh);
4468  }
4469 
4470  litem->w -= minx;
4471  litem->h -= miny;
4472 }
4473 
4475 {
4476  float scalex = 1.0f, scaley = 1.0f;
4477  int x, y, newx, newy, itemx, itemy, itemh, itemw;
4478 
4479  int minx = 1e6;
4480  int miny = 1e6;
4481  int totw = 0;
4482  int toth = 0;
4483 
4484  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4485  ui_item_offset(item, &itemx, &itemy);
4486  ui_item_size(item, &itemw, &itemh);
4487 
4488  minx = min_ii(minx, itemx);
4489  miny = min_ii(miny, itemy);
4490 
4491  totw = max_ii(totw, itemx + itemw);
4492  toth = max_ii(toth, itemy + itemh);
4493  }
4494 
4495  totw -= minx;
4496  toth -= miny;
4497 
4498  if (litem->w && totw > 0) {
4499  scalex = (float)litem->w / (float)totw;
4500  }
4501  if (litem->h && toth > 0) {
4502  scaley = (float)litem->h / (float)toth;
4503  }
4504 
4505  x = litem->x;
4506  y = litem->y - scaley * toth;
4507 
4508  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4509  ui_item_offset(item, &itemx, &itemy);
4510  ui_item_size(item, &itemw, &itemh);
4511 
4512  if (scalex != 1.0f) {
4513  newx = (itemx - minx) * scalex;
4514  itemw = (itemx - minx + itemw) * scalex - newx;
4515  itemx = minx + newx;
4516  }
4517 
4518  if (scaley != 1.0f) {
4519  newy = (itemy - miny) * scaley;
4520  itemh = (itemy - miny + itemh) * scaley - newy;
4521  itemy = miny + newy;
4522  }
4523 
4524  ui_item_position(item, x + itemx - minx, y + itemy - miny, itemw, itemh);
4525  }
4526 
4527  litem->w = scalex * totw;
4528  litem->h = litem->y - y;
4529  litem->x = x + litem->w;
4530  litem->y = y;
4531 }
4532 
4533 /* split layout */
4535 {
4536  ui_litem_estimate_row(litem);
4537  litem->item.flag &= ~UI_ITEM_FIXED_SIZE;
4538 }
4539 
4540 static void ui_litem_layout_split(uiLayout *litem)
4541 {
4543  float extra_pixel = 0.0f;
4544  const int tot = BLI_listbase_count(&litem->items);
4545 
4546  if (tot == 0) {
4547  return;
4548  }
4549 
4550  int x = litem->x;
4551  const int y = litem->y;
4552 
4553  const float percentage = (split->percentage == 0.0f) ? 1.0f / (float)tot : split->percentage;
4554 
4555  const int w = (litem->w - (tot - 1) * litem->space);
4556  int colw = w * percentage;
4557  colw = MAX2(colw, 0);
4558 
4559  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4560  int itemh;
4561  ui_item_size(item, NULL, &itemh);
4562 
4563  ui_item_position(item, x, y - itemh, colw, itemh);
4564  x += colw;
4565 
4566  if (item->next) {
4567  const float width = extra_pixel + (w - (int)(w * percentage)) / ((float)tot - 1);
4568  extra_pixel = width - (int)width;
4569  colw = (int)width;
4570  colw = MAX2(colw, 0);
4571 
4572  x += litem->space;
4573  }
4574  }
4575 
4576  litem->w = x - litem->x;
4577  litem->h = litem->y - y;
4578  litem->x = x;
4579  litem->y = y;
4580 }
4581 
4582 /* overlap layout */
4584 {
4585  litem->w = 0;
4586  litem->h = 0;
4587 
4588  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4589  int itemw, itemh;
4590  ui_item_size(item, &itemw, &itemh);
4591 
4592  litem->w = MAX2(itemw, litem->w);
4593  litem->h = MAX2(itemh, litem->h);
4594  }
4595 }
4596 
4598 {
4599 
4600  const int x = litem->x;
4601  const int y = litem->y;
4602 
4603  LISTBASE_FOREACH (uiItem *, item, &litem->items) {
4604  int itemw, itemh;
4605  ui_item_size(item, &itemw, &itemh);
4606  ui_item_position(item, x, y - itemh, litem->w, itemh);
4607 
4608  litem->h = MAX2(litem->h, itemh);
4609  }
4610 
4611  litem->x = x;
4612  litem->y = y - litem->h;
4613 }
4614 
4615 static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int align)
4616 {
4617  litem->root = layout->root;
4618  litem->align = align;
4619  /* Children of gridflow layout shall never have "ideal big size" returned as estimated size. */
4620  litem->variable_size = layout->variable_size || layout->item.type == ITEM_LAYOUT_GRID_FLOW;
4621  litem->active = true;
4622  litem->enabled = true;
4623  litem->context = layout->context;
4624  litem->redalert = layout->redalert;
4625  litem->w = layout->w;
4626  litem->emboss = layout->emboss;
4627  litem->item.flag = (layout->item.flag &
4629 
4630  if (layout->child_items_layout) {
4631  BLI_addtail(&layout->child_items_layout->items, litem);
4632  litem->parent = layout->child_items_layout;
4633  }
4634  else {
4635  BLI_addtail(&layout->items, litem);
4636  litem->parent = layout;
4637  }
4638 }
4639 
4640 static void ui_layout_heading_set(uiLayout *layout, const char *heading)
4641 {
4642  BLI_assert(layout->heading[0] == '\0');
4643  if (heading) {
4644  STRNCPY(layout->heading, heading);
4645  }
4646 }
4647 
4648 /* layout create functions */
4649 uiLayout *uiLayoutRow(uiLayout *layout, bool align)
4650 {
4651  uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
4652  ui_litem_init_from_parent(litem, layout, align);
4653 
4654  litem->item.type = ITEM_LAYOUT_ROW;
4655  litem->space = (align) ? 0 : layout->root->style->buttonspacex;
4656 
4657  UI_block_layout_set_current(layout->root->block, litem);
4658 
4659  return litem;
4660 }
4661 
4665 uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
4666 {
4667  uiLayout *litem = uiLayoutRow(layout, align);
4668  ui_layout_heading_set(litem, heading);
4669  return litem;
4670 }
4671 
4672 uiLayout *uiLayoutColumn(uiLayout *layout, bool align)
4673 {
4674  uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
4675  ui_litem_init_from_parent(litem, layout, align);
4676 
4677  litem->item.type = ITEM_LAYOUT_COLUMN;
4678  litem->space = (align) ? 0 : layout->root->style->buttonspacey;
4679 
4680  UI_block_layout_set_current(layout->root->block, litem);
4681 
4682  return litem;
4683 }
4684 
4691 uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading)
4692 {
4693  uiLayout *litem = uiLayoutColumn(layout, align);
4694  ui_layout_heading_set(litem, heading);
4695  return litem;
4696 }
4697 
4698 uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align)
4699 {
4700  uiLayoutItemFlow *flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
4701  ui_litem_init_from_parent(&flow->litem, layout, align);
4702 
4704  flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
4705  flow->number = number;
4706 
4707  UI_block_layout_set_current(layout->root->block, &flow->litem);
4708 
4709  return &flow->litem;
4710 }
4711 
4713  bool row_major,
4714  int columns_len,
4715  bool even_columns,
4716  bool even_rows,
4717  bool align)
4718 {
4719  uiLayoutItemGridFlow *flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__);
4721  ui_litem_init_from_parent(&flow->litem, layout, align);
4722 
4723  flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
4724  flow->row_major = row_major;
4725  flow->columns_len = columns_len;
4726  flow->even_columns = even_columns;
4727  flow->even_rows = even_rows;
4728 
4729  UI_block_layout_set_current(layout->root->block, &flow->litem);
4730 
4731  return &flow->litem;
4732 }
4733 
4735 {
4736  uiLayoutItemBx *box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
4737  ui_litem_init_from_parent(&box->litem, layout, false);
4738 
4739  box->litem.item.type = ITEM_LAYOUT_BOX;
4740  box->litem.space = layout->root->style->columnspace;
4741 
4742  UI_block_layout_set_current(layout->root->block, &box->litem);
4743 
4744  box->roundbox = uiDefBut(layout->root->block, type, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
4745 
4746  return box;
4747 }
4748 
4750 {
4751  /* radial layouts are only valid for radial menus */
4752  if (layout->root->type != UI_LAYOUT_PIEMENU) {
4753  return ui_item_local_sublayout(layout, layout, 0);
4754  }
4755 
4756  /* only one radial wheel per root layout is allowed, so check and return that, if it exists */
4757  LISTBASE_FOREACH (uiItem *, item, &layout->root->layout->items) {
4758  uiLayout *litem = (uiLayout *)item;
4759  if (litem->item.type == ITEM_LAYOUT_RADIAL) {
4760  UI_block_layout_set_current(layout->root->block, litem);
4761  return litem;
4762  }
4763  }
4764 
4765  uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
4766  ui_litem_init_from_parent(litem, layout, false);
4767 
4768  litem->item.type = ITEM_LAYOUT_RADIAL;
4769 
4770  UI_block_layout_set_current(layout->root->block, litem);
4771 
4772  return litem;
4773 }
4774 
4776 {
4777  return (uiLayout *)ui_layout_box(layout, UI_BTYPE_ROUNDBOX);
4778 }
4779 
4786 {
4787  LISTBASE_FOREACH (uiButtonItem *, bitem, &layout->items) {
4788  if (bitem->item.type != ITEM_BUTTON) {
4789  ui_layout_list_set_labels_active((uiLayout *)(&bitem->item));
4790  }
4791  else if (bitem->but->flag & UI_BUT_LIST_ITEM) {
4792  UI_but_flag_enable(bitem->but, UI_SELECT);
4793  }
4794  }
4795 }
4796 
4798  uiList *ui_list,
4799  PointerRNA *actptr,
4800  PropertyRNA *actprop)
4801 {
4803  uiBut *but = box->roundbox;
4804 
4805  but->custom_data = ui_list;
4806 
4807  but->rnapoin = *actptr;
4808  but->rnaprop = actprop;
4809 
4810  /* only for the undo string */
4811  if (but->flag & UI_BUT_UNDO) {
4812  but->tip = RNA_property_description(actprop);
4813  }
4814 
4815  return (uiLayout *)box;
4816 }
4817 
4818 uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align)
4819 {
4820  uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
4821  ui_litem_init_from_parent(litem, layout, align);
4822 
4823  litem->item.type = ITEM_LAYOUT_ABSOLUTE;
4824 
4825  UI_block_layout_set_current(layout->root->block, litem);
4826 
4827  return litem;
4828 }
4829 
4831 {
4832  uiBlock *block = uiLayoutGetBlock(layout);
4833  uiLayoutAbsolute(layout, false);
4834 
4835  return block;
4836 }
4837 
4839 {
4840  uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
4841  ui_litem_init_from_parent(litem, layout, false);
4842 
4843  litem->item.type = ITEM_LAYOUT_OVERLAP;
4844 
4845  UI_block_layout_set_current(layout->root->block, litem);
4846 
4847  return litem;
4848 }
4849 
4850 uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, bool align)
4851 {
4852  uiLayoutItemSplit *split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit");
4853  ui_litem_init_from_parent(&split->litem, layout, align);
4854 
4855  split->litem.item.type = ITEM_LAYOUT_SPLIT;
4856  split->litem.space = layout->root->style->columnspace;
4857  split->percentage = percentage;
4858 
4859  UI_block_layout_set_current(layout->root->block, &split->litem);
4860 
4861  return &split->litem;
4862 }
4863 
4864 void uiLayoutSetActive(uiLayout *layout, bool active)
4865 {
4866  layout->active = active;
4867 }
4868 
4869 void uiLayoutSetActiveDefault(uiLayout *layout, bool active_default)
4870 {
4871  layout->active_default = active_default;
4872 }
4873 
4874 void uiLayoutSetActivateInit(uiLayout *layout, bool activate_init)
4875 {
4876  layout->activate_init = activate_init;
4877 }
4878 
4880 {
4881  layout->enabled = enabled;
4882 }
4883 
4884 void uiLayoutSetRedAlert(uiLayout *layout, bool redalert)
4885 {
4886  layout->redalert = redalert;
4887 }
4888 
4889 void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect)
4890 {
4891  layout->keepaspect = keepaspect;
4892 }
4893 
4894 void uiLayoutSetAlignment(uiLayout *layout, char alignment)
4895 {
4896  layout->alignment = alignment;
4897 }
4898 
4899 void uiLayoutSetScaleX(uiLayout *layout, float scale)
4900 {
4901  layout->scale[0] = scale;
4902 }
4903 
4904 void uiLayoutSetScaleY(uiLayout *layout, float scale)
4905 {
4906  layout->scale[1] = scale;
4907 }
4908 
4909 void uiLayoutSetUnitsX(uiLayout *layout, float unit)
4910 {
4911  layout->units[0] = unit;
4912 }
4913 
4914 void uiLayoutSetUnitsY(uiLayout *layout, float unit)
4915 {
4916  layout->units[1] = unit;
4917 }
4918 
4920 {
4921  layout->emboss = emboss;
4922 }
4923 
4925 {
4926  return (layout->item.flag & UI_ITEM_PROP_SEP) != 0;
4927 }
4928 
4929 void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
4930 {
4931  SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP);
4932 }
4933 
4935 {
4936  return (layout->item.flag & UI_ITEM_PROP_DECORATE) != 0;
4937 }
4938 
4939 void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
4940 {
4942 }
4943 
4945 {
4946  return layout->active;
4947 }
4948 
4950 {
4951  return layout->active_default;
4952 }
4953 
4955 {
4956  return layout->activate_init;
4957 }
4958 
4960 {
4961  return layout->enabled;
4962 }
4963 
4965 {
4966  return layout->redalert;
4967 }
4968 
4970 {
4971  return layout->keepaspect;
4972 }
4973 
4975 {
4976  return layout->alignment;
4977 }
4978 
4980 {
4981  return layout->w;
4982 }
4983 
4985 {
4986  return layout->scale[0];
4987 }
4988 
4990 {
4991  return layout->scale[1];
4992 }
4993 
4995 {
4996  return layout->units[0];
4997 }
4998 
5000 {
5001  return layout->units[1];
5002 }
5003 
5005 {
5006  if (layout->emboss == UI_EMBOSS_UNDEFINED) {
5007  return layout->root->block->emboss;
5008  }
5009  return layout->emboss;
5010 }
5011 
5014 /* -------------------------------------------------------------------- */
5018 /* Disabled for performance reasons, but this could be turned on in the future. */
5019 // #define PROPERTY_SEARCH_USE_TOOLTIPS
5020 
5021 static bool block_search_panel_label_matches(const uiBlock *block, const char *search_string)
5022 {
5023  if ((block->panel != NULL) && (block->panel->type != NULL)) {
5024  if (BLI_strcasestr(block->panel->type->label, search_string)) {
5025  return true;
5026  }
5027  }
5028  return false;
5029 }
5030 
5034 static bool button_matches_search_filter(uiBut *but, const char *search_filter)
5035 {
5036  /* Do the shorter checks first for better performance in case there is a match. */
5037  if (BLI_strcasestr(but->str, search_filter)) {
5038  return true;
5039  }
5040 
5041  if (but->optype != NULL) {
5042  if (BLI_strcasestr(but->optype->name, search_filter)) {
5043  return true;
5044  }
5045  }
5046 
5047  if (but->rnaprop != NULL) {
5048  if (BLI_strcasestr(RNA_property_ui_name(but->rnaprop), search_filter)) {
5049  return true;
5050  }
5051 #ifdef PROPERTY_SEARCH_USE_TOOLTIPS
5052  if (BLI_strcasestr(RNA_property_description(but->rnaprop), search_filter)) {
5053  return true;
5054  }
5055 #endif
5056 
5057  /* Search through labels of enum property items if they are in a drop-down menu.
5058  * Unfortunately we have no #bContext here so we cannot search through RNA enums
5059  * with dynamic entries (or "itemf" functions) which require context. */
5060  if (but->type == UI_BTYPE_MENU) {
5061  PointerRNA *ptr = &but->rnapoin;
5062  PropertyRNA *enum_prop = but->rnaprop;
5063 
5064  int items_len;
5065  const EnumPropertyItem *items_array = NULL;
5066  bool free;
5067  RNA_property_enum_items_gettexted(NULL, ptr, enum_prop, &items_array, &items_len, &free);
5068 
5069  if (items_array == NULL) {
5070  return false;
5071  }
5072 
5073  for (int i = 0; i < items_len; i++) {
5074  /* Check for NULL name field which enums use for separators. */
5075  if (items_array[i].name == NULL) {
5076  continue;
5077  }
5078  if (BLI_strcasestr(items_array[i].name, search_filter)) {
5079  return true;
5080  }
5081  }
5082  if (free) {
5083  MEM_freeN((EnumPropertyItem *)items_array);
5084  }
5085  }
5086  }
5087 
5088  return false;
5089 }
5090 
5094 static bool button_group_has_search_match(uiButtonGroup *button_group, const char *search_filter)
5095 {
5096  LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) {
5097  uiBut *but = link->data;
5098  if (button_matches_search_filter(but, search_filter)) {
5099  return true;
5100  }
5101  }
5102 
5103  return false;
5104 }
5105 
5115 static bool block_search_filter_tag_buttons(uiBlock *block, const char *search_filter)
5116 {
5117  bool has_result = false;
5118  LISTBASE_FOREACH (uiButtonGroup *, button_group, &block->button_groups) {
5119  if (button_group_has_search_match(button_group, search_filter)) {
5120  has_result = true;
5121  }
5122  else {
5123  LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) {
5124  uiBut *but = link->data;
5126  }
5127  }
5128  }
5129  return has_result;
5130 }
5131 
5137 bool UI_block_apply_search_filter(uiBlock *block, const char *search_filter)
5138 {
5139  if (search_filter == NULL || search_filter[0] == '\0') {
5140  return false;
5141  }
5142 
5143  Panel *panel = block->panel;
5144 
5145  if (panel != NULL && panel->type->flag & PANEL_TYPE_NO_SEARCH) {
5146  /* Panels for active blocks should always have a type, otherwise they wouldn't be created. */
5147  BLI_assert(block->panel->type != NULL);
5148  if (panel->type->flag & PANEL_TYPE_NO_SEARCH) {
5149  return false;
5150  }
5151  }
5152 
5153  const bool panel_label_matches = block_search_panel_label_matches(block, search_filter);
5154 
5155  const bool has_result = (panel_label_matches) ?
5156  true :
5157  block_search_filter_tag_buttons(block, search_filter);
5158 
5159  if (panel != NULL) {
5160  if (has_result) {
5162  }
5163  }
5164 
5165  return has_result;
5166 }
5167 
5170 /* -------------------------------------------------------------------- */
5174 static void ui_item_scale(uiLayout *litem, const float scale[2])
5175 {
5176  int x, y, w, h;
5177 
5178  LISTBASE_FOREACH_BACKWARD (uiItem *, item, &litem->items) {
5179  if (item->type != ITEM_BUTTON) {
5180  uiLayout *subitem = (uiLayout *)item;
5181  ui_item_scale(subitem, scale);
5182  }
5183 
5184  ui_item_size(item, &w, &h);
5185  ui_item_offset(item, &x, &y);
5186 
5187  if (scale[0] != 0.0f) {
5188  x *= scale[0];
5189  w *= scale[0];
5190  }
5191 
5192  if (scale[1] != 0.0f) {
5193  y *= scale[1];
5194  h *= scale[1];
5195  }
5196 
5197  ui_item_position(item, x, y, w, h);
5198  }
5199 }
5200 
5201 static void ui_item_estimate(uiItem *item)
5202 {
5203  if (item->type != ITEM_BUTTON) {
5204  uiLayout *litem = (uiLayout *)item;
5205 
5206  LISTBASE_FOREACH (uiItem *, subitem, &litem->items) {
5207  ui_item_estimate(subitem);
5208  }
5209 
5210  if (BLI_listbase_is_empty(&litem->items)) {
5211  litem->w = 0;
5212  litem->h = 0;
5213  return;
5214  }
5215 
5216  if (litem->scale[0] != 0.0f || litem->scale[1] != 0.0f) {
5217  ui_item_scale(litem, litem->scale);
5218  }
5219 
5220  switch (litem->item.type) {
5221  case ITEM_LAYOUT_COLUMN:
5222  ui_litem_estimate_column(litem, false);
5223  break;
5226  break;
5227  case ITEM_LAYOUT_GRID_FLOW:
5229  break;
5230  case ITEM_LAYOUT_ROW:
5231  ui_litem_estimate_row(litem);
5232  break;
5233  case ITEM_LAYOUT_BOX:
5234  ui_litem_estimate_box(litem);
5235  break;
5236  case ITEM_LAYOUT_ROOT:
5237  ui_litem_estimate_root(litem);
5238  break;
5239  case ITEM_LAYOUT_ABSOLUTE:
5241  break;
5242  case ITEM_LAYOUT_SPLIT:
5243  ui_litem_estimate_split(litem);
5244  break;
5245  case ITEM_LAYOUT_OVERLAP:
5247  break;
5248  default:
5249  break;
5250  }
5251 
5252  /* Force fixed size. */
5253  if (litem->units[0] > 0) {
5254  litem->w = UI_UNIT_X * litem->units[0];
5255  }
5256  if (litem->units[1] > 0) {
5257  litem->h = UI_UNIT_Y * litem->units[1];
5258  }
5259  }
5260 }
5261 
5262 static void ui_item_align(uiLayout *litem, short nr)
5263 {
5264  LISTBASE_FOREACH_BACKWARD (uiItem *, item, &litem->items) {
5265  if (item->type == ITEM_BUTTON) {
5266  uiButtonItem *bitem = (uiButtonItem *)item;
5267 #ifndef USE_UIBUT_SPATIAL_ALIGN
5268  if (ui_but_can_align(bitem->but))
5269 #endif
5270  {
5271  if (!bitem->but->alignnr) {
5272  bitem->but->alignnr = nr;
5273  }
5274  }
5275  }
5276  else if (item->type == ITEM_LAYOUT_ABSOLUTE) {
5277  /* pass */
5278  }
5279  else if (item->type == ITEM_LAYOUT_OVERLAP) {
5280  /* pass */
5281  }
5282  else if (item->type == ITEM_LAYOUT_BOX) {
5283  uiLayoutItemBx *box = (uiLayoutItemBx *)item;
5284  if (!box->roundbox->alignnr) {
5285  box->roundbox->alignnr = nr;
5286  }
5287  }
5288  else if (((uiLayout *)item)->align) {
5289  ui_item_align((uiLayout *)item, nr);
5290  }
5291  }
5292 }
5293 
5294 static void ui_item_flag(uiLayout *litem, int flag)
5295 {
5296  LISTBASE_FOREACH_BACKWARD (uiItem *, item, &litem->items) {
5297  if (item->type == ITEM_BUTTON) {
5298  uiButtonItem *bitem = (uiButtonItem *)item;
5299  bitem->but->flag |= flag;
5300  }
5301  else {
5302  ui_item_flag((uiLayout *)item, flag);
5303  }
5304  }
5305 }
5306 
5307 static void ui_item_layout(uiItem *item)
5308 {
5309  if (item->type != ITEM_BUTTON) {
5310  uiLayout *litem = (uiLayout *)item;
5311 
5312  if (BLI_listbase_is_empty(&litem->items)) {
5313  return;
5314  }
5315 
5316  if (litem->align) {
5317  ui_item_align(litem, ++litem->root->block->alignnr);
5318  }
5319  if (!litem->active) {
5320  ui_item_flag(litem, UI_BUT_INACTIVE);
5321  }
5322  if (!litem->enabled) {
5323  ui_item_flag(litem, UI_BUT_DISABLED);
5324  }
5325 
5326  switch (litem->item.type) {
5327  case ITEM_LAYOUT_COLUMN:
5328  ui_litem_layout_column(litem, false, false);
5329  break;
5332  break;
5333  case ITEM_LAYOUT_GRID_FLOW:
5335  break;
5336  case ITEM_LAYOUT_ROW:
5337  ui_litem_layout_row(litem);
5338  break;
5339  case ITEM_LAYOUT_BOX:
5340  ui_litem_layout_box(litem);
5341  break;
5342  case ITEM_LAYOUT_ROOT:
5343  ui_litem_layout_root(litem);
5344  break;
5345  case ITEM_LAYOUT_ABSOLUTE:
5346  ui_litem_layout_absolute(litem);
5347  break;
5348  case ITEM_LAYOUT_SPLIT:
5349  ui_litem_layout_split(litem);
5350  break;
5351  case ITEM_LAYOUT_OVERLAP:
5352  ui_litem_layout_overlap(litem);
5353  break;
5354  case ITEM_LAYOUT_RADIAL:
5355  ui_litem_layout_radial(litem);
5356  break;
5357  default:
5358  break;
5359  }
5360 
5361  LISTBASE_FOREACH (uiItem *, subitem, &litem->items) {
5362  if (item->flag & UI_ITEM_BOX_ITEM) {
5363  subitem->flag |= UI_ITEM_BOX_ITEM;
5364  }
5365  ui_item_layout(subitem);
5366  }
5367  }
5368  else {
5369  if (item->flag & UI_ITEM_BOX_ITEM) {
5370  uiButtonItem *bitem = (uiButtonItem *)item;
5371  bitem->but->drawflag |= UI_BUT_BOX_ITEM;
5372  }
5373  }
5374 }
5375 
5376 static void ui_layout_end(uiBlock *block, uiLayout *layout, int *r_x, int *r_y)
5377 {
5378  if (layout->root->handlefunc) {
5379  UI_block_func_handle_set(block, layout->root->handlefunc, layout->root->argv);
5380  }
5381 
5382  ui_item_estimate(&layout->item);
5383  ui_item_layout(&layout->item);
5384 
5385  if (r_x) {
5386  *r_x = layout->x;
5387  }
5388  if (r_y) {
5389  *r_y = layout->y;
5390  }
5391 }
5392 
5393 static void ui_layout_free(uiLayout *layout)
5394 {
5395  LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
5396  if (item->type == ITEM_BUTTON) {
5397  uiButtonItem *bitem = (uiButtonItem *)item;
5398 
5399  bitem->but->layout = NULL;
5400  MEM_freeN(item);
5401  }
5402  else {
5403  ui_layout_free((uiLayout *)item);
5404  }
5405  }
5406 
5407  MEM_freeN(layout);
5408 }
5409 
5411 {
5412  if (root->padding) {
5413  /* add an invisible button for padding */
5414  uiBlock *block = root->block;
5415  uiLayout *prev_layout = block->curlayout;
5416 
5417  block->curlayout = root->layout;
5418  uiDefBut(
5419  block, UI_BTYPE_SEPR, 0, "", 0, 0, root->padding, root->padding, NULL, 0.0, 0.0, 0, 0, "");
5420  block->curlayout = prev_layout;
5421  }
5422 }
5423 
5425  int dir,
5426  int type,
5427  int x,
5428  int y,
5429  int size,
5430  int em,
5431  int padding,
5432  const uiStyle *style)
5433 {
5434  uiLayoutRoot *root = MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
5435  root->type = type;
5436  root->style = style;
5437  root->block = block;
5438  root->padding = padding;
5440 
5441  uiLayout *layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
5443 
5444  /* Only used when 'UI_ITEM_PROP_SEP' is set. */
5445  layout->item.flag = UI_ITEM_PROP_DECORATE;
5446 
5447  layout->x = x;
5448  layout->y = y;
5449  layout->root = root;
5450  layout->space = style->templatespace;
5451  layout->active = true;
5452  layout->enabled = true;
5453  layout->context = NULL;
5454  layout->emboss = UI_EMBOSS_UNDEFINED;
5455 
5457  layout->space = 0;
5458  }
5459 
5460  if (dir == UI_LAYOUT_HORIZONTAL) {
5461  layout->h = size;
5462  layout->root->emh = em * UI_UNIT_Y;
5463  }
5464  else {
5465  layout->w = size;
5466  layout->root->emw = em * UI_UNIT_X;
5467  }
5468 
5469  block->curlayout = layout;
5470  root->layout = layout;
5471  BLI_addtail(&block->layouts, root);
5472 
5474 
5475  return layout;
5476 }
5477 
5479 {
5480  return layout->root->block;
5481 }
5482 
5484 {
5485  return layout->root->opcontext;
5486 }
5487 
5489 {
5490  block->curlayout = layout;
5491 }
5492 
5493 void ui_layout_add_but(uiLayout *layout, uiBut *but)
5494 {
5495  uiButtonItem *bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
5496  bitem->item.type = ITEM_BUTTON;
5497  bitem->but = but;
5498 
5499  int w, h;
5500  ui_item_size((uiItem *)bitem, &w, &h);
5501  /* XXX uiBut hasn't scaled yet
5502  * we can flag the button as not expandable, depending on its size */
5503  if (w <= 2 * UI_UNIT_X && (!but->str || but->str[0] == '\0')) {
5504  bitem->item.flag |= UI_ITEM_FIXED_SIZE;
5505  }
5506 
5507  if (layout->child_items_layout) {
5508  BLI_addtail(&layout->child_items_layout->items, bitem);
5509  }
5510  else {
5511  BLI_addtail(&layout->items, bitem);
5512  }
5513  but->layout = layout;
5514 
5515  if (layout->context) {
5516  but->context = layout->context;
5517  but->context->used = true;
5518  }
5519 
5520  if (layout->emboss != UI_EMBOSS_UNDEFINED) {
5521  but->emboss = layout->emboss;
5522  }
5523 
5525 }
5526 
5527 bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but)
5528 {
5529  ListBase *child_list = layout->child_items_layout ? &layout->child_items_layout->items :
5530  &layout->items;
5531 
5532  LISTBASE_FOREACH (uiItem *, item, child_list) {
5533  if (item->type == ITEM_BUTTON) {
5534  uiButtonItem *bitem = (uiButtonItem *)item;
5535 
5536  if (bitem->but == old_but_ptr) {
5537  bitem->but = new_but;
5538  return true;
5539  }
5540  }
5541  else {
5542  if (ui_layout_replace_but_ptr((uiLayout *)item, old_but_ptr, new_but)) {
5543  return true;
5544  }
5545  }
5546  }
5547 
5548  return false;
5549 }
5550 
5551 void uiLayoutSetFixedSize(uiLayout *layout, bool fixed_size)
5552 {
5553  if (fixed_size) {
5554  layout->item.flag |= UI_ITEM_FIXED_SIZE;
5555  }
5556  else {
5557  layout->item.flag &= ~UI_ITEM_FIXED_SIZE;
5558  }
5559 }
5560 
5562 {
5563  return (layout->item.flag & UI_ITEM_FIXED_SIZE) != 0;
5564 }
5565 
5566 void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
5567 {
5568  layout->root->opcontext = opcontext;
5569 }
5570 
5571 void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
5572 {
5573  layout->root->handlefunc = handlefunc;
5574  layout->root->argv = argv;
5575 }
5576 
5583 {
5584  LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
5585  ui_layout_free(root->layout);
5586  MEM_freeN(root);
5587  }
5588 }
5589 
5590 void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
5591 {
5592  BLI_assert(block->active);
5593 
5594  if (r_x) {
5595  *r_x = 0;
5596  }
5597  if (r_y) {
5598  *r_y = 0;
5599  }
5600 
5601  block->curlayout = NULL;
5602 
5603  LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
5605 
5606  /* NULL in advance so we don't interfere when adding button */
5607  ui_layout_end(block, root->layout, r_x, r_y);
5608  ui_layout_free(root->layout);
5609  MEM_freeN(root);
5610  }
5611 
5612  BLI_listbase_clear(&block->layouts);
5613 
5614  /* XXX silly trick, interface_templates.c doesn't get linked
5615  * because it's not used by other files in this module? */
5616  {
5618  }
5619 }
5620 
5621 void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *ptr)
5622 {
5623  uiBlock *block = layout->root->block;
5624  layout->context = CTX_store_add(&block->contexts, name, ptr);
5625 }
5626 
5628 {
5629  return layout->context;
5630 }
5631 
5633 {
5634  uiBlock *block = layout->root->block;
5635  layout->context = CTX_store_add_all(&block->contexts, context);
5636 }
5637 
5639 {
5640  if (but->opptr) {
5641  uiLayoutSetContextPointer(layout, "button_operator", but->opptr);
5642  }
5643 
5644  if (but->rnapoin.data && but->rnaprop) {
5645  /* TODO: index could be supported as well */
5646  PointerRNA ptr_prop;
5647  RNA_pointer_create(NULL, &RNA_Property, but->rnaprop, &ptr_prop);
5648  uiLayoutSetContextPointer(layout, "button_prop", &ptr_prop);
5649  uiLayoutSetContextPointer(layout, "button_pointer", &but->rnapoin);
5650  }
5651 }
5652 
5653 /* this is a bit of a hack but best keep it in one place at least */
5655 {
5656  if (r_prop != NULL) {
5657  *r_prop = NULL;
5658  }
5659 
5661  MenuItemLevel *lvl = but->func_argN;
5662  wmOperatorType *ot = WM_operatortype_find(lvl->opname, false);
5663  if ((ot != NULL) && (r_prop != NULL)) {
5664  *r_prop = RNA_struct_type_find_property(ot->srna, lvl->propname);
5665  }
5666  return ot;
5667  }
5668  return NULL;
5669 }
5670 
5671 /* this is a bit of a hack but best keep it in one place at least */
5673 {
5675  return (MenuType *)but->poin;
5676  }
5677  return NULL;
5678 }
5679 
5680 /* this is a bit of a hack but best keep it in one place at least */
5682 {
5684  return (PanelType *)but->poin;
5685  }
5686  return NULL;
5687 }
5688 
5689 void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
5690 {
5691  Menu menu = {
5692  .layout = layout,
5693  .type = mt,
5694  };
5695 
5696  if (G.debug & G_DEBUG_WM) {
5697  printf("%s: opening menu \"%s\"\n", __func__, mt->idname);
5698  }
5699 
5700  if (layout->context) {
5701  CTX_store_set(C, layout->context);
5702  }
5703 
5704  mt->draw(C, &menu);
5705 
5706  if (layout->context) {
5707  CTX_store_set(C, NULL);
5708  }
5709 }
5710 
5711 static bool ui_layout_has_panel_label(const uiLayout *layout, const PanelType *pt)
5712 {
5713  LISTBASE_FOREACH (uiItem *, subitem, &layout->items) {
5714  if (subitem->type == ITEM_BUTTON) {
5715  uiButtonItem *bitem = (uiButtonItem *)subitem;
5716  if (!(bitem->but->flag & UI_HIDDEN) && STREQ(bitem->but->str, pt->label)) {
5717  return true;
5718  }
5719  }
5720  else {
5721  uiLayout *litem = (uiLayout *)subitem;
5722  if (ui_layout_has_panel_label(litem, pt)) {
5723  return true;
5724  }
5725  }
5726  }
5727 
5728  return false;
5729 }
5730 
5731 static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout, bool show_header)
5732 {
5733  Panel *panel = MEM_callocN(sizeof(Panel), "popover panel");
5734  panel->type = pt;
5735  panel->flag = PNL_POPOVER;
5736 
5737  uiLayout *last_item = layout->items.last;
5738 
5739  /* Draw main panel. */
5740  if (show_header) {
5741  uiLayout *row = uiLayoutRow(layout, false);
5742  if (pt->draw_header) {
5743  panel->layout = row;
5744  pt->draw_header(C, panel);
5745  panel->layout = NULL;
5746  }
5747 
5748  /* draw_header() is often used to add a checkbox to the header. If we add the label like below
5749  * the label is disconnected from the checkbox, adding a weird looking gap. As workaround, let
5750  * the checkbox add the label instead. */
5751  if (!ui_layout_has_panel_label(row, pt)) {
5752  uiItemL(row, CTX_IFACE_(pt->translation_context, pt->label), ICON_NONE);
5753  }
5754  }
5755 
5756  panel->layout = layout;
5757  pt->draw(C, panel);
5758  panel->layout = NULL;
5760 
5761  MEM_freeN(panel);
5762 
5763  /* Draw child panels. */
5764  LISTBASE_FOREACH (LinkData *, link, &pt->children) {
5765  PanelType *child_pt = link->data;
5766 
5767  if (child_pt->poll == NULL || child_pt->poll(C, child_pt)) {
5768  /* Add space if something was added to the layout. */
5769  if (last_item != layout->items.last) {
5770  uiItemS(layout);
5771  last_item = layout->items.last;
5772  }
5773 
5774  uiLayout *col = uiLayoutColumn(layout, false);
5775  ui_paneltype_draw_impl(C, child_pt, col, true);
5776  }
5777  }
5778 }
5779 
5784 {
5785  if (layout->context) {
5786  CTX_store_set(C, layout->context);
5787  }
5788 
5789  ui_paneltype_draw_impl(C, pt, layout, false);
5790 
5791  if (layout->context) {
5792  CTX_store_set(C, NULL);
5793  }
5794 }
5795 
5798 /* -------------------------------------------------------------------- */
5810 {
5811  uiBut *but = bitem->but;
5812  BLI_dynstr_appendf(ds, "'type':%d, ", (int)but->type);
5813  BLI_dynstr_appendf(ds, "'draw_string':'''%s''', ", but->drawstr);
5814  /* Not exactly needed, rna has this. */
5815  BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : "");
5816 
5817  if (but->optype) {
5818  char *opstr = WM_operator_pystring_ex(
5819  but->block->evil_C, NULL, false, true, but->optype, but->opptr);
5820  BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
5821  MEM_freeN(opstr);
5822  }
5823 
5824  {
5825  PropertyRNA *prop = NULL;
5827  if (ot) {
5828  char *opstr = WM_operator_pystring_ex(but->block->evil_C, NULL, false, true, ot, NULL);
5829  BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
5830  BLI_dynstr_appendf(ds, "'property':'''%s''', ", prop ? RNA_property_identifier(prop) : "");
5831  MEM_freeN(opstr);
5832  }
5833  }
5834 
5835  if (but->rnaprop) {
5836  BLI_dynstr_appendf(ds,
5837  "'rna':'%s.%s[%d]', ",
5840  but->rnaindex);
5841  }
5842 }
5843 
5845 {
5846  uiItem *item;
5847 
5848  BLI_dynstr_append(ds, "[");
5849 
5850  for (item = lb->first; item; item = item->next) {
5851 
5852  BLI_dynstr_append(ds, "{");
5853 
5854 #define CASE_ITEM(id) \
5855  case id: { \
5856  const char *id_str = STRINGIFY(id); \
5857  BLI_dynstr_append(ds, "'type': '"); \
5858  /* Skip 'ITEM_'. */ \
5859  BLI_dynstr_append(ds, id_str + 5); \
5860  BLI_dynstr_append(ds, "', "); \
5861  break; \
5862  } \
5863  ((void)0)
5864 
5865  switch (item->type) {
5878  }
5879 
5880 #undef CASE_ITEM
5881 
5882  switch (item->type) {
5883  case ITEM_BUTTON:
5885  break;
5886  default:
5887  BLI_dynstr_append(ds, "'items':");
5888  ui_layout_introspect_items(ds, &((uiLayout *)item)->items);
5889  break;
5890  }
5891 
5892  BLI_dynstr_append(ds, "}");
5893 
5894  if (item != lb->last) {
5895  BLI_dynstr_append(ds, ", ");
5896  }
5897  }
5898  /* Don't use a comma here as it's not needed and
5899  * causes the result to evaluate to a tuple of 1. */
5900  BLI_dynstr_append(ds, "]");
5901 }
5902 
5906 const char *UI_layout_introspect(uiLayout *layout)
5907 {
5908  DynStr *ds = BLI_dynstr_new();
5909  uiLayout layout_copy = *layout;
5910  layout_copy.item.next = NULL;
5911  layout_copy.item.prev = NULL;
5912  ListBase layout_dummy_list = {&layout_copy, &layout_copy};
5913  ui_layout_introspect_items(ds, &layout_dummy_list);
5914  const char *result = BLI_dynstr_get_cstring(ds);
5915  BLI_dynstr_free(ds);
5916  return result;
5917 }
5918 
5921 /* -------------------------------------------------------------------- */
5929 uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon)
5930 {
5931  const uiStyle *style = UI_style_get_dpi();
5932  const short icon_size = 64 * U.dpi_fac;
5933  const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points);
5934  const int dialog_width = icon_size + (text_points_max * size * U.dpi_fac);
5935  /* By default, the space between icon and text/buttons will be equal to the 'columnspace',
5936  this extra padding will add some space by increasing the left column width,
5937  making the icon placement more symmetrical, between the block edge and the text. */
5938  const float icon_padding = 5.0f * U.dpi_fac;
5939  /* Calculate the factor of the fixed icon column depending on the block width. */
5940  const float split_factor = ((float)icon_size + icon_padding) /
5941  (float)(dialog_width - style->columnspace);
5942 
5943  uiLayout *block_layout = UI_block_layout(
5944  block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style);
5945 
5946  /* Split layout to put alert icon on left side. */
5947  uiLayout *split_block = uiLayoutSplit(block_layout, split_factor, false);
5948 
5949  /* Alert icon on the left. */
5950  uiLayout *layout = uiLayoutRow(split_block, false);
5951  /* Using 'align_left' with 'row' avoids stretching the icon along the width of column. */
5953  uiDefButAlert(block, icon, 0, 0, icon_size, icon_size);
5954 
5955  /* The rest of the content on the right. */
5956  layout = uiLayoutColumn(split_block, false);
5957 
5958  return layout;
5959 }
5960 
typedef float(TangentPoint)[2]
void CTX_store_set(bContext *C, bContextStore *store)
Definition: context.c:186
struct ARegion * CTX_wm_menu(const bContext *C)
Definition: context.c:736
bContextStore * CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr)
Definition: context.c:126
bContextStore * CTX_store_add_all(ListBase *contexts, bContextStore *context)
Definition: context.c:154
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
#define G_MAIN
Definition: BKE_global.h:232
@ G_DEBUG_WM
Definition: BKE_global.h:138
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1040
struct IDProperty * IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:907
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct SpaceType * BKE_spacetype_from_id(int spaceid)
Definition: screen.c:382
struct ARegionType * BKE_regiontype_from_id(const struct SpaceType *st, int regionid)
@ PANEL_TYPE_NO_SEARCH
Definition: BKE_screen.h:307
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_INLINE
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:71
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:358
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
char * BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:323
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:107
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:116
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:188
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
Definition: BLI_listbase.h:184
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:352
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:180
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:161
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:165
#define STRNCPY(dst, src)
Definition: BLI_string.h:163
#define STRNCPY_RLEN(dst, src)
Definition: BLI_string.h:164
char * BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:578
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:70
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
#define POINTER_FROM_INT(i)
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define POINTER_AS_INT(i)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define MIN2(a, b)
#define STREQ(a, b)
#define TIP_(msgid)
#define CTX_IFACE_(context, msgid)
@ IDP_GROUP
Definition: DNA_ID.h:101
#define MAX_IDPROP_NAME
Definition: DNA_ID.h:92
@ PNL_POPOVER
#define RGN_ALIGN_ENUM_FROM_MASK(align)
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_RIGHT
#define OP_MAX_TYPENAME
_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 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 y
Read Guarded memory(de)allocation.
StructRNA RNA_Property
#define RNA_STRUCT_BEGIN(sptr, prop)
Definition: RNA_access.h:1274
#define RNA_STRUCT_END
Definition: RNA_access.h:1294
StructRNA RNA_Armature
#define RNA_warning(format,...)
Definition: RNA_access.h:1437
StructRNA RNA_KeyMapItem
PropertyType
Definition: RNA_types.h:72
@ PROP_FLOAT
Definition: RNA_types.h:75
@ PROP_BOOLEAN
Definition: RNA_types.h:73
@ PROP_ENUM
Definition: RNA_types.h:77
@ PROP_INT
Definition: RNA_types.h:74
@ PROP_STRING
Definition: RNA_types.h:76
@ PROP_POINTER
Definition: RNA_types.h:78
@ PROP_COLLECTION
Definition: RNA_types.h:79
@ PROP_UNIT_ROTATION
Definition: RNA_types.h:89
@ PROP_ENUM_FLAG
Definition: RNA_types.h:251
@ PROP_ICONS_CONSECUTIVE
Definition: RNA_types.h:198
PropertySubType
Definition: RNA_types.h:112
@ PROP_MATRIX
Definition: RNA_types.h:144
@ PROP_DIRECTION
Definition: RNA_types.h:141
@ PROP_LAYER_MEMBER
Definition: RNA_types.h:157
@ PROP_COLOR
Definition: RNA_types.h:139
@ PROP_AXISANGLE
Definition: RNA_types.h:147
@ PROP_DIRPATH
Definition: RNA_types.h:117
@ PROP_COLOR_GAMMA
Definition: RNA_types.h:151
@ PROP_LAYER
Definition: RNA_types.h:156
@ PROP_FILEPATH
Definition: RNA_types.h:116
#define C
Definition: RandGen.cpp:39
void UI_but_disable(uiBut *but, const char *disabled_hint)
Definition: interface.c:6102
uiBut * uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5603
#define UI_UNIT_Y
uiBut * uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5951
@ UI_ITEM_R_EVENT
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_O_DEPRESS
@ UI_ITEM_R_SPLIT_EMPTY_NAME
@ UI_ITEM_R_ICON_NEVER
@ UI_ITEM_R_IMMEDIATE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
@ UI_ITEM_R_COMPACT
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_NO_BG
@ UI_ITEM_R_CHECKBOX_INVERT
@ UI_ITEM_R_ICON_ONLY
@ UI_ITEM_R_FULL_EVENT
@ UI_ITEM_R_SLIDER
@ UI_BUT_TEXT_RIGHT
Definition: UI_interface.h:261
@ UI_BUT_ICON_LEFT
Definition: UI_interface.h:260
@ UI_BUT_CHECKBOX_INVERT
Definition: UI_interface.h:304
@ UI_BUT_TEXT_LEFT
Definition: UI_interface.h:259
@ UI_BUT_BOX_ITEM
Definition: UI_interface.h:286
uiBut * uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip)
Definition: interface.c:6410
eUIEmbossType
Definition: UI_interface.h:106
@ UI_EMBOSS_UNDEFINED
Definition: UI_interface.h:117
@ UI_EMBOSS_NONE
Definition: UI_interface.h:108
@ UI_EMBOSS_RADIAL
Definition: UI_interface.h:110
@ UI_EMBOSS_PULLDOWN
Definition: UI_interface.h:109
@ UI_EMBOSS_NONE_OR_STATUS
Definition: UI_interface.h:115
void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *but)
const struct uiStyle * UI_style_get_dpi(void)
uiBut * uiDefIconBut(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5223
@ UI_BUT_DRAG_LOCK
Definition: UI_interface.h:197
@ UI_BUT_LIST_ITEM
Definition: UI_interface.h:218
@ UI_BUT_REDALERT
Definition: UI_interface.h:204
@ UI_BUT_UNDO
Definition: UI_interface.h:208
@ UI_BUT_ACTIVE_DEFAULT
Definition: UI_interface.h:215
@ UI_BUT_IMMEDIATE
Definition: UI_interface.h:209
@ UI_BUT_ACTIVATE_ON_INIT
Definition: UI_interface.h:222
@ UI_BUT_DISABLED
Definition: UI_interface.h:199
@ UI_BUT_INACTIVE
Definition: UI_interface.h:206
@ UI_BUT_VALUE_CLEAR
Definition: UI_interface.h:231
@ UI_BUT_LAST_ACTIVE
Definition: UI_interface.h:207
bool UI_block_can_add_separator(const uiBlock *block)
@ UI_LAYOUT_PIEMENU
@ UI_LAYOUT_MENU
@ UI_LAYOUT_PANEL
@ UI_LAYOUT_VERT_BAR
@ UI_LAYOUT_TOOLBAR
@ UI_LAYOUT_HEADER
uiBut * uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:4687
uiBut * uiDefIconButI(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5341
struct PointerRNA * UI_but_operator_ptr_get(uiBut *but)
Definition: interface.c:6218
uiBut * uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5729
uiBut * uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, const char *name, int icon, int x, int y, int width, int height)
uiBut * uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5549
bool UI_but_is_userdef(const uiBut *but)
struct uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void UI_but_drawflag_enable(uiBut *but, int flag)
Definition: interface.c:6092
void UI_butstore_free(uiBlock *block, uiButStore *bs)
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg)
Definition: interface.c:6247
uiBut * uiDefIconButO_ptr(uiBlock *block, int type, struct wmOperatorType *ot, int opcontext, int icon, int x, int y, short width, short height, const char *tip)
Definition: interface.c:5572
@ UI_LAYOUT_ALIGN_LEFT
@ UI_LAYOUT_ALIGN_CENTER
@ UI_LAYOUT_ALIGN_RIGHT
@ UI_LAYOUT_ALIGN_EXPAND
void UI_but_drag_set_id(uiBut *but, struct ID *id)
Definition: interface.c:6127
void UI_but_func_search_set(uiBut *but, uiButSearchCreateFn search_create_fn, uiButSearchUpdateFn search_update_fn, void *arg, const bool free_arg, uiButSearchArgFreeFn search_arg_free_fn, uiButHandleFunc search_exec_fn, void *active)
Definition: interface.c:6613
void UI_but_type_set_menu_from_pulldown(uiBut *but)
Definition: interface.c:6114
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:90
void UI_but_unit_type_set(uiBut *but, const int unit_type)
Definition: interface.c:6228
#define UI_DPI_FAC
Definition: UI_interface.h:309
void UI_but_drawflag_disable(uiBut *but, int flag)
Definition: interface.c:6097
@ UI_BLOCK_LOOP
Definition: UI_interface.h:140
@ UI_BLOCK_IS_FLIP
Definition: UI_interface.h:141
@ UI_BLOCK_LIST_ITEM
Definition: UI_interface.h:160
@ UI_BLOCK_NO_FLIP
Definition: UI_interface.h:142
@ UI_BLOCK_POPUP_HOLD
Definition: UI_interface.h:159
void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
Definition: interface.c:6294
uiBut * uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5166
uiButStore * UI_butstore_create(uiBlock *block)
void UI_block_align_begin(uiBlock *block)
Definition: interface.c:3821
int UI_fontstyle_string_width(const struct uiFontStyle *fs, const char *str)
uiBut * uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, int x, int y, short width, short height, const char *tip)
Definition: interface.c:6435
void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p)
uiBut * uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip)
Definition: interface.c:6393
uiBut * uiDefButI(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:4958
uiBut * uiDefIconTextButO_ptr(uiBlock *block, int type, struct wmOperatorType *ot, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip)
Definition: interface.c:5975
void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *pup)
void(* uiMenuCreateFunc)(struct bContext *C, struct uiLayout *layout, void *arg1)
Definition: UI_interface.h:529
void(* uiMenuHandleFunc)(struct bContext *C, void *arg, int event)
Definition: UI_interface.h:530
void UI_block_direction_set(uiBlock *block, char direction)
Definition: interface.c:6028
void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN)
Definition: interface.c:6864
#define UI_FSTYLE_WIDGET
@ UI_DIR_DOWN
Definition: UI_interface.h:123
@ UI_DIR_RIGHT
Definition: UI_interface.h:125
@ UI_DIR_LEFT
Definition: UI_interface.h:124
@ UI_DIR_UP
Definition: UI_interface.h:122
#define UI_UNIT_X
@ UI_LAYOUT_VERTICAL
@ UI_LAYOUT_HORIZONTAL
eButType
Definition: UI_interface.h:333
@ UI_BTYPE_BUT
Definition: UI_interface.h:334
@ UI_BTYPE_TOGGLE
Definition: UI_interface.h:344
@ UI_BTYPE_TAB
Definition: UI_interface.h:354
@ UI_BTYPE_HOTKEY_EVENT
Definition: UI_interface.h:378
@ UI_BTYPE_LISTBOX
Definition: UI_interface.h:370
@ UI_BTYPE_SEPR_SPACER
Definition: UI_interface.h:389
@ UI_BTYPE_ROUNDBOX
Definition: UI_interface.h:363
@ UI_BTYPE_NUM_SLIDER
Definition: UI_interface.h:343
@ UI_BTYPE_TEXT
Definition: UI_interface.h:336
@ UI_BTYPE_LABEL
Definition: UI_interface.h:358
@ UI_BTYPE_ICON_TOGGLE_N
Definition: UI_interface.h:347
@ UI_BTYPE_DECORATOR
Definition: UI_interface.h:392
@ UI_BTYPE_ROW
Definition: UI_interface.h:335
@ UI_BTYPE_SEARCH_MENU
Definition: UI_interface.h:376
@ UI_BTYPE_UNITVEC
Definition: UI_interface.h:366
@ UI_BTYPE_SEPR_LINE
Definition: UI_interface.h:387
@ UI_BTYPE_KEY_EVENT
Definition: UI_interface.h:359
@ UI_BTYPE_POPOVER
Definition: UI_interface.h:355
@ UI_BTYPE_CHECKBOX_N
Definition: UI_interface.h:352
@ UI_BTYPE_SEPR
Definition: UI_interface.h:386
@ UI_BTYPE_NUM
Definition: UI_interface.h:341
@ UI_BTYPE_COLOR
Definition: UI_interface.h:353
@ UI_BTYPE_CHECKBOX
Definition: UI_interface.h:351
@ UI_BTYPE_MENU
Definition: UI_interface.h:338
@ UI_BTYPE_ICON_TOGGLE
Definition: UI_interface.h:346
#define UI_MAX_NAME_STR
Definition: UI_interface.h:91
void UI_template_fix_linking(void)
uiBut * uiDefButAlert(uiBlock *block, int icon, int x, int y, short width, short height)
Definition: interface.c:4728
uiBut * uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, int x, int y, short width, short height, const char *tip)
Definition: interface.c:5587
void UI_but_flag_enable(uiBut *but, int flag)
Definition: interface.c:6077
uiPopupMenu * UI_popup_menu_begin(struct bContext *C, const char *title, int icon) ATTR_NONNULL()
uiBut * uiDefButO_ptr(uiBlock *block, int type, struct wmOperatorType *ot, int opcontext, const char *str, int x, int y, short width, short height, const char *tip)
Definition: interface.c:5189
void UI_block_align_end(uiBlock *block)
Definition: interface.c:3834
eAlertIcon
#define KM_SHIFT
Definition: WM_types.h:221
@ WM_OP_INVOKE_REGION_WIN
Definition: WM_types.h:198
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:197
#define KM_CTRL
Definition: WM_types.h:222
#define KM_ALT
Definition: WM_types.h:223
#define KM_OSKEY
Definition: WM_types.h:224
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
#define str(s)
uint pos
uint col
uint padding(uint offset, uint alignment)
void ui_but_update(uiBut *but)
Definition: interface.c:3811
uiBut * ui_but_change_type(uiBut *but, eButType new_type)
Definition: interface.c:3935
void ui_def_but_icon_clear(uiBut *but)
Definition: interface.c:4169
void ui_but_rna_menu_convert_to_panel_type(uiBut *but, const char *panel_type)
Definition: interface.c:4367
void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_strip)
Definition: interface.c:1136
void ui_but_rna_menu_convert_to_menu_type(uiBut *but, const char *menu_type)
Definition: interface.c:4396
const char ui_radial_dir_order[8]
Definition: interface.c:1511
bool ui_but_can_align(const uiBut *but)
int ui_but_align_opposite_to_area_align_get(const ARegion *region)
void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
void ui_block_new_button_group(uiBlock *block, uiButtonGroupFlag flag)
void ui_button_group_add_but(uiBlock *block, uiBut *but)
bool enabled
#define RNA_NO_INDEX
RadialDirection
@ UI_PIE_DEGREES_RANGE_LARGE
bool ui_block_is_popup_any(const uiBlock *block) ATTR_WARN_UNUSED_RESULT
struct ARegion * ui_searchbox_create_generic(struct bContext *C, struct ARegion *butregion, uiButSearch *search_but)
#define PIE_MAX_ITEMS
void ui_pie_menu_level_create(uiBlock *block, struct wmOperatorType *ot, const char *propname, struct IDProperty *properties, const EnumPropertyItem *items, int totitem, int context, int flag)
bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT
void ui_panel_tag_search_filter_match(struct Panel *panel)
void ui_rna_collection_search_update_fn(const struct bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
#define RNA_ENUM_VALUE
void ui_but_pie_dir(RadialDirection dir, float vec[2])
@ UI_SELECT_DRAW
@ UI_HIDDEN
@ UI_SELECT
@ UI_SEARCH_FILTER_NO_MATCH
static void ui_litem_estimate_column(uiLayout *litem, bool is_box)
void uiItemBooleanO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
static uiLayout * ui_item_local_sublayout(uiLayout *test, uiLayout *layout, bool align)
static int ui_litem_min_width(int itemw)
void uiItemS_ex(uiLayout *layout, float factor)
static void ui_litem_layout_column_flow(uiLayout *litem)
void uiItemPointerR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop, const char *name, int icon)
bool uiLayoutGetActivateInit(uiLayout *layout)
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
void uiItemL_ex(uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert)
static uiBut * uiItemL_(uiLayout *layout, const char *name, int icon)
void uiLayoutSetActive(uiLayout *layout, bool active)
static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int align)
static void ui_item_flag(uiLayout *litem, int flag)
static void ui_item_move(uiItem *item, int delta_xmin, int delta_xmax)
static void ui_item_size(uiItem *item, int *r_w, int *r_h)
bool uiLayoutGetPropDecorate(uiLayout *layout)
int uiLayoutGetAlignment(uiLayout *layout)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
void uiLayoutSetUnitsY(uiLayout *layout, float unit)
void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon)
uiLayout * uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading)
static void ui_litem_layout_column(uiLayout *litem, bool is_box, bool is_menu)
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
static void ui_item_estimate(uiItem *item)
uiBut * ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
static void ui_litem_layout_overlap(uiLayout *litem)
void uiItemFullOMenuHold_ptr(uiLayout *layout, wmOperatorType *ot, const char *name, int icon, IDProperty *properties, int context, int flag, const char *menu_id, PointerRNA *r_opptr)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
static bool button_matches_search_filter(uiBut *but, const char *search_filter)
bool UI_block_apply_search_filter(uiBlock *block, const char *search_filter)
uiLayout * uiLayoutGridFlow(uiLayout *layout, bool row_major, int columns_len, bool even_columns, bool even_rows, bool align)
uiLayout * uiLayoutOverlap(uiLayout *layout)
static void ui_item_rna_size(uiLayout *layout, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, bool icon_only, bool compact, int *r_w, int *r_h)
void uiLayoutSetFixedSize(uiLayout *layout, bool fixed_size)
static void ui_litem_estimate_column_flow(uiLayout *litem)
#define CASE_ITEM(id)
static uiBut * ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN, const char *tip, bool force_menu)
float uiLayoutGetUnitsY(uiLayout *layout)
uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout)
void uiLayoutSetScaleY(uiLayout *layout, float scale)
void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
static void ui_layout_heading_set(uiLayout *layout, const char *heading)
void uiItemEnumO_string(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value_str)
static void ui_litem_estimate_split(uiLayout *litem)
static void ui_litem_estimate_overlap(uiLayout *litem)
static void ui_item_disabled(uiLayout *layout, const char *name)
static const char * ui_item_name_add_colon(const char *name, char namestr[UI_MAX_NAME_STR])
void uiItemIntO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
void uiItemL(uiLayout *layout, const char *name, int icon)
void uiLayoutSetActiveDefault(uiLayout *layout, bool active_default)
bContextStore * uiLayoutGetContextStore(uiLayout *layout)
void uiLayoutSetRedAlert(uiLayout *layout, bool redalert)
void uiItemFullR_with_menu(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon, const char *menu_type)
static uiLayout * ui_layout_heading_find(uiLayout *cur_layout)
static void ui_item_position(uiItem *item, int x, int y, int w, int h)
#define UI_ITEM_PROP_SEP_DIVIDE
uiLayout * uiLayoutAbsolute(uiLayout *layout, bool align)
void uiLayoutSetScaleX(uiLayout *layout, float scale)
void uiItemMenuEnumO_ptr(uiLayout *layout, bContext *C, wmOperatorType *ot, const char *propname, const char *name, int icon)
static bool ui_item_rna_is_expand(PropertyRNA *prop, int index, int item_flag)
static void ui_item_layout(uiItem *item)
static void ui_litem_layout_absolute(uiLayout *litem)
static bool ui_item_is_radial_displayable(uiItem *item)
float uiLayoutGetUnitsX(uiLayout *layout)
bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but)
static void ui_litem_grid_flow_compute(ListBase *items, UILayoutGridFlowInput *parameters, UILayoutGridFlowOutput *results)
struct UILayoutGridFlowInput UILayoutGridFlowInput
void uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opname, const char *propname, const char *name, int icon)
struct uiItem uiItem
uiLayout * uiLayoutBox(uiLayout *layout)
static uiLayoutItemBx * ui_layout_box(uiLayout *layout, int type)
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
bool uiLayoutGetEnabled(uiLayout *layout)
void uiItemV(uiLayout *layout, const char *name, int icon, int argval)
uiBlock * uiLayoutAbsoluteBlock(uiLayout *layout)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
wmOperatorType * UI_but_operatortype_get_from_enum_menu(uiBut *but, PropertyRNA **r_prop)
static void ui_item_enum_expand_exec(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, const char *uiname, const int h, const eButType but_type, const bool icon_only)
void uiItemS(uiLayout *layout)
PanelType * UI_but_paneltype_get(uiBut *but)
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
#define UI_ITEM_VARY_X
void uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *name, int icon, IDProperty *properties, int context, int flag, PointerRNA *r_opptr)
float uiLayoutGetScaleY(uiLayout *layout)
void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index)
static bool block_search_filter_tag_buttons(uiBlock *block, const char *search_filter)
void uiItemPopoverPanelFromGroup(uiLayout *layout, bContext *C, int space_id, int region_id, const char *context, const char *category)
static void ui_item_offset(uiItem *item, int *r_x, int *r_y)
void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int icon, const char *propname, int value)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
bool uiLayoutGetActive(uiLayout *layout)
static void ui_layout_heading_label_add(uiLayout *layout, uiLayout *heading_layout, bool right_align, bool respect_prop_split)
uiLayout * uiLayoutColumnFlow(uiLayout *layout, int number, bool align)
static void ui_litem_layout_row(uiLayout *litem)
struct MenuItemLevel MenuItemLevel
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname)
static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
static void ui_item_enum_expand_tabs(uiLayout *layout, bContext *C, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *ptr_highlight, PropertyRNA *prop_highlight, const char *uiname, const int h, const bool icon_only)
BLI_INLINE bool ui_layout_is_radial(const uiLayout *layout)
bool uiLayoutGetKeepAspect(uiLayout *layout)
static void ui_layout_add_padding_button(uiLayoutRoot *root)
struct uiLayoutItemRoot uiLayoutItemRoot
bool uiLayoutGetPropSep(uiLayout *layout)
void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt)
static int ui_layout_vary_direction(uiLayout *layout)
void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout)
void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon)
void uiLayoutSetUnitsX(uiLayout *layout, float unit)
void uiItemFloatO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, float value)
static void ui_litem_estimate_row(uiLayout *litem)
void uiItemEnumR_string_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *value, const char *name, int icon)
static void ui_layout_end(uiBlock *block, uiLayout *layout, int *r_x, int *r_y)
eUIEmbossType uiLayoutGetEmboss(uiLayout *layout)
@ UI_ITEM_INSIDE_PROP_SEP
@ UI_ITEM_PROP_DECORATE_NO_PAD
@ UI_ITEM_PROP_DECORATE
@ UI_ITEM_PROP_SEP
@ UI_ITEM_FIXED_SIZE
@ UI_ITEM_BOX_ITEM
@ UI_ITEM_AUTO_FIXED_SIZE
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
static bool block_search_panel_label_matches(const uiBlock *block, const char *search_string)
int uiLayoutGetLocalDir(const uiLayout *layout)
void uiItemSpacer(uiLayout *layout)
void uiItemM_ptr(uiLayout *layout, MenuType *mt, const char *name, int icon)
static int ui_item_fit(int item, int pos, int all, int available, bool is_last, int alignment, float *extra_pixel)
void ui_layout_list_set_labels_active(uiLayout *layout)
struct uiLayoutItemSplit uiLayoutItemSplit
void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect)
struct uiLayoutItemFlow uiLayoutItemFlow
void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
bool uiLayoutGetFixedSize(uiLayout *layout)
#define UI_ITEM_VARY_Y
static void ui_litem_estimate_box(uiLayout *litem)
static void ui_rna_collection_search_arg_free_fn(void *ptr)
void UI_context_active_but_prop_get_filebrowser(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop, bool *r_is_undo, bool *r_is_userdef)
void uiItemPopoverPanel_ptr(uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon)
static bool ui_layout_has_panel_label(const uiLayout *layout, const PanelType *pt)
#define UI_PROP_DECORATE
void uiItemMContents(uiLayout *layout, const char *menuname)
bool uiLayoutGetActiveDefault(uiLayout *layout)
int uiLayoutGetOperatorContext(uiLayout *layout)
static void ui_litem_estimate_grid_flow(uiLayout *litem)
void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname)
static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h), bool expand, bool slider, int toggle, bool icon_only, bool compact, bool show_text)
static void ui_keymap_but_cb(bContext *UNUSED(C), void *but_v, void *UNUSED(key_v))
uiLayout * uiLayoutRadial(uiLayout *layout)
void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value)
static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index)
void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss)
static void ui_layout_introspect_items(DynStr *ds, ListBase *lb)
static void ui_item_scale(uiLayout *litem, const float scale[2])
int uiLayoutGetWidth(uiLayout *layout)
static void ui_layout_introspect_button(DynStr *ds, uiButtonItem *bitem)
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
static void search_id_collection(StructRNA *ptype, PointerRNA *r_ptr, PropertyRNA **r_prop)
static void ui_litem_estimate_root(uiLayout *UNUSED(litem))
static void ui_litem_layout_split(uiLayout *litem)
void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, const char *name, int icon)
void uiItemEnumO_value(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
struct uiLayoutRoot uiLayoutRoot
float uiLayoutGetScaleX(uiLayout *layout)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutSplit(uiLayout *layout, float percentage, bool align)
void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but)
static void ui_but_tip_from_enum_item(uiBut *but, const EnumPropertyItem *item)
void uiItemPopoverPanel(uiLayout *layout, bContext *C, const char *panel_type, const char *name, int icon)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void UI_block_layout_free(uiBlock *block)
static void ui_litem_layout_radial(uiLayout *litem)
#define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement)
static void ui_litem_estimate_absolute(uiLayout *litem)
static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2)
static uiBut * ui_item_with_label(uiLayout *layout, uiBlock *block, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w_hint, int h, int flag)
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
uiLayout * uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon)
void uiItemEnumO_ptr(uiLayout *layout, wmOperatorType *ot, const char *name, int icon, const char *propname, int value)
static bool button_group_has_search_match(uiButtonGroup *button_group, const char *search_filter)
static bool ui_layout_variable_size(uiLayout *layout)
uiLayout * uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *actptr, PropertyRNA *actprop)
static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool compact)
void uiLayoutSetActivateInit(uiLayout *layout, bool activate_init)
static void ui_layout_free(uiLayout *layout)
static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, const char *uiname, const int h, const bool icon_only)
void uiItemStringO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value)
void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon)
static void ui_item_menu_hold(struct bContext *C, ARegion *butregion, uiBut *but)
void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value)
void uiItemFullO(uiLayout *layout, const char *opname, const char *name, int icon, IDProperty *properties, int context, int flag, PointerRNA *r_opptr)
static void ui_litem_layout_box(uiLayout *litem)
static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout, bool show_header)
uiItemType
@ ITEM_LAYOUT_COLUMN_FLOW
@ ITEM_LAYOUT_SPLIT
@ ITEM_LAYOUT_GRID_FLOW
@ ITEM_LAYOUT_ROOT
@ ITEM_LAYOUT_OVERLAP
@ ITEM_LAYOUT_RADIAL
@ ITEM_LAYOUT_ROW
@ ITEM_LAYOUT_ROW_FLOW
@ ITEM_LAYOUT_BOX
@ ITEM_BUTTON
@ ITEM_LAYOUT_COLUMN
@ ITEM_LAYOUT_ABSOLUTE
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg)
static void ui_item_align(uiLayout *litem, short nr)
struct uiLayoutItemBx uiLayoutItemBx
static void ui_litem_layout_grid_flow(uiLayout *litem)
static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
MenuType * UI_but_menutype_get(uiBut *but)
void uiItemsFullEnumO_items(uiLayout *layout, wmOperatorType *ot, PointerRNA ptr, PropertyRNA *prop, IDProperty *properties, int context, int flag, const EnumPropertyItem *item_array, int totitem)
struct uiLayoutItemGridFlow uiLayoutItemGridFlow
const char * UI_layout_introspect(uiLayout *layout)
bool uiLayoutGetRedAlert(uiLayout *layout)
static uiBut * uiItemFullO_ptr_ex(uiLayout *layout, wmOperatorType *ot, const char *name, int icon, IDProperty *properties, int context, int flag, PointerRNA *r_opptr)
void ui_layout_add_but(uiLayout *layout, uiBut *but)
static void ui_litem_layout_root(uiLayout *litem)
struct UILayoutGridFlowOutput UILayoutGridFlowOutput
void uiItemMenuFN(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *argN)
static void ui_item_enum_expand_elem_exec(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, const char *uiname, const int h, const eButType but_type, const bool icon_only, const EnumPropertyItem *item, const bool is_first)
void uiItemTabsEnumR_prop(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *ptr_highlight, PropertyRNA *prop_highlight, bool icon_only)
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const uiStyle *style)
static void ui_litem_layout_root_radial(uiLayout *litem)
struct uiButtonItem uiButtonItem
static uiLayout * ui_item_prop_split_layout_hack(uiLayout *layout_parent, uiLayout *layout_split)
static bool ui_item_is_radial_drawable(uiButtonItem *bitem)
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
static const char * ui_menu_enumpropname(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int retval)
void uiItemFullR_with_popover(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon, const char *panel_type)
void uiLayoutContextCopy(uiLayout *layout, bContextStore *context)
void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *ptr)
void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, IDProperty *properties, int context, int flag)
uiLayout * uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon)
#define ceilf(x)
#define sqrtf(x)
double parameters[NUM_PARAMETERS]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned a[3]
Definition: RandGen.cpp:92
bool active
all scheduled work for the GPU.
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
Definition: abc_util.cc:115
const char * RNA_struct_identifier(const StructRNA *type)
Definition: rna_access.c:723
void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
Definition: rna_access.c:2530
const char * RNA_property_description(PropertyRNA *prop)
Definition: rna_access.c:1150
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1223
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
Definition: rna_access.c:844
bool RNA_property_is_unlink(PropertyRNA *prop)
Definition: rna_access.c:6712
bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2168
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:6550
bool RNA_struct_is_ID(const StructRNA *type)
Definition: rna_access.c:797
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1145
bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value)
Definition: rna_access.c:6474
int RNA_property_ui_icon(const PropertyRNA *prop)
Definition: rna_access.c:2068
int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
Definition: rna_access.c:1229
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:6272
void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
Definition: rna_access.c:2420
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1155
const PointerRNA PointerRNA_NULL
Definition: rna_access.c:71
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6319
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:3562
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
char RNA_property_array_item_char(PropertyRNA *prop, int index)
Definition: rna_access.c:1250
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2317
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2331
void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
Definition: rna_access.c:1722
const char * RNA_property_translation_context(const PropertyRNA *prop)
Definition: rna_access.c:2063
PropertyRNA * RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
Definition: rna_access.c:953
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1567
int RNA_property_flag(PropertyRNA *prop)
Definition: rna_access.c:1192
int RNA_struct_ui_icon(const StructRNA *type)
Definition: rna_access.c:738
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:6366
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1218
bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
Definition: rna_access.c:1854
void RNA_property_enum_items_gettexted_all(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
Definition: rna_access.c:1738
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3543
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1160
void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
Definition: rna_access.c:1657
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2453
void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
Definition: rna_access.c:115
const char * RNA_property_ui_name(const PropertyRNA *prop)
Definition: rna_access.c:2043
struct SELECTID_Context context
Definition: select_engine.c:47
ListBase paneltypes
Definition: BKE_screen.h:216
short alignment
ListBase uiblocks
const char * identifier
Definition: RNA_types.h:446
const char * name
Definition: RNA_types.h:450
const char * description
Definition: RNA_types.h:452
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
char opname[OP_MAX_TYPENAME]
PointerRNA rnapoin
char propname[MAX_IDPROP_NAME]
const char * description
Definition: BKE_screen.h:379
char label[BKE_ST_MAXNAME]
Definition: BKE_screen.h:376
char idname[BKE_ST_MAXNAME]
Definition: BKE_screen.h:375
void(* draw)(const struct bContext *C, struct Menu *menu)
Definition: BKE_screen.h:384
char translation_context[BKE_ST_MAXNAME]
Definition: BKE_screen.h:377
struct uiLayout * layout
Definition: BKE_screen.h:392
void(* draw)(const struct bContext *C, struct Panel *panel)
Definition: BKE_screen.h:266
bool(* poll)(const struct bContext *C, struct PanelType *pt)
Definition: BKE_screen.h:260
void(* draw_header)(const struct bContext *C, struct Panel *panel)
Definition: BKE_screen.h:262
char translation_context[BKE_ST_MAXNAME]
Definition: BKE_screen.h:244
ListBase children
Definition: BKE_screen.h:289
char * description
Definition: BKE_screen.h:243
char label[BKE_ST_MAXNAME]
Definition: BKE_screen.h:242
struct PointerRNA * custom_data_ptr
struct PanelType * type
struct uiLayout * layout
Panel_Runtime runtime
short flag
struct StructRNA * type
Definition: RNA_types.h:51
void * data
Definition: RNA_types.h:52
struct ID * owner_id
Definition: RNA_types.h:50
unsigned int layer_used
struct EditBone * act_edbone
ListBase * edbo
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
eUIEmbossType emboss
ListBase layouts
ListBase button_groups
struct Panel * panel
uiPopupBlockHandle * handle
struct PieMenuData pie_data
ListBase buttons
uiButHandleFunc func
struct uiLayout * curlayout
void * evil_C
ListBase contexts
struct PropertyRNA * rnaprop
struct PointerRNA rnapoin
struct PointerRNA rnasearchpoin
struct PropertyRNA * rnasearchprop
const char * tip
struct bContextStore * context
void * custom_data
struct uiBut * next
short modifier_key
eButType type
float hardmax
uiButHandleFunc func
signed char pie_dir
uiBlock * block
eUIEmbossType emboss
uiMenuCreateFunc menu_create_func
char * poin
short alignnr
void * hold_argN
BIFIconID icon
struct PointerRNA * opptr
struct wmOperatorType * optype
char drawstr[UI_MAX_DRAW_STR]
uiLayout * layout
struct PropertyRNA * rnaprop
void * func_argN
char * str
struct PointerRNA rnapoin
void * prev
void * next
uiItemType type
const uiStyle * style
struct uiLayoutRoot * prev
struct uiLayoutRoot * next
uiMenuHandleFunc handlefunc
uiBlock * block
uiLayout * layout
float scale[2]
char heading[UI_MAX_NAME_STR]
ListBase items
uiLayoutRoot * root
bool active_default
float units[2]
bContextStore * context
eUIEmbossType emboss
uiLayout * child_items_layout
uiLayout * parent
bool activate_init
bool variable_size
short buttonspacey
short buttonspacex
short templatespace
uiFontStyle widget
short columnspace
uiFontStyle widgetlabel
short shift
Definition: WM_types.h:618
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
char *(* get_description)(struct bContext *C, struct wmOperatorType *, struct PointerRNA *)
Definition: WM_types.h:799
struct StructRNA * srna
Definition: WM_types.h:802
PropertyRNA * prop
Definition: WM_types.h:814
struct wmEvent * eventstate
__forceinline bool all(const avxb &b)
Definition: util_avxb.h:214
#define G(x, y, z)
uint len
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_keymap_item_to_string(const wmKeyMapItem *kmi, const bool compact, char *result, const int result_len)
Definition: wm_keymap.c:1213
char * WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, const bool is_strict, char *result, const int result_len)
Definition: wm_keymap.c:1587
MenuType * WM_menutype_find(const char *idname, bool quiet)
Definition: wm_menu_type.c:44
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
const char * WM_operatortype_name(struct wmOperatorType *ot, struct PointerRNA *properties)
char * WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, const bool macro_args, wmOperatorType *ot, PointerRNA *opptr)
Definition: wm_operators.c:228
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:584
void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
Definition: wm_operators.c:620
PanelType * WM_paneltype_find(const char *idname, bool quiet)
Definition: wm_panel_type.c:42