[Bf-blender-cvs] [e13bc48] pie-menus: Angle range based collision detection on pie menu radial items. Also some code to draw a central widget as well.

Antony Riakiotakis noreply at git.blender.org
Mon May 26 18:53:26 CEST 2014


Commit: e13bc487802dde63353d2c77d2eb74954d103a3e
Author: Antony Riakiotakis
Date:   Mon May 26 19:53:02 2014 +0300
https://developer.blender.org/rBe13bc487802dde63353d2c77d2eb74954d103a3e

Angle range based collision detection on pie menu radial items. Also
some code to draw a central widget as well.

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

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_layout.c
M	source/blender/editors/interface/interface_regions.c
M	source/blender/editors/interface/interface_widgets.c

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

diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index c565d79..951eecd 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1294,7 +1294,9 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
 	wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
 	
 	/* back */
-	if ((block->flag & UI_BLOCK_LOOP) && !(block->flag & UI_BLOCK_RADIAL))
+	if (block->flag & UI_BLOCK_RADIAL)
+		ui_draw_pie_center(block);
+	else if (block->flag & UI_BLOCK_LOOP)
 		ui_draw_menu_back(&style, block, &rect);
 	else if (block->panel)
 		ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar));
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index cdc66e1..d41c23f 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -6228,9 +6228,53 @@ static bool ui_but_contains_pt(uiBut *but, float mx, float my)
 	return BLI_rctf_isect_pt(&but->rect, mx, my);
 }
 
-static bool ui_but_contains_seg(uiBut *but, const float s1[2], const float s2[2])
+static bool ui_but_isect_pie_seg(uiBlock *block, uiBut *but, const float seg[2])
 {
-	return BLI_rctf_isect_segment(&but->rect, s1, s2);
+	float angle_range = (block->num_pie_items < 5) ? M_PI_4 : M_PI_4 / 2.0f;
+	float angle_pie;
+	float vec[2];
+
+	switch (but->pie_dir) {
+		case UI_RADIAL_E:
+			angle_pie = 0.0;
+			break;
+
+		case UI_RADIAL_NE:
+			angle_pie = M_PI_4;
+			break;
+
+		case UI_RADIAL_N:
+			angle_pie = M_PI_2;
+			break;
+
+		case UI_RADIAL_NW:
+			angle_pie = M_PI_2 + M_PI_4;
+			break;
+
+		case UI_RADIAL_W:
+			angle_pie = M_PI;
+			break;
+
+		case UI_RADIAL_SW:
+			angle_pie = M_PI + M_PI_4;
+			break;
+
+		case UI_RADIAL_S:
+			angle_pie = 3 * M_PI_2;
+			break;
+
+		case UI_RADIAL_SE:
+			angle_pie = 3 * M_PI_2 + M_PI_4;
+			break;
+	}
+
+	vec[0] = cosf(angle_pie);
+	vec[1] = sinf(angle_pie);
+
+	if (saacos(dot_v2v2(vec, seg)) < angle_range)
+		return true;
+
+	return false;
 }
 
 static uiBut *ui_but_find_activated(ARegion *ar)
@@ -6382,6 +6426,18 @@ bool ui_is_but_search_unlink_visible(const uiBut *but)
 	        (but->drawstr[0] != '\0'));
 }
 
