[Bf-blender-cvs] [5df597171bb] blender2.8: Manipulator: Support click only manipulator's

Campbell Barton noreply at git.blender.org
Tue Dec 19 02:47:41 CET 2017


Commit: 5df597171bb9065952436027f5a1a271368e51ff
Author: Campbell Barton
Date:   Tue Dec 19 12:31:40 2017 +1100
Branches: blender2.8
https://developer.blender.org/rB5df597171bb9065952436027f5a1a271368e51ff

Manipulator: Support click only manipulator's

Makes the 3D view navigation widget easier to use: dragging anywhere
in the rotation region now rotates without having to avoid the XYZ axis
hotspots which only activate on a single click.

Logic for drag detection is complicated by manipulators reliance
on keeping the modal operator running.
Currently this is wrapped in an ifdef,
we may want to implement it differently later.

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

M	source/blender/editors/space_view3d/view3d_manipulator_navigate.c
M	source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
M	source/blender/windowmanager/manipulators/WM_manipulator_types.h
M	source/blender/windowmanager/manipulators/intern/wm_manipulator.c
M	source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
M	source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c

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

diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
index b7a62c3e60f..bcc067b8fc1 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -163,6 +163,9 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
 			PointerRNA *ptr = WM_manipulator_operator_set(mpr, mapping[part_index], ot_viewnumpad, NULL);
 			RNA_enum_set(ptr, "type", RV3D_VIEW_FRONT + part_index);
 		}
+
+		/* When dragging an axis, use this instead. */
+		mpr->drag_part = 0;
 	}
 
 	mgroup->customdata = navgroup;
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
index b520f239ef5..aac13339b6b 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
@@ -96,7 +96,7 @@ static void axis_geom_draw(
 	};
 	qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
 
-	const float scale_axis = 0.33f;
+	const float scale_axis = 0.25f;
 	static const float axis_highlight[4] = {1, 1, 1, 1};
 	static const float axis_black[4] = {0, 0, 0, 1};
 	static float axis_color[3][4];
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_types.h b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
index e8b81e1a78c..f2c0a8e93d9 100644
--- a/source/blender/windowmanager/manipulators/WM_manipulator_types.h
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
@@ -182,6 +182,8 @@ struct wmManipulator {
 	/* Optional ID for highlighting different parts of this manipulator.
 	 * -1 when unset, otherwise a valid index. (Used as index to 'op_data'). */
 	int highlight_part;
+	/* For single click button manipulators, use a different part as a fallback, -1 when unused. */
+	int drag_part;
 
 	/* Transformation of the manipulator in 2d or 3d space.
 	 * - Matrix axis are expected to be unit length (scale is applied after).
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
index 7ca1f8fd5f2..5190a4932b4 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
@@ -98,6 +98,8 @@ static wmManipulator *wm_manipulator_create(
 	unit_m4(mpr->matrix_basis);
 	unit_m4(mpr->matrix_offset);
 
+	mpr->drag_part = -1;
+
 	return mpr;
 }
 
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
index edf10afad8c..10a76beada9 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
@@ -39,6 +39,7 @@
 
 #include "BLI_listbase.h"
 #include "BLI_string.h"
+#include "BLI_math.h"
 
 #include "BKE_context.h"
 #include "BKE_main.h"
@@ -61,6 +62,10 @@
 #  include "BPY_extern.h"
 #endif
 
+/* Allow manipulator part's to be single click only,
+ * dragging falls back to activating their 'drag_part' action. */
+#define USE_DRAG_DETECT
+
 /* -------------------------------------------------------------------- */
 /** \name wmManipulatorGroup
  *
@@ -307,15 +312,71 @@ typedef struct ManipulatorTweakData {
 
 	int init_event; /* initial event type */
 	int flag;       /* tweak flags */
+
+#ifdef USE_DRAG_DETECT
+	/* True until the mouse is moved (only use when the operator has no modal).
+	 * this allows some manipulators to be click-only. */
+	enum {
+		/* Don't detect dragging. */
+		DRAG_NOP = 0,
+		/* Detect dragging (wait until a drag or click is detected). */
+		DRAG_DETECT,
+		/* Drag has started, idle until there is no active modal operator.
+		 * This is needed because finishing the modal operator also exits
+		 * the modal manipulator state (un-grabbs the cursor).
+		 * Ideally this workaround could be removed later. */
+		DRAG_IDLE,
+	} drag_state;
+#endif
+
 } ManipulatorTweakData;
 
