From 85c1e61375532e91d5fc37b1d754cf76c17f7721 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 23 Jun 2018 16:31:28 +0200 Subject: UI: Add user defined context menu - Add/Remove from RMB context menu. - Stored in user preferences. - Access from Q key. See T55027. --- source/blender/editors/include/ED_screen.h | 13 +- .../blender/editors/interface/interface_handlers.c | 45 +++++++ source/blender/editors/screen/CMakeLists.txt | 1 + source/blender/editors/screen/screen_user_menu.c | 142 +++++++++++++++++++++ source/blender/editors/space_api/spacetypes.c | 2 + source/blender/editors/space_view3d/space_view3d.c | 5 - .../blender/editors/space_view3d/view3d_intern.h | 1 - .../blender/editors/space_view3d/view3d_toolbar.c | 130 ------------------- 8 files changed, 202 insertions(+), 137 deletions(-) create mode 100644 source/blender/editors/screen/screen_user_menu.c (limited to 'source/blender/editors') diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 9fcefc1e4b1..05b51dff4b4 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -60,6 +60,8 @@ struct Main; struct wmMsgBus; struct wmMsgSubscribeKey; struct wmMsgSubscribeValue; +struct wmOperatorType; +struct IDProperty; /* regions */ void ED_region_do_listen( @@ -311,6 +313,16 @@ int ED_operator_posemode_local(struct bContext *C); int ED_operator_mask(struct bContext *C); int ED_operator_camera(struct bContext *C); +/* screen_user_menu.c */ + +void ED_screen_user_menu_add( + struct bContext *C, const char *ui_name, + struct wmOperatorType *ot, struct IDProperty *prop, short opcontext); +void ED_screen_user_menu_remove(struct bUserMenuItem *umi); +struct bUserMenuItem *ED_screen_user_menu_find( + struct bContext *C, + struct wmOperatorType *ot, struct IDProperty *prop, short opcontext); +void ED_screen_user_menu_register(void); /* Cache display helpers */ @@ -333,4 +345,3 @@ void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *sa); #define ED_KEYMAP_HEADER 64 #endif /* __ED_SCREEN_H__ */ - diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index cb37c301031..6f3bbc5ab36 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -6649,6 +6649,30 @@ 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 void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *arg2) +{ + uiBut *but = arg1; + bUserMenuItem *umi = arg2; + if (umi) { + ED_screen_user_menu_remove(umi); + } + char drawstr[sizeof(but->drawstr)]; + STRNCPY(drawstr, but->drawstr); + if (but->flag & UI_BUT_HAS_SEP_CHAR) { + char *sep = strrchr(drawstr, UI_SEP_CHAR); + if (sep) { + *sep = '\0'; + } + } + ED_screen_user_menu_add(C, drawstr, but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext); +} + +static void popup_user_menu_remove_func(bContext *UNUSED(C), void *UNUSED(arg1), void *arg2) +{ + bUserMenuItem *umi = arg2; + ED_screen_user_menu_remove(umi); +} + /** * menu to chow when right clicking on the panel header */ @@ -7021,6 +7045,27 @@ static bool ui_but_menu(bContext *C, uiBut *but) UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); } + uiItemS(layout); + + { + bUserMenuItem *umi = ED_screen_user_menu_find( + C, but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext); + + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_MENU_PANEL, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Favourites Menu"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, + "Add to a user defined context menu (stored in the user preferences)"); + UI_but_func_set(but2, popup_user_menu_add_or_replace_func, but, umi); + if (umi) { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_CANCEL, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Favourites Menu"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, popup_user_menu_remove_func, NULL, umi); + } + } + /* Set the operator pointer for python access */ uiLayoutSetContextFromBut(layout, but); diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index 29b9971eabb..ee114eba3c5 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC screen_draw.c screen_edit.c screen_ops.c + screen_user_menu.c screendump.c workspace_edit.c workspace_layout_edit.c diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c new file mode 100644 index 00000000000..5a05b55675e --- /dev/null +++ b/source/blender/editors/screen/screen_user_menu.c @@ -0,0 +1,142 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/screen/screen_user_menu.c + * \ingroup spview3d + */ + +#include +#include +#include +#include + +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "BLT_translation.h" + +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_idprop.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +/* -------------------------------------------------------------------- */ +/** \name Utilities + * \{ */ + +void ED_screen_user_menu_add( + bContext *C, const char *ui_name, + wmOperatorType *ot, IDProperty *prop, short opcontext) +{ + SpaceLink *sl = CTX_wm_space_data(C); + bUserMenuItem *umi = MEM_callocN(sizeof(bUserMenuItem), __func__); + umi->space_type = sl ? sl->spacetype : SPACE_EMPTY; + umi->opcontext = opcontext; + if (!STREQ(ui_name, ot->name)) { + BLI_strncpy(umi->ui_name, ui_name, OP_MAX_TYPENAME); + } + BLI_strncpy(umi->opname, ot->idname, OP_MAX_TYPENAME); + BLI_strncpy(umi->context, CTX_data_mode_string(C), OP_MAX_TYPENAME); + umi->prop = prop ? IDP_CopyProperty(prop) : NULL; + BLI_addtail(&U.user_menu_items, umi); +} + +void ED_screen_user_menu_remove(bUserMenuItem *umi) +{ + BLI_remlink(&U.user_menu_items, umi); + if (umi->prop) { + IDP_FreeProperty(umi->prop); + MEM_freeN(umi->prop); + } + MEM_freeN(umi); +} + +bUserMenuItem *ED_screen_user_menu_find( + bContext *C, + wmOperatorType *ot, IDProperty *prop, short opcontext) +{ + SpaceLink *sl = CTX_wm_space_data(C); + const char *context = CTX_data_mode_string(C); + for (bUserMenuItem *umi = U.user_menu_items.first; umi; umi = umi->next) { + if (STREQ(ot->idname, umi->opname) && + (opcontext == umi->opcontext) && + (IDP_EqualsProperties(prop, umi->prop))) + { + if ((ELEM(umi->space_type, SPACE_TOPBAR) || (sl->spacetype == umi->space_type)) && + (STREQLEN(context, umi->context, OP_MAX_TYPENAME))) + { + return umi; + } + } + } + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Menu Definition + * \{ */ + +static void screen_user_menu_draw(const bContext *C, Menu *menu) +{ + SpaceLink *sl = CTX_wm_space_data(C); + const char *context = CTX_data_mode_string(C); + for (bUserMenuItem *umi = U.user_menu_items.first; umi; umi = umi->next) { + if ((ELEM(umi->space_type, SPACE_TOPBAR) || (sl->spacetype == umi->space_type)) && + (STREQLEN(context, umi->context, OP_MAX_TYPENAME))) + { + IDProperty *prop = umi->prop ? IDP_CopyProperty(umi->prop) : NULL; + uiItemFullO( + menu->layout, umi->opname, umi->ui_name[0] ? umi->ui_name : NULL, + ICON_NONE, prop, umi->opcontext, 0, NULL); + } + } +} + +void ED_screen_user_menu_register(void) +{ + MenuType *mt = MEM_callocN(sizeof(MenuType), __func__); + strcpy(mt->idname, "SCREEN_MT_user_menu"); + strcpy(mt->label, "Quick Favourites"); + strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + mt->draw = screen_user_menu_draw; + WM_menutype_add(mt); +} + +/** \} */ diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 33ec7f771ba..2ee791e81d6 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -127,6 +127,8 @@ void ED_spacetypes_init(void) ED_operatortypes_view2d(); ED_operatortypes_ui(); + ED_screen_user_menu_register(); + /* manipulator types */ ED_manipulatortypes_button_2d(); ED_manipulatortypes_dial_3d(); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 75267e990f7..4f960959abf 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1541,11 +1541,6 @@ void ED_spacetype_view3d(void) art->draw = view3d_tools_region_draw; BLI_addhead(&st->regiontypes, art); -#if 0 - /* unfinished still */ - view3d_toolshelf_register(art); -#endif - /* regions: header */ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region"); art->regionid = RGN_TYPE_HEADER; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 017b31a0bf2..4eb2a016b94 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -235,7 +235,6 @@ struct Object *ED_view3d_cameracontrol_object_get( /* view3d_toolbar.c */ void VIEW3D_OT_toolshelf(struct wmOperatorType *ot); -void view3d_toolshelf_register(struct ARegionType *art); /* view3d_snap.c */ bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]); diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index acceb40beaa..707e0e7a394 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -28,153 +28,24 @@ * \ingroup spview3d */ - #include #include #include #include -#include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLI_ghash.h" - -#include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_screen.h" - #include "WM_api.h" #include "WM_types.h" -#include "RNA_access.h" - #include "ED_screen.h" -#include "ED_undo.h" - -#include "UI_interface.h" -#include "UI_resources.h" #include "view3d_intern.h" /* own include */ -/* ******************* */ - -typedef struct CustomTool { - struct CustomTool *next, *prev; - char opname[OP_MAX_TYPENAME]; - char context[OP_MAX_TYPENAME]; -} CustomTool; - -static void operator_call_cb(struct bContext *C, void *arg_listbase, void *arg2) -{ - wmOperatorType *ot = arg2; - - if (ot) { - CustomTool *ct = MEM_callocN(sizeof(CustomTool), "CustomTool"); - - BLI_addtail(arg_listbase, ct); - BLI_strncpy(ct->opname, ot->idname, OP_MAX_TYPENAME); - BLI_strncpy(ct->context, CTX_data_mode_string(C), OP_MAX_TYPENAME); - } - -} - -static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items) -{ - GHashIterator iter; - - for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { - wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); - - if (BLI_strcasestr(ot->name, str)) { - if (WM_operator_poll((bContext *)C, ot)) { - - if (false == UI_search_item_add(items, ot->name, ot, 0)) - break; - } - } - } -} - - -/* ID Search browse menu, open */ -static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase) -{ - static char search[OP_MAX_TYPENAME]; - wmEvent event; - wmWindow *win = CTX_wm_window(C); - uiBlock *block; - uiBut *but; - - /* clear initial search string, then all items show */ - search[0] = 0; - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); - - /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL); - - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, ""); - UI_but_func_search_set(but, NULL, operator_search_cb, arg_listbase, operator_call_cb, NULL); - - UI_block_bounds_set_normal(block, 6); - UI_block_direction_set(block, UI_DIR_DOWN); - UI_block_end(C, block); - - wm_event_init_from_window(win, &event); - event.type = EVT_BUT_OPEN; - event.val = KM_PRESS; - event.customdata = but; - event.customdatafree = false; - wm_event_add(win, &event); - - return block; -} - - -static void view3d_panel_tool_shelf(const bContext *C, Panel *pa) -{ - SpaceLink *sl = CTX_wm_space_data(C); - SpaceType *st = NULL; - uiLayout *col; - const char *context = CTX_data_mode_string(C); - - if (sl) - st = BKE_spacetype_from_id(sl->spacetype); - - if (st && st->toolshelf.first) { - CustomTool *ct; - - for (ct = st->toolshelf.first; ct; ct = ct->next) { - if (STREQLEN(context, ct->context, OP_MAX_TYPENAME)) { - col = uiLayoutColumn(pa->layout, true); - uiItemFullO(col, ct->opname, NULL, ICON_NONE, NULL, WM_OP_INVOKE_REGION_WIN, 0, NULL); - } - } - } - col = uiLayoutColumn(pa->layout, true); - uiDefBlockBut(uiLayoutGetBlock(pa->layout), tool_search_menu, &st->toolshelf, "Add Tool", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Add Tool in shelf, gets saved in files"); -} - - -void view3d_toolshelf_register(ARegionType *art) -{ - PanelType *pt; - - pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel tools"); - strcpy(pt->idname, "VIEW3D_PT_tool_shelf"); - strcpy(pt->label, N_("Tool Shelf")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = view3d_panel_tool_shelf; - BLI_addtail(&art->paneltypes, pt); -} - /* ********** operator to open/close toolshelf region */ static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op)) @@ -200,4 +71,3 @@ void VIEW3D_OT_toolshelf(wmOperatorType *ot) /* flags */ ot->flag = 0; } - -- cgit v1.2.3