Blender  V3.3
interface_template_search_menu.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
10 #include <cstdio>
11 #include <cstring>
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "DNA_action_types.h"
17 #include "DNA_node_types.h"
18 #include "DNA_object_types.h"
19 #include "DNA_scene_types.h"
20 #include "DNA_shader_fx_types.h"
21 #include "DNA_texture_types.h"
22 
23 #include "BLI_alloca.h"
24 #include "BLI_dynstr.h"
25 #include "BLI_ghash.h"
26 #include "BLI_linklist.h"
27 #include "BLI_listbase.h"
28 #include "BLI_math_matrix.h"
29 #include "BLI_memarena.h"
30 #include "BLI_string.h"
31 #include "BLI_string_search.h"
32 #include "BLI_string_utils.h"
33 #include "BLI_utildefines.h"
34 
35 #include "BLT_translation.h"
36 
37 #include "BKE_context.h"
38 #include "BKE_global.h"
39 #include "BKE_screen.h"
40 
41 #include "ED_screen.h"
42 
43 #include "RNA_access.h"
44 #include "RNA_prototypes.h"
45 
46 #include "WM_api.h"
47 #include "WM_types.h"
48 
49 #include "UI_interface.h"
50 #include "interface_intern.h"
51 
52 /* For key-map item access. */
53 #include "wm_event_system.h"
54 
55 /* -------------------------------------------------------------------- */
69 
72 };
73 
77  const char *drawstr;
78 
81 };
82 
85  const char *drawstr;
86  const char *drawwstr_full;
88  const char *drawstr_submenu;
89  int icon;
90  int state;
91 
94 
95  enum Type {
96  Operator = 1,
97  RNA = 2,
98  } type;
99 
100  union {
102  struct {
107  } op;
108 
110  struct {
113  int index;
116  } rna;
117  };
118 
121 };
122 
128 
130  struct {
134 };
135 
136 static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v)
137 {
138  const MenuSearch_Item *menu_item_a = (MenuSearch_Item *)menu_item_a_v;
139  const MenuSearch_Item *menu_item_b = (MenuSearch_Item *)menu_item_b_v;
140  return strcmp(menu_item_a->drawwstr_full, menu_item_b->drawwstr_full);
141 }
142 
143 static const char *strdup_memarena(MemArena *memarena, const char *str)
144 {
145  const uint str_size = strlen(str) + 1;
146  char *str_dst = (char *)BLI_memarena_alloc(memarena, str_size);
147  memcpy(str_dst, str, str_size);
148  return str_dst;
149 }
150 
151 static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str)
152 {
153  const uint str_size = BLI_dynstr_get_len(dyn_str) + 1;
154  char *str_dst = (char *)BLI_memarena_alloc(memarena, str_size);
155  BLI_dynstr_get_cstring_ex(dyn_str, str_dst);
156  return str_dst;
157 }
158 
160  MemArena *memarena,
161  struct MenuType *mt,
162  const char *drawstr_submenu,
163  uiBut *but,
164  MenuSearch_Context *wm_context)
165 {
166  MenuSearch_Item *item = nullptr;
167 
168  /* Use override if the name is empty, this can happen with popovers. */
169  const char *drawstr_override = nullptr;
170  const char *drawstr_sep = (but->flag & UI_BUT_HAS_SEP_CHAR) ?
171  strrchr(but->drawstr, UI_SEP_CHAR) :
172  nullptr;
173  const bool drawstr_is_empty = (drawstr_sep == but->drawstr) || (but->drawstr[0] == '\0');
174 
175  if (but->optype != nullptr) {
176  if (drawstr_is_empty) {
177  drawstr_override = WM_operatortype_name(but->optype, but->opptr);
178  }
179 
180  item = (MenuSearch_Item *)BLI_memarena_calloc(memarena, sizeof(*item));
181  item->type = MenuSearch_Item::Type::Operator;
182 
183  item->op.type = but->optype;
184  item->op.opcontext = but->opcontext;
185  item->op.context = but->context;
186  item->op.opptr = but->opptr;
187  but->opptr = nullptr;
188  }
189  else if (but->rnaprop != nullptr) {
190  const int prop_type = RNA_property_type(but->rnaprop);
191 
192  if (drawstr_is_empty) {
193  if (prop_type == PROP_ENUM) {
194  const int value_enum = (int)but->hardmax;
195  EnumPropertyItem enum_item;
197  &but->rnapoin,
198  but->rnaprop,
199  value_enum,
200  &enum_item)) {
201  drawstr_override = enum_item.name;
202  }
203  else {
204  /* Should never happen. */
205  drawstr_override = "Unknown";
206  }
207  }
208  else {
209  drawstr_override = RNA_property_ui_name(but->rnaprop);
210  }
211  }
212 
213  if (!ELEM(prop_type, PROP_BOOLEAN, PROP_ENUM)) {
214  /* Note that these buttons are not prevented,
215  * but aren't typically used in menus. */
216  printf("Button '%s' in menu '%s' is a menu item with unsupported RNA type %d\n",
217  but->drawstr,
218  mt->idname,
219  prop_type);
220  }
221  else {
222  item = (MenuSearch_Item *)BLI_memarena_calloc(memarena, sizeof(*item));
223  item->type = MenuSearch_Item::Type::RNA;
224 
225  item->rna.ptr = but->rnapoin;
226  item->rna.prop = but->rnaprop;
227  item->rna.index = but->rnaindex;
228 
229  if (prop_type == PROP_ENUM) {
230  item->rna.enum_value = (int)but->hardmax;
231  }
232  }
233  }
234 
235  if (item != nullptr) {
236  /* Handle shared settings. */
237  if (drawstr_override != nullptr) {
238  const char *drawstr_suffix = drawstr_sep ? drawstr_sep : "";
239  std::string drawstr = std::string("(") + drawstr_override + ")" + drawstr_suffix;
240  item->drawstr = strdup_memarena(memarena, drawstr.c_str());
241  }
242  else {
243  item->drawstr = strdup_memarena(memarena, but->drawstr);
244  }
245 
246  item->icon = ui_but_icon(but);
247  item->state = (but->flag &
249  item->mt = mt;
250  item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : nullptr;
251 
252  item->wm_context = wm_context;
253 
254  BLI_addtail(&data->items, item);
255  return true;
256  }
257 
258  return false;
259 }
260 
265 {
266  bool changed = false;
267  switch (item->type) {
268  case MenuSearch_Item::Type::Operator: {
269  but->optype = item->op.type;
270  but->opcontext = item->op.opcontext;
271  but->context = item->op.context;
272  but->opptr = item->op.opptr;
273  changed = true;
274  break;
275  }
276  case MenuSearch_Item::Type::RNA: {
277  const int prop_type = RNA_property_type(item->rna.prop);
278 
279  but->rnapoin = item->rna.ptr;
280  but->rnaprop = item->rna.prop;
281  but->rnaindex = item->rna.index;
282 
283  if (prop_type == PROP_ENUM) {
284  but->hardmax = item->rna.enum_value;
285  }
286  changed = true;
287  break;
288  }
289  }
290 
291  if (changed) {
292  STRNCPY(but->drawstr, item->drawstr);
293  char *drawstr_sep = (item->state & UI_BUT_HAS_SEP_CHAR) ? strrchr(but->drawstr, UI_SEP_CHAR) :
294  nullptr;
295  if (drawstr_sep) {
296  *drawstr_sep = '\0';
297  }
298 
299  but->icon = (BIFIconID)item->icon;
300  but->str = but->strdata;
301  }
302 
303  return changed;
304 }
305 
310  wmWindow *win,
311  ScrArea *area,
312  ARegion *region,
313  LinkNode **menuid_stack_p,
314  GHash *menu_to_kmi,
315  GSet *menu_tagged)
316 {
318  ListBase *handlers[] = {
319  region ? &region->handlers : nullptr,
320  area ? &area->handlers : nullptr,
321  &win->handlers,
322  };
323 
324  for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) {
325  if (handlers[handler_index] == nullptr) {
326  continue;
327  }
328  LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers[handler_index]) {
329  /* During this loop, UI handlers for nested menus can tag multiple handlers free. */
330  if (handler_base->flag & WM_HANDLER_DO_FREE) {
331  continue;
332  }
333  if (handler_base->type != WM_HANDLER_TYPE_KEYMAP) {
334  continue;
335  }
336 
337  if (handler_base->poll == nullptr || handler_base->poll(region, win->eventstate)) {
338  wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base;
339  wmEventHandler_KeymapResult km_result;
340  WM_event_get_keymaps_from_handler(wm, win, handler, &km_result);
341  for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) {
342  wmKeyMap *keymap = km_result.keymaps[km_index];
343  if (keymap && WM_keymap_poll(C, keymap)) {
344  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
345  if (kmi->flag & KMI_INACTIVE) {
346  continue;
347  }
348  if (STR_ELEM(kmi->idname, "WM_OT_call_menu", "WM_OT_call_menu_pie")) {
349  char menu_idname[MAX_NAME];
350  RNA_string_get(kmi->ptr, "name", menu_idname);
351  MenuType *mt = WM_menutype_find(menu_idname, false);
352 
353  if (mt && BLI_gset_add(menu_tagged, mt)) {
354  /* Unlikely, but possible this will be included twice. */
355  BLI_linklist_prepend(menuid_stack_p, mt);
356 
357  void **kmi_p;
358  if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) {
359  *kmi_p = kmi;
360  }
361  }
362  }
363  }
364  }
365  }
366  }
367  }
368  }
369 }
370 
375 {
376  /* Add to temporary list so we can sort them separately. */
377  ListBase operator_items = {nullptr, nullptr};
378 
379  MemArena *memarena = data->memarena;
380  GHashIterator iter;
381  for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter);
382  BLI_ghashIterator_step(&iter)) {
384 
385  if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) {
386  continue;
387  }
388 
389  if (WM_operator_poll((bContext *)C, ot)) {
390  const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name);
391 
392  MenuSearch_Item *item = nullptr;
393  item = (MenuSearch_Item *)BLI_memarena_calloc(memarena, sizeof(*item));
394  item->type = MenuSearch_Item::Type::Operator;
395 
396  item->op.type = ot;
397  item->op.opcontext = WM_OP_INVOKE_DEFAULT;
398  item->op.context = nullptr;
399 
400  char idname_as_py[OP_MAX_TYPENAME];
401  char uiname[256];
402  WM_operator_py_idname(idname_as_py, ot->idname);
403 
404  SNPRINTF(uiname, "%s " UI_MENU_ARROW_SEP "%s", idname_as_py, ot_ui_name);
405 
406  item->drawwstr_full = strdup_memarena(memarena, uiname);
407  item->drawstr = ot_ui_name;
408 
409  item->wm_context = nullptr;
410 
411  BLI_addtail(&operator_items, item);
412  }
413  }
414 
416 
417  BLI_movelisttolist(&data->items, &operator_items);
418 }
419 
427  bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas)
428 {
429  MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
431  GHash *menu_parent_map = BLI_ghash_ptr_new(__func__);
432  GHash *menu_display_name_map = BLI_ghash_ptr_new(__func__);
433  const uiStyle *style = UI_style_get_dpi();
434 
435  /* Convert into non-ui structure. */
436  MenuSearch_Data *data = (MenuSearch_Data *)MEM_callocN(sizeof(*data), __func__);
437 
438  DynStr *dyn_str = BLI_dynstr_new_memarena();
439 
440  /* Use a stack of menus to handle and discover new menus in passes. */
441  LinkNode *menu_stack = nullptr;
442 
443  /* Tag menu types not to add, either because they have already been added
444  * or they have been blacklisted.
445  * Set of #MenuType. */
446  GSet *menu_tagged = BLI_gset_ptr_new(__func__);
448  GHash *menu_to_kmi = BLI_ghash_ptr_new(__func__);
449 
450  /* Blacklist menus we don't want to show. */
451  {
452  const char *idname_array[] = {
453  /* While we could include this, it's just showing filenames to load. */
454  "TOPBAR_MT_file_open_recent",
455  /* Showing undo history is not helpful since users may accidentally undo
456  * an action they intend to run. */
457  "TOPBAR_MT_undo_history",
458  };
459  for (int i = 0; i < ARRAY_SIZE(idname_array); i++) {
460  MenuType *mt = WM_menutype_find(idname_array[i], false);
461  if (mt != nullptr) {
462  BLI_gset_add(menu_tagged, mt);
463  }
464  }
465  }
466 
467  {
468  /* Exclude context menus because:
469  * - The menu items are available elsewhere (and will show up multiple times).
470  * - Menu items depend on exact context, making search results unpredictable
471  * (exact number of items selected for example). See design doc T74158.
472  * There is one exception,
473  * as the outliner only exposes functionality via the context menu. */
474  GHashIterator iter;
475 
476  for (WM_menutype_iter(&iter); (!BLI_ghashIterator_done(&iter));
477  (BLI_ghashIterator_step(&iter))) {
479  if (BLI_str_endswith(mt->idname, "_context_menu")) {
480  BLI_gset_add(menu_tagged, mt);
481  }
482  }
483  const char *idname_array[] = {
484  /* Add back some context menus. */
485  "OUTLINER_MT_context_menu",
486  };
487  for (int i = 0; i < ARRAY_SIZE(idname_array); i++) {
488  MenuType *mt = WM_menutype_find(idname_array[i], false);
489  if (mt != nullptr) {
490  BLI_gset_remove(menu_tagged, mt, nullptr);
491  }
492  }
493  }
494 
495  /* Collect contexts, one for each 'ui_type'. */
496  MenuSearch_Context *wm_contexts = nullptr;
497 
498  const EnumPropertyItem *space_type_ui_items = nullptr;
499  int space_type_ui_items_len = 0;
500  bool space_type_ui_items_free = false;
501 
502  /* Text used as prefix for top-bar menu items. */
503  const char *global_menu_prefix = nullptr;
504 
505  if (include_all_areas) {
506  bScreen *screen = WM_window_get_active_screen(win);
507 
508  /* First create arrays for ui_type. */
509  PropertyRNA *prop_ui_type = nullptr;
510  {
511  /* This must be a valid pointer, with only it's type checked. */
512  ScrArea area_dummy = {nullptr};
513  /* Anything besides #SPACE_EMPTY is fine,
514  * as this value is only included in the enum when set. */
515  area_dummy.spacetype = SPACE_TOPBAR;
516  PointerRNA ptr;
517  RNA_pointer_create(&screen->id, &RNA_Area, &area_dummy, &ptr);
518  prop_ui_type = RNA_struct_find_property(&ptr, "ui_type");
520  &ptr,
521  prop_ui_type,
522  &space_type_ui_items,
523  &space_type_ui_items_len,
524  &space_type_ui_items_free);
525 
526  wm_contexts = (MenuSearch_Context *)BLI_memarena_calloc(
527  memarena, sizeof(*wm_contexts) * space_type_ui_items_len);
528  for (int i = 0; i < space_type_ui_items_len; i++) {
529  wm_contexts[i].space_type_ui_index = -1;
530  }
531  }
532 
533  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
535  if (region != nullptr) {
536  PointerRNA ptr;
537  RNA_pointer_create(&screen->id, &RNA_Area, area, &ptr);
538  const int space_type_ui = RNA_property_enum_get(&ptr, prop_ui_type);
539 
540  const int space_type_ui_index = RNA_enum_from_value(space_type_ui_items, space_type_ui);
541  if (space_type_ui_index == -1) {
542  continue;
543  }
544 
545  if (wm_contexts[space_type_ui_index].space_type_ui_index != -1) {
546  ScrArea *area_best = wm_contexts[space_type_ui_index].area;
547  const uint value_best = (uint)area_best->winx * (uint)area_best->winy;
548  const uint value_test = (uint)area->winx * (uint)area->winy;
549  if (value_best > value_test) {
550  continue;
551  }
552  }
553 
554  wm_contexts[space_type_ui_index].space_type_ui_index = space_type_ui_index;
555  wm_contexts[space_type_ui_index].area = area;
556  wm_contexts[space_type_ui_index].region = region;
557  }
558  }
559 
560  global_menu_prefix = CTX_IFACE_(RNA_property_translation_context(prop_ui_type), "Top Bar");
561  }
562 
563  GHashIterator iter;
564 
565  for (int space_type_ui_index = -1; space_type_ui_index < space_type_ui_items_len;
566  space_type_ui_index += 1) {
567 
568  ScrArea *area = nullptr;
569  ARegion *region = nullptr;
570  MenuSearch_Context *wm_context = nullptr;
571 
572  if (include_all_areas) {
573  if (space_type_ui_index == -1) {
574  /* First run without any context, to populate the top-bar without. */
575  wm_context = nullptr;
576  area = nullptr;
577  region = nullptr;
578  }
579  else {
580  wm_context = &wm_contexts[space_type_ui_index];
581  if (wm_context->space_type_ui_index == -1) {
582  continue;
583  }
584 
585  area = wm_context->area;
586  region = wm_context->region;
587 
589  CTX_wm_region_set(C, region);
590  }
591  }
592  else {
593  area = area_init;
594  region = region_init;
595  }
596 
597  /* Populate menus from the editors,
598  * note that we could create a fake header, draw the header and extract the menus
599  * from the buttons, however this is quite involved and can be avoided as by convention
600  * each space-type has a single root-menu that headers use. */
601  {
602  const char *idname_array[2] = {nullptr};
603  int idname_array_len = 0;
604 
605  /* Use negative for global (no area) context, populate the top-bar. */
606  if (space_type_ui_index == -1) {
607  idname_array[idname_array_len++] = "TOPBAR_MT_editor_menus";
608  }
609 
610 #define SPACE_MENU_MAP(space_type, menu_id) \
611  case space_type: \
612  idname_array[idname_array_len++] = menu_id; \
613  break
614 #define SPACE_MENU_NOP(space_type) \
615  case space_type: \
616  break
617 
618  if (area != nullptr) {
619  SpaceLink *sl = (SpaceLink *)area->spacedata.first;
620  switch ((eSpace_Type)area->spacetype) {
621  SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus");
622  SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus");
623  SPACE_MENU_MAP(SPACE_OUTLINER, "OUTLINER_MT_editor_menus");
625  SPACE_MENU_MAP(SPACE_FILE, "FILEBROWSER_MT_editor_menus");
626  SPACE_MENU_MAP(SPACE_IMAGE, "IMAGE_MT_editor_menus");
627  SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus");
628  SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus");
629  SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus");
631  (((const SpaceAction *)sl)->mode == SACTCONT_TIMELINE) ?
632  "TIME_MT_editor_menus" :
633  "DOPESHEET_MT_editor_menus");
634  SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus");
635  SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus");
636  SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus");
637  SPACE_MENU_MAP(SPACE_USERPREF, "USERPREF_MT_editor_menus");
639  (((const SpaceClip *)sl)->mode == SC_MODE_TRACKING) ?
640  "CLIP_MT_tracking_editor_menus" :
641  "CLIP_MT_masking_editor_menus");
647  }
648  }
649  for (int i = 0; i < idname_array_len; i++) {
650  MenuType *mt = WM_menutype_find(idname_array[i], false);
651  if (mt != nullptr) {
652  /* Check if this exists because of 'include_all_areas'. */
653  if (BLI_gset_add(menu_tagged, mt)) {
654  BLI_linklist_prepend(&menu_stack, mt);
655  }
656  }
657  }
658  }
659 #undef SPACE_MENU_MAP
660 #undef SPACE_MENU_NOP
661 
662  bool has_keymap_menu_items = false;
663 
664  while (menu_stack != nullptr) {
665  MenuType *mt = (MenuType *)BLI_linklist_pop(&menu_stack);
666  if (!WM_menutype_poll(C, mt)) {
667  continue;
668  }
669 
670  uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
671  uiLayout *layout = UI_block_layout(
672  block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
673 
675 
677  UI_menutype_draw(C, mt, layout);
678 
679  UI_block_end(C, block);
680 
681  LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
682  MenuType *mt_from_but = nullptr;
683  /* Support menu titles with dynamic from initial labels
684  * (used by edit-mesh context menu). */
685  if (but->type == UI_BTYPE_LABEL) {
686 
687  /* Check if the label is the title. */
688  uiBut *but_test = but->prev;
689  while (but_test && but_test->type == UI_BTYPE_SEPR) {
690  but_test = but_test->prev;
691  }
692 
693  if (but_test == nullptr) {
695  menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr));
696  }
697  }
699  data, memarena, mt, nullptr, but, wm_context)) {
700  /* pass */
701  }
702  else if ((mt_from_but = UI_but_menutype_get(but))) {
703 
704  if (BLI_gset_add(menu_tagged, mt_from_but)) {
705  BLI_linklist_prepend(&menu_stack, mt_from_but);
706  }
707 
708  if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) {
710  memarena, sizeof(*menu_parent));
711  /* Use brackets for menu key shortcuts,
712  * converting "Text|Some-Shortcut" to "Text (Some-Shortcut)".
713  * This is needed so we don't right align sub-menu contents
714  * we only want to do that for the last menu item, not the path that leads to it.
715  */
716  const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ?
717  strrchr(but->drawstr, UI_SEP_CHAR) :
718  nullptr;
719  bool drawstr_is_empty = false;
720  if (drawstr_sep != nullptr) {
721  BLI_assert(BLI_dynstr_get_len(dyn_str) == 0);
722  /* Detect empty string, fallback to menu name. */
723  const char *drawstr = but->drawstr;
724  int drawstr_len = drawstr_sep - but->drawstr;
725  if (UNLIKELY(drawstr_len == 0)) {
726  drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label);
727  drawstr_len = strlen(drawstr);
728  if (drawstr[0] == '\0') {
729  drawstr_is_empty = true;
730  }
731  }
732  BLI_dynstr_nappend(dyn_str, drawstr, drawstr_len);
733  BLI_dynstr_appendf(dyn_str, " (%s)", drawstr_sep + 1);
734  menu_parent->drawstr = strdup_memarena_from_dynstr(memarena, dyn_str);
735  BLI_dynstr_clear(dyn_str);
736  }
737  else {
738  const char *drawstr = but->drawstr;
739  if (UNLIKELY(drawstr[0] == '\0')) {
740  drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label);
741  if (drawstr[0] == '\0') {
742  drawstr_is_empty = true;
743  }
744  }
745  menu_parent->drawstr = strdup_memarena(memarena, drawstr);
746  }
747  menu_parent->parent_mt = mt;
748  BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent);
749 
750  if (drawstr_is_empty) {
751  printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname);
752  }
753  }
754  }
755  else if (but->menu_create_func != nullptr) {
756  /* A non 'MenuType' menu button. */
757 
758  /* Only expand one level deep, this is mainly for expanding operator menus. */
759  const char *drawstr_submenu = but->drawstr;
760 
761  /* +1 to avoid overlap with the current 'block'. */
762  uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS);
763  uiLayout *sub_layout = UI_block_layout(
764  sub_block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
765 
767 
769 
770  but->menu_create_func(C, sub_layout, but->poin);
771 
772  UI_block_end(C, sub_block);
773 
774  LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) {
776  data, memarena, mt, drawstr_submenu, sub_but, wm_context);
777  }
778 
779  if (region) {
780  BLI_ghash_remove(region->runtime.block_name_map, sub_block->name, nullptr, nullptr);
781  BLI_remlink(&region->uiblocks, sub_block);
782  }
783  UI_block_free(nullptr, sub_block);
784  }
785  }
786  if (region) {
787  BLI_ghash_remove(region->runtime.block_name_map, block->name, nullptr, nullptr);
788  BLI_remlink(&region->uiblocks, block);
789  }
790  UI_block_free(nullptr, block);
791 
792  /* Add key-map items as a second pass,
793  * so all menus are accessed from the header & top-bar before key shortcuts are expanded. */
794  if ((menu_stack == nullptr) && (has_keymap_menu_items == false)) {
795  has_keymap_menu_items = true;
797  C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged);
798  }
799  }
800  }
801 
802  LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
803  item->menu_parent = (MenuSearch_Parent *)BLI_ghash_lookup(menu_parent_map, item->mt);
804  }
805 
806  GHASH_ITER (iter, menu_parent_map) {
808  menu_parent->parent = (MenuSearch_Parent *)BLI_ghash_lookup(menu_parent_map,
809  menu_parent->parent_mt);
810  }
811 
812  /* NOTE: currently this builds the full path for each menu item,
813  * that could be moved into the parent menu. */
814 
815  /* Set names as full paths. */
816  LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
817  BLI_assert(BLI_dynstr_get_len(dyn_str) == 0);
818 
819  if (include_all_areas) {
820  BLI_dynstr_appendf(dyn_str,
821  "%s: ",
822  (item->wm_context != nullptr) ?
823  space_type_ui_items[item->wm_context->space_type_ui_index].name :
824  global_menu_prefix);
825  }
826 
827  if (item->menu_parent != nullptr) {
828  MenuSearch_Parent *menu_parent = item->menu_parent;
829  menu_parent->temp_child = nullptr;
830  while (menu_parent && menu_parent->parent) {
831  menu_parent->parent->temp_child = menu_parent;
832  menu_parent = menu_parent->parent;
833  }
834  while (menu_parent) {
835  BLI_dynstr_append(dyn_str, menu_parent->drawstr);
836  BLI_dynstr_append(dyn_str, " " UI_MENU_ARROW_SEP " ");
837  menu_parent = menu_parent->temp_child;
838  }
839  }
840  else {
841  const char *drawstr = (const char *)BLI_ghash_lookup(menu_display_name_map, item->mt);
842  if (drawstr == nullptr) {
843  drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label);
844  }
845  BLI_dynstr_append(dyn_str, drawstr);
846 
847  wmKeyMapItem *kmi = (wmKeyMapItem *)BLI_ghash_lookup(menu_to_kmi, item->mt);
848  if (kmi != nullptr) {
849  char kmi_str[128];
850  WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str));
851  BLI_dynstr_appendf(dyn_str, " (%s)", kmi_str);
852  }
853 
854  BLI_dynstr_append(dyn_str, " " UI_MENU_ARROW_SEP " ");
855  }
856 
857  /* Optional nested menu. */
858  if (item->drawstr_submenu != nullptr) {
859  BLI_dynstr_append(dyn_str, item->drawstr_submenu);
860  BLI_dynstr_append(dyn_str, " " UI_MENU_ARROW_SEP " ");
861  }
862 
863  BLI_dynstr_append(dyn_str, item->drawstr);
864 
865  item->drawwstr_full = strdup_memarena_from_dynstr(memarena, dyn_str);
866  BLI_dynstr_clear(dyn_str);
867  }
868  BLI_dynstr_free(dyn_str);
869 
870  /* Finally sort menu items.
871  *
872  * NOTE: we might want to keep the in-menu order, for now sort all. */
874 
875  BLI_ghash_free(menu_parent_map, nullptr, nullptr);
876  BLI_ghash_free(menu_display_name_map, nullptr, nullptr);
877 
878  BLI_ghash_free(menu_to_kmi, nullptr, nullptr);
879 
880  BLI_gset_free(menu_tagged, nullptr);
881 
882  data->memarena = memarena;
883 
884  if (include_all_areas) {
885  CTX_wm_area_set(C, area_init);
886  CTX_wm_region_set(C, region_init);
887 
888  if (space_type_ui_items_free) {
889  MEM_freeN((void *)space_type_ui_items);
890  }
891  }
892 
893  /* Include all operators for developers,
894  * since it can be handy to have a quick way to access any operator,
895  * including operators being developed which haven't yet been added into the interface.
896  *
897  * These are added after all menu items so developers still get normal behavior by default,
898  * unless searching for something that isn't already in a menu (or scroll down).
899  *
900  * Keep this behind a developer only check:
901  * - Many operators need options to be set to give useful results, see: T74157.
902  * - User who really prefer to list all operators can use #WM_OT_search_operator.
903  */
904  if (U.flag & USER_DEVELOPER_UI) {
906  }
907 
908  return data;
909 }
910 
911 static void menu_search_arg_free_fn(void *data_v)
912 {
913  MenuSearch_Data *data = (MenuSearch_Data *)data_v;
914  LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
915  switch (item->type) {
916  case MenuSearch_Item::Type::Operator: {
917  if (item->op.opptr != nullptr) {
918  WM_operator_properties_free(item->op.opptr);
919  MEM_freeN(item->op.opptr);
920  }
921  }
922  case MenuSearch_Item::Type::RNA: {
923  break;
924  }
925  }
926  }
927 
928  BLI_memarena_free(data->memarena);
929 
930  MEM_freeN(data);
931 }
932 
933 static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
934 {
935  MenuSearch_Item *item = (MenuSearch_Item *)arg2;
936  if (item == nullptr) {
937  return;
938  }
939  if (item->state & UI_BUT_DISABLED) {
940  return;
941  }
942 
943  ScrArea *area_prev = CTX_wm_area(C);
944  ARegion *region_prev = CTX_wm_region(C);
945 
946  if (item->wm_context != nullptr) {
947  CTX_wm_area_set(C, item->wm_context->area);
949  }
950 
951  switch (item->type) {
952  case MenuSearch_Item::Type::Operator: {
953  CTX_store_set(C, item->op.context);
955  C, item->op.type, item->op.opcontext, item->op.opptr, nullptr, item->drawstr);
956  CTX_store_set(C, nullptr);
957  break;
958  }
959  case MenuSearch_Item::Type::RNA: {
960  PointerRNA *ptr = &item->rna.ptr;
961  PropertyRNA *prop = item->rna.prop;
962  const int index = item->rna.index;
963  const int prop_type = RNA_property_type(prop);
964  bool changed = false;
965 
966  if (prop_type == PROP_BOOLEAN) {
967  const bool is_array = RNA_property_array_check(prop);
968  if (is_array) {
969  const bool value = RNA_property_boolean_get_index(ptr, prop, index);
970  RNA_property_boolean_set_index(ptr, prop, index, !value);
971  }
972  else {
973  const bool value = RNA_property_boolean_get(ptr, prop);
974  RNA_property_boolean_set(ptr, prop, !value);
975  }
976  changed = true;
977  }
978  else if (prop_type == PROP_ENUM) {
979  RNA_property_enum_set(ptr, prop, item->rna.enum_value);
980  changed = true;
981  }
982 
983  if (changed) {
984  RNA_property_update(C, ptr, prop);
985  }
986  break;
987  }
988  }
989 
990  if (item->wm_context != nullptr) {
991  CTX_wm_area_set(C, area_prev);
992  CTX_wm_region_set(C, region_prev);
993  }
994 }
995 
997  void *arg,
998  const char *str,
999  uiSearchItems *items,
1000  const bool UNUSED(is_first))
1001 {
1003 
1004  StringSearch *search = BLI_string_search_new();
1005 
1006  LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
1007  BLI_string_search_add(search, item->drawwstr_full, item, 0);
1008  }
1009 
1010  MenuSearch_Item **filtered_items;
1011  const int filtered_amount = BLI_string_search_query(search, str, (void ***)&filtered_items);
1012 
1013  for (int i = 0; i < filtered_amount; i++) {
1014  MenuSearch_Item *item = filtered_items[i];
1015  if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state, 0)) {
1016  break;
1017  }
1018  }
1019 
1020  MEM_freeN(filtered_items);
1021  BLI_string_search_free(search);
1022 }
1023 
1026 /* -------------------------------------------------------------------- */
1035  void *arg,
1036  void *active,
1037  const struct wmEvent *event)
1038 {
1041  bool has_menu = false;
1042 
1043  memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data));
1044  uiBut *but = &data->context_menu_data.but;
1045  uiBlock *block = &data->context_menu_data.block;
1046 
1047  but->block = block;
1048 
1049  if (menu_items_to_ui_button(item, but)) {
1050  ScrArea *area_prev = CTX_wm_area(C);
1051  ARegion *region_prev = CTX_wm_region(C);
1052 
1053  if (item->wm_context != nullptr) {
1054  CTX_wm_area_set(C, item->wm_context->area);
1056  }
1057 
1058  if (ui_popup_context_menu_for_button(C, but, event)) {
1059  has_menu = true;
1060  }
1061 
1062  if (item->wm_context != nullptr) {
1063  CTX_wm_area_set(C, area_prev);
1064  CTX_wm_region_set(C, region_prev);
1065  }
1066  }
1067 
1068  return has_menu;
1069 }
1070 
1073 /* -------------------------------------------------------------------- */
1078  struct ARegion *region,
1079  const rcti *UNUSED(item_rect),
1080  void *arg,
1081  void *active)
1082 {
1085 
1086  memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data));
1087  uiBut *but = &data->context_menu_data.but;
1088  uiBlock *block = &data->context_menu_data.block;
1089  unit_m4(block->winmat);
1090  block->aspect = 1;
1091 
1092  but->block = block;
1093 
1094  /* Place the fake button at the cursor so the tool-tip is places properly. */
1095  float tip_init[2];
1096  const wmEvent *event = CTX_wm_window(C)->eventstate;
1097  tip_init[0] = event->xy[0];
1098  tip_init[1] = event->xy[1] - (UI_UNIT_Y / 2);
1099  ui_window_to_block_fl(region, block, &tip_init[0], &tip_init[1]);
1100 
1101  but->rect.xmin = tip_init[0];
1102  but->rect.xmax = tip_init[0];
1103  but->rect.ymin = tip_init[1];
1104  but->rect.ymax = tip_init[1];
1105 
1106  if (menu_items_to_ui_button(item, but)) {
1107  ScrArea *area_prev = CTX_wm_area(C);
1108  ARegion *region_prev = CTX_wm_region(C);
1109 
1110  if (item->wm_context != nullptr) {
1111  CTX_wm_area_set(C, item->wm_context->area);
1113  }
1114 
1115  ARegion *region_tip = UI_tooltip_create_from_button(C, region, but, false);
1116 
1117  if (item->wm_context != nullptr) {
1118  CTX_wm_area_set(C, area_prev);
1119  CTX_wm_region_set(C, region_prev);
1120  }
1121  return region_tip;
1122  }
1123 
1124  return nullptr;
1125 }
1126 
1129 /* -------------------------------------------------------------------- */
1134 {
1135  bContext *C = (bContext *)but->block->evil_C;
1136  wmWindow *win = CTX_wm_window(C);
1137  ScrArea *area = CTX_wm_area(C);
1138  ARegion *region = CTX_wm_region(C);
1139  /* When run from top-bar scan all areas in the current window. */
1140  const bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR));
1141  MenuSearch_Data *data = menu_items_from_ui_create(C, win, area, region, include_all_areas);
1143  /* Generic callback. */
1146  data,
1147  false,
1150  nullptr);
1151 
1155 }
1156 
1158 {
1159  uiBlock *block;
1160  uiBut *but;
1161  static char search[256] = "";
1162 
1163  block = uiLayoutGetBlock(layout);
1164  UI_block_layout_set_current(block, layout);
1165 
1166  but = uiDefSearchBut(
1167  block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, "");
1169 }
1170 
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
void CTX_store_set(bContext *C, bContextStore *store)
Definition: context.c:188
void CTX_wm_region_set(bContext *C, struct ARegion *region)
Definition: context.c:1009
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
void CTX_wm_area_set(bContext *C, struct ScrArea *area)
Definition: context.c:997
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
@ G_DEBUG_WM
Definition: BKE_global.h:179
struct ARegion * BKE_area_find_region_type(const struct ScrArea *area, int type)
#define BLI_assert(a)
Definition: BLI_assert.h:46
A dynamically sized string ADT.
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL()
Definition: BLI_dynstr.c:94
int BLI_dynstr_get_len(const DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:235
void BLI_dynstr_clear(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:263
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:281
DynStr * BLI_dynstr_new_memarena(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:60
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_dynstr_get_cstring_ex(const DynStr *__restrict ds, char *__restrict rets) ATTR_NONNULL()
Definition: BLI_dynstr.c:240
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:75
struct GSet GSet
Definition: BLI_ghash.h:340
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:822
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition: BLI_ghash.c:914
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:302
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:321
GSet * BLI_gset_ptr_new(const char *info)
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:734
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:790
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:755
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:969
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:310
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1002
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
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
void unit_m4(float m[4][4])
Definition: rct.c:1090
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:94
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:64
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:20
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:116
void * BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:153
#define STR_ELEM(...)
Definition: BLI_string.h:539
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:485
bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL()
Definition: string.c:887
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 ARRAY_SIZE(arr)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define CTX_IFACE_(context, msgid)
@ SACTCONT_TIMELINE
#define MAX_NAME
Definition: DNA_defs.h:48
Object is a sort of wrapper for general info.
@ RGN_TYPE_WINDOW
eSpace_Type
@ SPACE_TEXT
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_CONSOLE
@ SPACE_OUTLINER
@ SPACE_STATUSBAR
@ SPACE_TOPBAR
@ SPACE_NODE
@ SPACE_SPREADSHEET
@ SPACE_USERPREF
@ SPACE_FILE
@ SPACE_PROPERTIES
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_SCRIPT
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
@ SPACE_INFO
@ SC_MODE_TRACKING
@ USER_DEVELOPER_UI
#define OP_MAX_TYPENAME
Read Guarded memory(de)allocation.
@ PROP_BOOLEAN
Definition: RNA_types.h:59
@ PROP_ENUM
Definition: RNA_types.h:63
#define C
Definition: RandGen.cpp:25
@ UI_LAYOUT_VERTICAL
#define UI_UNIT_Y
uiBlock * uiLayoutGetBlock(uiLayout *layout)
@ UI_BUT_REDALERT
Definition: UI_interface.h:201
@ UI_BUT_DISABLED
Definition: UI_interface.h:196
@ UI_BUT_INACTIVE
Definition: UI_interface.h:203
@ UI_BUT_HAS_SEP_CHAR
Definition: UI_interface.h:222
@ UI_EMBOSS
Definition: UI_interface.h:108
const struct uiStyle * UI_style_get_dpi(void)
struct ARegion * UI_tooltip_create_from_button(struct bContext *C, struct ARegion *butregion, uiBut *but, bool is_label)
void UI_menutype_draw(struct bContext *C, struct MenuType *mt, struct uiLayout *layout)
#define UI_SEP_CHAR
Definition: UI_interface.h:83
void UI_but_func_search_set(uiBut *but, uiButSearchCreateFn search_create_fn, uiButSearchUpdateFn search_update_fn, void *arg, bool free_arg, uiFreeArgFunc search_arg_free_fn, uiButHandleFunc search_exec_fn, void *active)
Definition: interface.cc:6242
bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int but_flag, uint8_t name_prefix_offset)
@ UI_LAYOUT_MENU
void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn)
Definition: interface.cc:6316
void UI_block_end(const struct bContext *C, uiBlock *block)
void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn)
Definition: interface.cc:6300
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const struct uiStyle *style)
struct MenuType * UI_but_menutype_get(uiBut *but)
void UI_block_free(const struct bContext *C, uiBlock *block)
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
Definition: interface.cc:6308
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
uiBut * uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, int x, int y, short width, short height, float a1, float a2, const char *tip)
Definition: interface.cc:6217
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
#define UI_UNIT_X
void UI_block_flag_enable(uiBlock *block, int flag)
Definition: interface.cc:5848
@ UI_BTYPE_LABEL
Definition: UI_interface.h:354
@ UI_BTYPE_SEPR
Definition: UI_interface.h:385
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
@ UI_BLOCK_SHOW_SHORTCUT_ALWAYS
Definition: UI_interface.h:160
BIFIconID
Definition: UI_resources.h:18
@ WM_HANDLER_DO_FREE
Definition: WM_api.h:435
@ OPTYPE_INTERNAL
Definition: WM_types.h:168
wmOperatorCallContext
Definition: WM_types.h:199
@ WM_OP_INVOKE_REGION_WIN
Definition: WM_types.h:202
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:201
unsigned int U
Definition: btGjkEpa3.h:78
#define str(s)
void ui_window_to_block_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
Definition: interface.cc:191
bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *event)
#define UI_MENU_PADDING
struct ARegion * ui_searchbox_create_menu(struct bContext *C, struct ARegion *butregion, uiButSearch *search_but)
int ui_but_icon(const uiBut *but)
static const char * strdup_memarena(MemArena *memarena, const char *str)
static void menu_items_from_all_operators(bContext *C, MenuSearch_Data *data)
static const char * strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str)
static bool menu_items_to_ui_button(MenuSearch_Item *item, uiBut *but)
static void menu_types_add_from_keymap_items(bContext *C, wmWindow *win, ScrArea *area, ARegion *region, LinkNode **menuid_stack_p, GHash *menu_to_kmi, GSet *menu_tagged)
static struct ARegion * ui_search_menu_create_tooltip(struct bContext *C, struct ARegion *region, const rcti *UNUSED(item_rect), void *arg, void *active)
static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
void UI_but_func_menu_search(uiBut *but)
void uiTemplateMenuSearch(uiLayout *layout)
#define SPACE_MENU_NOP(space_type)
static void menu_search_update_fn(const bContext *UNUSED(C), void *arg, const char *str, uiSearchItems *items, const bool UNUSED(is_first))
static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v)
#define SPACE_MENU_MAP(space_type, menu_id)
static bool menu_items_from_ui_create_item_from_button(MenuSearch_Data *data, MemArena *memarena, struct MenuType *mt, const char *drawstr_submenu, uiBut *but, MenuSearch_Context *wm_context)
static bool ui_search_menu_create_context_menu(struct bContext *C, void *arg, void *active, const struct wmEvent *event)
static MenuSearch_Data * menu_items_from_ui_create(bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas)
static void menu_search_arg_free_fn(void *data_v)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define G(x, y, z)
static void area(int d1, int d2, int e1, int e2, float weights[2])
bool active
all scheduled work for the GPU.
void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
Definition: rna_access.c:2352
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1080
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:3421
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2138
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2153
const char * RNA_property_translation_context(const PropertyRNA *prop)
Definition: rna_access.c:1895
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2180
bool RNA_property_enum_item_from_value_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
Definition: rna_access.c:1842
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
Definition: rna_access.c:1736
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:1495
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2275
const char * RNA_property_ui_name(const PropertyRNA *prop)
Definition: rna_access.c:1875
#define UI_MENU_ARROW_SEP
struct GHash * block_name_map
ARegion_Runtime runtime
ListBase handlers
ListBase uiblocks
const char * name
Definition: RNA_types.h:465
struct MenuSearch_Data::@437 context_menu_data
wmOperatorCallContext opcontext
enum MenuSearch_Item::Type type
MenuSearch_Parent * menu_parent
MenuSearch_Context * wm_context
struct MenuSearch_Item::@433::@436 rna
struct MenuSearch_Item::@433::@435 op
char label[BKE_ST_MAXNAME]
Definition: BKE_screen.h:362
char idname[BKE_ST_MAXNAME]
Definition: BKE_screen.h:361
char translation_context[BKE_ST_MAXNAME]
Definition: BKE_screen.h:363
ListBase areabase
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
float winmat[4][4]
ListBase buttons
char name[UI_MAX_NAME_STR]
void * evil_C
wmOperatorCallContext opcontext
struct bContextStore * context
struct uiBut * prev
eButType type
float hardmax
uiBlock * block
BIFIconID icon
struct PointerRNA * opptr
struct wmOperatorType * optype
char drawstr[UI_MAX_DRAW_STR]
char strdata[UI_MAX_NAME_STR]
struct PropertyRNA * rnaprop
char * str
struct PointerRNA rnapoin
wmKeyMap * keymaps[3]
Definition: WM_api.h:335
int xy[2]
Definition: WM_types.h:682
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
const char * translation_context
Definition: WM_types.h:891
struct wmEvent * eventstate
bool WM_operator_poll(bContext *C, wmOperatorType *ot)
void WM_event_get_keymaps_from_handler(wmWindowManager *wm, wmWindow *win, wmEventHandler_Keymap *handler, wmEventHandler_KeymapResult *km_result)
void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C, wmOperatorType *ot, wmOperatorCallContext opcontext, PointerRNA *properties, const wmEvent *event, const char *drawstr)
@ WM_HANDLER_TYPE_KEYMAP
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_keymap_item_to_string(const wmKeyMapItem *kmi, const bool compact, char *result, const int result_len)
Definition: wm_keymap.c:1213
bool WM_keymap_poll(bContext *C, wmKeyMap *keymap)
Definition: wm_keymap.c:432
void WM_menutype_iter(GHashIterator *ghi)
Definition: wm_menu_type.c:46
MenuType * WM_menutype_find(const char *idname, bool quiet)
Definition: wm_menu_type.c:30
bool WM_menutype_poll(bContext *C, MenuType *mt)
Definition: wm_menu_type.c:87
void WM_operatortype_iter(GHashIterator *ghi)
const char * WM_operatortype_name(struct wmOperatorType *ot, struct PointerRNA *properties)
size_t WM_operator_py_idname(char *dst, const char *src)
Definition: wm_operators.c:110
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:783
bScreen * WM_window_get_active_screen(const wmWindow *win)
Definition: wm_window.c:2300