-static void manipulator_tweak_finish(bContext *C, wmOperator *op, const bool cancel)
+static bool manipulator_tweak_start(
+        bContext *C, wmManipulatorMap *mmap, wmManipulator *mpr, const wmEvent *event)
+{
+	/* activate highlighted manipulator */
+	wm_manipulatormap_modal_set(mmap, C, mpr, event, true);
+
+	return (mpr->state & WM_MANIPULATOR_STATE_MODAL);
+}
+
+static bool manipulator_tweak_start_and_finish(
+        bContext *C, wmManipulatorMap *mmap, wmManipulator *mpr, const wmEvent *event, bool *r_is_modal)
+{
+	wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, mpr->highlight_part);
+	if (r_is_modal) {
+		*r_is_modal = false;
+	}
+	if (mpop && mpop->type) {
+		/* XXX temporary workaround for modal manipulator operator
+		 * conflicting with modal operator attached to manipulator */
+		if (mpop->type->modal) {
+			/* activate highlighted manipulator */
+			wm_manipulatormap_modal_set(mmap, C, mpr, event, true);
+			if (r_is_modal) {
+				*r_is_modal = true;
+			}
+		}
+		else {
+			/* Allow for 'button' manipulators, single click to run an action. */
+			WM_operator_name_call_ptr(C, mpop->type, WM_OP_INVOKE_DEFAULT, &mpop->ptr);
+		}
+		return true;
+	}
+	else {
+		return false;
+	}
+}
+
+static void manipulator_tweak_finish(bContext *C, wmOperator *op, const bool cancel, bool clear_modal)
 {
 	ManipulatorTweakData *mtweak = op->customdata;
 	if (mtweak->mpr_modal->type->exit) {
 		mtweak->mpr_modal->type->exit(C, mtweak->mpr_modal, cancel);
 	}
-	wm_manipulatormap_modal_set(mtweak->mmap, C, mtweak->mpr_modal, NULL, false);
+	if (clear_modal) {
+		wm_manipulatormap_modal_set(mtweak->mmap, C, mtweak->mpr_modal, NULL, false);
+	}
 	MEM_freeN(mtweak);
 }
 
