[Bf-blender-cvs] [27e03dc] master: Fix T44422: Zoom to mouse fails in camera view

Campbell Barton noreply at git.blender.org
Thu Apr 23 16:19:35 CEST 2015


Commit: 27e03dcd21872d9daf73adf42c69c04c5806ac07
Author: Campbell Barton
Date:   Fri Apr 24 00:12:16 2015 +1000
Branches: master
https://developer.blender.org/rB27e03dcd21872d9daf73adf42c69c04c5806ac07

Fix T44422: Zoom to mouse fails in camera view

Camera now supports all zoom styles too.

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

M	source/blender/editors/space_view3d/view3d_edit.c
M	source/blender/makesdna/DNA_view3d_types.h

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

diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 236fefc..3f6f17d 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -517,6 +517,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
 
 typedef struct ViewOpsData {
 	/* context pointers (assigned by viewops_data_alloc) */
+	Scene *scene;
 	ScrArea *sa;
 	ARegion *ar;
 	View3D *v3d;
@@ -589,6 +590,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
 
 	/* store data */
 	op->customdata = vod;
+	vod->scene = CTX_data_scene(C);
 	vod->sa = CTX_wm_area(C);
 	vod->ar = CTX_wm_region(C);
 	vod->v3d = vod->sa->spacedata.first;
@@ -2093,16 +2095,63 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
 	WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
 }
 
-static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
+static void view_zoom_mouseloc_camera(
+        Scene *scene, View3D *v3d,
+        ARegion *ar, float dfac, int mx, int my)
 {
 	RegionView3D *rv3d = ar->regiondata;
+	const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
+	const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
+	const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
+
+
+	if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+		float zoomfac_px;
+		rctf camera_frame_old;
+		rctf camera_frame_new;
+
+		const float pt_src[2] = {mx, my};
+		float pt_dst[2];
+		float delta_px[2];
+
+		ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false);
+		BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
+
+		rv3d->camzoom = camzoom_new;
+		CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+
+		ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false);
+		BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin);
+
+		BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
+		sub_v2_v2v2(delta_px, pt_dst, pt_src);
+
+		/* translate the camera offset using pixel space delta
+		 * mapped back to the camera (same logic as panning in camera view) */
+		zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f;
+
+		rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px);
+		rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px);
+		CLAMP(rv3d->camdx, -1.0f, 1.0f);
+		CLAMP(rv3d->camdy, -1.0f, 1.0f);
+	}
+	else {
+		rv3d->camzoom = camzoom_new;
+		CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+	}
+}
+
+static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my)
+{
+	RegionView3D *rv3d = ar->regiondata;
+	const float dist_new = rv3d->dist * dfac;
 
 	if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
 		float dvec[3];
 		float tvec[3];
 		float tpos[3];
 		float mval_f[2];
-		float new_dist;
+
 		float zfac;
 
 		negate_v3_v3(tpos, rv3d->ofs);
@@ -2119,105 +2168,133 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
 		negate_v3(tvec);
 
 		/* Offset to target position and dolly */
-		new_dist = rv3d->dist * dfac;
-
 		copy_v3_v3(rv3d->ofs, tvec);
-		rv3d->dist = new_dist;
+		rv3d->dist = dist_new;
 
 		/* Calculate final offset */
 		madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac);
 	}
 	else {
-		rv3d->dist *= dfac;
+		rv3d->dist = dist_new;
 	}
 }
 
