diff options
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/include/ED_screen.h | 7 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_context_menu.c | 46 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_user_menu.c | 72 |
3 files changed, 117 insertions, 8 deletions
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 0785b63ca37..5ff58da735f 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -63,6 +63,7 @@ struct wmMsgSubscribeValue; struct wmOperatorType; struct IDProperty; struct MenuType; +struct PropertyRNA; /* regions */ void ED_region_do_listen( @@ -330,6 +331,9 @@ struct bUserMenuItem_Op *ED_screen_user_menu_item_find_operator( struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu( struct ListBase *lb, const struct MenuType *mt); +struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop( + struct ListBase *lb, + const char *context_data_path, const char *prop_id, int prop_index); void ED_screen_user_menu_item_add_operator( struct ListBase *lb, const char *ui_name, @@ -337,6 +341,9 @@ void ED_screen_user_menu_item_add_operator( void ED_screen_user_menu_item_add_menu( struct ListBase *lb, const char *ui_name, const struct MenuType *mt); +void ED_screen_user_menu_item_add_prop( + ListBase *lb, const char *ui_name, + const char *context_data_path, const char *prop_id, int prop_index); void ED_screen_user_menu_item_remove( struct ListBase *lb, struct bUserMenuItem *umi); diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index d425ba1f985..240649c8ab0 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -216,12 +216,16 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL); } -static bool ui_but_is_user_menu_compatible(uiBut *but) +static bool ui_but_is_user_menu_compatible(bContext *C, uiBut *but) { - return (but->optype || UI_but_menutype_get(but)); + return (but->optype || + (but->rnaprop && + (RNA_property_type(but->rnaprop) == PROP_BOOLEAN) && + (WM_context_member_from_ptr(C, &but->rnapoin) != NULL)) || + UI_but_menutype_get(but)); } -static bUserMenuItem *ui_but_user_menu_find(uiBut *but, bUserMenu *um) +static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *um) { MenuType *mt = NULL; if (but->optype) { @@ -229,6 +233,12 @@ static bUserMenuItem *ui_but_user_menu_find(uiBut *but, bUserMenu *um) return (bUserMenuItem *)ED_screen_user_menu_item_find_operator( &um->items, but->optype, prop, but->opcontext); } + else if (but->rnaprop) { + const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin); + const char *prop_id = RNA_property_identifier(but->rnaprop); + return (bUserMenuItem *)ED_screen_user_menu_item_find_prop( + &um->items, member_id, prop_id, but->rnaindex); + } else if ((mt = UI_but_menutype_get(but))) { return (bUserMenuItem *)ED_screen_user_menu_item_find_menu( &um->items, mt); @@ -238,9 +248,9 @@ static bUserMenuItem *ui_but_user_menu_find(uiBut *but, bUserMenu *um) } } -static void ui_but_user_menu_add(uiBut *but, bUserMenu *um) +static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) { - BLI_assert(ui_but_is_user_menu_compatible(but)); + BLI_assert(ui_but_is_user_menu_compatible(C, but)); char drawstr[sizeof(but->drawstr)]; STRNCPY(drawstr, but->drawstr); @@ -257,6 +267,26 @@ static void ui_but_user_menu_add(uiBut *but, bUserMenu *um) &um->items, drawstr, but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext); } + else if (but->rnaprop) { + /* Note: 'member_id' may be a path. */ + const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin); + const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin); + const char *member_id_data_path = member_id; + if (data_path) { + member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path); + } + const char *prop_id = RNA_property_identifier(but->rnaprop); + /* Note, ignore 'drawstr', use property idname always. */ + ED_screen_user_menu_item_add_prop( + &um->items, "", + member_id_data_path, prop_id, but->rnaindex); + if (data_path) { + MEM_freeN((void *)data_path); + } + if (member_id != member_id_data_path) { + MEM_freeN((void *)member_id_data_path); + } + } else if ((mt = UI_but_menutype_get(but))) { ED_screen_user_menu_item_add_menu( &um->items, drawstr, @@ -268,7 +298,7 @@ static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *U { uiBut *but = arg1; bUserMenu *um = ED_screen_user_menu_ensure(C); - ui_but_user_menu_add(but, um); + ui_but_user_menu_add(C, but, um); } static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *arg2) @@ -658,7 +688,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) } /* Favorites Menu */ - if (ui_but_is_user_menu_compatible(but)) { + if (ui_but_is_user_menu_compatible(C, but)) { uiBlock *block = uiLayoutGetBlock(layout); const int w = uiLayoutGetWidth(layout); uiBut *but2; @@ -672,7 +702,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) bUserMenu *um = ED_screen_user_menu_find(C); if (um) { - bUserMenuItem *umi = ui_but_user_menu_find(but, um); + bUserMenuItem *umi = ui_but_user_menu_find(C, but, um); if (umi != NULL) { but2 = uiDefIconTextBut( block, UI_BTYPE_BUT, 0, ICON_CANCEL, diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c index c51227d7107..f62dc1ee500 100644 --- a/source/blender/editors/screen/screen_user_menu.c +++ b/source/blender/editors/screen/screen_user_menu.c @@ -56,6 +56,8 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "RNA_access.h" + /* -------------------------------------------------------------------- */ /** \name Menu Type * \{ */ @@ -113,6 +115,24 @@ struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu( return NULL; } +struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop( + struct ListBase *lb, + const char *context_data_path, const char *prop_id, int prop_index) +{ + for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) { + if (umi->type == USER_MENU_TYPE_PROP) { + bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi; + if (STREQ(context_data_path, umi_pr->context_data_path) && + STREQ(prop_id, umi_pr->prop_id) && + (prop_index == umi_pr->prop_index)) + { + return umi_pr; + } + } + } + return NULL; +} + void ED_screen_user_menu_item_add_operator( ListBase *lb, const char *ui_name, const wmOperatorType *ot, const IDProperty *prop, short opcontext) @@ -137,6 +157,17 @@ void ED_screen_user_menu_item_add_menu( STRNCPY(umi_mt->mt_idname, mt->idname); } +void ED_screen_user_menu_item_add_prop( + ListBase *lb, const char *ui_name, + const char *context_data_path, const char *prop_id, int prop_index) +{ + bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_PROP); + STRNCPY(umi_pr->item.ui_name, ui_name); + STRNCPY(umi_pr->context_data_path, context_data_path); + STRNCPY(umi_pr->prop_id, prop_id); + umi_pr->prop_index = prop_index; +} + void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi) { BLI_remlink(lb, umi); @@ -176,6 +207,47 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu) uiItemM(menu->layout, umi_mt->mt_idname, ui_name, ICON_NONE); } + else if (umi->type == USER_MENU_TYPE_PROP) { + bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi; + + char *data_path = strchr(umi_pr->context_data_path, '.'); + if (data_path) { + *data_path = '\0'; + } + PointerRNA ptr = CTX_data_pointer_get(C, umi_pr->context_data_path); + if (ptr.type == NULL) { + PointerRNA ctx_ptr; + RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr); + if (!RNA_path_resolve_full(&ctx_ptr, umi_pr->context_data_path, &ptr, NULL, NULL)) { + ptr.type = NULL; + } + } + if (data_path) { + *data_path = '.'; + data_path += 1; + } + + bool ok = false; + if (ptr.type != NULL) { + PropertyRNA *prop = NULL; + PointerRNA prop_ptr = ptr; + if ((data_path == NULL) || RNA_path_resolve_full(&ptr, data_path, &prop_ptr, NULL, NULL)) { + prop = RNA_struct_find_property(&prop_ptr, umi_pr->prop_id); + if (prop) { + ok = true; + uiItemFullR( + menu->layout, + &prop_ptr, prop, umi_pr->prop_index, + 0, 0, ui_name, ICON_NONE); + } + } + } + if (!ok) { + char label[512]; + SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id); + uiItemL(menu->layout, label, ICON_NONE); + } + } else if (umi->type == USER_MENU_TYPE_SEP) { uiItemS(menu->layout); } |