[Bf-blender-cvs] [3f80acc] master: Fix T44011: Ruler/Knife/Loop-cut fail in quad-view

Campbell Barton noreply at git.blender.org
Mon Apr 27 11:19:43 CEST 2015


Commit: 3f80accfb34dd10e70380139941bcaf62702a6f8
Author: Campbell Barton
Date:   Mon Apr 27 18:53:45 2015 +1000
Branches: master
https://developer.blender.org/rB3f80accfb34dd10e70380139941bcaf62702a6f8

Fix T44011: Ruler/Knife/Loop-cut fail in quad-view

This is a kind of sloppy-focus,
resolving long standing bug with loop-cut/knife/ruler /w quad-view.

Where activating a tool would lock onto one of quad-views,
especially problematic when activating from the toolbar or menus.

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

M	source/blender/blenkernel/BKE_screen.h
M	source/blender/blenkernel/intern/screen.c
M	source/blender/editors/mesh/editmesh_knife.c
M	source/blender/editors/mesh/editmesh_loopcut.c
M	source/blender/editors/space_view3d/view3d_ruler.c
M	source/blender/makesdna/DNA_screen_types.h
M	source/blender/makesdna/DNA_windowmanager_types.h
M	source/blender/makesrna/intern/rna_wm.c
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/wm_event_system.h

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

diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 4349993..bb76454 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -280,6 +280,7 @@ void            BKE_screen_area_free(struct ScrArea *sa);
 
 struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
 struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
+struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y);
 struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
 struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min);
 struct ScrArea *BKE_screen_find_area_xy(struct bScreen *sc, const int spacetype, int x, int y);
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 3c43bfa..36fd598 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -405,6 +405,23 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa)
 	return NULL;
 }
 
+ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y)
+{
+	ARegion *ar_found = NULL;
+	if (sa) {
+		ARegion *ar;
+		for (ar = sa->regionbase.first; ar; ar = ar->next) {
+			if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) {
+				if (BLI_rcti_isect_pt(&ar->winrct, x, y)) {
+					ar_found = ar;
+					break;
+				}
+			}
+		}
+	}
+	return ar_found;
+}
+
 /**
  * \note, ideally we can get the area from the context,
  * there are a few places however where this isn't practical.
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index df91679..4f88390 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -3051,6 +3051,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 
 	knifetool_init(C, kcd, only_select, cut_through, true);
 
+	op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
 	/* add a modal handler for this operator - handles loop selection */
 	WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR);
 	WM_event_add_modal_handler(C, op);
@@ -3143,6 +3145,9 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
 		return OPERATOR_FINISHED;
 	}
 
+	em_setup_viewcontext(C, &kcd->vc);
+	kcd->ar = kcd->vc.ar;
+
 	view3d_operator_needs_opengl(C);
 	ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d);  /* needed to initialize clipping */
 
@@ -3302,6 +3307,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
 		}
 	}
 
+	if (kcd->mode == MODE_DRAGGING) {
+		op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+	}
+	else {
+		op->flag |= OP_IS_MODAL_CURSOR_REGION;
+	}
+
 	if (do_refresh) {
 		/* we don't really need to update mval,
 		 * but this happens to be the best way to refresh at the moment */
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index a4ea2ab..c7f9522 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -553,6 +553,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
 
 	/* add a modal handler for this operator - handles loop selection */
 	if (is_interactive) {
+		op->flag |= OP_IS_MODAL_CURSOR_REGION;
 		WM_event_add_modal_handler(C, op);
 	}
 
@@ -639,6 +640,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
 	bool show_cuts = false;
 	const bool has_numinput = hasNumInput(&lcd->num);
 
+	em_setup_viewcontext(C, &lcd->vc);
+	lcd->ar = lcd->vc.ar;
+
 	view3d_operator_needs_opengl(C);
 
 	/* using the keyboard to input the number of cuts */
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index eba3186..addda0a 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -187,6 +187,7 @@ typedef struct RulerInfo {
 
 	/* wm state */
 	wmWindow *win;
+	ScrArea *sa;
 	ARegion *ar;
 	void *draw_handle_pixel;
 } RulerInfo;
@@ -435,7 +436,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
 	UnitSettings *unit = &scene->unit;
 	RulerItem *ruler_item;
 	RulerInfo *ruler_info = arg;
-	RegionView3D *rv3d = ruler_info->ar->regiondata;
+	RegionView3D *rv3d = ar->regiondata;
 //	ARegion *ar = ruler_info->ar;
 	const float cap_size = 4.0f;
 	const float bg_margin = 4.0f * U.pixelsize;
@@ -798,12 +799,14 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
 	op->customdata = ruler_info;
 
 	ruler_info->win = win;
-	ruler_info->ar = ar;
+	ruler_info->sa = sa;
 	ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel,
 	                                                           ruler_info, REGION_DRAW_POST_PIXEL);
 
 	view3d_ruler_header_update(sa);
 
