static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx) { const bool free = true; ARegion *ar; View3D *v3d = sa->spacedata.first; Object *camera_old, *camera_new; if (v3d->localvd == NULL) return; camera_old = v3d->camera; camera_new = v3d->localvd->camera; v3d->near = v3d->localvd->near; v3d->far = v3d->localvd->far; v3d->lay = v3d->localvd->lay; v3d->layact = v3d->localvd->layact; v3d->drawtype = v3d->localvd->drawtype; v3d->camera = v3d->localvd->camera; if (free) { MEM_freeN(v3d->localvd); v3d->localvd = NULL; } for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = ar->regiondata; if (rv3d->localvd) { Object *camera_old_rv3d, *camera_new_rv3d; camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : NULL; camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : NULL; rv3d->view = rv3d->localvd->view; rv3d->persp = rv3d->localvd->persp; rv3d->camzoom = rv3d->localvd->camzoom; ED_view3d_smooth_view_ex( wm, win, sa, v3d, ar, camera_old_rv3d, camera_new_rv3d, rv3d->localvd->ofs, rv3d->localvd->viewquat, &rv3d->localvd->dist, NULL, smooth_viewtx); if (free) { MEM_freeN(rv3d->localvd); rv3d->localvd = NULL; } } ED_view3d_shade_update(bmain, scene, v3d, sa); } } }
void ED_view3d_smooth_view( bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera, Object *camera, const float *ofs, const float *quat, const float *dist, const float *lens, const int smooth_viewtx) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); ScrArea *sa = CTX_wm_area(C); ED_view3d_smooth_view_ex( wm, win, sa, v3d, ar, oldcamera, camera, ofs, quat, dist, lens, smooth_viewtx); }
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; }
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; }