diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-06-30 21:59:10 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-06-30 22:08:48 +0300 |
commit | 6a13b6324b42fedb0ad886e6c64816358058d627 (patch) | |
tree | dd7e42720031978eb7083b370cce458bfedb0c43 /source | |
parent | 7d48a342d66cc7664b008ff512bd00e740eb7629 (diff) |
UI: support check-boxes in quick menu
Could support other RNA types,
however menus don't work well in this case.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/blender_user_menu.c | 9 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 8 | ||||
-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 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 9 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 9 |
8 files changed, 148 insertions, 13 deletions
diff --git a/source/blender/blenkernel/intern/blender_user_menu.c b/source/blender/blenkernel/intern/blender_user_menu.c index 387776aa144..3ec46e23cd1 100644 --- a/source/blender/blenkernel/intern/blender_user_menu.c +++ b/source/blender/blenkernel/intern/blender_user_menu.c @@ -76,14 +76,17 @@ bUserMenuItem *BKE_blender_user_menu_item_add(ListBase *lb, int type) { uint size; - if (type == USER_MENU_TYPE_OPERATOR) { + if (type == USER_MENU_TYPE_SEP) { + size = sizeof(bUserMenuItem); + } + else if (type == USER_MENU_TYPE_OPERATOR) { size = sizeof(bUserMenuItem_Op); } else if (type == USER_MENU_TYPE_MENU) { size = sizeof(bUserMenuItem_Menu); } - else if (type == USER_MENU_TYPE_SEP) { - size = sizeof(bUserMenuItem); + else if (type == USER_MENU_TYPE_PROP) { + size = sizeof(bUserMenuItem_Prop); } else { BLI_assert(0); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 61762b5d7ed..e7bca4c7e5b 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1254,6 +1254,14 @@ static void write_userdef(WriteData *wd, const UserDef *userdef) IDP_WriteProperty(umi_op->prop, wd); } } + else if (umi->type == USER_MENU_TYPE_MENU) { + const bUserMenuItem_Menu *umi_mt = (const bUserMenuItem_Menu *)umi; + writestruct(wd, DATA, bUserMenuItem_Menu, 1, umi_mt); + } + else if (umi->type == USER_MENU_TYPE_PROP) { + const bUserMenuItem_Prop *umi_pr = (const bUserMenuItem_Prop *)umi; + writestruct(wd, DATA, bUserMenuItem_Prop, 1, umi_pr); + } else { writestruct(wd, DATA, bUserMenuItem, 1, umi); } 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); } diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 59c6aa9bd1b..d2782dee9ff 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -465,10 +465,19 @@ typedef struct bUserMenuItem_Menu { char mt_idname[64]; } bUserMenuItem_Menu; +typedef struct bUserMenuItem_Prop { + bUserMenuItem item; + char context_data_path[256]; + char prop_id[64]; + int prop_index; + char _pad0[4]; +} bUserMenuItem_Prop; + enum { USER_MENU_TYPE_SEP = 1, USER_MENU_TYPE_OPERATOR = 2, USER_MENU_TYPE_MENU = 3, + USER_MENU_TYPE_PROP = 4, }; typedef struct SolidLight { diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index f294e95e05c..a96d9bec61a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -422,6 +422,7 @@ char *WM_prop_pystring_assign(struct bContext *C, struct PointerRNA *ptr, struc void WM_operator_bl_idname(char *to, const char *from); void WM_operator_py_idname(char *to, const char *from); bool WM_operator_py_idname_ok_or_report(struct ReportList *reports, const char *classname, const char *idname); +const char *WM_context_member_from_ptr(struct bContext *C, const struct PointerRNA *ptr); /* *************** uilist types ******************** */ void WM_uilisttype_init(void); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 334e4a70f9c..496c9b1eb19 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -805,7 +805,7 @@ bool WM_operator_pystring_abbreviate(char *str, int str_len_max) /* return NULL if no match is found */ #if 0 -static const char *wm_context_member_from_ptr(bContext *C, PointerRNA *ptr) +static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr) { /* loop over all context items and do 2 checks * @@ -860,7 +860,7 @@ static const char *wm_context_member_from_ptr(bContext *C, PointerRNA *ptr) /* use hard coded checks for now */ -static const char *wm_context_member_from_ptr(bContext *C, PointerRNA *ptr) +static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr) { const char *member_id = NULL; @@ -985,6 +985,11 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert return ret; } +const char *WM_context_member_from_ptr(bContext *C, const PointerRNA *ptr) +{ + return wm_context_member_from_ptr(C, ptr); +} + char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index) { char *lhs, *rhs, *ret; |