Blender  V3.3
interface_utils.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation. All rights reserved. */
3 
8 #include <cctype>
9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 
13 #include "DNA_object_types.h"
14 #include "DNA_screen_types.h"
15 
16 #include "ED_screen.h"
17 
18 #include "BLI_listbase.h"
19 #include "BLI_math.h"
20 #include "BLI_string.h"
21 #include "BLI_string_search.h"
22 #include "BLI_utildefines.h"
23 
24 #include "BLT_translation.h"
25 
26 #include "BKE_context.h"
27 #include "BKE_global.h"
28 #include "BKE_lib_id.h"
29 #include "BKE_report.h"
30 
31 #include "MEM_guardedalloc.h"
32 
33 #include "RNA_access.h"
34 
35 #include "UI_interface.h"
36 #include "UI_interface_icons.h"
37 #include "UI_resources.h"
38 #include "UI_view2d.h"
39 
40 #include "WM_api.h"
41 #include "WM_types.h"
42 
43 #include "interface_intern.h"
44 
45 /*************************** RNA Utilities ******************************/
46 
48  PointerRNA *ptr,
49  PropertyRNA *prop,
50  int index,
51  const char *name,
52  int icon,
53  int x,
54  int y,
55  int width,
56  int height)
57 {
58  uiBut *but = nullptr;
59 
60  switch (RNA_property_type(prop)) {
61  case PROP_BOOLEAN: {
62  if (RNA_property_array_check(prop) && index == -1) {
63  return nullptr;
64  }
65 
66  if (icon && name && name[0] == '\0') {
67  but = uiDefIconButR_prop(block,
69  0,
70  icon,
71  x,
72  y,
73  width,
74  height,
75  ptr,
76  prop,
77  index,
78  0,
79  0,
80  -1,
81  -1,
82  nullptr);
83  }
84  else if (icon) {
85  but = uiDefIconTextButR_prop(block,
87  0,
88  icon,
89  name,
90  x,
91  y,
92  width,
93  height,
94  ptr,
95  prop,
96  index,
97  0,
98  0,
99  -1,
100  -1,
101  nullptr);
102  }
103  else {
104  but = uiDefButR_prop(block,
106  0,
107  name,
108  x,
109  y,
110  width,
111  height,
112  ptr,
113  prop,
114  index,
115  0,
116  0,
117  -1,
118  -1,
119  nullptr);
120  }
121  break;
122  }
123  case PROP_INT:
124  case PROP_FLOAT: {
125  if (RNA_property_array_check(prop) && index == -1) {
127  but = uiDefButR_prop(block,
129  0,
130  name,
131  x,
132  y,
133  width,
134  height,
135  ptr,
136  prop,
137  -1,
138  0,
139  0,
140  0,
141  0,
142  nullptr);
143  }
144  else {
145  return nullptr;
146  }
147  }
148  else if (RNA_property_subtype(prop) == PROP_PERCENTAGE ||
150  but = uiDefButR_prop(block,
152  0,
153  name,
154  x,
155  y,
156  width,
157  height,
158  ptr,
159  prop,
160  index,
161  0,
162  0,
163  -1,
164  -1,
165  nullptr);
166  }
167  else {
168  but = uiDefButR_prop(block,
169  UI_BTYPE_NUM,
170  0,
171  name,
172  x,
173  y,
174  width,
175  height,
176  ptr,
177  prop,
178  index,
179  0,
180  0,
181  0,
182  0,
183  nullptr);
184  }
185 
188  }
189  break;
190  }
191  case PROP_ENUM:
192  if (icon && name && name[0] == '\0') {
193  but = uiDefIconButR_prop(block,
195  0,
196  icon,
197  x,
198  y,
199  width,
200  height,
201  ptr,
202  prop,
203  index,
204  0,
205  0,
206  -1,
207  -1,
208  nullptr);
209  }
210  else if (icon) {
211  but = uiDefIconTextButR_prop(block,
213  0,
214  icon,
215  nullptr,
216  x,
217  y,
218  width,
219  height,
220  ptr,
221  prop,
222  index,
223  0,
224  0,
225  -1,
226  -1,
227  nullptr);
228  }
229  else {
230  but = uiDefButR_prop(block,
232  0,
233  name,
234  x,
235  y,
236  width,
237  height,
238  ptr,
239  prop,
240  index,
241  0,
242  0,
243  -1,
244  -1,
245  nullptr);
246  }
247  break;
248  case PROP_STRING:
249  if (icon && name && name[0] == '\0') {
250  but = uiDefIconButR_prop(block,
252  0,
253  icon,
254  x,
255  y,
256  width,
257  height,
258  ptr,
259  prop,
260  index,
261  0,
262  0,
263  -1,
264  -1,
265  nullptr);
266  }
267  else if (icon) {
268  but = uiDefIconTextButR_prop(block,
270  0,
271  icon,
272  name,
273  x,
274  y,
275  width,
276  height,
277  ptr,
278  prop,
279  index,
280  0,
281  0,
282  -1,
283  -1,
284  nullptr);
285  }
286  else {
287  but = uiDefButR_prop(block,
289  0,
290  name,
291  x,
292  y,
293  width,
294  height,
295  ptr,
296  prop,
297  index,
298  0,
299  0,
300  -1,
301  -1,
302  nullptr);
303  }
304 
306  /* TEXTEDIT_UPDATE is usually used for search buttons. For these we also want
307  * the 'x' icon to clear search string, so setting VALUE_CLEAR flag, too. */
309  }
310  break;
311  case PROP_POINTER: {
312  if (icon == 0) {
313  const PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
314  icon = RNA_struct_ui_icon(pptr.type ? pptr.type : RNA_property_pointer_type(ptr, prop));
315  }
316  if (icon == ICON_DOT) {
317  icon = 0;
318  }
319 
320  but = uiDefIconTextButR_prop(block,
322  0,
323  icon,
324  name,
325  x,
326  y,
327  width,
328  height,
329  ptr,
330  prop,
331  index,
332  0,
333  0,
334  -1,
335  -1,
336  nullptr);
337  ui_but_add_search(but, ptr, prop, nullptr, nullptr, false);
338  break;
339  }
340  case PROP_COLLECTION: {
341  char text[256];
342  BLI_snprintf(
343  text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop));
344  but = uiDefBut(
345  block, UI_BTYPE_LABEL, 0, text, x, y, width, height, nullptr, 0, 0, 0, 0, nullptr);
347  break;
348  }
349  default:
350  but = nullptr;
351  break;
352  }
353 
354  return but;
355 }
356 
358  PointerRNA *ptr,
359  PropertyRNA *prop,
360  const int icon,
361  const int x,
362  const int y,
363  const int tot_width,
364  const int height)
365 {
366  const int len = RNA_property_array_length(ptr, prop);
367  if (len == 0) {
368  return;
369  }
370 
371  const int item_width = tot_width / len;
372 
373  UI_block_align_begin(block);
374  for (int i = 0; i < len; i++) {
375  uiDefAutoButR(block, ptr, prop, i, "", icon, x + i * item_width, y, item_width, height);
376  }
377  UI_block_align_end(block);
378 }
379 
381  PointerRNA *ptr,
382  bool (*check_prop)(PointerRNA *ptr,
383  PropertyRNA *prop,
384  void *user_data),
385  void *user_data,
386  PropertyRNA *prop_activate_init,
387  const eButLabelAlign label_align,
388  const bool compact)
389 {
391  uiLayout *col;
392  const char *name;
393 
394  RNA_STRUCT_BEGIN (ptr, prop) {
395  const int flag = RNA_property_flag(prop);
396 
397  if (flag & PROP_HIDDEN) {
398  continue;
399  }
400  if (check_prop && check_prop(ptr, prop, user_data) == 0) {
401  return_info |= UI_PROP_BUTS_ANY_FAILED_CHECK;
402  continue;
403  }
404 
405  const PropertyType type = RNA_property_type(prop);
406  switch (label_align) {
409  const bool is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(prop));
410 
411  name = RNA_property_ui_name(prop);
412 
413  if (label_align == UI_BUT_LABEL_ALIGN_COLUMN) {
414  col = uiLayoutColumn(layout, true);
415 
416  if (!is_boolean) {
417  uiItemL(col, name, ICON_NONE);
418  }
419  }
420  else {
422  col = uiLayoutColumn(layout, true);
423  /* Let uiItemFullR() create the split layout. */
424  uiLayoutSetPropSep(col, true);
425  }
426 
427  break;
428  }
430  default:
431  col = layout;
432  name = nullptr; /* no smart label alignment, show default name with button */
433  break;
434  }
435 
436  /* Only buttons that can be edited as text. */
437  const bool use_activate_init = ((prop == prop_activate_init) &&
439 
440  if (use_activate_init) {
442  }
443 
444  uiItemFullR(col, ptr, prop, -1, 0, compact ? UI_ITEM_R_COMPACT : 0, name, ICON_NONE);
445  return_info &= ~UI_PROP_BUTS_NONE_ADDED;
446 
447  if (use_activate_init) {
449  }
450  }
452 
453  return return_info;
454 }
455 
457 {
458  but->identity_cmp_func = cmp_fn;
459 }
460 
461 /* *** RNA collection search menu *** */
462 
465  void *data;
466  char *name;
467  int index;
468  int iconid;
469  bool is_id;
472 };
473 
475  const bool requires_exact_data_name,
476  const bool has_id_icon,
477  uiSearchItems *items)
478 {
479  char name_buf[UI_MAX_DRAW_STR];
480 
481  /* If no item has an own icon to display, libraries can use the library icons rather than the
482  * name prefix for showing the library status. */
484  if (!has_id_icon && cis->is_id && !requires_exact_data_name) {
485  cis->iconid = UI_icon_from_library(static_cast<const ID *>(cis->data));
486  /* No need to re-allocate, string should be shorter than before (lib status prefix is
487  * removed). */
489  name_buf, static_cast<const ID *>(cis->data), false, UI_SEP_CHAR, &name_prefix_offset);
490  BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name));
491  strcpy(cis->name, name_buf);
492  }
493 
494  return UI_search_item_add(items,
495  cis->name,
496  cis->data,
497  cis->iconid,
498  cis->has_sep_char ? (int)UI_BUT_HAS_SEP_CHAR : 0,
500 }
501 
503  const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
504 {
505  uiRNACollectionSearch *data = static_cast<uiRNACollectionSearch *>(arg);
506  const int flag = RNA_property_flag(data->target_prop);
507  ListBase *items_list = MEM_cnew<ListBase>("items_list");
508  const bool is_ptr_target = (RNA_property_type(data->target_prop) == PROP_POINTER);
509  /* For non-pointer properties, UI code acts entirely based on the item's name. So the name has to
510  * match the RNA name exactly. So only for pointer properties, the name can be modified to add
511  * further UI hints. */
512  const bool requires_exact_data_name = !is_ptr_target;
513  const bool skip_filter = is_first;
514  char name_buf[UI_MAX_DRAW_STR];
515  char *name;
516  bool has_id_icon = false;
517 
518  StringSearch *search = skip_filter ? nullptr : BLI_string_search_new();
519 
520  if (data->search_prop != nullptr) {
521  /* build a temporary list of relevant items first */
522  int item_index = 0;
523  RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) {
524 
525  if (flag & PROP_ID_SELF_CHECK) {
526  if (itemptr.data == data->target_ptr.owner_id) {
527  continue;
528  }
529  }
530 
531  /* use filter */
532  if (is_ptr_target) {
533  if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0) {
534  continue;
535  }
536  }
537 
538  int name_prefix_offset = 0;
539  int iconid = ICON_NONE;
540  bool has_sep_char = false;
541  const bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type);
542 
543  if (is_id) {
544  iconid = ui_id_icon_get(C, static_cast<ID *>(itemptr.data), false);
545  if (!ELEM(iconid, 0, ICON_BLANK1)) {
546  has_id_icon = true;
547  }
548 
549  if (requires_exact_data_name) {
550  name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), nullptr);
551  }
552  else {
553  const ID *id = static_cast<ID *>(itemptr.data);
555  BLI_STATIC_ASSERT(sizeof(name_buf) >= MAX_ID_FULL_NAME_UI,
556  "Name string buffer should be big enough to hold full UI ID name");
557  name = name_buf;
559  }
560  }
561  else {
562  name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), nullptr);
563  }
564 
565  if (name) {
566  CollItemSearch *cis = MEM_cnew<CollItemSearch>(__func__);
567  cis->data = itemptr.data;
568  cis->name = BLI_strdup(name);
569  cis->index = item_index;
570  cis->iconid = iconid;
571  cis->is_id = is_id;
573  cis->has_sep_char = has_sep_char;
574  if (!skip_filter) {
575  BLI_string_search_add(search, name, cis, 0);
576  }
577  BLI_addtail(items_list, cis);
578  if (name != name_buf) {
579  MEM_freeN(name);
580  }
581  }
582 
583  item_index++;
584  }
585  RNA_PROP_END;
586  }
587  else {
588  BLI_assert(RNA_property_type(data->target_prop) == PROP_STRING);
590  data->target_prop);
592 
593  struct SearchVisitUserData {
594  StringSearch *search;
595  bool skip_filter;
596  int item_index;
597  ListBase *items_list;
598  const char *func_id;
599  } user_data = {nullptr};
600 
601  user_data.search = search;
602  user_data.skip_filter = skip_filter;
603  user_data.items_list = items_list;
604  user_data.func_id = __func__;
605 
607  C,
608  &data->target_ptr,
609  data->target_prop,
610  str,
611  [](void *user_data, const StringPropertySearchVisitParams *visit_params) {
612  const bool show_extra_info = (G.debug_value == 102);
613 
614  SearchVisitUserData *search_data = (struct SearchVisitUserData *)user_data;
615  CollItemSearch *cis = MEM_cnew<CollItemSearch>(search_data->func_id);
616  cis->data = nullptr;
617  if (visit_params->info && show_extra_info) {
618  cis->name = BLI_sprintfN(
619  "%s" UI_SEP_CHAR_S "%s", visit_params->text, visit_params->info);
620  }
621  else {
622  cis->name = BLI_strdup(visit_params->text);
623  }
624  cis->index = search_data->item_index;
625  cis->iconid = ICON_NONE;
626  cis->is_id = false;
627  cis->name_prefix_offset = 0;
628  cis->has_sep_char = visit_params->info != nullptr;
629  if (!search_data->skip_filter) {
630  BLI_string_search_add(search_data->search, visit_params->text, cis, 0);
631  }
632  BLI_addtail(search_data->items_list, cis);
633  search_data->item_index++;
634  },
635  (void *)&user_data);
636 
637  if (search_flag & PROP_STRING_SEARCH_SORT) {
638  BLI_listbase_sort(items_list, [](const void *a_, const void *b_) -> int {
639  const CollItemSearch *cis_a = (const CollItemSearch *)a_;
640  const CollItemSearch *cis_b = (const CollItemSearch *)b_;
641  return BLI_strcasecmp_natural(cis_a->name, cis_b->name);
642  });
643  int i = 0;
644  LISTBASE_FOREACH (CollItemSearch *, cis, items_list) {
645  cis->index = i;
646  i++;
647  }
648  }
649  }
650 
651  if (skip_filter) {
652  LISTBASE_FOREACH (CollItemSearch *, cis, items_list) {
653  if (!add_collection_search_item(cis, requires_exact_data_name, has_id_icon, items)) {
654  break;
655  }
656  }
657  }
658  else {
659  CollItemSearch **filtered_items;
660  int filtered_amount = BLI_string_search_query(search, str, (void ***)&filtered_items);
661 
662  for (int i = 0; i < filtered_amount; i++) {
663  CollItemSearch *cis = filtered_items[i];
664  if (!add_collection_search_item(cis, requires_exact_data_name, has_id_icon, items)) {
665  break;
666  }
667  }
668 
669  MEM_freeN(filtered_items);
670  BLI_string_search_free(search);
671  }
672 
673  LISTBASE_FOREACH (CollItemSearch *, cis, items_list) {
674  MEM_freeN(cis->name);
675  }
676  BLI_freelistN(items_list);
677  MEM_freeN(items_list);
678 }
679 
680 int UI_icon_from_id(const ID *id)
681 {
682  if (id == nullptr) {
683  return ICON_NONE;
684  }
685 
686  /* exception for objects */
687  if (GS(id->name) == ID_OB) {
688  Object *ob = (Object *)id;
689 
690  if (ob->type == OB_EMPTY) {
691  return ICON_EMPTY_DATA;
692  }
693  return UI_icon_from_id(static_cast<const ID *>(ob->data));
694  }
695 
696  /* otherwise get it through RNA, creating the pointer
697  * will set the right type, also with subclassing */
698  PointerRNA ptr;
699  RNA_id_pointer_create((ID *)id, &ptr);
700 
701  return (ptr.type) ? RNA_struct_ui_icon(ptr.type) : ICON_NONE;
702 }
703 
705 {
706  if (type & RPT_ERROR_ALL) {
707  return ICON_CANCEL;
708  }
709  if (type & RPT_WARNING_ALL) {
710  return ICON_ERROR;
711  }
712  if (type & RPT_INFO_ALL) {
713  return ICON_INFO;
714  }
715  if (type & RPT_DEBUG_ALL) {
716  return ICON_SYSTEM;
717  }
718  if (type & RPT_PROPERTY) {
719  return ICON_OPTIONS;
720  }
721  if (type & RPT_OPERATOR) {
722  return ICON_CHECKMARK;
723  }
724  return ICON_INFO;
725 }
726 
728 {
729  if (type & RPT_ERROR_ALL) {
730  return TH_INFO_ERROR;
731  }
732  if (type & RPT_WARNING_ALL) {
733  return TH_INFO_WARNING;
734  }
735  if (type & RPT_INFO_ALL) {
736  return TH_INFO_INFO;
737  }
738  if (type & RPT_DEBUG_ALL) {
739  return TH_INFO_DEBUG;
740  }
741  if (type & RPT_PROPERTY) {
742  return TH_INFO_PROPERTY;
743  }
744  if (type & RPT_OPERATOR) {
745  return TH_INFO_OPERATOR;
746  }
747  return TH_INFO_WARNING;
748 }
749 
751 {
752  if (type & RPT_ERROR_ALL) {
753  return TH_INFO_ERROR_TEXT;
754  }
755  if (type & RPT_WARNING_ALL) {
756  return TH_INFO_WARNING_TEXT;
757  }
758  if (type & RPT_INFO_ALL) {
759  return TH_INFO_INFO_TEXT;
760  }
761  if (type & RPT_DEBUG_ALL) {
762  return TH_INFO_DEBUG_TEXT;
763  }
764  if (type & RPT_PROPERTY) {
765  return TH_INFO_PROPERTY_TEXT;
766  }
767  if (type & RPT_OPERATOR) {
768  return TH_INFO_OPERATOR_TEXT;
769  }
770  return TH_INFO_WARNING_TEXT;
771 }
772 
773 /********************************** Misc **************************************/
774 
775 int UI_calc_float_precision(int prec, double value)
776 {
777  static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {
778  1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6};
779  static const double max_pow = 10000000.0; /* pow(10, UI_PRECISION_FLOAT_MAX) */
780 
782  BLI_assert(fabs(pow10_neg[prec] - pow(10, -prec)) < 1e-16);
783 
784  /* Check on the number of decimal places need to display the number,
785  * this is so 0.00001 is not displayed as 0.00,
786  * _but_, this is only for small values as 10.0001 will not get the same treatment.
787  */
788  value = fabs(value);
789  if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) {
790  int value_i = (int)((value * max_pow) + 0.5);
791  if (value_i != 0) {
792  const int prec_span = 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */
793  int test_prec;
794  int prec_min = -1;
795  int dec_flag = 0;
796  int i = UI_PRECISION_FLOAT_MAX;
797  while (i && value_i) {
798  if (value_i % 10) {
799  dec_flag |= 1 << i;
800  prec_min = i;
801  }
802  value_i /= 10;
803  i--;
804  }
805 
806  /* even though its a small value, if the second last digit is not 0, use it */
807  test_prec = prec_min;
808 
809  dec_flag = (dec_flag >> (prec_min + 1)) & ((1 << prec_span) - 1);
810 
811  while (dec_flag) {
812  test_prec++;
813  dec_flag = dec_flag >> 1;
814  }
815 
816  if (test_prec > prec) {
817  prec = test_prec;
818  }
819  }
820  }
821 
822  CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
823 
824  return prec;
825 }
826 
827 bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength)
828 {
829  if (but->rnapoin.owner_id && but->rnapoin.data && but->rnaprop) {
830  BLI_snprintf(r_str,
831  maxlength,
832  "%s.%s",
835  return true;
836  }
837  if (but->optype) {
838  WM_operator_py_idname(r_str, but->optype->idname);
839  return true;
840  }
841 
842  *r_str = '\0';
843  return false;
844 }
845 
846 bool UI_but_online_manual_id_from_active(const bContext *C, char *r_str, size_t maxlength)
847 {
849 
850  if (but) {
851  return UI_but_online_manual_id(but, r_str, maxlength);
852  }
853 
854  *r_str = '\0';
855  return false;
856 }
857 
858 /* -------------------------------------------------------------------- */
859 
860 static rctf ui_but_rect_to_view(const uiBut *but, const ARegion *region, const View2D *v2d)
861 {
862  rctf region_rect;
863  ui_block_to_region_rctf(region, but->block, &region_rect, &but->rect);
864 
865  rctf view_rect;
866  UI_view2d_region_to_view_rctf(v2d, &region_rect, &view_rect);
867 
868  return view_rect;
869 }
870 
878 static bool ui_view2d_cur_ensure_rect_in_view(View2D *v2d, const rctf *rect)
879 {
880  const float rect_width = BLI_rctf_size_x(rect);
881  const float rect_height = BLI_rctf_size_y(rect);
882 
883  rctf *cur = &v2d->cur;
884  const float cur_width = BLI_rctf_size_x(cur);
885  const float cur_height = BLI_rctf_size_y(cur);
886 
887  bool changed = false;
888 
889  /* Snap to bottom edge. Also use if rect is higher than view bounds (could be a parameter). */
890  if ((cur->ymin > rect->ymin) || (rect_height > cur_height)) {
891  cur->ymin = rect->ymin;
892  cur->ymax = cur->ymin + cur_height;
893  changed = true;
894  }
895  /* Snap to upper edge. */
896  else if (cur->ymax < rect->ymax) {
897  cur->ymax = rect->ymax;
898  cur->ymin = cur->ymax - cur_height;
899  changed = true;
900  }
901  /* Snap to left edge. Also use if rect is wider than view bounds. */
902  else if ((cur->xmin > rect->xmin) || (rect_width > cur_width)) {
903  cur->xmin = rect->xmin;
904  cur->xmax = cur->xmin + cur_width;
905  changed = true;
906  }
907  /* Snap to right edge. */
908  else if (cur->xmax < rect->xmax) {
909  cur->xmax = rect->xmax;
910  cur->xmin = cur->xmax - cur_width;
911  changed = true;
912  }
913  else {
914  BLI_assert(BLI_rctf_inside_rctf(cur, rect));
915  }
916 
917  return changed;
918 }
919 
920 void UI_but_ensure_in_view(const bContext *C, ARegion *region, const uiBut *but)
921 {
922  View2D *v2d = &region->v2d;
923  /* Uninitialized view or region that doesn't use View2D. */
924  if ((v2d->flag & V2D_IS_INIT) == 0) {
925  return;
926  }
927 
928  rctf rect = ui_but_rect_to_view(but, region, v2d);
929 
930  const int margin = UI_UNIT_X * 0.5f;
931  BLI_rctf_pad(&rect, margin, margin);
932 
933  const bool changed = ui_view2d_cur_ensure_rect_in_view(v2d, &rect);
934  if (changed) {
937  }
938 }
939 
940 /* -------------------------------------------------------------------- */
952 struct uiButStore {
953  struct uiButStore *next, *prev;
956 };
957 
961 };
962 
964 {
965  uiButStore *bs_handle = MEM_cnew<uiButStore>(__func__);
966 
967  bs_handle->block = block;
968  BLI_addtail(&block->butstore, bs_handle);
969 
970  return bs_handle;
971 }
972 
973 void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
974 {
975  /* Workaround for button store being moved into new block,
976  * which then can't use the previous buttons state
977  * ('ui_but_update_from_old_block' fails to find a match),
978  * keeping the active button in the old block holding a reference
979  * to the button-state in the new block: see T49034.
980  *
981  * Ideally we would manage moving the 'uiButStore', keeping a correct state.
982  * All things considered this is the most straightforward fix - Campbell.
983  */
984  if (block != bs_handle->block && bs_handle->block != nullptr) {
985  block = bs_handle->block;
986  }
987 
988  BLI_freelistN(&bs_handle->items);
989  BLI_assert(BLI_findindex(&block->butstore, bs_handle) != -1);
990  BLI_remlink(&block->butstore, bs_handle);
991 
992  MEM_freeN(bs_handle);
993 }
994 
996 {
997  return (bs->block != nullptr);
998 }
999 
1001 {
1002  LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
1003  LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
1004  if (*bs_elem->but_p == but) {
1005  return true;
1006  }
1007  }
1008  }
1009 
1010  return false;
1011 }
1012 
1014 {
1015  uiButStoreElem *bs_elem = MEM_cnew<uiButStoreElem>(__func__);
1016  BLI_assert(*but_p);
1017  bs_elem->but_p = but_p;
1018 
1019  BLI_addtail(&bs_handle->items, bs_elem);
1020 }
1021 
1023 {
1024  LISTBASE_FOREACH_MUTABLE (uiButStoreElem *, bs_elem, &bs_handle->items) {
1025  if (bs_elem->but_p == but_p) {
1026  BLI_remlink(&bs_handle->items, bs_elem);
1027  MEM_freeN(bs_elem);
1028  }
1029  }
1030 
1031  BLI_assert(0);
1032 }
1033 
1034 bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src)
1035 {
1036  bool found = false;
1037 
1038  LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
1039  LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
1040  if (*bs_elem->but_p == but_src) {
1041  *bs_elem->but_p = but_dst;
1042  found = true;
1043  }
1044  }
1045  }
1046 
1047  return found;
1048 }
1049 
1051 {
1052  LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
1053  bs_handle->block = nullptr;
1054  LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
1055  *bs_elem->but_p = nullptr;
1056  }
1057  }
1058 }
1059 
1061 {
1062  /* move this list to the new block */
1063  if (block->oldblock) {
1064  if (block->oldblock->butstore.first) {
1065  BLI_movelisttolist(&block->butstore, &block->oldblock->butstore);
1066  }
1067  }
1068 
1069  if (LIKELY(block->butstore.first == nullptr)) {
1070  return;
1071  }
1072 
1073  /* warning, loop-in-loop, in practice we only store <10 buttons at a time,
1074  * so this isn't going to be a problem, if that changes old-new mapping can be cached first */
1075  LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
1076  BLI_assert(ELEM(bs_handle->block, nullptr, block) ||
1077  (block->oldblock && block->oldblock == bs_handle->block));
1078 
1079  if (bs_handle->block == block->oldblock) {
1080  bs_handle->block = block;
1081 
1082  LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
1083  if (*bs_elem->but_p) {
1084  uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p);
1085 
1086  /* can be nullptr if the buttons removed,
1087  * NOTE: we could allow passing in a callback when buttons are removed
1088  * so the caller can cleanup */
1089  *bs_elem->but_p = but_new;
1090  }
1091  }
1092  }
1093  }
1094 }
1095 
void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const struct ID *id, bool add_lib_hint, char separator_char, int *r_prefix_len)
#define MAX_ID_FULL_NAME_UI
Definition: BKE_lib_id.h:551
#define BLI_STATIC_ASSERT(a, msg)
Definition: BLI_assert.h:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_rctf_pad(struct rctf *rect, float pad_x, float pad_y)
Definition: rct.c:615
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
bool BLI_rctf_inside_rctf(const rctf *rct_a, const rctf *rct_b)
Definition: rct.c:192
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:198
int BLI_strcasecmp_natural(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:719
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
void BLI_string_search_add(StringSearch *search, const char *str, void *user_data, int weight)
void BLI_string_search_free(StringSearch *search)
StringSearch * BLI_string_search_new(void)
int BLI_string_search_query(StringSearch *search, const char *query, void ***r_data)
unsigned int uint
Definition: BLI_sys_types.h:67
#define ELEM(...)
#define LIKELY(x)
#define IFACE_(msgid)
int rect_width(int rect[2][2])
Definition: Basic.c:42
int rect_height(int rect[2][2])
Definition: Basic.c:46
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ ID_OB
Definition: DNA_ID_enums.h:47
Object is a sort of wrapper for general info.
@ OB_EMPTY
@ V2D_IS_INIT
#define RPT_ERROR_ALL
#define RPT_INFO_ALL
#define RPT_WARNING_ALL
#define RPT_DEBUG_ALL
void ED_region_tag_redraw_no_rebuild(struct ARegion *region)
Definition: area.c:674
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define RNA_PROP_END
Definition: RNA_access.h:563
#define RNA_STRUCT_BEGIN(sptr, prop)
Definition: RNA_access.h:569
#define RNA_STRUCT_END
Definition: RNA_access.h:589
#define RNA_PROP_BEGIN(sptr, itemptr, prop)
Definition: RNA_access.h:556
eStringPropertySearchFlag
Definition: RNA_types.h:547
@ PROP_STRING_SEARCH_SORT
Definition: RNA_types.h:554
@ PROP_STRING_SEARCH_SUPPORTED
Definition: RNA_types.h:552
PropertyType
Definition: RNA_types.h:58
@ PROP_FLOAT
Definition: RNA_types.h:61
@ PROP_BOOLEAN
Definition: RNA_types.h:59
@ PROP_ENUM
Definition: RNA_types.h:63
@ PROP_INT
Definition: RNA_types.h:60
@ PROP_STRING
Definition: RNA_types.h:62
@ PROP_POINTER
Definition: RNA_types.h:64
@ PROP_COLLECTION
Definition: RNA_types.h:65
@ PROP_ID_SELF_CHECK
Definition: RNA_types.h:232
@ PROP_TEXTEDIT_UPDATE
Definition: RNA_types.h:209
@ PROP_HIDDEN
Definition: RNA_types.h:216
@ PROP_COLOR
Definition: RNA_types.h:153
@ PROP_PERCENTAGE
Definition: RNA_types.h:143
@ PROP_FACTOR
Definition: RNA_types.h:144
@ PROP_COLOR_GAMMA
Definition: RNA_types.h:165
#define C
Definition: RandGen.cpp:25
eAutoPropButsReturn
@ UI_PROP_BUTS_ANY_FAILED_CHECK
@ UI_PROP_BUTS_NONE_ADDED
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.cc:5733
@ UI_BUT_DISABLED
Definition: UI_interface.h:196
@ UI_BUT_HAS_SEP_CHAR
Definition: UI_interface.h:222
@ UI_BUT_VALUE_CLEAR
Definition: UI_interface.h:228
@ UI_BUT_TEXTEDIT_UPDATE
Definition: UI_interface.h:226
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
#define UI_SEP_CHAR
Definition: UI_interface.h:83
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.cc:4806
void uiItemL(uiLayout *layout, const char *name, int icon)
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.cc:5570
uiBut * UI_context_active_but_get(const struct bContext *C)
bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int but_flag, uint8_t name_prefix_offset)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
bool(* uiButIdentityCompareFunc)(const uiBut *a, const uiBut *b)
Definition: UI_interface.h:513
#define UI_PRECISION_FLOAT_MAX
eButLabelAlign
@ UI_BUT_LABEL_ALIGN_SPLIT_COLUMN
@ UI_BUT_LABEL_ALIGN_NONE
@ UI_BUT_LABEL_ALIGN_COLUMN
@ UI_ITEM_R_COMPACT
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:91
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.cc:5280
void UI_block_align_begin(uiBlock *block)
Definition: interface.cc:3910
void uiLayoutSetActivateInit(uiLayout *layout, bool activate_init)
void uiItemFullR(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag, const char *name, int icon)
#define UI_UNIT_X
@ UI_BTYPE_NUM_SLIDER
Definition: UI_interface.h:339
@ UI_BTYPE_TEXT
Definition: UI_interface.h:332
@ UI_BTYPE_LABEL
Definition: UI_interface.h:354
@ UI_BTYPE_SEARCH_MENU
Definition: UI_interface.h:372
@ UI_BTYPE_NUM
Definition: UI_interface.h:337
@ UI_BTYPE_COLOR
Definition: UI_interface.h:349
@ UI_BTYPE_CHECKBOX
Definition: UI_interface.h:347
@ UI_BTYPE_MENU
Definition: UI_interface.h:334
@ UI_BTYPE_ICON_TOGGLE
Definition: UI_interface.h:342
void UI_but_flag_enable(uiBut *but, int flag)
Definition: interface.cc:5858
void UI_block_align_end(uiBlock *block)
Definition: interface.cc:3923
int UI_icon_from_library(const struct ID *id)
@ TH_INFO_PROPERTY_TEXT
Definition: UI_resources.h:324
@ TH_INFO_WARNING_TEXT
Definition: UI_resources.h:318
@ TH_INFO_DEBUG
Definition: UI_resources.h:321
@ TH_INFO_INFO
Definition: UI_resources.h:319
@ TH_INFO_INFO_TEXT
Definition: UI_resources.h:320
@ TH_INFO_PROPERTY
Definition: UI_resources.h:323
@ TH_INFO_DEBUG_TEXT
Definition: UI_resources.h:322
@ TH_INFO_ERROR
Definition: UI_resources.h:315
@ TH_INFO_ERROR_TEXT
Definition: UI_resources.h:316
@ TH_INFO_OPERATOR
Definition: UI_resources.h:325
@ TH_INFO_WARNING
Definition: UI_resources.h:317
@ TH_INFO_OPERATOR_TEXT
Definition: UI_resources.h:326
void UI_view2d_region_to_view_rctf(const struct View2D *v2d, const struct rctf *rect_src, struct rctf *rect_dst) ATTR_NONNULL()
void UI_view2d_curRect_changed(const struct bContext *C, struct View2D *v2d)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
void * user_data
int len
Definition: draw_manager.c:108
#define str(s)
uint col
uiBut * ui_but_find_new(uiBlock *block_new, const uiBut *but_old)
Definition: interface.cc:794
void ui_block_to_region_rctf(const ARegion *region, uiBlock *block, rctf *rct_dst, const rctf *rct_src)
Definition: interface.cc:160
int ui_id_icon_get(const bContext *C, ID *id, const bool big)
uiBut * ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop, bool results_are_suggestions)
int UI_text_colorid_from_report_type(int type)
int UI_icon_from_report_type(int type)
eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr, bool(*check_prop)(PointerRNA *ptr, PropertyRNA *prop, void *user_data), void *user_data, PropertyRNA *prop_activate_init, const eButLabelAlign label_align, const bool compact)
bool UI_butstore_is_valid(uiButStore *bs)
int UI_icon_from_id(const ID *id)
int UI_icon_colorid_from_report_type(int type)
uiBut * uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, const char *name, int icon, int x, int y, int width, int height)
void UI_butstore_update(uiBlock *block)
void uiDefAutoButsArrayR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, const int icon, const int x, const int y, const int tot_width, const int height)
static bool ui_view2d_cur_ensure_rect_in_view(View2D *v2d, const rctf *rect)
void UI_but_func_identity_compare_set(uiBut *but, uiButIdentityCompareFunc cmp_fn)
void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p)
bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src)
static bool add_collection_search_item(CollItemSearch *cis, const bool requires_exact_data_name, const bool has_id_icon, uiSearchItems *items)
void ui_rna_collection_search_update_fn(const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
bool UI_butstore_is_registered(uiBlock *block, uiBut *but)
uiButStore * UI_butstore_create(uiBlock *block)
void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p)
void UI_butstore_clear(uiBlock *block)
static rctf ui_but_rect_to_view(const uiBut *but, const ARegion *region, const View2D *v2d)
bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength)
void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
void UI_but_ensure_in_view(const bContext *C, ARegion *region, const uiBut *but)
int UI_calc_float_precision(int prec, double value)
bool UI_but_online_manual_id_from_active(const bContext *C, char *r_str, size_t maxlength)
#define GS(x)
Definition: iris.c:225
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:26
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
ccl_device_inline float3 pow(float3 v, float e)
Definition: math_float3.h:533
const char * RNA_struct_identifier(const StructRNA *type)
Definition: rna_access.c:586
void RNA_property_string_search(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *edit_text, StringPropertySearchVisitFunc visit_fn, void *visit_user_data)
Definition: rna_access.c:3390
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1080
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
bool RNA_struct_is_ID(const StructRNA *type)
Definition: rna_access.c:655
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1000
eStringPropertySearchFlag RNA_property_string_search_flag(PropertyRNA *prop)
Definition: rna_access.c:3374
char * RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
Definition: rna_access.c:907
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3493
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1405
bool RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
Definition: rna_access.c:1431
int RNA_property_flag(PropertyRNA *prop)
Definition: rna_access.c:1055
int RNA_struct_ui_icon(const StructRNA *type)
Definition: rna_access.c:601
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1075
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1015
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3762
const char * RNA_property_ui_name(const PropertyRNA *prop)
Definition: rna_access.c:1875
struct CollItemSearch * next
struct CollItemSearch * prev
Definition: DNA_ID.h:368
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
void * data
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
short flag
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
uiBlock * oldblock
ListBase butstore
struct uiButStoreElem * prev
struct uiButStoreElem * next
uiBlock * block
struct uiButStore * next
struct uiButStore * prev
ListBase items
uiButIdentityCompareFunc identity_cmp_func
uiBlock * block
struct wmOperatorType * optype
struct PropertyRNA * rnaprop
struct PointerRNA rnapoin
const char * idname
Definition: WM_types.h:890
static int cmp_fn(const void *a, const void *b)
PointerRNA * ptr
Definition: wm_files.c:3480
size_t WM_operator_py_idname(char *dst, const char *src)
Definition: wm_operators.c:110