+static void ui_block_calculate_pie_segment(const float mx, const float my, float seg2[2], const uiBlock *block)
+{
+	float seg1[2];
+
+	seg1[0] = BLI_rctf_cent_x(&block->rect);
+	seg1[1] = BLI_rctf_cent_y(&block->rect);
+
+	seg2[0] = mx - seg1[0];
+	seg2[1] = my - seg1[1];
+	normalize_v2(seg2);
+}
+
 /* x and y are only used in case event is NULL... */
 static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit)
 {
@@ -6389,8 +6445,7 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c
 	uiBut *but, *butover = NULL;
 
 	float mx, my;
-	float seg1[2];
-	float seg2[2];
+	float seg[2];
 
 //	if (!win->active)
 //		return NULL;
@@ -6403,26 +6458,13 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c
 		ui_window_to_block_fl(ar, block, &mx, &my);
 
 		if (block->flag & UI_BLOCK_RADIAL) {
-			int centerpixels = 10;
-
-			seg1[0] = 0.5 * (block->rect.xmax - block->rect.xmin);
-			seg1[1] = 0.5 * (block->rect.ymax - block->rect.ymin);
-
-			seg2[0] = mx - seg1[0];
-			seg2[1] = my - seg1[1];
-			normalize_v2(seg2);
-
-			/* make a big enough segment for intersection */
-			seg1[0] = centerpixels * seg2[0] + seg1[0];
-			seg1[1] = centerpixels * seg2[1] + seg1[1];
-			seg2[0] = 10000.0 * seg2[0] + seg1[0];
-			seg2[1] = 10000.0 * seg2[1] + seg1[1];
+			ui_block_calculate_pie_segment(mx, my, seg, block);
 		}
 
 		for (but = block->buttons.last; but; but = but->prev) {
 			if (ui_is_but_interactive(but, labeledit)) {
 				if (but->dt == UI_EMBOSSR) {
-					if (ui_but_contains_seg(but, seg1, seg2)) {
+					if (ui_but_isect_pie_seg(block, but, seg)) {
 						butover = but;
 						break;
 					}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 7d83fb1..1c1f3eb 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -122,6 +122,19 @@ enum {
 	/* warn: rest of uiBut->flag in UI_interface.h */
 };
 
+/* but->pie_dir */
+typedef enum RadialDirection {
+	UI_RADIAL_NONE = 0,
+	UI_RADIAL_N  = 1,
+	UI_RADIAL_NE = 2,
+	UI_RADIAL_E  = 3,
+	UI_RADIAL_SE = 4,
+	UI_RADIAL_S  = 5,
+	UI_RADIAL_SW = 6,
+	UI_RADIAL_W  = 7,
+	UI_RADIAL_NW = 8
+} RadialDirection;
+
 /* internal panel drawing defines */
 #define PNL_GRID    (UI_UNIT_Y / 5) /* 4 default */
 #define PNL_HEADER  (UI_UNIT_Y + 4) /* 24 default */
@@ -226,6 +239,7 @@ struct uiBut {
 	BIFIconID icon;
 	bool lock;
 	char dt; /* drawtype: UI_EMBOSS, UI_EMBOSSN ... etc, copied from the block */
+	char pie_dir; /* direction in a pie menu, used for collision detection */
 	char changed; /* could be made into a single flag */
 	unsigned char unit_type; /* so buttons can support unit systems which are not RNA */
 	short modifier_key;
@@ -355,6 +369,8 @@ struct uiBlock {
 	char display_device[64]; /* display device name used to display this block,
 	                          * used by color widgets to transform colors from/to scene linear
 	                          */
+	int num_pie_items; /* number of pie items, useful to determine collision based on how pie items are distributed */
+	float pie_center_width; /* width of the central text of the pie menu */
 };
 
 typedef struct uiSafetyRct {
@@ -549,6 +565,7 @@ uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
 void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
 void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha);
 void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
+void ui_draw_pie_center(uiBlock *block);
 uiWidgetColors *ui_tooltip_get_theme(void);
 void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
 void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 7084925..11351d1 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2092,16 +2092,18 @@ static void ui_litem_layout_column(uiLayout *litem)
 
 /* calculates the angle of a specified button in a radial menu,
  * stores a float vector in unit circle */
-static void ui_get_radialbut_vec(float *vec, short itemnum, short totitems)
+static RadialDirection ui_get_radialbut_vec(float *vec, short itemnum, short totitems)
 {
-	float angle=0;
+	float angle = 0.0f;
+	RadialDirection dir = UI_RADIAL_NONE;
+
 	/* this goes in a seemingly weird pattern:
 
+		4
+	 5     6
+	1       2
+	 7     8
 		3
-	 4     5
-	0       1
-	 6     7
-		2
 
 	but it's actually quite logical. It's designed to be 'upwards compatible'
 	for muscle memory so that the menu item locations are fixed and don't move
@@ -2118,37 +2120,49 @@ static void ui_get_radialbut_vec(float *vec, short itemnum, short totitems)
 	--Matt 07/2006
 	*/
 
-	if (itemnum <= 4) {
+	if (itemnum < 5) {
 		switch(itemnum) {
 			case 1:
-				angle = 270;
+				dir = UI_RADIAL_W;
+				angle = 180.0f;
 				break;
 			case 2:
-				angle = 90;
+				dir = UI_RADIAL_E;
+				angle = 0.0f;
 				break;
 			case 3:
-				angle = 180;
+				dir = UI_RADIAL_S;
+				angle = 270.0f;
 				break;
 			case 4:
-				angle = 0;
+				dir = UI_RADIAL_N;
+				angle = 90.0f;
 				break;
 		}
-	} else if (totitems <= 8) {
+	}
+	else if (totitems < 9) {
 		switch(itemnum) {
 			case 5:
-				angle = 45;
+				dir = UI_RADIAL_NW;
+				angle = 135;
 				break;
 			case 6:
-				angle = 135;
+				dir = UI_RADIAL_NE;
+				angle = 45;
 				break;
 			case 7:
+				dir = UI_RADIAL_SW;
 				angle = 225;
 				break;
 			case 8:
+				dir = UI_RADIAL_SE;
 				angle = 315;
 				break;
 		}
-	} else {	/* subdivide quadrants progressively, depending on number of items */
+	}
+	else {
+#if 0
+		/* subdivide quadrants progressively, depending on number of items */
 		int anglepad, curquad, numinquad, aligncorrect=0;
 		int quaditems, overflow;
 
@@ -2190,12 +2204,15 @@ static void ui_get_radialbut_vec(float *vec, short itemnum, short totitems)
 			aligncorrect = angle - 360;
 
 		angle += aligncorrect/17;	/* 17 == magic number, works nicely */
+#endif
 	}
 
 	angle = angle / 180.0f * M_PI;
 
-	vec[0] = sin(angle);
-	vec[1] = cos(angle);
+	vec[0] = cos(angle);
+	vec[1] = sin(angle);
+
+	return dir;
 }
 
 static bool ui_item_is_radial_displayable (uiButtonItem *UNUSED(bitem))
@@ -2237,9 +2254,10 @@ static void ui_litem_layout_radial(uiLayout *litem)
 
 			/* not all button types are drawn in a radial menu, do filtering here */
 			if(ui_item_is_radial_displayable(bitem)) {
+
 				itemnum++;
 
-				ui_get_radialbut_vec(vec, itemnum, totitems);
+				bitem->but->pie_dir = ui_get_radialbut_vec(vec, itemnum, totitems);
 				/* scale the buttons */
 				bitem->but->rect.ymax *= 1.5;
 				/* add a little bit more here */
@@ -2252,6 +2270,8 @@ static void ui_litem_layout_radial(uiLayout *litem)
 				maxx = max_ii(maxx, x + vec[0] * pie_radius + itemw/2);
 				miny = min_ii(miny, y + vec[1] * pie_radius - itemh/2);
 				maxy = max_ii(maxy, y + vec[1] * pie_radius + itemh/2);
+
+				bitem->but->block->num_pie_items = totitems;
 			}
 		}
 	}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index a78e19a..b1154e4 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -2176,7 +2176,7 @@ struct uiPopupMenu {
 };
 
 struct uiPieMenu {
-	uiBlock *block;
+	uiBlock *block_radial; /* radial block of the pie menu (more could be added later) */
 	uiLayout *layout;
 
 	/*center coordinates of pie menu in window space */
@@ -2424,7 +2424,7 @@ static uiBlock *ui_block_func_PIE(bContext *C, uiPopupBlockHandle *handle, void
 
 	

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list