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.c260
1 files changed, 244 insertions, 16 deletions
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 3629c72ce49..084b0c0ac67 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -43,6 +43,8 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "PIL_time.h"
+
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_report.h"
@@ -1704,18 +1706,69 @@ uiBlock *ui_popup_block_refresh(
BLI_addhead(&block->saferct, saferct);
}
- /* clip block with window boundary */
- ui_popup_block_clip(window, block);
-
- /* the block and buttons were positioned in window space as in 2.4x, now
- * these menu blocks are regions so we bring it back to region space.
- * additionally we add some padding for the menu shadow or rounded menus */
- ar->winrct.xmin = block->rect.xmin - width;
- ar->winrct.xmax = block->rect.xmax + width;
- ar->winrct.ymin = block->rect.ymin - width;
- ar->winrct.ymax = block->rect.ymax + MENU_TOP;
-
- ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+ if (block->flag & UI_BLOCK_RADIAL) {
+ uiBut *but;
+ int win_width = UI_SCREEN_MARGIN;
+ int winx, winy;
+
+ int x_offset = 0, y_offset = 0;
+
+ winx = WM_window_pixels_x(window);
+ winy = WM_window_pixels_y(window);
+
+ copy_v2_v2(block->pie_data.pie_center_init, block->pie_data.pie_center_spawned);
+
+ /* only try translation if area is large enough */
+ if (BLI_rctf_size_x(&block->rect) < winx - (2.0f * win_width)) {
+ if (block->rect.xmin < win_width ) x_offset += win_width - block->rect.xmin;
+ if (block->rect.xmax > winx - win_width) x_offset += winx - win_width - block->rect.xmax;
+ }
+
+ if (BLI_rctf_size_y(&block->rect) < winy - (2.0f * win_width)) {
+ if (block->rect.ymin < win_width ) y_offset += win_width - block->rect.ymin;
+ if (block->rect.ymax > winy - win_width) y_offset += winy - win_width - block->rect.ymax;
+ }
+ /* if we are offsetting set up initial data for timeout functionality */
+
+ if ((x_offset != 0) || (y_offset != 0)) {
+ block->pie_data.pie_center_spawned[0] += x_offset;
+ block->pie_data.pie_center_spawned[1] += y_offset;
+
+ ui_block_translate(block, x_offset, y_offset);
+
+ if (U.pie_initial_timeout > 0)
+ block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
+ }
+
+ ar->winrct.xmin = 0;
+ ar->winrct.xmax = winx;
+ ar->winrct.ymin = 0;
+ ar->winrct.ymax = winy;
+
+ ui_block_calculate_pie_segment(block, block->pie_data.pie_center_init);
+
+ /* 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));
+ }
+ }
+ }
+ }
+ else {
+ /* clip block with window boundary */
+ ui_popup_block_clip(window, block);
+ /* the block and buttons were positioned in window space as in 2.4x, now
+ * these menu blocks are regions so we bring it back to region space.
+ * additionally we add some padding for the menu shadow or rounded menus */
+ ar->winrct.xmin = block->rect.xmin - width;
+ ar->winrct.xmax = block->rect.xmax + width;
+ ar->winrct.ymin = block->rect.ymin - width;
+ ar->winrct.ymax = block->rect.ymax + MENU_TOP;
+
+ ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+ }
if (block_old) {
block->oldblock = block_old;
@@ -2353,6 +2406,12 @@ struct uiPopupMenu {
void *menu_arg;
};
+struct uiPieMenu {
+ uiBlock *block_radial; /* radial block of the pie menu (more could be added later) */
+ uiLayout *layout;
+ int mx, my;
+};
+
static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
{
uiBlock *block;
@@ -2526,7 +2585,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut
if (!but) {
handle->popup = true;
- UI_add_popup_handlers(C, &window->modalhandlers, handle);
+ UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
WM_event_add_mousemove(C);
}
@@ -2588,7 +2647,7 @@ void uiPupMenuEnd(bContext *C, uiPopupMenu *pup)
menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup);
menu->popup = true;
- UI_add_popup_handlers(C, &window->modalhandlers, menu);
+ UI_add_popup_handlers(C, &window->modalhandlers, menu, false);
WM_event_add_mousemove(C);
MEM_freeN(pup);
@@ -2599,6 +2658,175 @@ uiLayout *uiPupMenuLayout(uiPopupMenu *pup)
return pup->layout;
}
+/*************************** Pie Menus ***************************************/
+
+static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handle, void *arg_pie)
+{
+ uiBlock *block;
+ uiPieMenu *pie = arg_pie;
+ int minwidth, width, height;
+
+ minwidth = 50;
+ block = pie->block_radial;
+
+ /* 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)
+ uiBlockSetRegion(block, handle->region);
+
+ uiBlockLayoutResolve(block, &width, &height);
+
+ uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
+
+ block->minbounds = minwidth;
+ block->bounds = 1;
+ block->mx = 0;
+ block->my = 0;
+ block->bounds_type = UI_BLOCK_BOUNDS_PIE_CENTER;
+
+ block->pie_data.pie_center_spawned[0] = pie->mx;
+ block->pie_data.pie_center_spawned[1] = pie->my;
+
+ return pie->block_radial;
+}
+
+static float uiPieTitleWidth(const char *name, int icon)
+{
+ return (UI_GetStringWidth(name) +
+ (UI_UNIT_X * (1.50f + (icon ? 0.25f : 0.0f))));
+}
+
+uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const wmEvent *event)
+{
+ uiStyle *style = UI_GetStyleDraw();
+ uiPieMenu *pie = MEM_callocN(sizeof(uiPopupMenu), "pie menu");
+
+ pie->block_radial = uiBeginBlock(C, NULL, __func__, UI_EMBOSS);
+ /* may be useful later to allow spawning pies
+ * from old positions */
+ /* pie->block_radial->flag |= UI_BLOCK_POPUP_MEMORY; */
+ pie->block_radial->puphash = ui_popup_menu_hash(title);
+ pie->block_radial->flag |= UI_BLOCK_RADIAL;
+ pie->block_radial->pie_data.event = event->type;
+
+ pie->layout = uiBlockLayout(pie->block_radial, UI_LAYOUT_VERTICAL, UI_LAYOUT_PIEMENU, 0, 0, 200, 0, 0, style);
+ pie->mx = event->x;
+ pie->my = event->y;
+
+ /* create title button */
+ if (title[0]) {
+ char titlestr[256];
+ int w;
+ if (icon) {
+ BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
+ w = uiPieTitleWidth(titlestr, icon);
+ uiDefIconTextBut(pie->block_radial, LABEL, 0, icon, titlestr, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ w = uiPieTitleWidth(title, 0);
+ uiDefBut(pie->block_radial, LABEL, 0, title, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ }
+
+ return pie;
+}
+
+void uiPieMenuEnd(bContext *C, uiPieMenu *pie)
+{
+ wmWindow *window = CTX_wm_window(C);
+ uiPopupBlockHandle *menu;
+
+ menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie);
+ menu->popup = true;
+ menu->towardstime = PIL_check_seconds_timer();
+
+ UI_add_popup_handlers(C, &window->modalhandlers, menu, true);
+ WM_event_add_mousemove(C);
+
+ MEM_freeN(pie);
+}
+
+uiLayout *uiPieMenuLayout(uiPieMenu *pie)
+{
+ return pie->layout;
+}
+
+void uiPieMenuInvoke(struct bContext *C, const char *idname, const wmEvent *event)
+{
+ uiPieMenu *pie;
+ uiLayout *layout;
+ Menu menu;
+ MenuType *mt = WM_menutype_find(idname, true);
+
+ if (mt == NULL) {
+ printf("%s: named menu \"%s\" not found\n", __func__, idname);
+ return;
+ }
+
+ if (mt->poll && mt->poll(C, mt) == 0)
+ return;
+
+ pie = uiPieMenuBegin(C, IFACE_(mt->label), ICON_NONE, event);
+ layout = uiPieMenuLayout(pie);
+
+ menu.layout = layout;
+ menu.type = mt;
+
+ if (G.debug & G_DEBUG_WM) {
+ printf("%s: opening menu \"%s\"\n", __func__, idname);
+ }
+
+ mt->draw(C, &menu);
+
+ uiPieMenuEnd(C, pie);
+}
+
+void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
+ const char *propname, const wmEvent *event)
+{
+ uiPieMenu *pie;
+ uiLayout *layout;
+
+ pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event);
+ layout = uiPieMenuLayout(pie);
+
+ layout = uiLayoutRadial(layout);
+ uiItemsEnumO(layout, opname, propname);
+
+ uiPieMenuEnd(C, pie);
+}
+
+void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path,
+ const wmEvent *event)
+{
+ PointerRNA ctx_ptr;
+ PointerRNA r_ptr;
+ PropertyRNA *r_prop;
+ uiPieMenu *pie;
+ uiLayout *layout;
+
+ RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
+
+ if (!RNA_path_resolve(&ctx_ptr, path, &r_ptr, &r_prop)) {
+ return;
+ }
+
+ /* invalid property, only accept enums */
+ if (RNA_property_type(r_prop) != PROP_ENUM) {
+ BLI_assert(0);
+ return;
+ }
+
+ pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event);
+ layout = uiPieMenuLayout(pie);
+
+ layout = uiLayoutRadial(layout);
+ uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, NULL, 0);
+
+ uiPieMenuEnd(C, pie);
+}
+
+
/*************************** Standard Popup Menus ****************************/
void uiPupMenuReports(bContext *C, ReportList *reports)
@@ -2695,7 +2923,7 @@ void uiPupBlockO(bContext *C, uiBlockCreateFunc func, void *arg, const char *opn
handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
handle->opcontext = opcontext;
- UI_add_popup_handlers(C, &window->modalhandlers, handle);
+ UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
WM_event_add_mousemove(C);
}
@@ -2718,7 +2946,7 @@ void uiPupBlockEx(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_f
handle->cancel_func = cancel_func;
// handle->opcontext = opcontext;
- UI_add_popup_handlers(C, &window->modalhandlers, handle);
+ UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
WM_event_add_mousemove(C);
}