Example #1
0
static bool view3d_localview_init(
        wmWindowManager *wm, wmWindow *win,
        Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx,
        ReportList *reports)
{
	View3D *v3d = sa->spacedata.first;
	Base *base;
	float min[3], max[3], box[3], mid[3];
	float size = 0.0f, size_persp = 0.0f, size_ortho = 0.0f;
	unsigned int locallay;
	bool ok = false;

	if (v3d->localvd) {
		return ok;
	}

	INIT_MINMAX(min, max);

	locallay = free_localbit(bmain);

	if (locallay == 0) {
		BKE_report(reports, RPT_ERROR, "No more than 8 local views");
		ok = false;
	}
	else {
		if (scene->obedit) {
			BKE_object_minmax(scene->obedit, min, max, false);
			
			ok = true;
		
			BASACT->lay |= locallay;
			scene->obedit->lay = BASACT->lay;
		}
		else {
			for (base = FIRSTBASE; base; base = base->next) {
				if (TESTBASE(v3d, base)) {
					BKE_object_minmax(base->object, min, max, false);
					base->lay |= locallay;
					base->object->lay = base->lay;
					ok = true;
				}
			}
		}

		sub_v3_v3v3(box, max, min);
		size = max_fff(box[0], box[1], box[2]);

		/* do not zoom closer than the near clipping plane */
		size = max_ff(size, v3d->near * 1.5f);

		/* perspective size (we always switch out of camera view so no need to use its lens size) */
		size_persp = ED_view3d_radius_to_persp_dist(focallength_to_fov(v3d->lens, DEFAULT_SENSOR_WIDTH), size / 2.0f) * VIEW3D_MARGIN;
		size_ortho = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN;
	}
	
	if (ok == true) {
		ARegion *ar;
		
		v3d->localvd = MEM_mallocN(sizeof(View3D), "localview");
		
		memcpy(v3d->localvd, v3d, sizeof(View3D));

		mid_v3_v3v3(mid, min, max);

		copy_v3_v3(v3d->cursor, mid);

		for (ar = sa->regionbase.first; ar; ar = ar->next) {
			if (ar->regiontype == RGN_TYPE_WINDOW) {
				RegionView3D *rv3d = ar->regiondata;

				/* new view values */
				Object *camera_old = NULL;
				float dist_new, ofs_new[3];

				rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region");
				memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D));

				negate_v3_v3(ofs_new, mid);

				if (rv3d->persp == RV3D_CAMOB) {
					rv3d->persp = RV3D_PERSP;
					camera_old = v3d->camera;
				}

				/* perspective should be a bit farther away to look nice */
				if (rv3d->persp != RV3D_ORTHO) {
					dist_new = size_persp;
				}
				else {
					dist_new = size_ortho;
				}

				/* correction for window aspect ratio */
				if (ar->winy > 2 && ar->winx > 2) {
					float asp = (float)ar->winx / (float)ar->winy;
					if (asp < 1.0f) asp = 1.0f / asp;
					dist_new *= asp;
				}

				ED_view3d_smooth_view_ex(
				        wm, win, sa,
				        v3d, ar, camera_old, NULL,
				        ofs_new, NULL, &dist_new, NULL,
				        smooth_viewtx);
			}
		}
		
		v3d->lay = locallay;
	}
	else {
		/* clear flags */ 
		for (base = FIRSTBASE; base; base = base->next) {
			if (base->lay & locallay) {
				base->lay -= locallay;
				if (base->lay == 0) base->lay = v3d->layact;
				if (base->object != scene->obedit) base->flag |= SELECT;
				base->object->lay = base->lay;
			}
		}
	}

	return ok;
}
Example #2
0
static bool view3d_localview_init(
        wmWindowManager *wm, wmWindow *win,
        Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx,
        ReportList *reports)
{
	View3D *v3d = sa->spacedata.first;
	Base *base;
	float min[3], max[3], box[3], mid[3];
	float size = 0.0f;
	unsigned int locallay;
	bool ok = false;

	if (v3d->localvd) {
		return ok;
	}

	INIT_MINMAX(min, max);

	locallay = free_localbit(bmain);

	if (locallay == 0) {
		BKE_report(reports, RPT_ERROR, "No more than 8 local views");
		ok = false;
	}
	else {
		if (scene->obedit) {
			BKE_object_minmax(scene->obedit, min, max, false);
			
			ok = true;
		
			BASACT->lay |= locallay;
			scene->obedit->lay = BASACT->lay;
		}
		else {
			for (base = FIRSTBASE; base; base = base->next) {
				if (TESTBASE(v3d, base)) {
					BKE_object_minmax(base->object, min, max, false);
					base->lay |= locallay;
					base->object->lay = base->lay;
					ok = true;
				}
			}
		}

		sub_v3_v3v3(box, max, min);
		size = max_fff(box[0], box[1], box[2]);
	}
	
	if (ok == true) {
		ARegion *ar;
		
		v3d->localvd = MEM_mallocN(sizeof(View3D), "localview");
		
		memcpy(v3d->localvd, v3d, sizeof(View3D));

		mid_v3_v3v3(mid, min, max);

		copy_v3_v3(v3d->cursor, mid);

		for (ar = sa->regionbase.first; ar; ar = ar->next) {
			if (ar->regiontype == RGN_TYPE_WINDOW) {
				RegionView3D *rv3d = ar->regiondata;
				bool ok_dist = true;

				/* new view values */
				Object *camera_old = NULL;
				float dist_new, ofs_new[3];

				rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region");
				memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D));

				negate_v3_v3(ofs_new, mid);

				if (rv3d->persp == RV3D_CAMOB) {
					rv3d->persp = RV3D_PERSP;
					camera_old = v3d->camera;
				}

				if (rv3d->persp == RV3D_ORTHO) {
					if (size < 0.0001f) {
						ok_dist = false;
					}
				}

				if (ok_dist) {
					dist_new = ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
					if (rv3d->persp == RV3D_PERSP) {
						/* don't zoom closer than the near clipping plane */
						dist_new = max_ff(dist_new, v3d->near * 1.5f);
					}
				}

				ED_view3d_smooth_view_ex(
				        wm, win, sa,
				        v3d, ar, camera_old, NULL,
				        ofs_new, NULL, ok_dist ? &dist_new : NULL, NULL,
				        smooth_viewtx);
			}
		}
		
		v3d->lay = locallay;
	}
	else {
		/* clear flags */ 
		for (base = FIRSTBASE; base; base = base->next) {
			if (base->lay & locallay) {
				base->lay -= locallay;
				if (base->lay == 0) base->lay = v3d->layact;
				if (base->object != scene->obedit) base->flag |= SELECT;
				base->object->lay = base->lay;
			}
		}
	}

	return ok;
}