[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