[Bf-blender-cvs] [1288342] wiggly-widgets: Get manipulator handling to work!

Julian Eisel noreply at git.blender.org
Sat Aug 22 16:24:46 CEST 2015


Commit: 12883426a43be3ef6882387967000ceb5d8b4a23
Author: Julian Eisel
Date:   Sat Aug 22 15:15:02 2015 +0200
Branches: wiggly-widgets
https://developer.blender.org/rB12883426a43be3ef6882387967000ceb5d8b4a23

Get manipulator handling to work!

Meaning manipulator finally does what it's supposed to do.

There is still a crash when leaving active window while transforming, and drawing of dragged widget is also a bit jiggly, but everything else seems to work :)

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

M	source/blender/editors/transform/manipulator_widget.c
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_widgets.c
M	source/blender/windowmanager/wm_event_system.h

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

diff --git a/source/blender/editors/transform/manipulator_widget.c b/source/blender/editors/transform/manipulator_widget.c
index 46551a1..f632c90 100644
--- a/source/blender/editors/transform/manipulator_widget.c
+++ b/source/blender/editors/transform/manipulator_widget.c
@@ -288,6 +288,33 @@ static void manipulator_get_axis_color(const RegionView3D *rv3d, const int axis_
 	}
 }
 
+static void manipulator_get_axis_constraint(const int axis_idx, int r_axis[3])
+{
+	zero_v3_int(r_axis);
+
+	switch (axis_idx) {
+		case MAN_AXIS_TRANS_X:
+		case MAN_AXIS_ROT_X:
+		case MAN_AXIS_SCALE_X:
+			r_axis[0] = 1;
+			break;
+		case MAN_AXIS_TRANS_Y:
+		case MAN_AXIS_ROT_Y:
+		case MAN_AXIS_SCALE_Y:
+			r_axis[1] = 1;
+			break;
+		case MAN_AXIS_TRANS_Z:
+		case MAN_AXIS_ROT_Z:
+		case MAN_AXIS_SCALE_Z:
+			r_axis[2] = 1;
+			break;
+		case MAN_AXIS_TRANS_C:
+		case MAN_AXIS_ROT_C:
+		case MAN_AXIS_SCALE_C:
+			break;
+	}
+}
+
 
 /* **************** Preparation Stuff **************** */
 
@@ -939,6 +966,26 @@ static ManipulatorGroup *manipulatorgroup_init(
 	return man;
 }
 
