diff options
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_edit.c')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_edit.c | 519 |
1 files changed, 358 insertions, 161 deletions
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 2509ae75744..d563c07baf3 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -40,6 +40,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_camera_types.h" +#include "DNA_lamp_types.h" #include "MEM_guardedalloc.h" @@ -55,6 +56,8 @@ #include "BKE_paint.h" #include "BKE_report.h" #include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_depsgraph.h" /* for ED_view3d_camera_lock_sync */ #include "BIF_gl.h" @@ -79,6 +82,60 @@ /* ********************** view3d_edit: view manipulations ********************* */ +int ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d) +{ + return ((v3d->camera) && + (v3d->camera->id.lib == NULL) && + (v3d->flag2 & V3D_LOCK_CAMERA) && + (rv3d->persp==RV3D_CAMOB)); +} + +void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d) +{ + if(ED_view3d_camera_lock_check(v3d, rv3d)) { + ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); + } +} + +void ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) +{ + if(ED_view3d_camera_lock_check(v3d, rv3d)) { + Object *root_parent; + + if((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (root_parent= v3d->camera->parent)) { + Object *ob_update; + float view_mat[4][4]; + float diff_mat[4][4]; + float parent_mat[4][4]; + + while(root_parent->parent) { + root_parent= root_parent->parent; + } + + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + + invert_m4_m4(v3d->camera->imat, v3d->camera->obmat); + mul_m4_m4m4(diff_mat, v3d->camera->imat, view_mat); + + mul_m4_m4m4(parent_mat, root_parent->obmat, diff_mat); + object_apply_mat4(root_parent, parent_mat, TRUE, FALSE); + + ob_update= v3d->camera; + while(ob_update) { + DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); + WM_main_add_notifier(NC_OBJECT|ND_TRANSFORM, ob_update); + ob_update= ob_update->parent; + } + } + else { + ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); + DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); + WM_main_add_notifier(NC_OBJECT|ND_TRANSFORM, v3d->camera); + } + } +} + + /* ********************* box view support ***************** */ static void view3d_boxview_clip(ScrArea *sa) @@ -277,6 +334,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, short do_clip) typedef struct ViewOpsData { ScrArea *sa; ARegion *ar; + View3D *v3d; RegionView3D *rv3d; /* needed for continuous zoom */ @@ -331,7 +389,6 @@ static void calctrackballvec(rcti *rect, int mx, int my, float *vec) static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) { static float lastofs[3] = {0,0,0}; - View3D *v3d; RegionView3D *rv3d; ViewOpsData *vod= MEM_callocN(sizeof(ViewOpsData), "viewops data"); @@ -339,8 +396,13 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) op->customdata= vod; vod->sa= CTX_wm_area(C); vod->ar= CTX_wm_region(C); - v3d= vod->sa->spacedata.first; + vod->v3d= vod->sa->spacedata.first; vod->rv3d= rv3d= vod->ar->regiondata; + + /* set the view from the camera, if view locking is enabled. + * we may want to make this optional but for now its needed always */ + ED_view3d_camera_lock_init(vod->v3d, vod->rv3d); + vod->dist0= rv3d->dist; copy_qt_qt(vod->oldquat, rv3d->viewquat); vod->origx= vod->oldx= event->x; @@ -358,8 +420,8 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ - if((vod->use_dyn_ofs=view_autodist(CTX_data_scene(C), vod->ar, v3d, event->mval, vod->dyn_ofs))) { - if (rv3d->persp==RV3D_PERSP) { + if((vod->use_dyn_ofs=ED_view3d_autodist(CTX_data_scene(C), vod->ar, vod->v3d, event->mval, vod->dyn_ofs))) { + if (rv3d->is_persp) { float my_origin[3]; /* original G.vd->ofs */ float my_pivot[3]; /* view */ float dvec[3]; @@ -382,7 +444,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) sub_v3_v3v3(my_pivot, rv3d->ofs, upvec); negate_v3(my_pivot); /* ofs is flipped */ - /* find a new ofs value that is allong the view axis (rather then the mouse location) */ + /* find a new ofs value that is allong the view axis (rather than the mouse location) */ closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin); vod->dist0 = rv3d->dist = len_v3v3(my_pivot, dvec); @@ -390,17 +452,19 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) } negate_v3(vod->dyn_ofs); copy_v3_v3(vod->ofs, rv3d->ofs); - } else { - vod->ofs[0] = vod->ofs[1] = vod->ofs[2] = 0.0f; } } - /* for dolly */ - window_to_3d_vector(vod->ar, vod->mousevec, (vod->oldx - vod->ar->winrct.xmin)-(vod->ar->winx)/2, (vod->oldy - vod->ar->winrct.ymin)-(vod->ar->winy)/2); + { + /* for dolly */ + float mval_f[2]; + VECCOPY2D(mval_f, event->mval); + ED_view3d_win_to_vector(vod->ar, mval_f, vod->mousevec); + } /* lookup, we dont pass on v3d to prevent confusement */ - vod->grid= v3d->grid; - vod->far= v3d->far; + vod->grid= vod->v3d->grid; + vod->far= vod->v3d->far; calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec); @@ -546,7 +610,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) { RegionView3D *rv3d= vod->rv3d; - rv3d->view= 0; /* need to reset everytime because of view snapping */ + rv3d->view= RV3D_VIEW_USER; /* need to reset everytime because of view snapping */ if (U.flag & USER_TRACKBALL) { float phi, si, q1[4], dvec[3], newvec[3]; @@ -711,6 +775,8 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) /* avoid precision loss over time */ normalize_qt(rv3d->viewquat); + ED_view3d_camera_lock_sync(vod->v3d, rv3d); + ED_region_tag_redraw(vod->ar); } @@ -754,7 +820,7 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) viewrotate_apply(vod, event->x, event->y); } else if (event_code==VIEW_CONFIRM) { - request_depth_update(vod->rv3d); + ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); return OPERATOR_FINISHED; @@ -782,18 +848,18 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) if(rv3d->persp != RV3D_PERSP) { if (U.uiflag & USER_AUTOPERSP) { - rv3d->persp= RV3D_PERSP; + if(!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { + rv3d->persp= RV3D_PERSP; + } } else if(rv3d->persp==RV3D_CAMOB) { /* changed since 2.4x, use the camera view */ - View3D *v3d = vod->sa->spacedata.first; - - if(v3d->camera) { - view3d_apply_ob(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); + if(vod->v3d->camera) { + ED_view3d_from_object(vod->v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); } - if(rv3d->persp==RV3D_CAMOB) { + if(!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { rv3d->persp= rv3d->lpersp; } } @@ -802,7 +868,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) if (event->type == MOUSEPAN) { viewrotate_apply(vod, event->prevx, event->prevy); - request_depth_update(rv3d); + ED_view3d_depth_tag_update(rv3d); viewops_data_free(C, op); @@ -811,7 +877,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) else if (event->type == MOUSEROTATE) { /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */ viewrotate_apply(vod, event->prevx, event->y); - request_depth_update(rv3d); + ED_view3d_depth_tag_update(rv3d); viewops_data_free(C, op); @@ -837,6 +903,13 @@ static int view3d_camera_active_poll(bContext *C) return 0; } +static int viewrotate_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} + void VIEW3D_OT_rotate(wmOperatorType *ot) { @@ -849,6 +922,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->invoke= viewrotate_invoke; ot->modal= viewrotate_modal; ot->poll= ED_operator_region_view3d_active; + ot->cancel= viewrotate_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -894,20 +968,21 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf) static void viewmove_apply(ViewOpsData *vod, int x, int y) { - if(vod->rv3d->persp==RV3D_CAMOB) { - float zoomfac= ((float)M_SQRT2 + (float)vod->rv3d->camzoom / 50.0f); - zoomfac= (zoomfac * zoomfac) * 0.5f; - + if((vod->rv3d->persp==RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { + const float zoomfac= BKE_screen_view3d_zoom_to_fac((float)vod->rv3d->camzoom) * 2.0f; vod->rv3d->camdx += (vod->oldx - x)/(vod->ar->winx * zoomfac); vod->rv3d->camdy += (vod->oldy - y)/(vod->ar->winy * zoomfac); CLAMP(vod->rv3d->camdx, -1.0f, 1.0f); CLAMP(vod->rv3d->camdy, -1.0f, 1.0f); -// XXX preview3d_event= 0; } else { float dvec[3]; + float mval_f[2]; + + mval_f[0]= x - vod->oldx; + mval_f[1]= y - vod->oldy; + ED_view3d_win_to_delta(vod->ar, mval_f, dvec); - window_to_3d_delta(vod->ar, dvec, x-vod->oldx, y-vod->oldy); add_v3_v3(vod->rv3d->ofs, dvec); if(vod->rv3d->viewlock & RV3D_BOXVIEW) @@ -917,6 +992,8 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y) vod->oldx= x; vod->oldy= y; + ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); + ED_region_tag_redraw(vod->ar); } @@ -954,7 +1031,7 @@ static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) viewmove_apply(vod, event->x, event->y); } else if (event_code==VIEW_CONFIRM) { - request_depth_update(vod->rv3d); + ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); @@ -966,13 +1043,15 @@ static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) { + ViewOpsData *vod; + /* makes op->customdata */ viewops_data_create(C, op, event); + vod= op->customdata; if (event->type == MOUSEPAN) { - ViewOpsData *vod= op->customdata; viewmove_apply(vod, event->prevx, event->prevy); - request_depth_update(vod->rv3d); + ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); @@ -986,6 +1065,13 @@ static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) } } +static int viewmove_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} + void VIEW3D_OT_move(wmOperatorType *ot) { @@ -998,6 +1084,7 @@ void VIEW3D_OT_move(wmOperatorType *ot) ot->invoke= viewmove_invoke; ot->modal= viewmove_modal; ot->poll= ED_operator_view3d_active; + ot->cancel= viewmove_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -1005,6 +1092,7 @@ void VIEW3D_OT_move(wmOperatorType *ot) /* ************************ viewzoom ******************************** */ +/* viewdolly_modal_keymap has an exact copy of this, apply fixes to both */ /* called in transform_ops.c, on each regeneration of keymaps */ void viewzoom_modal_keymap(wmKeyConfig *keyconf) { @@ -1045,21 +1133,17 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) float dvec[3]; float tvec[3]; float tpos[3]; + float mval_f[2]; float new_dist; - short vb[2], mouseloc[2]; - - mouseloc[0]= mx - ar->winrct.xmin; - mouseloc[1]= my - ar->winrct.ymin; - - /* find the current window width and height */ - vb[0] = ar->winx; - vb[1] = ar->winy; negate_v3_v3(tpos, rv3d->ofs); /* Project cursor position into 3D space */ initgrabz(rv3d, tpos[0], tpos[1], tpos[2]); - window_to_3d_delta(ar, dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2); + + mval_f[0]= (float)(((mx - ar->winrct.xmin) * 2) - ar->winx) / 2.0f; + mval_f[1]= (float)(((my - ar->winrct.ymin) * 2) - ar->winy) / 2.0f; + ED_view3d_win_to_delta(ar, mval_f, dvec); /* Calculate view target position for dolly */ add_v3_v3v3(tvec, tpos, dvec); @@ -1137,28 +1221,15 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, zfac * vod->rv3d->dist < 10.0f * vod->far) view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy); - - if ((U.uiflag & USER_ORBIT_ZBUF) && (viewzoom==USER_ZOOM_CONT) && (vod->rv3d->persp==RV3D_PERSP)) { - float upvec[3], mat[3][3]; - - /* Secret apricot feature, translate the view when in continues mode */ - upvec[0] = upvec[1] = 0.0f; - upvec[2] = (vod->dist0 - vod->rv3d->dist) * vod->grid; - vod->rv3d->dist = vod->dist0; - copy_m3_m4(mat, vod->rv3d->viewinv); - mul_m3_v3(mat, upvec); - add_v3_v3(vod->rv3d->ofs, upvec); - } else { - /* these limits were in old code too */ - if(vod->rv3d->dist<0.001f * vod->grid) vod->rv3d->dist= 0.001f * vod->grid; - if(vod->rv3d->dist>10.0f * vod->far) vod->rv3d->dist=10.0f * vod->far; - } - -// XXX if(vod->rv3d->persp==RV3D_ORTHO || vod->rv3d->persp==RV3D_CAMOB) preview3d_event= 0; + /* these limits were in old code too */ + if(vod->rv3d->dist<0.001f * vod->grid) vod->rv3d->dist= 0.001f * vod->grid; + if(vod->rv3d->dist>10.0f * vod->far) vod->rv3d->dist=10.0f * vod->far; if(vod->rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_sync(vod->sa, vod->ar); + ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); + ED_region_tag_redraw(vod->ar); } @@ -1199,7 +1270,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event) viewzoom_apply(vod, event->x, event->y, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0); } else if (event_code==VIEW_CONFIRM) { - request_depth_update(vod->rv3d); + ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); return OPERATOR_FINISHED; @@ -1214,6 +1285,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op) RegionView3D *rv3d; ScrArea *sa; ARegion *ar; + short use_cam_zoom; int delta= RNA_int_get(op->ptr, "delta"); int mx, my; @@ -1235,9 +1307,11 @@ static int viewzoom_exec(bContext *C, wmOperator *op) mx= RNA_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : ar->winx / 2; my= RNA_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2; + use_cam_zoom= (rv3d->persp==RV3D_CAMOB) && !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d)); + if(delta < 0) { /* this min and max is also in viewmove() */ - if(rv3d->persp==RV3D_CAMOB) { + if(use_cam_zoom) { rv3d->camzoom-= 10; if(rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom= RV3D_CAMZOOM_MIN; } @@ -1246,7 +1320,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op) } } else { - if(rv3d->persp==RV3D_CAMOB) { + if(use_cam_zoom) { rv3d->camzoom+= 10; if(rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom= RV3D_CAMZOOM_MAX; } @@ -1258,7 +1332,10 @@ static int viewzoom_exec(bContext *C, wmOperator *op) if(rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_sync(sa, ar); - request_depth_update(rv3d); + ED_view3d_depth_tag_update(rv3d); + + ED_view3d_camera_lock_sync(v3d, rv3d); + ED_region_tag_redraw(ar); viewops_data_free(C, op); @@ -1266,9 +1343,48 @@ static int viewzoom_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +/* this is an exact copy of viewzoom_modal_keymap */ +/* called in transform_ops.c, on each regeneration of keymaps */ +void viewdolly_modal_keymap(wmKeyConfig *keyconf) +{ + static EnumPropertyItem modal_items[] = { + {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + + {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, + {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, + + {0, NULL, 0, NULL, NULL}}; + + wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Dolly Modal"); + + /* this function is called for each spacetype, only needs to add map once */ + if(keymap) return; + + keymap= WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items); + + /* items for modal map */ + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); + + /* disabled mode switching for now, can re-implement better, later on + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); + */ + + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly"); +} + /* viewdolly_invoke() copied this function, changes here may apply there */ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) { + ViewOpsData *vod; + + /* makes op->customdata */ + viewops_data_create(C, op, event); + vod= op->customdata; + /* if one or the other zoom position aren't set, set from event */ if (!RNA_property_is_set(op->ptr, "mx") || !RNA_property_is_set(op->ptr, "my")) { @@ -1277,18 +1393,9 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) } if(RNA_property_is_set(op->ptr, "delta")) { - /* makes op->customdata */ - viewops_data_create(C, op, event); viewzoom_exec(C, op); } else { - ViewOpsData *vod; - - /* makes op->customdata */ - viewops_data_create(C, op, event); - - vod= op->customdata; - if (event->type == MOUSEZOOM) { /* Bypass Zoom invert flag for track pads (pass FALSE always) */ @@ -1301,7 +1408,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) vod->origy = vod->oldy = vod->origy + event->x - event->prevx; viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, FALSE); } - request_depth_update(vod->rv3d); + ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); return OPERATOR_FINISHED; @@ -1322,6 +1429,12 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } +static int viewzoom_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} void VIEW3D_OT_zoom(wmOperatorType *ot) { @@ -1335,6 +1448,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) ot->exec= viewzoom_exec; ot->modal= viewzoom_modal; ot->poll= ED_operator_region_view3d_active; + ot->cancel= viewzoom_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -1349,7 +1463,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) static void view_dolly_mouseloc(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac) { RegionView3D *rv3d= ar->regiondata; - madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, 1.0 - dfac); + madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0 - dfac)); } static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_invert) @@ -1379,6 +1493,8 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv if(vod->rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_sync(vod->sa, vod->ar); + ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); + ED_region_tag_redraw(vod->ar); } @@ -1415,7 +1531,7 @@ static int viewdolly_modal(bContext *C, wmOperator *op, wmEvent *event) viewdolly_apply(vod, event->x, event->y, (U.uiflag & USER_ZOOM_INVERT) != 0); } else if (event_code==VIEW_CONFIRM) { - request_depth_update(vod->rv3d); + ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); return OPERATOR_FINISHED; @@ -1426,14 +1542,13 @@ static int viewdolly_modal(bContext *C, wmOperator *op, wmEvent *event) static int viewdolly_exec(bContext *C, wmOperator *op) { - View3D *v3d; + /* View3D *v3d; */ RegionView3D *rv3d; ScrArea *sa; ARegion *ar; float mousevec[3]; int delta= RNA_int_get(op->ptr, "delta"); - int mx, my; if(op->customdata) { ViewOpsData *vod= op->customdata; @@ -1445,10 +1560,11 @@ static int viewdolly_exec(bContext *C, wmOperator *op) else { sa= CTX_wm_area(C); ar= CTX_wm_region(C); - normalize_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv[2]); + negate_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv[2]); + normalize_v3(mousevec); } - v3d= sa->spacedata.first; + /* v3d= sa->spacedata.first; */ /* UNUSED */ rv3d= ar->regiondata; /* overwrite the mouse vector with the view direction (zoom into the center) */ @@ -1456,11 +1572,6 @@ static int viewdolly_exec(bContext *C, wmOperator *op) normalize_v3_v3(mousevec, rv3d->viewinv[2]); } - mx= RNA_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : ar->winx / 2; - my= RNA_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2; - - - if(delta < 0) { view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 1.2f); } @@ -1471,7 +1582,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op) if(rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_sync(sa, ar); - request_depth_update(rv3d); + ED_view3d_depth_tag_update(rv3d); ED_region_tag_redraw(ar); viewops_data_free(C, op); @@ -1481,7 +1592,13 @@ static int viewdolly_exec(bContext *C, wmOperator *op) /* copied from viewzoom_invoke(), changes here may apply there */ static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ +{ + ViewOpsData *vod; + + /* makes op->customdata */ + viewops_data_create(C, op, event); + vod= op->customdata; + /* if one or the other zoom position aren't set, set from event */ if (!RNA_property_is_set(op->ptr, "mx") || !RNA_property_is_set(op->ptr, "my")) { @@ -1490,21 +1607,13 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event) } if(RNA_property_is_set(op->ptr, "delta")) { - /* makes op->customdata */ - viewops_data_create(C, op, event); viewdolly_exec(C, op); } else { - ViewOpsData *vod; - - /* makes op->customdata */ - viewops_data_create(C, op, event); - - vod= op->customdata; - /* overwrite the mouse vector with the view direction (zoom into the center) */ if((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) { - normalize_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]); + negate_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]); + normalize_v3(vod->mousevec); } if (event->type == MOUSEZOOM) { @@ -1520,7 +1629,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event) vod->origy = vod->oldy = vod->origy + event->x - event->prevx; viewdolly_apply(vod, event->prevx, event->prevy, FALSE); } - request_depth_update(vod->rv3d); + ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); return OPERATOR_FINISHED; @@ -1540,13 +1649,27 @@ static int viewdolly_poll(bContext *C) { RegionView3D *rv3d= CTX_wm_region_view3d(C); - if (rv3d && rv3d->persp == RV3D_PERSP) { - return 1; + if(rv3d) { + if (rv3d->persp == RV3D_PERSP) { + return 1; + } + else { + View3D *v3d= CTX_wm_view3d(C); + if (ED_view3d_camera_lock_check(v3d, rv3d)) { + return 1; + } + } } - return 0; } +static int viewdolly_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} + void VIEW3D_OT_dolly(wmOperatorType *ot) { /* identifiers */ @@ -1559,6 +1682,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot) ot->exec= viewdolly_exec; ot->modal= viewdolly_modal; ot->poll= viewdolly_poll; + ot->cancel= viewdolly_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -1578,6 +1702,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in Scene *scene= CTX_data_scene(C); Base *base; float *curs; + const short skip_camera= ED_view3d_camera_lock_check(v3d, rv3d); int center= RNA_boolean_get(op->ptr, "center"); @@ -1598,6 +1723,11 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in for(base= scene->base.first; base; base= base->next) { if(BASE_VISIBLE(v3d, base)) { onedone= 1; + + if(skip_camera && base->object == v3d->camera) { + continue; + } + minmax_object(base->object, min, max); } } @@ -1633,7 +1763,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in new_dist*= size; } - if (rv3d->persp==RV3D_CAMOB) { + if ((rv3d->persp==RV3D_CAMOB) && !ED_view3d_camera_lock_check(v3d, rv3d)) { rv3d->persp= RV3D_PERSP; smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, &new_dist, NULL); } @@ -1677,6 +1807,7 @@ static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) /* like a loca Object *obedit= CTX_data_edit_object(C); float size, min[3], max[3], afm[3]; int ok=0, ok_dist=1; + const short skip_camera= ED_view3d_camera_lock_check(v3d, rv3d); /* SMOOTHVIEW */ float new_ofs[3]; @@ -1730,17 +1861,20 @@ static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) /* like a loca ok= PE_minmax(scene, min, max); } else { - Base *base= FIRSTBASE; - while(base) { + Base *base; + for(base= FIRSTBASE; base; base = base->next) { if(TESTBASE(v3d, base)) { + if(skip_camera && base->object == v3d->camera) { + continue; + } + /* account for duplis */ if (minmax_object_duplis(scene, base->object, min, max)==0) minmax_object(base->object, min, max); /* use if duplis not found */ ok= 1; } - base= base->next; } } @@ -1749,7 +1883,7 @@ static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) /* like a loca sub_v3_v3v3(afm, max, min); size= MAX3(afm[0], afm[1], afm[2]); - if(rv3d->persp==RV3D_ORTHO) { + if(!rv3d->is_persp) { if(size < 0.0001f) { /* if its a sinble point. dont even re-scale */ ok_dist= 0; } @@ -1776,7 +1910,7 @@ static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) /* like a loca new_dist*= size; } - if (rv3d->persp==RV3D_CAMOB) { + if (rv3d->persp==RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) { rv3d->persp= RV3D_PERSP; smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, &new_dist, NULL); } @@ -1844,10 +1978,23 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot) static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */ { + ARegion *ar= CTX_wm_region(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); + Scene *scene= CTX_data_scene(C); + float xfac, yfac; + float size[2]; rv3d->camdx= rv3d->camdy= 0.0f; + view3d_viewborder_size_get(scene, ar, size); + + /* 4px is just a little room from the edge of the area */ + xfac= (float)ar->winx / (float)(size[0] + 4); + yfac= (float)ar->winy / (float)(size[1] + 4); + + rv3d->camzoom= BKE_screen_view3d_zoom_from_fac(MIN2(xfac, yfac)); + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, CTX_wm_view3d(C)); return OPERATOR_FINISHED; @@ -1887,7 +2034,7 @@ static int render_border_exec(bContext *C, wmOperator *op) rect.ymax= RNA_int_get(op->ptr, "ymax"); /* calculate range */ - view3d_calc_camera_border(scene, ar, rv3d, v3d, &vb, FALSE); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE); scene->r.border.xmin= ((float)rect.xmin-vb.xmin)/(vb.xmax-vb.xmin); scene->r.border.ymin= ((float)rect.ymin-vb.ymin)/(vb.ymax-vb.ymin); @@ -1929,6 +2076,7 @@ void VIEW3D_OT_render_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= render_border_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= view3d_camera_active_poll; @@ -1993,7 +2141,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) cent[0] = (((double)rect.xmin)+((double)rect.xmax)) / 2; cent[1] = (((double)rect.ymin)+((double)rect.ymax)) / 2; - if (rv3d->persp==RV3D_PERSP) { + if (rv3d->is_persp) { double p_corner[3]; /* no depths to use, we cant do anything! */ @@ -2029,13 +2177,17 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) new_ofs[0] = -p[0]; new_ofs[1] = -p[1]; new_ofs[2] = -p[2]; - } else { + } + else { + float mval_f[2]; /* We cant use the depth, fallback to the old way that dosnt set the center depth */ copy_v3_v3(new_ofs, rv3d->ofs); initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]); - window_to_3d_delta(ar, dvec, (rect.xmin+rect.xmax-vb[0])/2, (rect.ymin+rect.ymax-vb[1])/2); + mval_f[0]= (rect.xmin + rect.xmax - vb[0]) / 2.0f; + mval_f[1]= (rect.ymin + rect.ymax - vb[1]) / 2.0f; + ED_view3d_win_to_delta(ar, mval_f, dvec); /* center the view to the center of the rectangle */ sub_v3_v3(new_ofs, dvec); } @@ -2059,10 +2211,11 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, wmEvent *event) { + View3D *v3d= CTX_wm_view3d(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); /* if in camera view do not exec the operator so we do not conflict with set render border*/ - if (rv3d->persp != RV3D_CAMOB) + if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) return WM_border_select_invoke(C, op, event); else return OPERATOR_PASS_THROUGH; @@ -2079,6 +2232,7 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot) ot->invoke= view3d_zoom_border_invoke; ot->exec= view3d_zoom_border_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_region_view3d_active; @@ -2101,9 +2255,9 @@ static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar) int im_width= (scene->r.size*scene->r.xsch)/100; view3d_viewborder_size_get(scene, ar, size); - - rv3d->camzoom= (sqrtf(4.0f * (float)im_width/size[0]) - (float)M_SQRT2) * 50.0f; - rv3d->camzoom= CLAMPIS(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + + rv3d->camzoom= BKE_screen_view3d_zoom_from_fac((float)im_width/size[0]); + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); } static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op)) @@ -2175,7 +2329,7 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar, float q1, float invert_qt(obact_quat); mul_qt_qtqt(new_quat, new_quat, obact_quat); - rv3d->view= view= 0; + rv3d->view= view= RV3D_VIEW_USER; } } @@ -2367,6 +2521,7 @@ static EnumPropertyItem prop_view_orbit_items[] = { static int vieworbit_exec(bContext *C, wmOperator *op) { + View3D *v3d= CTX_wm_view3d(C); ARegion *ar= ED_view3d_context_region_unlock(C); RegionView3D *rv3d= ar->regiondata; /* no NULL check is needed, poll checks */ float phi, q1[4], new_quat[4]; @@ -2375,8 +2530,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op) orbitdir = RNA_enum_get(op->ptr, "type"); if(rv3d->viewlock==0) { - - if(rv3d->persp != RV3D_CAMOB) { + if((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { if(orbitdir == V3D_VIEW_STEPLEFT || orbitdir == V3D_VIEW_STEPRIGHT) { float si; /* z-axis */ @@ -2387,7 +2541,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op) q1[1]= q1[2]= 0.0; q1[3]= si; mul_qt_qtqt(new_quat, rv3d->viewquat, q1); - rv3d->view= 0; + rv3d->view= RV3D_VIEW_USER; } else if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) { /* horizontal axis */ @@ -2399,7 +2553,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op) q1[0]= (float)cos(phi); mul_v3_fl(q1+1, sin(phi)); mul_qt_qtqt(new_quat, rv3d->viewquat, q1); - rv3d->view= 0; + rv3d->view= RV3D_VIEW_USER; } smooth_view(C, CTX_wm_view3d(C), ar, NULL, NULL, NULL, new_quat, NULL, NULL); @@ -2437,15 +2591,16 @@ static int viewpan_exec(bContext *C, wmOperator *op) ARegion *ar= CTX_wm_region(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); float vec[3]; + float mval_f[2]= {0.0f, 0.0f}; int pandir; pandir = RNA_enum_get(op->ptr, "type"); initgrabz(rv3d, 0.0, 0.0, 0.0); - if(pandir == V3D_VIEW_PANRIGHT) window_to_3d_delta(ar, vec, -32, 0); - else if(pandir == V3D_VIEW_PANLEFT) window_to_3d_delta(ar, vec, 32, 0); - else if(pandir == V3D_VIEW_PANUP) window_to_3d_delta(ar, vec, 0, -25); - else if(pandir == V3D_VIEW_PANDOWN) window_to_3d_delta(ar, vec, 0, 25); + if(pandir == V3D_VIEW_PANRIGHT) { mval_f[0]= -32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } + else if(pandir == V3D_VIEW_PANLEFT) { mval_f[0]= 32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } + else if(pandir == V3D_VIEW_PANUP) { mval_f[1]= -25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } + else if(pandir == V3D_VIEW_PANDOWN) { mval_f[1]= 25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } add_v3_v3(rv3d->ofs, vec); if(rv3d->viewlock & RV3D_BOXVIEW) @@ -2681,7 +2836,7 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op) view3d_set_viewcontext(C, &vc); view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */ - view3d_calculate_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect); + ED_view3d_calc_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect); return OPERATOR_FINISHED; } @@ -2716,6 +2871,7 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) ot->invoke= view3d_clipping_invoke; ot->exec= view3d_clipping_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_region_view3d_active; @@ -2739,7 +2895,7 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *eve View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3]; - short mx, my, mval[2]; + int mval[2]; // short ctrl= 0; // XXX int flip; fp= give_cursor(scene, v3d); @@ -2747,10 +2903,7 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *eve // if(obedit && ctrl) lr_click= 1; copy_v3_v3(oldcurs, fp); - mx= event->x - ar->winrct.xmin; - my= event->y - ar->winrct.ymin; - - project_short_noclip(ar, fp, mval); + project_int_noclip(ar, fp, mval); flip= initgrabz(rv3d, fp[0], fp[1], fp[2]); /* reset the depth based on the view offset */ @@ -2758,7 +2911,7 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *eve negate_v3_v3(fp, rv3d->ofs); /* re initialize */ - project_short_noclip(ar, fp, mval); + project_int_noclip(ar, fp, mval); flip= initgrabz(rv3d, fp[0], fp[1], fp[2]); } @@ -2766,23 +2919,22 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *eve short depth_used = 0; if (U.uiflag & USER_ORBIT_ZBUF) { /* maybe this should be accessed some other way */ - short mval_depth[2]; - mval_depth[0]= mx; - mval_depth[1]= my; view3d_operator_needs_opengl(C); - if (view_autodist(scene, ar, v3d, mval_depth, fp)) + if (ED_view3d_autodist(scene, ar, v3d, event->mval, fp)) depth_used= 1; } if(depth_used==0) { - window_to_3d_delta(ar, dvec, mval[0]-mx, mval[1]-my); + float mval_f[2]; + VECSUB2D(mval_f, mval, event->mval); + ED_view3d_win_to_delta(ar, mval_f, dvec); sub_v3_v3(fp, dvec); } } else { - dx= ((float)(mx-(ar->winx/2)))*rv3d->zfac/(ar->winx/2); - dy= ((float)(my-(ar->winy/2)))*rv3d->zfac/(ar->winy/2); + dx= ((float)(event->mval[0]-(ar->winx/2)))*rv3d->zfac/(ar->winx/2); + dy= ((float)(event->mval[1]-(ar->winy/2)))*rv3d->zfac/(ar->winy/2); fz= rv3d->persmat[0][3]*fp[0]+ rv3d->persmat[1][3]*fp[1]+ rv3d->persmat[2][3]*fp[2]+ rv3d->persmat[3][3]; fz= fz/rv3d->zfac; @@ -2897,7 +3049,7 @@ void VIEW3D_OT_enable_manipulator(wmOperatorType *ot) /* ************************* below the line! *********************** */ -static float view_autodist_depth_margin(ARegion *ar, const short mval[2], int margin) +static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin) { ViewDepths depth_temp= {0}; rcti rect; @@ -2925,7 +3077,7 @@ static float view_autodist_depth_margin(ARegion *ar, const short mval[2], int ma } /* XXX todo Zooms in on a border drawn by the user */ -int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, const short mval[2], float mouse_worldloc[3] ) //, float *autodist ) +int ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2], float mouse_worldloc[3] ) //, float *autodist ) { bglMats mats; /* ZBuffer depth vars */ float depth_close= FLT_MAX; @@ -2952,7 +3104,7 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, const short mval[2], f return 1; } -int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, float *autodist ) +int ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, float *autodist ) { /* Get Z Depths, needed for perspective, nice for ortho */ switch(mode) { @@ -2968,7 +3120,7 @@ int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, flo } // no 4x4 sampling, run view_autodist_init first -int view_autodist_simple(ARegion *ar, const short mval[2], float mouse_worldloc[3], int margin, float *force_depth) //, float *autodist ) +int ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth) //, float *autodist ) { bglMats mats; /* ZBuffer depth vars, could cache? */ float depth; @@ -2996,7 +3148,7 @@ int view_autodist_simple(ARegion *ar, const short mval[2], float mouse_worldloc[ return 1; } -int view_autodist_depth(struct ARegion *ar, const short mval[2], int margin, float *depth) +int ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin, float *depth) { *depth= view_autodist_depth_margin(ar, mval, margin); @@ -3006,11 +3158,11 @@ int view_autodist_depth(struct ARegion *ar, const short mval[2], int margin, flo static int depth_segment_cb(int x, int y, void *userData) { struct { struct ARegion *ar; int margin; float depth; } *data = userData; - short mval[2]; + int mval[2]; float depth; - mval[0]= (short)x; - mval[1]= (short)y; + mval[0]= x; + mval[1]= y; depth= view_autodist_depth_margin(data->ar, mval, data->margin); @@ -3023,7 +3175,7 @@ static int depth_segment_cb(int x, int y, void *userData) } } -int view_autodist_depth_segment(struct ARegion *ar, const short mval_sta[2], const short mval_end[2], int margin, float *depth) +int ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth) { struct { struct ARegion *ar; int margin; float depth; } data = {NULL}; int p1[2]; @@ -3434,21 +3586,66 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int UNUSED(mode)) } #endif // if 0, unused NDof code -/* give a 4x4 matrix from a perspective view, only needs viewquat, ofs and dist - * basically the same as... - * rv3d->persp= RV3D_PERSP - * setviewmatrixview3d(scene, v3d, rv3d); - * setcameratoview3d(v3d, rv3d, v3d->camera); - * ...but less of a hassle - * */ -void view3d_persp_mat4(RegionView3D *rv3d, float mat[][4]) -{ - float qt[4], dvec[3]; - copy_qt_qt(qt, rv3d->viewquat); - qt[0]= -qt[0]; - quat_to_mat4(mat, qt); - mat[3][2] -= rv3d->dist; - translate_m4(mat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); - mul_v3_v3fl(dvec, mat[2], -rv3d->dist); - sub_v3_v3v3(mat[3], dvec, rv3d->ofs); + +/* Gets the view trasnformation from a camera +* currently dosnt take camzoom into account +* +* The dist is not modified for this function, if NULL its assimed zero +* */ +void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist) +{ + /* Offset */ + if (ofs) + negate_v3_v3(ofs, mat[3]); + + /* Quat */ + if (quat) { + float imat[4][4]; + invert_m4_m4(imat, mat); + mat4_to_quat(quat, imat); + } + + if (dist) { + float nmat[3][3]; + float vec[3]; + + vec[0]= 0.0f; + vec[1]= 0.0f; + vec[2]= -(*dist); + + copy_m3_m4(nmat, mat); + normalize_m3(nmat); + + mul_m3_v3(nmat, vec);; + sub_v3_v3(ofs, vec); + } +} + +void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], const float dist) +{ + float iviewquat[4]= {-quat[0], quat[1], quat[2], quat[3]}; + float dvec[3]= {0.0f, 0.0f, dist}; + + quat_to_mat4(mat, iviewquat); + mul_mat3_m4_v3(mat, dvec); + sub_v3_v3v3(mat[3], dvec, ofs); +} + + +/* object -> view */ +void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens) +{ + ED_view3d_from_m4(ob->obmat, ofs, quat, dist); + + if (lens) { + ED_view3d_ob_clip_range_get(ob, lens, NULL, NULL); + } +} + +/* view -> object */ +void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist) +{ + float mat[4][4]; + ED_view3d_to_m4(mat, ofs, quat, dist); + object_apply_mat4(ob, mat, TRUE, TRUE); } |