[Bf-blender-cvs] [36f18cd] wiggly-widgets: Arrow widget interaction:

Antony Riakiotakis noreply at git.blender.org
Wed Nov 19 12:32:33 CET 2014


Commit: 36f18cd35c40eb5f6e6fc03c4f53dd02ee179b5c
Author: Antony Riakiotakis
Date:   Wed Nov 19 12:32:21 2014 +0100
Branches: wiggly-widgets
https://developer.blender.org/rB36f18cd35c40eb5f6e6fc03c4f53dd02ee179b5c

Arrow widget interaction:

Fix interaction when pivot is beside the camera. basically we now do all
calculations in 3D space and we do not scale correct the offset in 3D -
this creates a nasty dependency loop between drawing and calculation for
widgets bound to properties - ie offset depends on scale but scale
depends on screen position - ie offset.

Also added an extra callback to get the final position of the widget in
3d space and use that to calculate the scale. This takes care of
bringing a close to the camera widget to the background and the widget
keeping its initial size. The final position can be different from the
initial position, especially when the widget is offset from the original
position.

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

M	source/blender/editors/space_view3d/space_view3d.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_generic_widgets.c
M	source/blender/windowmanager/intern/wm_widgets.c
M	source/blender/windowmanager/wm.h

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

diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 9f03741..15c4516 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -735,7 +735,7 @@ static void WIDGETGROUP_camera_create(struct wmWidgetGroup *wgroup)
 	wmWidget *widget = NULL;
 	PointerRNA *cameraptr = MEM_callocN(sizeof(PointerRNA), "camerawidgetptr");
 