+	op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
 	WM_cursor_modal_set(win, BC_CROSSCURSOR);
 	WM_event_add_modal_handler(C, op);
 
@@ -829,11 +832,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
 	RegionView3D *rv3d = ar->regiondata;
 
 	/* its possible to change spaces while running the operator [#34894] */
-	if (UNLIKELY(ar != CTX_wm_region(C))) {
+	if (UNLIKELY(sa != ruler_info->sa)) {
 		exit_code = OPERATOR_FINISHED;
 		goto exit;
 	}
 
+	ruler_info->ar = ar;
+
 	switch (event->type) {
 		case LEFTMOUSE:
 			if (event->val == KM_RELEASE) {
@@ -1019,6 +1024,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
 
 	}
 
+	if (ruler_info->state == RULER_STATE_DRAG) {
+		op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+	}
+	else {
+		op->flag |= OP_IS_MODAL_CURSOR_REGION;
+	}
+
 	if (do_draw) {
 		view3d_ruler_header_update(sa);
 
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 13365ad..eb76c90 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -374,6 +374,8 @@ enum {
 	RGN_TYPE_TOOL_PROPS = 6,
 	RGN_TYPE_PREVIEW = 7
 };
+/* use for function args */
+#define RGN_TYPE_ANY -1
 
 /* region alignment */
 #define RGN_ALIGN_NONE		0
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 4aa49ee..51ed8bb 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -390,10 +390,16 @@ enum {
 
 /* wmOperator flag */
 enum {
-	OP_IS_MODAL_GRAB_CURSOR    = (1 << 0),
 	/* low level flag so exec() operators can tell if they were invoked, use with care.
 	 * typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */
-	OP_IS_INVOKE       = (1 << 1),
+	OP_IS_INVOKE = (1 << 0),
+
+	/* When the cursor is grabbed */
+	OP_IS_MODAL_GRAB_CURSOR    = (1 << 1),
+
+	/* allow modal operators to have the region under the cursor for their context
+	 * (the regiontype is maintained to prevent errors) */
+	OP_IS_MODAL_CURSOR_REGION = (1 << 2),
 };
 
 #endif /* __DNA_WINDOWMANAGER_TYPES_H__ */
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index ded4ea0..3b8ddd0 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1416,6 +1416,10 @@ static void rna_def_operator_options_runtime(BlenderRNA *brna)
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_INVOKE);
 	RNA_def_property_ui_text(prop, "Invoke", "True when invoked (even if only the execute callbacks available)");
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+	prop = RNA_def_property(srna, "use_cursor_region", PROP_BOOLEAN, PROP_BOOLEAN);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_CURSOR_REGION);
+	RNA_def_property_ui_text(prop, "Focus Region", "Enable to use the region under the cursor for modal execution");
 }
 
 static void rna_def_operator(BlenderRNA *brna)
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 8c97d39..830feed 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1337,7 +1337,7 @@ void wm_event_free_handler(wmEventHandler *handler)
 }
 
 /* only set context when area/region is part of screen */
-static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
+static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wmEvent *event)
 {
 	bScreen *screen = CTX_wm_screen(C);
 	
@@ -1358,10 +1358,27 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
 			}
 			else {
 				ARegion *ar;
+				wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL;
 				CTX_wm_area_set(C, sa);
-				for (ar = sa->regionbase.first; ar; ar = ar->next)
-					if (ar == handler->op_region)
-						break;
+
+				if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) {
+					ar = BKE_area_find_region_xy(sa, handler->op_region_type, event->x, event->y);
+					if (ar) {
+						handler->op_region = ar;
+					}
+				}
+				else {
+					ar = NULL;
+				}
+
+				if (ar == NULL) {
+					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);
@@ -1379,11 +1396,12 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
 	/* C is zero on freeing database, modal handlers then already were freed */
 	while ((handler = BLI_pophead(handlers))) {
 		if (handler->op) {
+			wmWindow *win = CTX_wm_window(C);
 			if (handler->op->type->cancel) {
 				ScrArea *area = CTX_wm_area(C);
 				ARegion *region = CTX_wm_region(C);
 				
-				wm_handler_op_context(C, handler);
+				wm_handler_op_context(C, handler, win->eventstate);
 


@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list