+/**
+ * Custom handler for manipulator widgets
+ */
+static int manipulator_handler(bContext *C, const wmEvent *UNUSED(event), wmWidget *widget)
+{
+	const ScrArea *sa = CTX_wm_area(C);
+	ARegion *ar = CTX_wm_region(C);
+	View3D *v3d = sa->spacedata.first;
+	RegionView3D *rv3d = ar->regiondata;
+
+	if (calc_manipulator_stats(C)) {
+		manipulator_prepare_mat(CTX_data_scene(C), v3d, rv3d);
+		WM_widget_set_origin(widget, rv3d->twmat[3]);
+	}
+
+	ED_region_tag_redraw(ar);
+
+	return OPERATOR_PASS_THROUGH;
+}
+
 void WIDGETGROUP_manipulator_draw(const struct bContext *C, struct wmWidgetGroup *wgroup)
 {
 	const ScrArea *sa = CTX_wm_area(C);
@@ -978,6 +1025,9 @@ void WIDGETGROUP_manipulator_draw(const struct bContext *C, struct wmWidgetGroup
 	{
 		const short axis_type = manipulator_get_axis_type(man, axis);
 		const int aidx_norm = manipulator_index_normalize(axis_idx);
+		int constraint_axis[3] = {1, 0, 0};
+
+		PointerRNA *ptr;
 		float line_vec[2][3];
 		float col[4];
 
@@ -987,7 +1037,10 @@ void WIDGETGROUP_manipulator_draw(const struct bContext *C, struct wmWidgetGroup
 		}
 
 		manipulator_get_axis_color(rv3d, axis_idx, col);
+		manipulator_get_axis_constraint(axis_idx, constraint_axis);
 		WM_widget_set_origin(axis, rv3d->twmat[3]);
+		/* custom handler! */
+		axis->handler = manipulator_handler;
 
 		switch(axis_idx) {
 			case MAN_AXIS_TRANS_X:
@@ -1027,15 +1080,17 @@ void WIDGETGROUP_manipulator_draw(const struct bContext *C, struct wmWidgetGroup
 
 		switch (axis_type) {
 			case MAN_AXES_TRANSLATE:
-				WM_widget_operator(axis, "TRANSFORM_OT_translate");
+				ptr = WM_widget_operator(axis, "TRANSFORM_OT_translate");
 				break;
 			case MAN_AXES_ROTATE:
-				WM_widget_operator(axis, "TRANSFORM_OT_rotate");
+				ptr = WM_widget_operator(axis, "TRANSFORM_OT_rotate");
 				break;
 			case MAN_AXES_SCALE:
-				WM_widget_operator(axis, "TRANSFORM_OT_resize");
+				ptr = WM_widget_operator(axis, "TRANSFORM_OT_resize");
 				break;
 		}
+		RNA_boolean_set_array(ptr, "constraint_axis", constraint_axis);
+		RNA_boolean_set(ptr, "release_confirm", 1);
 	}
 	MAN_ITER_AXES_END;
 }
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index d1d2025..b884c00 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1451,40 +1451,6 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wm
 	}
 }
 
-static void wm_handler_widgetmap_context(bContext *C, wmEventHandler *handler)
-{
-	bScreen *screen = CTX_wm_screen(C);
-	
-	if (screen) {
-		if (handler->op_area == NULL) {
-			/* do nothing in this context */
-		}
-		else {
-			ScrArea *sa;
-			
-			for (sa = screen->areabase.first; sa; sa = sa->next)
-				if (sa == handler->op_area)
-					break;
-			if (sa == NULL) {
-				/* when changing screen layouts with running modal handlers (like render display), this
-				 * is not an error to print */
-				if (handler->widgetmap == NULL)
-					printf("internal error: modal widgetmap handler has invalid area\n");
-			}
-			else {
-				ARegion *ar;
-				CTX_wm_area_set(C, sa);
-				for (ar = sa->regionbase.first; ar; ar = ar->next)
-					if (ar == handler->op_region)
-						break;
-				/* XXX no warning print here, after full-area and back regions are remade */
-				if (ar)
-					CTX_wm_region_set(C, ar);
-			}
-		}
-	}
-}
-
 /* called on exit or remove area, only here call cancel callback */
 void WM_event_remove_handlers(bContext *C, ListBase *handlers)
 {
@@ -2091,16 +2057,17 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
 				}
 			}
 			else if (handler->widgetmap) {
-				struct wmWidgetMap *wmap = handler->widgetmap;
+				wmWidgetMap *wmap = handler->widgetmap;
 				unsigned char part;
 				short event_processed = 0;
 				wmWidget *widget = wm_widgetmap_get_active_widget(wmap);
 				ScrArea *area = CTX_wm_area(C);
 				ARegion *region = CTX_wm_region(C);
-				
-				wm_handler_widgetmap_context(C, handler);
+
+				wm_widgetmap_handler_context(C, handler);
 				wm_region_mouse_co(C, event);
-				
+
+				/* handle the widget first, before passing the event down */
 				switch (event->type) {
 					case MOUSEMOVE:
 						if (widget) {
@@ -2145,7 +2112,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
 				/* restore the area */
 				CTX_wm_area_set(C, area);
 				CTX_wm_region_set(C, region);
-				
+
 				if (handler->op) {
 					/* if event was processed by an active widget pass the modified event to the operator */
 					if (event_processed) {
@@ -2155,9 +2122,14 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
 				}
 			}
 			else {
-				/* handle the widget first, before passing the event down */
+				/* context region may be changed in wm_handler_operator_call */
+				ARegion *ar = CTX_wm_region(C);
+
 				/* modal, swallows all */
 				action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
+
+				/* update widgets during modal handlers */
+				wm_widget_handler_modal_update(C, event, handler, ar);
 			}
 
 			if (action & WM_HANDLER_BREAK) {
diff --git a/source/blender/windowmanager/intern/wm_widgets.c b/source/blender/windowmanager/intern/wm_widgets.c
index 3446bb4..dc0f17d 100644
--- a/source/blender/windowmanager/intern/wm_widgets.c
+++ b/source/blender/windowmanager/intern/wm_widgets.c
@@ -766,10 +766,11 @@ void wm_widgetmap_set_active_widget(
 	if (widget) {
 		if (call_op) {
 			wmOperatorType *ot;
-			const char *opname = (widget->opname) ? widget->opname : "WM_OT_widget_tweak";
-			
+			const bool has_custom_op = widget->opname != NULL;
+			const char *opname = has_custom_op ? widget->opname : "WM_OT_widget_tweak";
+
 			ot = WM_operatortype_find(opname, 0);
-			
+
 			if (ot) {
 				/* first activate the widget itself */
 				if (widget->invoke && widget->handler) {
@@ -783,12 +784,12 @@ void wm_widgetmap_set_active_widget(
 				if (WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &widget->opptr) == OPERATOR_RUNNING_MODAL) {
 					/* check if operator added a a modal event handler */
 					wmEventHandler *handler = CTX_wm_window(C)->modalhandlers.first;
-					
-					if (handler && handler->op && handler->op->type == ot) {
+
+					if (has_custom_op == false && handler && handler->op && handler->op->type == ot) {
 						handler->widgetmap = wmap;
 					}
 				}
-				
+
 				/* we failed to hook the widget to the operator handler or operator was cancelled, return */
 				if (!wmap->active_widget) {
 					widget->flag &= ~WM_WIDGET_ACTIVE;
@@ -836,6 +837,71 @@ void wm_widgetmap_set_active_widget(
 	}
 }
 
+void wm_widgetmap_handler_context(bContext *C, wmEventHandler *handler)
+{
+	bScreen *screen = CTX_wm_screen(C);
+
+	if (screen) {
+		if (handler->op_area == NULL) {
+			/* do nothing in this context */
+		}
+		else {
+			ScrArea *sa;
+
+			for (sa = screen->areabase.first; sa; sa = sa->next)
+				if (sa == handler->op_area)
+					break;
+			if (sa == NULL) {
+				/* when changing screen layouts with running modal handlers (like render display), this
+				 * is not an error to print */
+				if (handler->widgetmap == NULL)
+					printf("internal error: modal widgetmap handler has invalid area\n");
+			}
+			else {
+				ARegion *ar;
+				CTX_wm_area_set(C, sa);
+				for (ar = sa->regionbase.first; ar; ar = ar->next)
+					if (ar == handler->op_region)
+						break;
+				/* XXX no warning print here, after full-area and back regions are remade */
+				if (ar)
+					CTX_wm_region_set(C, ar);
+			}
+		}
+	}
+}
+
+void wm_widget_handler_modal_update(bContext *C, wmEvent *event, wmEventHandler *handler, ARegion *ar)
+{
+	wmWidgetMap *wmap;
+
+	for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
+		wmWidget *widget = wm_widgetmap_get_active_widget(wmap);
+		ScrArea *area = CTX_wm_area(C);
+		ARegion *region = CTX_wm_region(C);
+
+		if (!widget)
+			continue;
+
+		wm_widgetmap_handler_context(C, handler);
+
+		/* regular update for running operator */
+		if (handler->op) {
+			if (widget && widget->handler) {
+				widget->handler(C, event, widget);
+			}
+		}
+		/* operator not running anymore */
+		else {
+			wm_widgetmap_set_active_widget(wmap, C, event, NULL, false);
+		}
+
+		/* restore the area */
+		CTX_wm_area_set(C, area);
+		CTX_wm_region_set(C, region);
+	}
+}
+
 wmWidget *wm_widgetmap_get_active_widget(wmWidgetMap *wmap)
 {
 	return wmap->active_widget;
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 38bf430..8c9d3aa 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -101,6 +101,9 @@ void        wm_drags_check_ops(bContext *C, wmEvent *event);
 void        wm_drags_draw(bContext *C, wmWindow *win, rcti *rect);
 
 /* wm_widgets.c */
+void wm_widget_handler_modal_update(bContext *C, wmEvent *event, wmEventHandler *handler, struct ARegion *ar);
+void wm_widgetmap_handler_context(bContext *C, wmEventHandler *handler);
+
 struct wmWidget *wm_widget_find_highlig

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list