-	widget = WIDGET_arrow_new(UI_ARROW_STYLE_OFFSET_3D, NULL);
+	widget = WIDGET_arrow_new(0, NULL);
 	WM_widget_register(wgroup, widget);
 	WIDGET_arrow_set_color(widget, color_camera);
 
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 06f491a..ffc7850 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -518,8 +518,6 @@ enum {
 	UI_ARROW_STYLE_INVERTED      = (1 << 2),
 	/* clamp arrow interaction to property width */
 	UI_ARROW_STYLE_CONSTRAINED   = (1 << 3),
-	/* force offset to be in 3D space, even if widget system is not 3D */
-	UI_ARROW_STYLE_OFFSET_3D   = (1 << 4),
 };
 
 enum {
diff --git a/source/blender/windowmanager/intern/wm_generic_widgets.c b/source/blender/windowmanager/intern/wm_generic_widgets.c
index e813d6c..278e1d6 100644
--- a/source/blender/windowmanager/intern/wm_generic_widgets.c
+++ b/source/blender/windowmanager/intern/wm_generic_widgets.c
@@ -150,11 +150,22 @@ typedef struct ArrowInteraction {
 	float orig_origin[3];
 	float orig_mouse[2];
 	float orig_offset;
+	float orig_scale;
 
 	/* direction vector, projected in screen space */
 	float proj_direction[2];
 } ArrowInteraction;
 
+
+static void widget_arrow_get_final_pos(struct wmWidget *widget, float pos[3])
+{
+	ArrowWidget *arrow = (ArrowWidget *)widget;
+
+	mul_v3_v3fl(pos, arrow->direction, arrow->offset);
+	add_v3_v3(pos, arrow->widget.origin);
+}
+
+
 static void arrow_draw_intern(ArrowWidget *arrow, bool select, bool highlight, float scale)
 {
 	float rot[3][3];
@@ -162,11 +173,7 @@ static void arrow_draw_intern(ArrowWidget *arrow, bool select, bool highlight, f
 	float up[3] = {0.0f, 0.0f, 1.0f};
 	float final_pos[3];
 
-	if (arrow->style & UI_ARROW_STYLE_OFFSET_3D)
-		mul_v3_v3fl(final_pos, arrow->direction, arrow->offset);
-	else
-		mul_v3_v3fl(final_pos, arrow->direction, scale * arrow->offset);
-	add_v3_v3(final_pos, arrow->widget.origin);
+	widget_arrow_get_final_pos((wmWidget *)arrow, final_pos);
 
 	rotation_between_vecs_to_mat3(rot, up, arrow->direction);
 	copy_m4_m3(mat, rot);
@@ -188,15 +195,9 @@ static void arrow_draw_intern(ArrowWidget *arrow, bool select, bool highlight, f
 	if (arrow->widget.interaction_data) {
 		ArrowInteraction *data = arrow->widget.interaction_data;
 
-		if (arrow->style & UI_ARROW_STYLE_OFFSET_3D)
-			mul_v3_v3fl(final_pos, arrow->direction, data->orig_offset);
-		else
-			mul_v3_v3fl(final_pos, arrow->direction, scale * data->orig_offset);
-		add_v3_v3(final_pos, arrow->widget.origin);
-
 		copy_m4_m3(mat, rot);
-		copy_v3_v3(mat[3], final_pos);
-		mul_mat3_m4_fl(mat, scale);
+		copy_v3_v3(mat[3], data->orig_origin);
+		mul_mat3_m4_fl(mat, data->orig_scale);
 
 		glPushMatrix();
 		glMultMatrixf(&mat[0][0]);
@@ -235,17 +236,19 @@ static int widget_arrow_handler(struct bContext *C, const struct wmEvent *event,
 	float offset[4];
 	float m_diff[2];
 	float dir_2d[2], dir2d_final[2];
-	float fac, zfac, widget_scale;
+	float fac, zfac;
 	float facdir = 1.0f;
-
-	widget_scale = (arrow->style & UI_ARROW_STYLE_OFFSET_3D) ? 1.0 : widget->scale;
+	bool flip;
 
 	copy_v3_v3(orig_origin, data->orig_origin);
 	orig_origin[3] = 1.0f;
 	add_v3_v3v3(offset, orig_origin, arrow->direction);
 	offset[3] = 1.0f;
 
-	zfac = ED_view3d_calc_zfac(rv3d, orig_origin, NULL);
+	zfac = ED_view3d_calc_zfac(rv3d, orig_origin, &flip);
+
+	if (flip)
+		zfac *= -1.0;
 
 	/* multiply to projection space */
 	mul_m4_v4(rv3d->persmat, orig_origin);
@@ -292,7 +295,7 @@ static int widget_arrow_handler(struct bContext *C, const struct wmEvent *event,
 	else if (widget->prop) {
 		float value;
 
-		value = data->orig_offset + facdir / widget_scale * len_v3(offset);
+		value = data->orig_offset + facdir * len_v3(offset);
 		if (arrow->style & UI_ARROW_STYLE_CONSTRAINED) {
 			if (arrow->style & UI_ARROW_STYLE_INVERTED)
 				value = arrow->min + arrow->range - (value * arrow->range / ARROW_RANGE);
@@ -314,7 +317,7 @@ static int widget_arrow_handler(struct bContext *C, const struct wmEvent *event,
 			arrow->offset = RNA_property_float_get(widget->ptr, widget->prop);
 	}
 	else {
-		arrow->offset = facdir / widget_scale * len_v3(offset);
+		arrow->offset = facdir * len_v3(offset);
 	}
 
 	/* tag the region for redraw */
@@ -337,7 +340,9 @@ static int widget_arrow_activate(struct bContext *UNUSED(C), const struct wmEven
 		data->orig_mouse[0] = event->mval[0];
 		data->orig_mouse[1] = event->mval[1];
 
-		copy_v3_v3(data->orig_origin, widget->origin);
+		data->orig_scale = widget->scale;
+
+		widget_arrow_get_final_pos(widget, data->orig_origin);
 
 		widget->interaction_data = data;
 	}
@@ -394,6 +399,7 @@ wmWidget *WIDGET_arrow_new(int style, void *customdata)
 	arrow = MEM_callocN(sizeof(ArrowWidget), "arrowwidget");
 	
 	arrow->widget.draw = widget_arrow_draw;
+	arrow->widget.get_final_position = 	widget_arrow_get_final_pos;
 	arrow->widget.intersect = NULL;
 	arrow->widget.handler = widget_arrow_handler;
 	arrow->widget.activate_state = widget_arrow_activate;
@@ -536,10 +542,10 @@ void WIDGET_dial_set_color(struct wmWidget *widget, float color[4])
 
 void WIDGET_dial_set_direction(struct wmWidget *widget, float direction[3])
 {
-	DialWidget *arrow = (DialWidget *)widget;
+	DialWidget *dial = (DialWidget *)widget;
 
-	copy_v3_v3(arrow->direction, direction);
-	normalize_v3(arrow->direction);
+	copy_v3_v3(dial->direction, direction);
+	normalize_v3(dial->direction);
 }
 
 /********* Cage widget ************/
@@ -552,7 +558,7 @@ typedef struct CageWidget {
 	int style;
 } CageWidget;
 
-static void widget_cage_draw(struct wmWidget *widget, const struct bContext *C)
+static void widget_cage_draw(struct wmWidget *widget, const struct bContext *UNUSED(C))
 {
 	CageWidget *cage = (CageWidget *)widget;
 
diff --git a/source/blender/windowmanager/intern/wm_widgets.c b/source/blender/windowmanager/intern/wm_widgets.c
index daeef99..244f1d2 100644
--- a/source/blender/windowmanager/intern/wm_widgets.c
+++ b/source/blender/windowmanager/intern/wm_widgets.c
@@ -262,9 +262,16 @@ void WM_widgets_draw(const struct bContext *C, struct ARegion *ar, bool is_3d)
 	if (widget) {
 		float scale = 1.0;
 
-		if (do_scale)
-			scale = ED_view3d_pixel_size(rv3d, widget->origin) * U.tw_size;
-
+		if (do_scale) {
+			if (widget->get_final_position) {
+				float position[3];
+				widget->get_final_position(widget, position);
+				scale = ED_view3d_pixel_size(rv3d, position) * U.tw_size;
+			}
+			else {
+				scale = ED_view3d_pixel_size(rv3d, widget->origin) * U.tw_size;
+			}
+		}
 		/* notice that we don't update the widgetgroup, widget is now on its own, it should have all
 		 * relevant data to update itself */
 		widget->scale = scale;
@@ -287,8 +294,16 @@ void WM_widgets_draw(const struct bContext *C, struct ARegion *ar, bool is_3d)
 					if (!(widget_iter->flag & WM_WIDGET_SKIP_DRAW)) {
 						float scale = 1.0;
 
-						if (do_scale)
-							scale = ED_view3d_pixel_size(rv3d, widget_iter->origin) * U.tw_size;
+						if (do_scale) {
+							if (widget_iter->get_final_position) {
+								float position[3];
+								widget_iter->get_final_position(widget_iter, position);
+								scale = ED_view3d_pixel_size(rv3d, position) * U.tw_size;
+							}
+							else {
+								scale = ED_view3d_pixel_size(rv3d, widget_iter->origin) * U.tw_size;
+							}
+						}
 
 						widget_iter->scale = scale;
 						widget_iter->draw(widget_iter, C);
@@ -425,8 +440,16 @@ static void widget_find_active_3D_loop(bContext *C, ListBase *visible_widgets)
 
 		widget = link->data;
 
-		if (!(U.tw_flag & V3D_3D_WIDGETS))
-			scale = ED_view3d_pixel_size(rv3d, widget->origin) * U.tw_size;
+		if (!(U.tw_flag & V3D_3D_WIDGETS)) {
+			if (widget->get_final_position) {
+				float position[3];
+				widget->get_final_position(widget, position);
+				scale = ED_view3d_pixel_size(rv3d, position) * U.tw_size;
+			}
+			else {
+				scale = ED_view3d_pixel_size(rv3d, widget->origin) * U.tw_size;
+			}
+		}
 		/* reset the scale here. We might have more than one 3d view so scale is not guaranteed to
 		 * have stayed the same */
 		widget->scale = scale;
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index e5c5019..656e401 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -72,12 +72,16 @@ typedef struct wmWidget {
 	/* widget-specific handler to update widget attributes when a property is bound */
 	void (*bind_to_prop)(struct wmWidget *widget);
 
+	/* returns the final position which may be different from the origin, depending on the widget.
+	 * used in calculations of scale */
+	void (*get_final_position)(struct wmWidget *widget, float vec[3]);
+
 	int  flag; /* flags set by drawing and interaction, such as highlighting */
 
 	/* activate a widget state when the user clicks on it */
 	int (*activate_state)(struct bContext *C, const struct wmEvent *event, struct wmWidget *widget, int state);
 
-	/* position in space, 2d or 3d */
+	/* center of widget in space, 2d or 3d */
 	float origin[3];
 
 	/* runtime property, set the scale while drawing on the viewport */




More information about the Bf-blender-cvs mailing list