Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/interface/interface_regions.c')
-rw-r--r--source/blender/editors/interface/interface_regions.c364
1 files changed, 293 insertions, 71 deletions
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 0b586dd9fca..b3972bebd96 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -70,7 +70,6 @@
#include "interface_intern.h"
-#define MENU_TOP (int)(8 * UI_DPI_FAC)
#define MENU_PADDING (int)(0.2f * UI_UNIT_Y)
#define MENU_BORDER (int)(0.3f * U.widget_unit)
@@ -112,13 +111,19 @@ bool ui_but_menu_step_poll(const uiBut *but)
BLI_assert(but->type == UI_BTYPE_MENU);
/* currenly only RNA buttons */
- return (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM);
+ return ((but->menu_step_func != NULL) ||
+ (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM));
}
int ui_but_menu_step(uiBut *but, int direction)
{
if (ui_but_menu_step_poll(but)) {
- return rna_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, direction);
+ if (but->menu_step_func) {
+ return but->menu_step_func(but->block->evil_C, direction, but->poin);
+ }
+ else {
+ return rna_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, direction);
+ }
}
printf("%s: cannot cycle button '%s'\n", __func__, but->str);
@@ -233,11 +238,11 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
int i, multisample_enabled;
/* disable AA, makes widgets too blurry */
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE_ARB);
+ multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
if (multisample_enabled)
- glDisable(GL_MULTISAMPLE_ARB);
+ glDisable(GL_MULTISAMPLE);
- wmOrtho2_region_ui(ar);
+ wmOrtho2_region_pixelspace(ar);
/* draw background */
ui_draw_tooltip_background(UI_style_get(), NULL, &bbox);
@@ -337,7 +342,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
BLF_disable(blf_mono_font, BLF_WORD_WRAP);
if (multisample_enabled)
- glEnable(GL_MULTISAMPLE_ARB);
+ glEnable(GL_MULTISAMPLE);
}
static void ui_tooltip_region_free_cb(ARegion *ar)
@@ -349,24 +354,8 @@ static void ui_tooltip_region_free_cb(ARegion *ar)
ar->regiondata = NULL;
}
-ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
+static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
{
- const float pad_px = UI_TIP_PADDING;
- wmWindow *win = CTX_wm_window(C);
- uiStyle *style = UI_style_get();
- static ARegionType type;
- ARegion *ar;
- uiTooltipData *data;
-/* IDProperty *prop;*/
- char buf[512];
- /* aspect values that shrink text are likely unreadable */
- const float aspect = min_ff(1.0f, but->block->aspect);
- int fonth, fontw;
- int winx, ofsx, ofsy, h, i;
- rctf rect_fl;
- rcti rect_i;
- int font_flag = 0;
-
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
@@ -375,11 +364,10 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
- if (but->drawflag & UI_BUT_NO_TOOLTIP)
- return NULL;
+ char buf[512];
/* create tooltip data */
- data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
+ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
UI_but_string_info_get(C, but, &but_tip, &enum_label, &enum_tip, &op_keymap, &prop_keymap, &rna_struct, &rna_prop, NULL);
@@ -529,33 +517,18 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
if (but->rnapoin.id.data) {
/* this could get its own 'BUT_GET_...' type */
- PointerRNA *ptr = &but->rnapoin;
- PropertyRNA *prop = but->rnaprop;
- ID *id = ptr->id.data;
-
- char *id_path;
- char *data_path = NULL;
/* never fails */
- id_path = RNA_path_full_ID_py(id);
-
- if (ptr->data && prop) {
- data_path = RNA_path_from_ID_to_property(ptr, prop);
- }
+ char *id_path;
- if (data_path) {
- const char *data_delim = (data_path[0] == '[') ? "" : ".";
- BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]),
- "%s%s%s", /* no need to translate */
- id_path, data_delim, data_path);
- MEM_freeN(data_path);
+ if (but->rnaprop) {
+ id_path = RNA_path_full_property_py_ex(&but->rnapoin, but->rnaprop, but->rnaindex, true);
}
- else if (prop) {
- /* can't find the path. be explicit in our ignorance "..." */
- BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]),
- "%s ... %s", /* no need to translate */
- id_path, rna_prop.strinfo ? rna_prop.strinfo : RNA_property_identifier(prop));
+ else {
+ id_path = RNA_path_full_struct_py(&but->rnapoin);
}
+
+ BLI_strncat_utf8(data->lines[data->totline], id_path, sizeof(data->lines[0]));
MEM_freeN(id_path);
data->format[data->totline].style = UI_TIP_STYLE_MONO;
@@ -586,6 +559,36 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
MEM_freeN(data);
return NULL;
}
+ else {
+ return data;
+ }
+}
+
+ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
+{
+ const float pad_px = UI_TIP_PADDING;
+ wmWindow *win = CTX_wm_window(C);
+ const int winx = WM_window_pixels_x(win);
+ uiStyle *style = UI_style_get();
+ static ARegionType type;
+ ARegion *ar;
+/* IDProperty *prop;*/
+ /* aspect values that shrink text are likely unreadable */
+ const float aspect = min_ff(1.0f, but->block->aspect);
+ int fonth, fontw;
+ int ofsx, ofsy, h, i;
+ rctf rect_fl;
+ rcti rect_i;
+ int font_flag = 0;
+
+ if (but->drawflag & UI_BUT_NO_TOOLTIP) {
+ return NULL;
+ }
+
+ uiTooltipData *data = ui_tooltip_data_from_button(C, but);
+ if (data == NULL) {
+ return NULL;
+ }
/* create area region */
ar = ui_region_temp_add(CTX_wm_screen(C));
@@ -602,7 +605,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
UI_fontstyle_set(&data->fstyle);
- data->wrap_width = min_ii(UI_TIP_MAXWIDTH * U.pixelsize / aspect, WM_window_pixels_x(win) - (UI_TIP_PADDING * 2));
+ data->wrap_width = min_ii(UI_TIP_MAXWIDTH * U.pixelsize / aspect, winx - (UI_TIP_PADDING * 2));
font_flag |= BLF_WORD_WRAP;
if (data->fstyle.kerning == 1) {
@@ -625,8 +628,9 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
w = BLF_width_ex(data->fstyle.uifont_id, data->header, sizeof(data->header), &info);
- if (enum_label.strinfo) {
- x_pos = info.width + (U.widget_unit / 2);
+ /* check for enum label */
+ if (data->active_info[0]) {
+ x_pos = info.width;
w = max_ii(w, x_pos + BLF_width(data->fstyle.uifont_id, data->active_info, sizeof(data->active_info)));
}
}
@@ -694,8 +698,6 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
#undef TIP_BORDER_Y
/* clip with window boundaries */
- winx = WM_window_pixels_x(win);
-
if (rect_i.xmax > winx) {
/* super size */
if (rect_i.xmax > winx + rect_i.xmin) {
@@ -822,12 +824,12 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int
int UI_searchbox_size_y(void)
{
- return SEARCH_ITEMS * UI_UNIT_Y + 2 * MENU_TOP;
+ return SEARCH_ITEMS * UI_UNIT_Y + 2 * UI_POPUP_MENU_TOP;
}
int UI_searchbox_size_x(void)
{
- return 12 * UI_UNIT_X;
+ return 10 * UI_UNIT_X;
}
int UI_search_items_find_index(uiSearchItems *items, const char *name)
@@ -898,13 +900,13 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
}
/* list view */
else {
- int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / SEARCH_ITEMS;
+ int buth = (BLI_rcti_size_y(&data->bbox) - 2 * UI_POPUP_MENU_TOP) / SEARCH_ITEMS;
*r_rect = data->bbox;
r_rect->xmin = data->bbox.xmin + 3.0f;
r_rect->xmax = data->bbox.xmax - 3.0f;
- r_rect->ymax = data->bbox.ymax - MENU_TOP - itemnr * buth;
+ r_rect->ymax = data->bbox.ymax - UI_POPUP_MENU_TOP - itemnr * buth;
r_rect->ymin = r_rect->ymax - buth;
}
@@ -1083,7 +1085,7 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
uiSearchboxData *data = ar->regiondata;
/* pixel space */
- wmOrtho2_region_ui(ar);
+ wmOrtho2_region_pixelspace(ar);
if (data->noback == false)
ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
@@ -1162,7 +1164,7 @@ static void ui_searchbox_region_free_cb(ARegion *ar)
ar->regiondata = NULL;
}
-ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
+ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but)
{
wmWindow *win = CTX_wm_window(C);
uiStyle *style = UI_style_get();
@@ -1326,6 +1328,110 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
return ar;
}
+/**
+ * Similar to Python's `str.title` except...
+ *
+ * - we know words are upper case and ascii only.
+ * - '_' are replaces by spaces.
+ */
+static void str_tolower_titlecaps_ascii(char *str, const size_t len)
+{
+ size_t i;
+ bool prev_delim = true;
+
+ for (i = 0; (i < len) && str[i]; i++) {
+ if (str[i] >= 'A' && str[i] <= 'Z') {
+ if (prev_delim == false) {
+ str[i] += 'a' - 'A';
+ }
+ }
+ else if (str[i] == '_') {
+ str[i] = ' ';
+ }
+
+ prev_delim = ELEM(str[i], ' ') || (str[i] >= '0' && str[i] <= '9');
+ }
+
+}
+
+static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARegion *ar)
+{
+ uiSearchboxData *data = ar->regiondata;
+
+ /* pixel space */
+ wmOrtho2_region_pixelspace(ar);
+
+ if (data->noback == false)
+ ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
+
+ /* draw text */
+ if (data->items.totitem) {
+ rcti rect;
+ int a;
+
+ /* draw items */
+ for (a = 0; a < data->items.totitem; a++) {
+ rcti rect_pre, rect_post;
+ ui_searchbox_butrect(&rect, data, a);
+
+ rect_pre = rect;
+ rect_post = rect;
+
+ rect_pre.xmax = rect_post.xmin = rect.xmin + ((rect.xmax - rect.xmin) / 4);
+
+ /* widget itself */
+ {
+ wmOperatorType *ot = data->items.pointers[a];
+
+ int state = (a == data->active) ? UI_ACTIVE : 0;
+ char text_pre[128];
+ char *text_pre_p = strstr(ot->idname, "_OT_");
+ if (text_pre_p == NULL) {
+ text_pre[0] = '\0';
+ }
+ else {
+ int text_pre_len;
+ text_pre_p += 1;
+ text_pre_len = BLI_strncpy_rlen(
+ text_pre, ot->idname, min_ii(sizeof(text_pre), text_pre_p - ot->idname));
+ text_pre[text_pre_len] = ':';
+ text_pre[text_pre_len + 1] = '\0';
+ str_tolower_titlecaps_ascii(text_pre, sizeof(text_pre));
+ }
+
+ rect_pre.xmax += 4; /* sneaky, avoid showing ugly margin */
+ ui_draw_menu_item(&data->fstyle, &rect_pre, text_pre, data->items.icons[a], state, false);
+ ui_draw_menu_item(&data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep);
+ }
+
+ }
+ /* indicate more */
+ if (data->items.more) {
+ ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
+ glEnable(GL_BLEND);
+ UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
+ glDisable(GL_BLEND);
+ }
+ if (data->items.offset) {
+ ui_searchbox_butrect(&rect, data, 0);
+ glEnable(GL_BLEND);
+ UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
+ glDisable(GL_BLEND);
+ }
+ }
+}
+
+ARegion *ui_searchbox_create_operator(bContext *C, ARegion *butregion, uiBut *but)
+{
+ ARegion *ar;
+
+ ar = ui_searchbox_create_generic(C, butregion, but);
+
+ ar->type->draw = ui_searchbox_region_draw_cb__operator;
+
+ return ar;
+}
+
void ui_searchbox_free(bContext *C, ARegion *ar)
{
ui_region_temp_remove(C, CTX_wm_screen(C), ar);
@@ -1515,7 +1621,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
// yof = ysize; (not with menu scrolls)
}
}
-
+
+#if 0 /* seems redundant and causes issues with blocks inside big regions */
/* or no space left or right */
if (left == 0 && right == 0) {
if (dir1 == UI_DIR_UP || dir1 == UI_DIR_DOWN) {
@@ -1523,7 +1630,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
xof = -block->rect.xmin + 5;
}
}
-
+#endif
+
#if 0
/* clamp to window bounds, could be made into an option if its ever annoying */
if ( (offscreen = (block->rect.ymin + yof)) < 0) yof -= offscreen; /* bottom */
@@ -1630,8 +1738,8 @@ static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
if (block->rect.ymin < width)
block->rect.ymin = width;
- if (block->rect.ymax > winy - MENU_TOP)
- block->rect.ymax = winy - MENU_TOP;
+ if (block->rect.ymax > winy - UI_POPUP_MENU_TOP)
+ block->rect.ymax = winy - UI_POPUP_MENU_TOP;
/* ensure menu items draw inside left/right boundary */
for (bt = block->buttons.first; bt; bt = bt->next) {
@@ -1680,10 +1788,20 @@ void ui_popup_block_scrolltest(uiBlock *block)
static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle)
{
- ui_region_temp_remove(C, CTX_wm_screen(C), handle->region);
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
+
+ ui_region_temp_remove(C, sc, handle->region);
+
+ /* reset to region cursor (only if there's not another menu open) */
+ if (BLI_listbase_is_empty(&sc->regionbase)) {
+ ED_region_cursor_set(win, CTX_wm_area(C), CTX_wm_region(C));
+ /* in case cursor needs to be changed again */
+ WM_event_add_mousemove(C);
+ }
if (handle->scrolltimer)
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), handle->scrolltimer);
+ WM_event_remove_timer(CTX_wm_manager(C), win, handle->scrolltimer);
}
/**
@@ -1760,7 +1878,6 @@ uiBlock *ui_popup_block_refresh(
}
if (block->flag & UI_BLOCK_RADIAL) {
- uiBut *but;
int win_width = UI_SCREEN_MARGIN;
int winx, winy;
@@ -1802,9 +1919,9 @@ uiBlock *ui_popup_block_refresh(
/* lastly set the buttons at the center of the pie menu, ready for animation */
if (U.pie_animation_timeout > 0) {
- for (but = block->buttons.first; but; but = but->next) {
- if (but->pie_dir != UI_RADIAL_NONE) {
- BLI_rctf_recenter(&but->rect, UNPACK2(block->pie_data.pie_center_spawned));
+ for (uiBut *but_iter = block->buttons.first; but_iter; but_iter = but_iter->next) {
+ if (but_iter->pie_dir != UI_RADIAL_NONE) {
+ BLI_rctf_recenter(&but_iter->rect, UNPACK2(block->pie_data.pie_center_spawned));
}
}
}
@@ -1818,7 +1935,7 @@ uiBlock *ui_popup_block_refresh(
ar->winrct.xmin = block->rect.xmin - margin;
ar->winrct.xmax = block->rect.xmax + margin;
ar->winrct.ymin = block->rect.ymin - margin;
- ar->winrct.ymax = block->rect.ymax + MENU_TOP;
+ ar->winrct.ymax = block->rect.ymax + UI_POPUP_MENU_TOP;
ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
}
@@ -1858,11 +1975,19 @@ uiPopupBlockHandle *ui_popup_block_create(
void *arg)
{
wmWindow *window = CTX_wm_window(C);
+ uiBut *activebut = UI_context_active_but_get(C);
static ARegionType type;
ARegion *ar;
uiBlock *block;
uiPopupBlockHandle *handle;
+ /* disable tooltips from buttons below */
+ if (activebut) {
+ UI_but_tooltip_timer_remove(C, activebut);
+ }
+ /* standard cursor by default */
+ WM_cursor_set(window, CURSOR_STD);
+
/* create handle */
handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
@@ -2839,6 +2964,8 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co
}
/* do not align left */
but->drawflag &= ~UI_BUT_TEXT_LEFT;
+ pie->block_radial->pie_data.title = but->str;
+ pie->block_radial->pie_data.icon = icon;
}
return pie;
@@ -2950,6 +3077,101 @@ int UI_pie_menu_invoke_from_rna_enum(
return OPERATOR_INTERFACE;
}
+/**
+ * \name Pie Menu Levels
+ *
+ * Pie menus can't contain more than 8 items (yet). When using #uiItemsFullEnumO, a "More" button is created that calls
+ * a new pie menu if the enum has too many items. We call this a new "level".
+ * Indirect recursion is used, so that a theoretically unlimited number of items is supported.
+ *
+ * This is a implementation specifically for operator enums, needed since the object mode pie now has more than 8
+ * items. Ideally we'd have some way of handling this for all kinds of pie items, but that's tricky.
+ *
+ * - Julian (Feb 2016)
+ *
+ * \{ */
+
+typedef struct PieMenuLevelData {
+ char title[UI_MAX_NAME_STR]; /* parent pie title, copied for level */
+ int icon; /* parent pie icon, copied for level */
+ int totitem; /* total count of *remaining* items */
+
+ /* needed for calling uiItemsFullEnumO_array again for new level */
+ wmOperatorType *ot;
+ const char *propname;
+ IDProperty *properties;
+ int context, flag;
+} PieMenuLevelData;
+
+/**
+ * Invokes a new pie menu for a new level.
+ */
+static void ui_pie_menu_level_invoke(bContext *C, void *argN, void *arg2)
+{
+ EnumPropertyItem *item_array = (EnumPropertyItem *)argN;
+ PieMenuLevelData *lvl = (PieMenuLevelData *)arg2;
+ wmWindow *win = CTX_wm_window(C);
+
+ uiPieMenu *pie = UI_pie_menu_begin(C, IFACE_(lvl->title), lvl->icon, win->eventstate);
+ uiLayout *layout = UI_pie_menu_layout(pie);
+
+ layout = uiLayoutRadial(layout);
+
+ PointerRNA ptr;
+
+ WM_operator_properties_create_ptr(&ptr, lvl->ot);
+ /* so the context is passed to itemf functions (some need it) */
+ WM_operator_properties_sanitize(&ptr, false);
+ PropertyRNA *prop = RNA_struct_find_property(&ptr, lvl->propname);
+
+ if (prop) {
+ uiItemsFullEnumO_items(
+ layout, lvl->ot, ptr, prop, lvl->properties, lvl->context, lvl->flag,
+ item_array, lvl->totitem);
+ }
+ else {
+ RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), lvl->propname);
+ }
+
+ UI_pie_menu_end(C, pie);
+}
+
+/**
+ * Set up data for defining a new pie menu level and add button that invokes it.
+ */
+void ui_pie_menu_level_create(
+ uiBlock *block, wmOperatorType *ot, const char *propname, IDProperty *properties,
+ const EnumPropertyItem *items, int totitem, int context, int flag)
+{
+ const int totitem_parent = PIE_MAX_ITEMS - 1;
+ const int totitem_remain = totitem - totitem_parent;
+ size_t array_size = sizeof(EnumPropertyItem) * totitem_remain;
+
+ /* used as but->func_argN so freeing is handled elsewhere */
+ EnumPropertyItem *remaining = MEM_mallocN(array_size + sizeof(EnumPropertyItem), "pie_level_item_array");
+ memcpy(remaining, items + totitem_parent, array_size);
+ /* a NULL terminating sentinal element is required */
+ memset(&remaining[totitem_remain], 0, sizeof(EnumPropertyItem));
+
+
+ /* yuk, static... issue is we can't reliably free this without doing dangerous changes */
+ static PieMenuLevelData lvl;
+ BLI_strncpy(lvl.title, block->pie_data.title, UI_MAX_NAME_STR);
+ lvl.totitem = totitem_remain;
+ lvl.ot = ot;
+ lvl.propname = propname;
+ lvl.properties = properties;
+ lvl.context = context;
+ lvl.flag = flag;
+
+ /* add a 'more' menu entry */
+ uiBut *but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_PLUS, "More", 0, 0, UI_UNIT_X * 3, UI_UNIT_Y, NULL,
+ 0.0f, 0.0f, 0.0f, 0.0f, "Show more items of this menu");
+ UI_but_funcN_set(but, ui_pie_menu_level_invoke, remaining, &lvl);
+}
+
+/** \} */ /* Pie Menu Levels */
+
/*************************** Standard Popup Menus ****************************/