-
-static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzoom, const short zoom_invert)
+static float viewzoom_scale_value(
+        const rcti *winrct,
+        const short viewzoom,
+        const bool zoom_invert, const bool zoom_invert_force,
+        const int xy[2], const int xy_orig[2],
+        const float val, const float val_orig,
+        double *r_timer_lastdraw)
 {
-	float zfac = 1.0;
-	bool use_cam_zoom;
-	float dist_range[2];
-
-	use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d));
-
-	ED_view3d_dist_range_get(vod->v3d, dist_range);
-
-	if (use_cam_zoom) {
-		float delta;
-		delta = (xy[0] - vod->origx + xy[1] - vod->origy) / 10.0f;
-		vod->rv3d->camzoom = vod->camzoom_prev + (zoom_invert ? -delta : delta);
-
-		CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
-	}
+	float zfac;
 
 	if (viewzoom == USER_ZOOM_CONT) {
 		double time = PIL_check_seconds_timer();
-		float time_step = (float)(time - vod->timer_lastdraw);
+		float time_step = (float)(time - *r_timer_lastdraw);
 		float fac;
 
 		if (U.uiflag & USER_ZOOM_HORIZ) {
-			fac = (float)(vod->origx - xy[0]);
+			fac = (float)(xy_orig[0] - xy[0]);
 		}
 		else {
-			fac = (float)(vod->origy - xy[1]);
+			fac = (float)(xy_orig[1] - xy[1]);
 		}
 
-		if (zoom_invert) {
+		if (zoom_invert != zoom_invert_force) {
 			fac = -fac;
 		}
 
 		/* oldstyle zoom */
 		zfac = 1.0f + ((fac / 20.0f) * time_step);
-		vod->timer_lastdraw = time;
+		*r_timer_lastdraw = time;
 	}
 	else if (viewzoom == USER_ZOOM_SCALE) {
 		/* method which zooms based on how far you move the mouse */
 
 		const int ctr[2] = {
-		    BLI_rcti_cent_x(&vod->ar->winrct),
-		    BLI_rcti_cent_y(&vod->ar->winrct),
+		    BLI_rcti_cent_x(winrct),
+		    BLI_rcti_cent_y(winrct),
 		};
-		const float len_new = 5 + len_v2v2_int(ctr, xy);
-		const float len_old = 5 + len_v2v2_int(ctr, &vod->origx);
-		zfac = vod->dist_prev * ((len_old + 5) / (len_new + 5)) / vod->rv3d->dist;
+		float len_new = 5 + len_v2v2_int(ctr, xy);
+		float len_old = 5 + len_v2v2_int(ctr, xy_orig);
+
+		/* intentionally ignore 'zoom_invert' for scale */
+		if (zoom_invert_force) {
+			SWAP(float, len_new, len_old);
+		}
+
+		zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val;
 	}
 	else {  /* USER_ZOOM_DOLLY */
-		float len1, len2;
-		
+		float len_new = 5;
+		float len_old = 5;
+
 		if (U.uiflag & USER_ZOOM_HORIZ) {
-			len1 = (vod->ar->winrct.xmax - xy[0]) + 5;
-			len2 = (vod->ar->winrct.xmax - vod->origx) + 5;
+			len_new += (winrct->xmax - xy[0]);
+			len_old += (winrct->xmax - xy_orig[0]);
 		}
 		else {
-			len1 = (vod->ar->winrct.ymax - xy[1]) + 5;
-			len2 = (vod->ar->winrct.ymax - vod->origy) + 5;
-		}
-		if (zoom_invert) {
-			SWAP(float, len1, len2);
+			len_new += (winrct->ymax - xy[1]);
+			len_old += (winrct->ymax - xy_orig[1]);
 		}
-		
-		if (use_cam_zoom) {
-			/* zfac is ignored in this case, see below */
-#if 0
-			zfac = vod->camzoom_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom;
-#endif
-		}
-		else {
-			zfac = vod->dist_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist;
+
+		if (zoom_invert != zoom_invert_force) {
+			SWAP(float, len_new, len_old);
 		}
+
+		zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val;
 	}
 
-	if (!use_cam_zoom) {
-		if (zfac != 1.0f) {
-			const float zfac_min = dist_range[0] / vod->rv3d->dist;
-			const float zfac_max = dist_range[1] / vod->rv3d->dist;
-			CLAMP(zfac, zfac_min, zfac_max);
 
-			if (zfac != 1.0f) {
-				view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy);
-			}
-		}
+	return zfac;
+}
+
+static void viewzoom_apply_camera(
+        ViewOpsData *vod, const int xy[2],
+        const short viewzoom, const bool zoom_invert)
+{
+	float zfac;
+	float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->camzoom_prev) * 2.0f;
+	float zoomfac =      BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
+
+	zfac = viewzoom_scale_value(
+	       &vod->ar->winrct, viewzoom, zoom_invert, true, xy, &vod->origx,
+	       zoomfac, zoomfac_prev,
+	       &vod->timer_lastdraw);
+
+	if (zfac != 1.0f && zfac != 0.0f) {
+		/* calculate inverted, then invert again (needed because of camera zoom scaling) */
+		zfac = 1.0f / zfac;
+		view_zoom_mouseloc_camera(
+		        vod->scene, vod->v3d,
+		        vod->ar, zfac, vod->oldx, vod->oldy);
+	}
+
+	ED_region_tag_redraw(vod->ar);
+}
+
+static void viewzoom_apply_3d(
+        ViewOpsData *vod, const int xy[2],
+        const short viewzoom, const bool zoom_invert)
+{
+	float zfac;
+	float dist_range[2];
+
+	ED_view3d_dist_range_get(vod->v3d, dist_range);
+
+	zfac = viewzoom_scale_value(
+	       &vod->ar->winrct, viewzoom, zoom_invert, false, xy, &vod->origx,
+	       vod->rv3d->dist, vod->dist_prev,
+	       &vod->timer_lastdraw);
+
+	if (zfac != 1.0f) {
+		const float zfac_min = dist_range[0] / vod->rv3d->dist;
+		const float zfac_max = dist_range[1] / vod->rv3d->dist;
+		CLAMP(zfac, zfac_min, zfac_max);
+
+		view_zoom_mouseloc_3d(
+		        vod->ar, zfac, vod->oldx, vod->oldy);
 	}
 
 	/* these limits were in old code too */
@@ -2231,6 +2308,19 @@ static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzo
 	ED_region_tag_redraw(vod->ar);
 }
 
+static void viewzoom_apply(
+        ViewOpsData *vod, const int xy[2],
+        const short viewzoom, const bool zoom_invert)
+{
+	if ((vod->rv3d->persp == RV3D_CAMOB) &&
+	    (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0)
+	{
+		viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert);
+	}
+	else {
+		viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert);
+	}
+}
 
 static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
 {
@@ -2291,6 +2381,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
 
 static int viewzoom_exec(bContext *C, wmOperator *op)
 {
+	Scene *scene = CTX_data_scene(C);
 	View3D *v3d;
 	RegionView3D *rv3d;
 	ScrArea *sa;
@@ -2323,22 +2414,26 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
 	ED_view3d_dist_range_get(v3d, dist_range);
 
 	if (delta < 0) {
+		const float step = 1.2f;
 		/* this min and max is also in viewmove() */
 		if (use_cam_zoom) {
-			rv3d->camzoom -= 10.0f;
-			if (rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom = RV3D_CAMZOOM_MIN;
+			view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my);
 		}
-		else if (rv3d->dist < dist_range[1]) {
-			view_zoom_mouseloc(ar, 1.2f, mx, my);
+		else {
+			if (rv3d->dist < dist_range[1]) {
+				view_zoom_mouseloc_3d(ar, step, mx, my);
+			}
 		}
 	}
 	else {
+		const float step = 1.0f / 1.2f;
 		if (use_cam_zoom) {
-			rv3d->camzoom += 10.0f;
-			if (rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom = RV3D_C

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list