[Bf-blender-cvs] [9fcc1a3] master: Pie menus: Confirm threshold

Antony Riakiotakis noreply at git.blender.org
Mon Oct 13 14:35:52 CEST 2014


Commit: 9fcc1a32df1377d22b950854fabc7af53a67b813
Author: Antony Riakiotakis
Date:   Fri Oct 10 19:13:40 2014 +0200
Branches: master
https://developer.blender.org/rB9fcc1a32df1377d22b950854fabc7af53a67b813

Pie menus: Confirm threshold

This commit adds a confirm threshold property to pie menus.

Basically, this will confirm the pie menu automatically when
the distance from the center of the pie exceeds that threshold without
a need to release the pie button.

The confirm threshold will only work if it is larger than the pie
threshold.

The confirmation actually occur when the mouse stops moving, to
allow multiple pie menus to be better linked together, (see below)

This functionality also facilitates the ability for chained pie menus by
dragging. Basically, a pie menu item can be a call_menu_pie operator and
the new pie menu will still use the original pie menu release event for
confirmation. This should allow for quick, gesture based navigation in
pie menu hierarchies (going back in the hierarchy is still not supported
though)

There will be a demonstration pie in the official add-on soon

===================================================================

M	release/scripts/modules/bpy_types.py
M	release/scripts/startup/bl_ui/space_userpref.py
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_regions.c
M	source/blender/editors/interface/interface_widgets.c
M	source/blender/makesdna/DNA_userdef_types.h
M	source/blender/makesdna/DNA_windowmanager_types.h
M	source/blender/makesrna/intern/rna_userdef.c
M	source/blender/windowmanager/intern/wm_event_system.c

===================================================================

diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index e197663..c7ec7e1 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -144,10 +144,11 @@ class WindowManager(bpy_types.ID):
         import bpy
         pie = self.piemenu_begin__internal(title, icon, event)
 
-        try:
-            draw_func(pie, bpy.context)
-        finally:
-            self.piemenu_end__internal(pie)
+        if pie:
+            try:
+                draw_func(pie, bpy.context)
+            finally:
+                self.piemenu_end__internal(pie)
 
 
 class _GenericBone:
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index dc18dd7..a7ddec0 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -223,6 +223,7 @@ class USERPREF_PT_interface(Panel):
         sub.prop(view, "pie_initial_timeout")
         sub.prop(view, "pie_menu_radius")
         sub.prop(view, "pie_menu_threshold")
+        sub.prop(view, "pie_menu_confirm")
         col.separator()
         col.separator()
         col.separator()
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index b987f97..41bf5d5 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 5bd85f8..fc9d1d9 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 2f66c4a..efd67ef 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 5739ebe..49823d4 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 cli

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list