@@ -324,13 +385,57 @@ static int manipulator_tweak_modal(bContext *C, wmOperator *op, const wmEvent *e
 	ManipulatorTweakData *mtweak = op->customdata;
 	wmManipulator *mpr = mtweak->mpr_modal;
 	int retval = OPERATOR_PASS_THROUGH;
+	bool clear_modal = true;
 
 	if (mpr == NULL) {
 		BLI_assert(0);
 		return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
 	}
 
-	if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
+#ifdef USE_DRAG_DETECT
+	wmManipulatorMap *mmap = mtweak->mmap;
+	if (mtweak->drag_state == DRAG_DETECT) {
+		if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+			if (len_manhattan_v2v2_int(&event->x, mmap->mmap_context.event_xy) > 2) {
+				mtweak->drag_state = DRAG_IDLE;
+				mpr->highlight_part = mpr->drag_part;
+			}
+		}
+		else if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
+			mtweak->drag_state = DRAG_NOP;
+			retval = OPERATOR_FINISHED;
+		}
+
+		if (mtweak->drag_state != DRAG_DETECT) {
+			/* Follow logic in 'manipulator_tweak_invoke' */
+			bool is_modal = false;
+			if (manipulator_tweak_start_and_finish(C, mmap, mpr, event, &is_modal)) {
+				if (is_modal) {
+					clear_modal = false;
+				}
+			}
+			else {
+				if (!manipulator_tweak_start(C, mmap, mpr, event)) {
+					retval = OPERATOR_FINISHED;
+				}
+			}
+		}
+	}
+	if (mtweak->drag_state == DRAG_IDLE) {
+		if (mmap->mmap_context.modal != NULL) {
+			return OPERATOR_PASS_THROUGH;
+		}
+		else {
+			manipulator_tweak_finish(C, op, false, false);
+			return OPERATOR_FINISHED;
+		}
+	}
+#endif  /* USE_DRAG_DETECT */
+
+	if (retval == OPERATOR_FINISHED) {
+		/* pass */
+	}
+	else if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
 		retval = OPERATOR_FINISHED;
 	}
 	else if (event->type == EVT_MODAL_MAP) {
@@ -358,7 +463,7 @@ static int manipulator_tweak_modal(bContext *C, wmOperator *op, const wmEvent *e
 	}
 
 	if (retval != OPERATOR_PASS_THROUGH) {
-		manipulator_tweak_finish(C, op, retval != OPERATOR_FINISHED);
+		manipulator_tweak_finish(C, op, retval != OPERATOR_FINISHED, clear_modal);
 		return retval;
 	}
 
@@ -368,7 +473,7 @@ static int manipulator_tweak_modal(bContext *C, wmOperator *op, const wmEvent *e
 		int modal_retval = modal_fn(C, mpr, event, mtweak->flag);
 
 		if ((modal_retval & OPERATOR_RUNNING_MODAL) == 0) {
-			manipulator_tweak_finish(C, op, (modal_retval & OPERATOR_CANCELLED) != 0);
+			manipulator_tweak_finish(C, op, (modal_retval & OPERATOR_CANCELLED) != 0, true);
 			return OPERATOR_FINISHED;
 		}
 
@@ -394,30 +499,35 @@ static int manipulator_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *
 		return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
 	}
 
-	wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, mpr->highlight_part);
+	bool use_drag_fallback = false;
 
-	/* Allow for 'button' manipulators, single click to run an action. */
-	if (mpop && mpop->type) {
-		if (mpop->type->modal == NULL) {
-			WM_operator_name_call_ptr(C, mpop->type, WM_OP_INVOKE_DEFAULT, &mpop->ptr);
+#ifdef USE_DRAG_DETECT
+	use_drag_fallback = !ELEM(mpr->drag_part, -1, mpr->highlight_part);
+#endif
+
+	if (use_drag_fallback == false) {
+		if (manipulator_tweak_start_and_finish(C, mmap, mpr, event, NULL)) {
 			return OPERATOR_FINISHED;
 		}
 	}
 
-	/* activate highlighted manipulator */
-	wm_manipulatormap_modal_set(mmap, C, mpr, event, true);
-
-	/* XXX temporary workaround for modal manipulator operator
-	 * conflicting with modal operator attached to manipulator */
-	if (mpop && mpop->type) {
-		if (mpop->type->modal) {
-			return OPERATOR_FINISHED;
+	bool use_drag_detect = false;
+#ifdef USE_DRAG_DETECT
+	if (use_drag_fallback) {
+		wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, mpr->highlight_part);
+		if (mpop && mpop->type) {
+			if (mpop->type->modal == NULL) {
+				use_drag_detect = true;
+			}
 		}
 	}
+#endif
 
-	/* Couldn't start the manipulator. */
-	if ((mpr->state & WM_MANIPULATOR_STATE_MODAL) == 0) {
-		return OPERATOR_PASS_THROUGH;
+	if (use_drag_detect == false) {
+		if (!manipulator_tweak_start(C, mmap, mpr, event)) {
+			/* failed to start */
+			return OPERATOR_PASS_THROUGH;
+		}
 	}
 
 	ManipulatorTweakData *mtweak = MEM_mallocN(sizeof(ManipulatorTweakData), __func__);
@@ -427,6 +537,10

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list