40#include "RNA_prototypes.hh"
52#include <fmt/format.h>
101 if (this->opptr !=
nullptr) {
103 MEM_delete(this->opptr);
105 MEM_delete(this->context);
115 std::variant<OperatorData, PropertyData>
data;
151 std::string drawstr_override;
154 const bool drawstr_is_empty = sep_index == 0 || but->
drawstr.empty();
156 if (but->
optype !=
nullptr) {
157 if (drawstr_is_empty) {
163 auto &op_data = std::get<MenuSearch_Item::OperatorData>(item->
data);
164 op_data.type = but->
optype;
166 op_data.context = but->
context ? MEM_new<bContextStore>(__func__, *but->
context) :
nullptr;
167 op_data.opptr = but->
opptr;
171 but->
opptr =
nullptr;
173 else if (but->
rnaprop !=
nullptr) {
176 if (drawstr_is_empty) {
178 const int value_enum = int(but->
hardmax);
186 drawstr_override = enum_item.
name;
190 drawstr_override =
"Unknown";
201 printf(
"Button '%s' in menu '%s' is a menu item with unsupported RNA type %d\n",
211 auto &rna_data = std::get<MenuSearch_Item::PropertyData>(item->
data);
216 rna_data.enum_value = int(but->
hardmax);
221 if (item !=
nullptr) {
223 if (!drawstr_override.empty()) {
224 const StringRef drawstr_suffix = sep_index == std::string::npos ?
227 std::string drawstr = std::string(
"(") + drawstr_override +
")" + drawstr_suffix;
242 data->items.append(*item);
254 bool changed =
false;
255 if (
auto *op_data = std::get_if<MenuSearch_Item::OperatorData>(&item->
data)) {
256 but->
optype = op_data->type;
258 but->
context = op_data->context;
259 but->
opptr = op_data->opptr;
262 else if (
auto *rna_data = std::get_if<MenuSearch_Item::PropertyData>(&item->
data)) {
270 but->
hardmax = rna_data->enum_value;
279 if (sep_index != std::string::npos) {
280 but->
drawstr.resize(sep_index);
310 region ? ®ion->
runtime->handlers :
nullptr,
315 for (
int handler_index = 0; handler_index <
ARRAY_SIZE(handlers); handler_index++) {
316 if (handlers[handler_index] ==
nullptr) {
328 if (handler_base->poll ==
nullptr || handler_base->poll(win, area, region, win->
eventstate))
333 for (
int km_index = 0; km_index < km_result.
keymaps_len; km_index++) {
340 if (
STR_ELEM(kmi->idname,
"WM_OT_call_menu",
"WM_OT_call_menu_pie")) {
345 if (mt && menu_tagged.
add(mt)) {
347 menu_stack.
push({mt});
348 menu_to_kmi.
add(mt, kmi);
374 const char *ot_ui_name =
CTX_IFACE_(
ot->translation_context,
ot->name);
378 auto &op_data = std::get<MenuSearch_Item::OperatorData>(item.
data);
381 op_data.context =
nullptr;
394 operator_items.
append(item);
400 data->items.extend(operator_items);
413 bool include_all_areas,
414 const char *single_menu_idname)
422 if (old_context_store) {
423 context_store = *old_context_store;
432 fmt::memory_buffer str_buf;
444 const char *idname_array[] = {
446 (single_menu_idname &&
STREQ(single_menu_idname,
"TOPBAR_MT_file_open_recent")) ?
448 "TOPBAR_MT_file_open_recent",
451 "TOPBAR_MT_undo_history",
454 if (!idname_array[
i]) {
464 if (!single_menu_idname) {
476 const char *idname_array[] = {
478 "OUTLINER_MT_context_menu",
492 int space_type_ui_items_len = 0;
493 bool space_type_ui_items_free =
false;
496 const char *global_menu_prefix =
nullptr;
498 if (include_all_areas) {
514 &space_type_ui_items,
515 &space_type_ui_items_len,
516 &space_type_ui_items_free);
520 for (
int i = 0;
i < space_type_ui_items_len;
i++) {
527 if (region !=
nullptr) {
532 if (space_type_ui_index == -1) {
536 if (wm_contexts[space_type_ui_index].space_type_ui_index != -1) {
537 ScrArea *area_best = wm_contexts[space_type_ui_index].
area;
539 const uint value_test =
uint(area->winx) *
uint(area->winy);
540 if (value_best > value_test) {
546 wm_contexts[space_type_ui_index].
area = area;
547 wm_contexts[space_type_ui_index].
region = region;
554 for (
int space_type_ui_index = -1; space_type_ui_index < space_type_ui_items_len;
555 space_type_ui_index += 1)
562 if (include_all_areas) {
563 if (space_type_ui_index == -1) {
565 wm_context =
nullptr;
570 wm_context = &wm_contexts[space_type_ui_index];
575 area = wm_context->
area;
576 region = wm_context->
region;
584 region = region_init;
587 if (single_menu_idname) {
589 if (menu_tagged.
add(mt)) {
590 menu_stack.
push({mt});
599 const char *idname_array[2] = {
nullptr};
600 int idname_array_len = 0;
603 if (space_type_ui_index == -1) {
604 idname_array[idname_array_len++] =
"TOPBAR_MT_editor_menus";
607#define SPACE_MENU_MAP(space_type, menu_id) \
609 idname_array[idname_array_len++] = menu_id; \
611#define SPACE_MENU_NOP(space_type) \
615 if (area !=
nullptr) {
634 "CLIP_MT_tracking_editor_menus" :
635 "CLIP_MT_masking_editor_menus");
643 for (
int i = 0;
i < idname_array_len;
i++) {
647 if (menu_tagged.
add(mt)) {
648 menu_stack.
push({mt});
656 bool has_keymap_menu_items =
false;
678 if (current_menu.
context.has_value()) {
687 const std::unique_ptr<uiBut> &but = block->
buttons[
i];
694 const std::unique_ptr<uiBut> *but_test = block->
buttons.
begin() +
i - 1;
699 if (but_test < block->buttons.begin()) {
709 const bool uses_context = but->context &&
711 const bool tagged_first_time = menu_tagged.
add(mt_from_but);
712 const bool scan_submenu = tagged_first_time || uses_context;
724 bool drawstr_is_empty =
false;
725 if (drawstr_sep !=
nullptr) {
728 const char *drawstr = but->drawstr.c_str();
729 int drawstr_len = drawstr_sep - but->drawstr.c_str();
732 drawstr_len = strlen(drawstr);
733 if (drawstr[0] ==
'\0') {
734 drawstr_is_empty =
true;
737 str_buf.append(
StringRef(drawstr, drawstr_len));
738 fmt::format_to(fmt::appender(str_buf),
" ({})", drawstr_sep + 1);
740 StringRef(str_buf.data(), str_buf.size()));
744 const char *drawstr = but->drawstr.c_str();
747 if (drawstr[0] ==
'\0') {
748 drawstr_is_empty =
true;
755 if (drawstr_is_empty) {
756 printf(
"Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->
idname);
760 menu_stack.
push({mt_from_but, menu_parent, *but->context});
763 menu_stack.
push({mt_from_but, menu_parent});
767 else if (but->menu_create_func !=
nullptr) {
793 bool poll_success =
true;
795 if (pt->poll && (pt->poll(
C, pt) ==
false)) {
796 poll_success =
false;
801 but->menu_create_func(
C, &sub_layout, but->poin);
811 for (
const std::unique_ptr<uiBut> &sub_but : sub_block->
buttons) {
813 data, scope, mt, sub_but.get(), wm_context, menu_parent);
818 region->
runtime->block_name_map.remove(sub_block->
name);
825 region->
runtime->block_name_map.remove(block->
name);
830 if (single_menu_idname ==
nullptr) {
833 if (menu_stack.
is_empty() && (has_keymap_menu_items ==
false)) {
834 has_keymap_menu_items =
true;
836 C, win, area, region, menu_stack, menu_to_kmi, menu_tagged);
849 if (include_all_areas) {
850 fmt::format_to(fmt::appender(str_buf),
860 while (menu_parent && menu_parent->
parent) {
862 menu_parent = menu_parent->
parent;
864 while (menu_parent) {
865 str_buf.append(menu_parent->
drawstr);
871 const char *drawstr = menu_display_name_map.
lookup_default(item.
mt,
nullptr);
872 if (drawstr ==
nullptr) {
878 if (kmi !=
nullptr) {
880 fmt::format_to(fmt::appender(str_buf),
" ({})", kmi_str);
897 if (include_all_areas) {
901 if (space_type_ui_items_free) {
932 if (item ==
nullptr) {
947 if (
auto *op_data = std::get_if<MenuSearch_Item::OperatorData>(&item->
data)) {
950 C, op_data->type, op_data->opcontext, op_data->opptr,
nullptr, item->
drawstr);
953 else if (
auto *rna_data = std::get_if<MenuSearch_Item::PropertyData>(&item->
data)) {
956 const int index = rna_data->index;
958 bool changed =
false;
1028 bool has_menu =
false;
1030 new (&
data->context_menu_data.but)
uiBut();
1032 uiBut *but = &
data->context_menu_data.but;
1071 new (&
data->context_menu_data.but)
uiBut();
1073 uiBut *but = &
data->context_menu_data.but;
1083 tip_init[0] =
event->
xy[0];
1084 tip_init[1] =
event->xy[1] - (
UI_UNIT_Y / 2);
1127 !single_menu_idname;
1129 C, win, area, region, include_all_areas, single_menu_idname);
1149 static char search[256] =
"";
1151 block = layout->
block();
1155 block, search, 0, ICON_VIEWZOOM,
sizeof(search), 0, 0,
UI_UNIT_X * 6,
UI_UNIT_Y,
"");
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
const bContextStore * CTX_store_get(const bContext *C)
void CTX_store_set(bContext *C, const bContextStore *store)
void CTX_wm_area_set(bContext *C, ScrArea *area)
void CTX_wm_region_set(bContext *C, ARegion *region)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
#define LISTBASE_FOREACH(type, var, list)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void unit_m4(float m[4][4])
#define BLI_SCOPED_DEFER(function_to_defer)
int bool bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL(1
#define SNPRINTF_UTF8(dst, format,...)
#define CTX_IFACE_(context, msgid)
Read Guarded memory(de)allocation.
@ UI_BLOCK_SHOW_SHORTCUT_ALWAYS
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType emboss)
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)
MenuType * UI_but_menutype_get(const uiBut *but)
const uiStyle * UI_style_get_dpi()
void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn)
uiBut * uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxncpy, int x, int y, short width, short height, std::optional< blender::StringRef > tip)
ARegion * UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_quick_tip)
bool UI_search_item_add(uiSearchItems *items, blender::StringRef name, void *poin, int iconid, int but_flag, uint8_t name_prefix_offset)
void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn)
PanelType * UI_but_paneltype_get(const uiBut *but)
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
void UI_block_free(const bContext *C, uiBlock *block)
void UI_block_flag_enable(uiBlock *block, int flag)
void UI_block_end(const bContext *C, uiBlock *block)
void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout)
BMesh const char void * data
void append(const T &value)
IndexRange index_range() const
StringRefNull copy_string(StringRef str)
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
T & construct(Args &&...args)
LinearAllocator & allocator()
bool remove(const Key &key)
void push(const T &value)
constexpr const char * c_str() const
constexpr StringRef drop_prefix(int64_t n) const
void append(const T &value)
void add(const StringRef str, T *user_data, const int weight=0)
Vector< T * > query(const StringRef query) const
void ui_window_to_block_fl(const ARegion *region, const uiBlock *block, float *x, float *y)
ARegion * ui_searchbox_create_menu(bContext *C, ARegion *butregion, uiButSearch *search_but)
int ui_but_icon(const uiBut *but)
void MEM_freeN(void *vmemh)
uiLayout & block_layout(uiBlock *block, LayoutDirection direction, LayoutType type, int x, int y, int size, int em, int padding, const uiStyle *style)
void block_layout_set_current(uiBlock *block, uiLayout *layout)
void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
bool RNA_property_array_check(PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
PropertyType RNA_property_type(PropertyRNA *prop)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_property_translation_context(const PropertyRNA *prop)
const char * RNA_property_ui_name(const PropertyRNA *prop, const PointerRNA *ptr)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_property_enum_item_from_value_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
#define UI_MENU_ARROW_SEP
ARegionRuntimeHandle * runtime
blender::Vector< bContextStoreEntry > entries
blender::Vector< std::unique_ptr< uiBut > > buttons
blender::wm::OpCallContext opcontext
const bContextStore * context
void operator_context_set(blender::wm::OpCallContext opcontext)
void context_copy(const bContextStore *context)
struct wmEvent * eventstate
void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C, wmOperatorType *ot, blender::wm::OpCallContext opcontext, PointerRNA *properties, const wmEvent *event, const StringRef drawstr)
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)
bool WM_keymap_poll(bContext *C, wmKeyMap *keymap)
std::optional< std::string > WM_keymap_item_to_string(const wmKeyMapItem *kmi, const bool compact)
blender::Span< wmOperatorType * > WM_operatortypes_registered_get()
std::string WM_operatortype_name(wmOperatorType *ot, PointerRNA *properties)
size_t WM_operator_py_idname(char *dst, const char *src)
void WM_operator_properties_free(PointerRNA *ptr)
bScreen * WM_window_get_active_screen(const wmWindow *win)