diff options
Diffstat (limited to 'source/blender/editors')
5 files changed, 104 insertions, 38 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index b987f970b9e..41bf5d5494e 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1312,10 +1312,6 @@ void uiDrawBlock(const bContext *C, uiBlock *block) rcti rect; int multisample_enabled; - /* early exit if cancelled */ - if ((block->flag & UI_BLOCK_RADIAL) && (block->pie_data.flags & UI_PIE_FINISHED)) - return; - /* get menu region or area region */ ar = CTX_wm_menu(C); if (!ar) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 5bd85f855ba..fc9d1d9f090 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -8632,6 +8632,13 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle duration = menu->scrolltimer->duration; + event_xy[0] = event->x; + event_xy[1] = event->y; + + ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]); + + ui_block_calculate_pie_segment(block, event_xy); + if (event->type == TIMER) { if (event->customdata == menu->scrolltimer) { /* deactivate initial direction after a while */ @@ -8677,24 +8684,26 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle ED_region_tag_redraw(ar); } } - } - event_xy[0] = event->x; - event_xy[1] = event->y; + /* check pie velociy here if gesture has ended */ + if (block->pie_data.flags & UI_PIE_GESTURE_END_WAIT) { + float len_sq = 10; - ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]); + /* use a time threshold to ensure we leave time to the mouse to move */ + if (duration - block->pie_data.duration_gesture > 0.02) { + len_sq = len_squared_v2v2(event_xy, block->pie_data.last_pos); + copy_v2_v2(block->pie_data.last_pos, event_xy); + block->pie_data.duration_gesture = duration; + } - ui_block_calculate_pie_segment(block, event_xy); + if (len_sq < 1.0) { + uiBut *but = ui_but_find_activated(menu->region); - if (block->pie_data.flags & UI_PIE_FINISHED) { - if ((event->type == block->pie_data.event && event->val == KM_RELEASE) || - ((event->type == RIGHTMOUSE || event->type == ESCKEY) && (event->val == KM_PRESS))) - { - menu->menuretval = UI_RETURN_OK; + if (but) { + return ui_but_pie_menu_apply(C, menu, but, true); + } + } } - - ED_region_tag_redraw(ar); - return WM_UI_HANDLER_BREAK; } if (event->type == block->pie_data.event && !is_click_style) { @@ -8714,9 +8723,18 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle block->pie_data.flags |= UI_PIE_CLICK_STYLE; } else { + float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init); uiBut *but = ui_but_find_activated(menu->region); + if (but && (U.pie_menu_confirm >= U.pie_menu_threshold) && + (sqrtf(len_sq) >= U.pie_menu_confirm)) + { + if (but) + return ui_but_pie_menu_apply(C, menu, but, true); + } + retval = ui_but_pie_menu_apply(C, menu, but, true); + } } } @@ -8726,11 +8744,23 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle switch (event->type) { case MOUSEMOVE: - if (!is_click_style && - (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) > PIE_CLICK_THRESHOLD_SQ)) - { - block->pie_data.flags |= UI_PIE_DRAG_STYLE; + if (!is_click_style) { + float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init); + + if (len_sq > PIE_CLICK_THRESHOLD_SQ) + { + block->pie_data.flags |= UI_PIE_DRAG_STYLE; + } + + if ((U.pie_menu_confirm >= U.pie_menu_threshold) && + (sqrtf(len_sq) >= U.pie_menu_confirm)) + { + block->pie_data.flags |= UI_PIE_GESTURE_END_WAIT; + copy_v2_v2(block->pie_data.last_pos, event_xy); + block->pie_data.duration_gesture = duration; + } } + ui_handle_menu_button(C, event, menu); /* mouse move should always refresh the area for pie menus */ @@ -8750,13 +8780,7 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle case ESCKEY: case RIGHTMOUSE: - if (!is_click_style) { - block->pie_data.flags |= UI_PIE_FINISHED; - menu->menuretval = 0; - ED_region_tag_redraw(ar); - } - else - menu->menuretval = UI_RETURN_CANCEL; + menu->menuretval = UI_RETURN_CANCEL; break; case AKEY: @@ -9043,6 +9067,7 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata) struct ARegion *menu_region; /* we block all events, this is modal interaction, except for drop events which is described below */ int retval = WM_UI_HANDLER_BREAK; + bool reset_pie = false; menu_region = CTX_wm_menu(C); CTX_wm_menu_set(C, menu->region); @@ -9063,6 +9088,13 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata) wmWindow *win = CTX_wm_window(C); /* copy values, we have to free first (closes region) */ uiPopupBlockHandle temp = *menu; + uiBlock *block = menu->region->uiblocks.first; + + /* set last pie event to allow chained pie spawning */ + if (block->flag & UI_BLOCK_RADIAL) { + win->last_pie_event = block->pie_data.event; + reset_pie = true; + } ui_popup_block_free(C, menu); UI_remove_popup_handlers(&win->modalhandlers, menu); @@ -9094,6 +9126,14 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata) /* delayed apply callbacks */ ui_apply_but_funcs_after(C); + if (reset_pie) { + /* reaqcuire window in case pie invalidates it somehow */ + wmWindow *win = CTX_wm_window(C); + + if (win) + win->last_pie_event = EVENT_NONE; + } + CTX_wm_region_set(C, menu_region); return retval; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 2f66c4a9900..efd67effd73 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -168,9 +168,9 @@ enum { UI_PIE_INITIAL_DIRECTION = (1 << 1), /* use initial center of pie menu to calculate direction */ UI_PIE_DRAG_STYLE = (1 << 2), /* pie menu is drag style */ UI_PIE_INVALID_DIR = (1 << 3), /* mouse not far enough from center position */ - UI_PIE_FINISHED = (1 << 4), /* pie menu finished but we still wait for a release event */ - UI_PIE_CLICK_STYLE = (1 << 5), /* pie menu changed to click style, click to confirm */ - UI_PIE_ANIMATION_FINISHED = (1 << 6), /* pie animation finished, do not calculate any more motio */ + UI_PIE_CLICK_STYLE = (1 << 4), /* pie menu changed to click style, click to confirm */ + UI_PIE_ANIMATION_FINISHED = (1 << 5), /* pie animation finished, do not calculate any more motion */ + UI_PIE_GESTURE_END_WAIT = (1 << 6), /* pie gesture selection has been done, now wait for mouse motion to end */ }; #define PIE_CLICK_THRESHOLD_SQ 50.0f @@ -310,6 +310,8 @@ struct PieMenuData { float pie_dir[2]; float pie_center_init[2]; float pie_center_spawned[2]; + float last_pos[2]; + double duration_gesture; int flags; int event; /* initial event used to fire the pie menu, store here so we can query for release */ float alphafac; diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 5739ebebe64..49823d4e472 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2709,8 +2709,18 @@ static float uiPieTitleWidth(const char *name, int icon) 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"); + uiStyle *style; + uiPieMenu *pie; + short event_type; + + wmWindow *win = CTX_wm_window(C); + + /* allow respawning a pie from the last pie event */ + if (event->type == win->lock_pie_event && event->type != win->last_pie_event) + return NULL; + + style = UI_GetStyleDraw(); + pie = MEM_callocN(sizeof(uiPopupMenu), "pie menu"); pie->block_radial = uiBeginBlock(C, NULL, __func__, UI_EMBOSS); /* may be useful later to allow spawning pies @@ -2718,10 +2728,17 @@ uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const /* 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; + + if (win->last_pie_event != EVENT_NONE) + event_type = win->last_pie_event; + else + event_type = event->type; + + pie->block_radial->pie_data.event = event_type; + win->lock_pie_event = event_type; /* if pie is spawned by a left click, it is always assumed to be click style */ - if (event->type == LEFTMOUSE) { + if (event_type == LEFTMOUSE) { pie->block_radial->flag |= UI_PIE_CLICK_STYLE; } @@ -2785,7 +2802,8 @@ void uiPieMenuInvoke(struct bContext *C, const char *idname, const wmEvent *even if (mt->poll && mt->poll(C, mt) == 0) return; - pie = uiPieMenuBegin(C, IFACE_(mt->label), ICON_NONE, event); + if (!(pie = uiPieMenuBegin(C, IFACE_(mt->label), ICON_NONE, event))) + return; layout = uiPieMenuLayout(pie); menu.layout = layout; @@ -2806,7 +2824,9 @@ void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char * uiPieMenu *pie; uiLayout *layout; - pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event); + if (!(pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event))) + return; + layout = uiPieMenuLayout(pie); layout = uiLayoutRadial(layout); @@ -2836,7 +2856,9 @@ void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path, return; } - pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event); + if (!(pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event))) + return; + layout = uiPieMenuLayout(pie); layout = uiLayoutRadial(layout); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f958c70ae50..2355d2be9e6 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -3838,6 +3838,8 @@ void ui_draw_pie_center(uiBlock *block) float pie_radius_internal = U.pixelsize * U.pie_menu_threshold; float pie_radius_external = U.pixelsize * (U.pie_menu_threshold + 7.0f); + float pie_confirm_radius = U.pixelsize * (U.pie_menu_confirm); + float pie_confirm_external = U.pixelsize * (U.pie_menu_confirm + 2.0f); int subd = 40; @@ -3874,6 +3876,10 @@ void ui_draw_pie_center(uiBlock *block) glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd); glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd); + if (pie_confirm_radius > pie_radius_external) { + glColor4ub(btheme->tui.wcol_pie_menu.text_sel[0], btheme->tui.wcol_pie_menu.text_sel[1], btheme->tui.wcol_pie_menu.text_sel[2], 64); + draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, NULL, NULL, false); + } glDisable(GL_BLEND); glPopMatrix(); } |