diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-04-22 18:16:39 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-04-22 18:45:14 +0300 |
commit | e6d1fb87c6b0184416ce202ccba6a96a3ee04552 (patch) | |
tree | 39e1e321364129dfae355ecff938f0bafb5eae33 | |
parent | b8e7991811dcf6fa698077f850fef17be83d2abb (diff) |
UI: Initial popover support for panels
- UILayout.popover(.. panel_type ..)
A single panel
- UILayout.popover_group(.. panel categories ..)
Expands all panels matching args.
Currently used in the topbar for redo and paint options.
-rw-r--r-- | release/scripts/modules/bpy_types.py | 9 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_topbar.py | 25 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 26 | ||||
-rw-r--r-- | source/blender/editors/interface/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 12 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 12 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_layout.c | 114 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_region_popover.c | 283 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 2 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_ui_api.c | 46 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_wm.c | 17 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_wm_api.c | 34 |
13 files changed, 581 insertions, 1 deletions
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 1124070fea2..324bb43d890 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -144,6 +144,15 @@ class WindowManager(bpy_types.ID): finally: self.popmenu_end__internal(popup) + def popover(self, draw_func, title="", icon='NONE'): + import bpy + popup = self.popover_begin__internal(title, icon) + + try: + draw_func(popup, bpy.context) + finally: + self.popover_end__internal(popup) + def popup_menu_pie(self, event, draw_func, title="", icon='NONE'): import bpy pie = self.piemenu_begin__internal(title, icon, event) diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index e9258f10882..868c60b6a1a 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -113,12 +113,37 @@ class TOPBAR_HT_lower_bar(Header): act_mode_item = bpy.types.Object.bl_rna.properties['mode'].enum_items[object_mode] layout.operator_menu_enum("object.mode_set", "mode", text=act_mode_item.name, icon=act_mode_item.icon) + mode = context.mode + + # Example of how toolsettings can be accessed as pop-overs. + if mode == 'SCULPT': + layout.popover_group(space_type='VIEW_3D', region_type='TOOLS', context="", category="Tools") + elif mode == 'PAINT_VERTEX': + layout.popover_group(space_type='VIEW_3D', region_type='TOOLS', context="", category="Tools") + elif mode == 'PAINT_WEIGHT': + layout.popover_group(space_type='VIEW_3D', region_type='TOOLS', context="", category="Tools") + elif mode == 'PAINT_TEXTURE': + layout.popover_group(space_type='VIEW_3D', region_type='TOOLS', context="", category="Tools") + def draw_right(self, context): layout = self.layout # Placeholder layout.operator("ed.undo_history", text="...") + # Last Action (redo) + layout.label("Last Action:") + operators = context.window_manager.operators + op = operators[-1] if operators else None + row = layout.row() + row.enabled = op is not None + row.popover( + space_type='VIEW_3D', + region_type='TOOL_PROPS', + panel_type="VIEW3D_PT_last_operator", + text=op.name if op else "Last Action...", + ) + class INFO_MT_editor_menus(Menu): bl_idname = "INFO_MT_editor_menus" diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 67b9f391ac6..191c34fc7f2 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -265,6 +265,7 @@ typedef enum { UI_BTYPE_CHECKBOX_N = (14 << 9), UI_BTYPE_COLOR = (15 << 9), UI_BTYPE_TAB = (16 << 9), + UI_BTYPE_POPOVER = (17 << 9), UI_BTYPE_SCROLL = (18 << 9), UI_BTYPE_BLOCK = (19 << 9), UI_BTYPE_LABEL = (20 << 9), @@ -409,6 +410,17 @@ int UI_popup_menu_invoke(struct bContext *C, const char *idname, struct ReportLi void UI_popup_menu_retval_set(const uiBlock *block, const int retval, const bool enable); void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *but); +/* interface_region_popover.c */ + +typedef struct uiPopover uiPopover; + +uiPopover *UI_popover_begin( + struct bContext *C) ATTR_NONNULL(); +uiPopover *UI_popover_begin_ex( + struct bContext *C, const char *block_name) ATTR_NONNULL(); +void UI_popover_end(struct bContext *C, struct uiPopover *head); +struct uiLayout *UI_popover_layout(uiPopover *head); + /* interface_region_menu_pie.c */ /* Pie menus */ typedef struct uiPieMenu uiPieMenu; @@ -911,6 +923,7 @@ void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct Pointe void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context); const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing struct MenuType *UI_but_menutype_get(uiBut *but); +struct PanelType *UI_but_paneltype_get(uiBut *but); void UI_menutype_draw(struct bContext *C, struct MenuType *mt, struct uiLayout *layout); /* Only for convenience. */ @@ -1090,6 +1103,19 @@ void uiItemM(uiLayout *layout, struct bContext *C, const char *menuname, const c void uiItemV(uiLayout *layout, const char *name, int icon, int argval); /* value */ void uiItemS(uiLayout *layout); /* separator */ +void uiItemPopoverPanel_ptr( + uiLayout *layout, struct bContext *C, + struct PanelType *pt, + const char *name, int icon); +void uiItemPopoverPanel( + uiLayout *layout, struct bContext *C, + int space_id, int region_id, const char *panelname, + const char *name, int icon); +void uiItemPopoverPanelFromGroup( + uiLayout *layout, struct bContext *C, + int space_id, int region_id, + const char *context, const char *category); + void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg); void uiItemMenuEnumO_ptr(uiLayout *layout, struct bContext *C, struct wmOperatorType *ot, const char *propname, const char *name, int icon); void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, const char *propname, const char *name, int icon); diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index c023816b52c..cc5c580ad38 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -59,6 +59,7 @@ set(SRC interface_region_color_picker.c interface_region_menu_pie.c interface_region_menu_popup.c + interface_region_popover.c interface_region_popup.c interface_region_search.c interface_region_tooltip.c diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 9e88c3cbb7f..4fbb8025af1 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3431,6 +3431,7 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat uiBlockCreateFunc func = NULL; uiBlockHandleCreateFunc handlefunc = NULL; uiMenuCreateFunc menufunc = NULL; + uiMenuCreateFunc popoverfunc = NULL; void *arg = NULL; switch (but->type) { @@ -3450,6 +3451,11 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat menufunc = but->menu_create_func; arg = but->poin; break; + case UI_BTYPE_POPOVER: + BLI_assert(but->menu_create_func); + popoverfunc = but->menu_create_func; + arg = but->poin; + break; case UI_BTYPE_COLOR: ui_but_v3_get(but, data->origvec); copy_v3_v3(data->vec, data->origvec); @@ -3474,6 +3480,11 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat if (but->block->handle) data->menu->popup = but->block->handle->popup; } + else if (popoverfunc) { + data->menu = ui_popover_panel_create(C, data->region, but, popoverfunc, arg); + if (but->block->handle) + data->menu->popup = but->block->handle->popup; + } #ifdef USE_ALLSELECT { @@ -7046,6 +7057,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * retval = ui_do_but_TEX(C, block, but, data, event); break; case UI_BTYPE_MENU: + case UI_BTYPE_POPOVER: case UI_BTYPE_BLOCK: case UI_BTYPE_PULLDOWN: retval = ui_do_but_BLOCK(C, but, data, event); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index e0b0a8eeaab..b9e680f009a 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -615,6 +615,18 @@ uiPopupBlockHandle *ui_popup_menu_create( struct bContext *C, struct ARegion *butregion, uiBut *but, uiMenuCreateFunc create_func, void *arg); +/* interface_region_popover.c */ +uiBlock *ui_popover_block_refresh( + struct bContext *C, uiPopupBlockHandle *handle, + ARegion *butregion, uiBut *but); +uiPopupBlockHandle *ui_popover_block_create( + struct bContext *C, struct ARegion *butregion, uiBut *but, + uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, + void *arg); +uiPopupBlockHandle *ui_popover_panel_create( + struct bContext *C, struct ARegion *butregion, uiBut *but, + uiMenuCreateFunc create_func, void *arg); + /* interface_region_menu_pie.c */ void ui_pie_menu_level_create( uiBlock *block, struct wmOperatorType *ot, const char *propname, IDProperty *properties, diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 7193ad64359..3ea6ae08173 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1824,6 +1824,35 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } +static void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_mt) +{ + PanelType *pt = (PanelType *)arg_mt; + + /* TODO: move into UI_paneltype_draw */ + Panel *panel = MEM_callocN(sizeof(Panel), "popover panel"); + panel->type = pt; + + if (layout->context) { + CTX_store_set(C, layout->context); + } + + if (pt->draw_header) { + panel->layout = uiLayoutRow(layout, false); + pt->draw_header(C, panel); + panel->layout = NULL; + } + + panel->layout = layout; + pt->draw(C, panel); + panel->layout = NULL; + + if (layout->context) { + CTX_store_set(C, NULL); + } + + MEM_freeN(panel); +} + static uiBut *ui_item_menu( uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN, const char *tip, bool force_menu) @@ -1901,6 +1930,79 @@ void uiItemM(uiLayout *layout, bContext *UNUSED(C), const char *menuname, const ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL, TIP_(mt->description), false); } +/* popover */ +void uiItemPopoverPanel_ptr(uiLayout *layout, bContext *UNUSED(C), PanelType *pt, const char *name, int icon) +{ + if (!name) { + name = CTX_IFACE_(pt->translation_context, pt->label); + } + + if (layout->root->type == UI_LAYOUT_MENU && !icon) + icon = ICON_BLANK1; + + uiBut *but = ui_item_menu(layout, name, icon, ui_item_paneltype_func, pt, NULL, NULL, false); + but->type = UI_BTYPE_POPOVER; +} + +void uiItemPopoverPanel( + uiLayout *layout, bContext *C, + int space_id, int region_id, const char *panel_type, + const char *name, int icon) +{ + SpaceType *st = BKE_spacetype_from_id(space_id); + if (st == NULL) { + RNA_warning("space type not found %d", space_id); + return; + } + ARegionType *art = BKE_regiontype_from_id(st, region_id); + if (art == NULL) { + RNA_warning("region type not found %d", region_id); + return; + } + + PanelType *pt; + for (pt = art->paneltypes.first; pt; pt = pt->next) { + if (STREQ(pt->idname, panel_type)) { + break; + } + } + + if (pt == NULL) { + RNA_warning("area type not found %s", panel_type); + return; + } + + uiItemPopoverPanel_ptr(layout, C, pt, name, icon); +} + +void uiItemPopoverPanelFromGroup( + uiLayout *layout, bContext *C, + int space_id, int region_id, const char *context, const char *category) +{ + SpaceType *st = BKE_spacetype_from_id(space_id); + if (st == NULL) { + RNA_warning("space type not found %d", space_id); + return; + } + ARegionType *art = BKE_regiontype_from_id(st, region_id); + if (art == NULL) { + RNA_warning("region type not found %d", region_id); + return; + } + + for (PanelType *pt = art->paneltypes.first; pt; pt = pt->next) { + /* Causes too many panels, check context. */ + if (/* (*context == '\0') || */ STREQ(pt->context, context)) { + if ((*category == '\0') || STREQ(pt->category, category)) { + if (pt->poll == NULL || pt->poll(C, pt)) { + uiItemPopoverPanel_ptr(layout, C, pt, NULL, ICON_NONE); + } + } + } + } +} + + /* label item */ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon) { @@ -3604,6 +3706,18 @@ MenuType *UI_but_menutype_get(uiBut *but) } } +/* this is a bit of a hack but best keep it in one place at least */ +PanelType *UI_but_paneltype_get(uiBut *but) +{ + if (but->menu_create_func == ui_item_paneltype_func) { + return (PanelType *)but->poin; + } + else { + return NULL; + } +} + + void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout) { Menu menu = { diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c new file mode 100644 index 00000000000..035efb368a6 --- /dev/null +++ b/source/blender/editors/interface/interface_region_popover.c @@ -0,0 +1,283 @@ +/* + * ***** 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) 2008 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/interface/interface_region_popover.c + * \ingroup edinterface + * + * Pop-Over Region + * + * \note This is very close to 'interface_region_menu_popup.c' + * + * We could even merge them, however menu logic is already over-loaded. + * PopOver's have the following differences. + * + * - UI is not constrained to a list. + * - Pressing a button won't close the pop-over. + * - Different draw style (to show this is has different behavior from a menu). + * - #PanelType are used insetead of #MenuType. + * - No menu flipping support. + * - No moving the menu to fit the mouse cursor. + * - No key accelerators to access menu items + * (if we add support they would work differently). + * - No arrow key navigation. + * - No menu memory. + * - No title. + */ + +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_userdef_types.h" + +#include "BLI_math.h" +#include "BLI_listbase.h" + +#include "BLI_string.h" +#include "BLI_rect.h" +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_report.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" + +#include "UI_interface.h" + +#include "BLT_translation.h" + +#include "ED_screen.h" + +#include "interface_intern.h" +#include "interface_regions_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name Popup Menu with Callback or String + * \{ */ + +struct uiPopover { + uiBlock *block; + uiLayout *layout; + uiBut *but; + ARegion *butregion; + + int mx, my; + bool popover, slideout; + + uiMenuCreateFunc menu_func; + void *menu_arg; +}; + +static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup) +{ + uiBlock *block; + uiPopover *pup = arg_pup; + int offset[2], minwidth, width, height; + + if (pup->menu_func) { + pup->block->handle = handle; + pup->menu_func(C, pup->layout, pup->menu_arg); + pup->block->handle = NULL; + } + + if (pup->but) { + /* minimum width to enforece */ + minwidth = BLI_rctf_size_x(&pup->but->rect); + } + else { + minwidth = 50; + } + + block = pup->block; + + /* in some cases we create the block before the region, + * so we set it delayed here if necessary */ + if (BLI_findindex(&handle->region->uiblocks, block) == -1) + UI_block_region_set(block, handle->region); + + block->direction = UI_DIR_DOWN; + + UI_block_layout_resolve(block, &width, &height); + + UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_KEEP_OPEN); + + if (pup->popover) { + UI_block_flag_enable(block, UI_BLOCK_LOOP); + UI_block_direction_set(block, block->direction); + block->minbounds = minwidth; + UI_block_bounds_set_popup(block, 1, offset[0], offset[1]); + } + else { + /* for a header menu we set the direction automatic */ + block->minbounds = minwidth; + UI_block_bounds_set_normal(block, 1); + } + + /* if menu slides out of other menu, override direction */ + if (pup->slideout) + UI_block_direction_set(block, UI_DIR_RIGHT); + + return pup->block; +} + +uiPopupBlockHandle *ui_popover_panel_create( + bContext *C, ARegion *butregion, uiBut *but, + uiMenuCreateFunc menu_func, void *arg) +{ + wmWindow *window = CTX_wm_window(C); + uiStyle *style = UI_style_get_dpi(); + uiPopupBlockHandle *handle; + uiPopover *pup; + + pup = MEM_callocN(sizeof(uiPopover), __func__); + pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS); + UI_block_emboss_set(pup->block, UI_EMBOSS); + pup->layout = UI_block_layout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 0, MENU_PADDING, style); + pup->slideout = false; // but ? ui_block_is_menu(but->block) : false; + pup->but = but; + uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN); + + if (!but) { + /* no button to start from, means we are a popover */ + pup->mx = window->eventstate->x; + pup->my = window->eventstate->y; + pup->popover = true; + pup->block->flag |= UI_BLOCK_NO_FLIP; + } + /* some enums reversing is strange, currently we have no good way to + * reverse some enum's but not others, so reverse all so the first menu + * items are always close to the mouse cursor */ + else { + if (but->context) + uiLayoutContextCopy(pup->layout, but->context); + } + + /* menu is created from a callback */ + pup->menu_func = menu_func; + pup->menu_arg = arg; + + handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup); + + if (!but) { + handle->popup = true; + + UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); + WM_event_add_mousemove(C); + } + + handle->can_refresh = false; + MEM_freeN(pup); + + return handle; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Popup Menu API with begin & end + * \{ */ + +/** + * Only return handler, and set optional title. + * \param block_name: Assigned to uiBlock.name (useful info for debugging). + */ +uiPopover *UI_popover_begin_ex(bContext *C, const char *block_name) +{ + uiStyle *style = UI_style_get_dpi(); + uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu"); + + pup->block = UI_block_begin(C, NULL, block_name, UI_EMBOSS); + pup->layout = UI_block_layout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 0, MENU_PADDING, style); + + /* Copied from menus, change if needed. */ + uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN); + + /* create in advance so we can let buttons point to retval already */ + pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle"); + + return pup; +} + +uiPopover *UI_popover_begin(bContext *C) +{ + return UI_popover_begin_ex(C, __func__); +} + +/** + * Setting the button makes the popover open from the button instead of the cursor. + */ +#if 0 +void UI_popover_panel_but_set(uiPopover *pup, struct ARegion *butregion, uiBut *but) +{ + pup->but = but; + pup->butregion = butregion; +} +#endif + +/* set the whole structure to work */ +void UI_popover_end(bContext *C, uiPopover *pup) +{ + wmWindow *window = CTX_wm_window(C); + uiPopupBlockHandle *menu; + uiBut *but = NULL; + ARegion *butregion = NULL; + + pup->popover = true; + pup->mx = window->eventstate->x; + pup->my = window->eventstate->y; + + if (pup->but) { + but = pup->but; + butregion = pup->butregion; + } + + menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup); + menu->popup = true; + + UI_popup_handlers_add(C, &window->modalhandlers, menu, 0); + WM_event_add_mousemove(C); + + menu->can_refresh = false; + MEM_freeN(pup); +} + +uiLayout *UI_popover_layout(uiPopover *pup) +{ + return pup->layout; +} + +/** \} */ + +/* We may want to support this in futurew */ +/* Similar to UI_popup_menu_invoke */ +// int UI_popover_panel_invoke(bContext *C, const char *idname, ReportList *reports); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 5eafd6cf596..f1b1ef44bef 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -4414,7 +4414,7 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) wt->draw(&wt->wcol, rect, block->flag, block->direction); else wt->draw(&wt->wcol, rect, 0, 0); - + if (block) { float draw_color[4]; unsigned char *color = (unsigned char *)wt->wcol.text; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 80eaa8f2649..fd83e386004 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -664,6 +664,7 @@ extern StructRNA RNA_TransformSequence; extern StructRNA RNA_UILayout; extern StructRNA RNA_UIList; extern StructRNA RNA_UIPieMenu; +extern StructRNA RNA_uiPopover; extern StructRNA RNA_UIPopupMenu; extern StructRNA RNA_UVWarpModifier; extern StructRNA RNA_UVProjectModifier; diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 367efd71519..a8ae3374b16 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -268,6 +268,29 @@ static void rna_uiItemM(uiLayout *layout, bContext *C, const char *menuname, con uiItemM(layout, C, menuname, name, icon); } +static void rna_uiItemPopoverPanel( + uiLayout *layout, bContext *C, + int space_type, int region_type, const char *panel_type, + const char *name, const char *text_ctxt, + int translate, int icon, int icon_value) +{ + /* Get translated name (label). */ + name = rna_translate_ui_text(name, text_ctxt, NULL, NULL, translate); + + if (icon_value && !icon) { + icon = icon_value; + } + + uiItemPopoverPanel(layout, C, space_type, region_type, panel_type, name, icon); +} + +static void rna_uiItemPopoverPanelFromGroup( + uiLayout *layout, bContext *C, + int space_id, int region_id, const char *context, const char *category) +{ + uiItemPopoverPanelFromGroup(layout, C, space_id, region_id, context, category); +} + static void rna_uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *name, const char *text_ctxt, int translate) { @@ -670,6 +693,29 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item"); + func = RNA_def_function(srna, "popover", "rna_uiItemPopoverPanel"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + parm = RNA_def_enum(func, "space_type", rna_enum_space_type_items, 0, "Space Type", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_enum(func, "region_type", rna_enum_region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_string(func, "panel_type", NULL, 0, "", "Identifier of the panel"); + api_ui_item_common(func); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED); + RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item"); + + func = RNA_def_function(srna, "popover_group", "rna_uiItemPopoverPanelFromGroup"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + parm = RNA_def_enum(func, "space_type", rna_enum_space_type_items, 0, "Space Type", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_enum(func, "region_type", rna_enum_region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_string(func, "context", NULL, 0, "", "panel type context"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_string(func, "category", NULL, 0, "", "panel type category"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + func = RNA_def_function(srna, "separator", "uiItemS"); RNA_def_function_ui_description(func, "Item. Inserts empty space into the layout between items"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index d7718d2e0f2..0fa7f53da9b 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -629,6 +629,17 @@ static PointerRNA rna_PopupMenu_layout_get(PointerRNA *ptr) return rptr; } +static PointerRNA rna_PopoverMenu_layout_get(PointerRNA *ptr) +{ + struct uiPopover *pup = ptr->data; + uiLayout *layout = UI_popover_layout(pup); + + PointerRNA rptr; + RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr); + + return rptr; +} + static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr) { struct uiPieMenu *pie = ptr->data; @@ -1978,6 +1989,11 @@ static void rna_def_popupmenu(BlenderRNA *brna) rna_def_popup_menu_wrapper(brna, "UIPopupMenu", "uiPopupMenu", "rna_PopupMenu_layout_get"); } +static void rna_def_popovermenu(BlenderRNA *brna) +{ + rna_def_popup_menu_wrapper(brna, "UIPopover", "uiPopover", "rna_PopoverMenu_layout_get"); +} + static void rna_def_piemenu(BlenderRNA *brna) { rna_def_popup_menu_wrapper(brna, "UIPieMenu", "uiPieMenu", "rna_PieMenu_layout_get"); @@ -2415,6 +2431,7 @@ void RNA_def_wm(BlenderRNA *brna) rna_def_event(brna); rna_def_timer(brna); rna_def_popupmenu(brna); + rna_def_popovermenu(brna); rna_def_piemenu(brna); rna_def_window(brna); rna_def_windowmanager(brna); diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 28d8115f8c6..c053f980ff3 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -348,6 +348,24 @@ static void rna_PopMenuEnd(bContext *C, PointerRNA *handle) UI_popup_menu_end(C, handle->data); } +/* popover wrapper */ +static PointerRNA rna_PopoverBegin(bContext *C) +{ + PointerRNA r_ptr; + void *data; + + data = (void *)UI_popover_begin(C); + + RNA_pointer_create(NULL, &RNA_UIPopover, data, &r_ptr); + + return r_ptr; +} + +static void rna_PopoverEnd(bContext *C, PointerRNA *handle) +{ + UI_popover_end(C, handle->data); +} + /* pie menu wrapper */ static PointerRNA rna_PieMenuBegin(bContext *C, const char *title, int icon, PointerRNA *event) { @@ -541,6 +559,22 @@ void RNA_api_wm(StructRNA *srna) parm = RNA_def_pointer(func, "menu", "UIPopupMenu", "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR); + + /* wrap UI_popover_panel_begin */ + func = RNA_def_function(srna, "popover_begin__internal", "rna_PopoverBegin"); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT); + /* return */ + parm = RNA_def_pointer(func, "menu", "UIPopover", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR); + RNA_def_function_return(func, parm); + + /* wrap UI_popover_panel_end */ + func = RNA_def_function(srna, "popover_end__internal", "rna_PopoverEnd"); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT); + parm = RNA_def_pointer(func, "menu", "UIPopover", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR); + + /* wrap uiPieMenuBegin */ func = RNA_def_function(srna, "piemenu_begin__internal", "rna_PieMenuBegin"); RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT); |