|
Blender
V2.59
|
00001 /* 00002 * $Id: view3d_edit.c 39108 2011-08-06 22:31:16Z merwin $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2008 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * 00024 * Contributor(s): Blender Foundation 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include <string.h> 00035 #include <stdio.h> 00036 #include <math.h> 00037 #include <float.h> 00038 00039 #include "DNA_armature_types.h" 00040 #include "DNA_object_types.h" 00041 #include "DNA_scene_types.h" 00042 #include "DNA_camera_types.h" 00043 #include "DNA_lamp_types.h" 00044 00045 #include "MEM_guardedalloc.h" 00046 00047 #include "BLI_blenlib.h" 00048 #include "BLI_math.h" 00049 #include "BLI_rand.h" 00050 #include "BLI_utildefines.h" 00051 00052 #include "BKE_context.h" 00053 #include "BKE_image.h" 00054 #include "BKE_library.h" 00055 #include "BKE_object.h" 00056 #include "BKE_paint.h" 00057 #include "BKE_report.h" 00058 #include "BKE_scene.h" 00059 #include "BKE_screen.h" 00060 #include "BKE_depsgraph.h" /* for ED_view3d_camera_lock_sync */ 00061 00062 00063 #include "BIF_gl.h" 00064 #include "BIF_glutil.h" 00065 00066 #include "WM_api.h" 00067 #include "WM_types.h" 00068 00069 #include "RNA_access.h" 00070 #include "RNA_define.h" 00071 00072 #include "ED_particle.h" 00073 #include "ED_screen.h" 00074 #include "ED_transform.h" 00075 #include "ED_mesh.h" 00076 #include "ED_view3d.h" 00077 00078 00079 #include "PIL_time.h" /* smoothview */ 00080 00081 #include "view3d_intern.h" // own include 00082 00083 /* ********************** view3d_edit: view manipulations ********************* */ 00084 00085 int ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d) 00086 { 00087 return ((v3d->camera) && 00088 (v3d->camera->id.lib == NULL) && 00089 (v3d->flag2 & V3D_LOCK_CAMERA) && 00090 (rv3d->persp==RV3D_CAMOB)); 00091 } 00092 00093 void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d) 00094 { 00095 if(ED_view3d_camera_lock_check(v3d, rv3d)) { 00096 ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); 00097 } 00098 } 00099 00100 void ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) 00101 { 00102 if(ED_view3d_camera_lock_check(v3d, rv3d)) { 00103 Object *root_parent; 00104 00105 if((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (root_parent= v3d->camera->parent)) { 00106 Object *ob_update; 00107 float view_mat[4][4]; 00108 float diff_mat[4][4]; 00109 float parent_mat[4][4]; 00110 00111 while(root_parent->parent) { 00112 root_parent= root_parent->parent; 00113 } 00114 00115 ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); 00116 00117 invert_m4_m4(v3d->camera->imat, v3d->camera->obmat); 00118 mul_m4_m4m4(diff_mat, v3d->camera->imat, view_mat); 00119 00120 mul_m4_m4m4(parent_mat, root_parent->obmat, diff_mat); 00121 object_apply_mat4(root_parent, parent_mat, TRUE, FALSE); 00122 00123 ob_update= v3d->camera; 00124 while(ob_update) { 00125 DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); 00126 WM_main_add_notifier(NC_OBJECT|ND_TRANSFORM, ob_update); 00127 ob_update= ob_update->parent; 00128 } 00129 } 00130 else { 00131 ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); 00132 DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); 00133 WM_main_add_notifier(NC_OBJECT|ND_TRANSFORM, v3d->camera); 00134 } 00135 } 00136 } 00137 00138 00139 /* ********************* box view support ***************** */ 00140 00141 static void view3d_boxview_clip(ScrArea *sa) 00142 { 00143 ARegion *ar; 00144 BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb"); 00145 float clip[6][4]; 00146 float x1= 0.0f, y1= 0.0f, z1= 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f}; 00147 int val; 00148 00149 /* create bounding box */ 00150 for(ar= sa->regionbase.first; ar; ar= ar->next) { 00151 if(ar->regiontype==RGN_TYPE_WINDOW) { 00152 RegionView3D *rv3d= ar->regiondata; 00153 00154 if(rv3d->viewlock & RV3D_BOXCLIP) { 00155 if(ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { 00156 if(ar->winx>ar->winy) x1= rv3d->dist; 00157 else x1= ar->winx*rv3d->dist/ar->winy; 00158 00159 if(ar->winx>ar->winy) y1= ar->winy*rv3d->dist/ar->winx; 00160 else y1= rv3d->dist; 00161 copy_v2_v2(ofs, rv3d->ofs); 00162 } 00163 else if(ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { 00164 ofs[2]= rv3d->ofs[2]; 00165 00166 if(ar->winx>ar->winy) z1= ar->winy*rv3d->dist/ar->winx; 00167 else z1= rv3d->dist; 00168 } 00169 } 00170 } 00171 } 00172 00173 for(val=0; val<8; val++) { 00174 if(ELEM4(val, 0, 3, 4, 7)) 00175 bb->vec[val][0]= -x1 - ofs[0]; 00176 else 00177 bb->vec[val][0]= x1 - ofs[0]; 00178 00179 if(ELEM4(val, 0, 1, 4, 5)) 00180 bb->vec[val][1]= -y1 - ofs[1]; 00181 else 00182 bb->vec[val][1]= y1 - ofs[1]; 00183 00184 if(val > 3) 00185 bb->vec[val][2]= -z1 - ofs[2]; 00186 else 00187 bb->vec[val][2]= z1 - ofs[2]; 00188 } 00189 00190 /* normals for plane equations */ 00191 normal_tri_v3( clip[0],bb->vec[0], bb->vec[1], bb->vec[4]); 00192 normal_tri_v3( clip[1],bb->vec[1], bb->vec[2], bb->vec[5]); 00193 normal_tri_v3( clip[2],bb->vec[2], bb->vec[3], bb->vec[6]); 00194 normal_tri_v3( clip[3],bb->vec[3], bb->vec[0], bb->vec[7]); 00195 normal_tri_v3( clip[4],bb->vec[4], bb->vec[5], bb->vec[6]); 00196 normal_tri_v3( clip[5],bb->vec[0], bb->vec[2], bb->vec[1]); 00197 00198 /* then plane equations */ 00199 for(val=0; val<5; val++) { 00200 clip[val][3]= - clip[val][0]*bb->vec[val][0] - clip[val][1]*bb->vec[val][1] - clip[val][2]*bb->vec[val][2]; 00201 } 00202 clip[5][3]= - clip[5][0]*bb->vec[0][0] - clip[5][1]*bb->vec[0][1] - clip[5][2]*bb->vec[0][2]; 00203 00204 /* create bounding box */ 00205 for(ar= sa->regionbase.first; ar; ar= ar->next) { 00206 if(ar->regiontype==RGN_TYPE_WINDOW) { 00207 RegionView3D *rv3d= ar->regiondata; 00208 00209 if(rv3d->viewlock & RV3D_BOXCLIP) { 00210 rv3d->rflag |= RV3D_CLIPPING; 00211 memcpy(rv3d->clip, clip, sizeof(clip)); 00212 if(rv3d->clipbb) MEM_freeN(rv3d->clipbb); 00213 rv3d->clipbb= MEM_dupallocN(bb); 00214 } 00215 } 00216 } 00217 MEM_freeN(bb); 00218 } 00219 00220 /* sync center/zoom view of region to others, for view transforms */ 00221 static void view3d_boxview_sync(ScrArea *sa, ARegion *ar) 00222 { 00223 ARegion *artest; 00224 RegionView3D *rv3d= ar->regiondata; 00225 short clip= 0; 00226 00227 for(artest= sa->regionbase.first; artest; artest= artest->next) { 00228 if(artest!=ar && artest->regiontype==RGN_TYPE_WINDOW) { 00229 RegionView3D *rv3dtest= artest->regiondata; 00230 00231 if(rv3dtest->viewlock) { 00232 rv3dtest->dist= rv3d->dist; 00233 00234 if( ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ) { 00235 if( ELEM(rv3dtest->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) 00236 rv3dtest->ofs[0]= rv3d->ofs[0]; 00237 else if( ELEM(rv3dtest->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) 00238 rv3dtest->ofs[1]= rv3d->ofs[1]; 00239 } 00240 else if( ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK) ) { 00241 if( ELEM(rv3dtest->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) 00242 rv3dtest->ofs[0]= rv3d->ofs[0]; 00243 else if( ELEM(rv3dtest->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) 00244 rv3dtest->ofs[2]= rv3d->ofs[2]; 00245 } 00246 else if( ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ) { 00247 if( ELEM(rv3dtest->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) 00248 rv3dtest->ofs[1]= rv3d->ofs[1]; 00249 if( ELEM(rv3dtest->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) 00250 rv3dtest->ofs[2]= rv3d->ofs[2]; 00251 } 00252 00253 clip |= rv3dtest->viewlock & RV3D_BOXCLIP; 00254 00255 ED_region_tag_redraw(artest); 00256 } 00257 } 00258 } 00259 00260 if(clip) { 00261 view3d_boxview_clip(sa); 00262 } 00263 } 00264 00265 /* for home, center etc */ 00266 void view3d_boxview_copy(ScrArea *sa, ARegion *ar) 00267 { 00268 ARegion *artest; 00269 RegionView3D *rv3d= ar->regiondata; 00270 short clip= 0; 00271 00272 for(artest= sa->regionbase.first; artest; artest= artest->next) { 00273 if(artest!=ar && artest->regiontype==RGN_TYPE_WINDOW) { 00274 RegionView3D *rv3dtest= artest->regiondata; 00275 00276 if(rv3dtest->viewlock) { 00277 rv3dtest->dist= rv3d->dist; 00278 copy_v3_v3(rv3dtest->ofs, rv3d->ofs); 00279 ED_region_tag_redraw(artest); 00280 00281 clip |= rv3dtest->viewlock & RV3D_BOXCLIP; 00282 } 00283 } 00284 } 00285 00286 if(clip) { 00287 view3d_boxview_clip(sa); 00288 } 00289 } 00290 00291 /* 'clip' is used to know if our clip setting has changed */ 00292 void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, short do_clip) 00293 { 00294 ARegion *arsync= NULL; 00295 RegionView3D *rv3d= ar->regiondata; 00296 short viewlock; 00297 /* this function copies flags from the first of the 3 other quadview 00298 regions to the 2 other, so it assumes this is the region whose 00299 properties are always being edited, weak */ 00300 viewlock= rv3d->viewlock; 00301 00302 if((viewlock & RV3D_LOCKED)==0) 00303 viewlock= 0; 00304 else if((viewlock & RV3D_BOXVIEW)==0) { 00305 viewlock &= ~RV3D_BOXCLIP; 00306 do_clip= TRUE; 00307 } 00308 00309 for(; ar; ar= ar->prev) { 00310 if(ar->alignment==RGN_ALIGN_QSPLIT) { 00311 rv3d= ar->regiondata; 00312 rv3d->viewlock= viewlock; 00313 00314 if(do_clip && (viewlock & RV3D_BOXCLIP)==0) { 00315 rv3d->rflag &= ~RV3D_BOXCLIP; 00316 } 00317 00318 /* use arsync so we sync with one of the aligned views below 00319 * else the view jumps on changing view settings like 'clip' 00320 * since it copies from the perspective view */ 00321 arsync= ar; 00322 } 00323 } 00324 00325 if(rv3d->viewlock & RV3D_BOXVIEW) { 00326 view3d_boxview_copy(sa, arsync ? arsync : sa->regionbase.last); 00327 } 00328 00329 ED_area_tag_redraw(sa); 00330 } 00331 00332 /* ************************** init for view ops **********************************/ 00333 00334 typedef struct ViewOpsData { 00335 ScrArea *sa; 00336 ARegion *ar; 00337 View3D *v3d; 00338 RegionView3D *rv3d; 00339 00340 /* needed for continuous zoom */ 00341 wmTimer *timer; 00342 double timer_lastdraw; 00343 00344 float oldquat[4]; 00345 float trackvec[3]; 00346 float mousevec[3]; /* dolly only */ 00347 float reverse, dist0; 00348 float grid, far; 00349 short axis_snap; /* view rotate only */ 00350 00351 /* use for orbit selection and auto-dist */ 00352 float ofs[3], dyn_ofs[3]; 00353 short use_dyn_ofs; 00354 00355 int origx, origy, oldx, oldy; 00356 int origkey; /* the key that triggered the operator */ 00357 00358 } ViewOpsData; 00359 00360 #define TRACKBALLSIZE (1.1) 00361 00362 static void calctrackballvec(rcti *rect, int mx, int my, float *vec) 00363 { 00364 float x, y, radius, d, z, t; 00365 00366 radius= TRACKBALLSIZE; 00367 00368 /* normalize x and y */ 00369 x= (rect->xmax + rect->xmin)/2 - mx; 00370 x/= (float)((rect->xmax - rect->xmin)/4); 00371 y= (rect->ymax + rect->ymin)/2 - my; 00372 y/= (float)((rect->ymax - rect->ymin)/2); 00373 00374 d = sqrt(x*x + y*y); 00375 if (d < radius * (float)M_SQRT1_2) /* Inside sphere */ 00376 z = sqrt(radius*radius - d*d); 00377 else 00378 { /* On hyperbola */ 00379 t = radius / (float)M_SQRT2; 00380 z = t*t / d; 00381 } 00382 00383 vec[0]= x; 00384 vec[1]= y; 00385 vec[2]= -z; /* yah yah! */ 00386 } 00387 00388 00389 static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) 00390 { 00391 static float lastofs[3] = {0,0,0}; 00392 RegionView3D *rv3d; 00393 ViewOpsData *vod= MEM_callocN(sizeof(ViewOpsData), "viewops data"); 00394 00395 /* store data */ 00396 op->customdata= vod; 00397 vod->sa= CTX_wm_area(C); 00398 vod->ar= CTX_wm_region(C); 00399 vod->v3d= vod->sa->spacedata.first; 00400 vod->rv3d= rv3d= vod->ar->regiondata; 00401 00402 /* set the view from the camera, if view locking is enabled. 00403 * we may want to make this optional but for now its needed always */ 00404 ED_view3d_camera_lock_init(vod->v3d, vod->rv3d); 00405 00406 vod->dist0= rv3d->dist; 00407 copy_qt_qt(vod->oldquat, rv3d->viewquat); 00408 vod->origx= vod->oldx= event->x; 00409 vod->origy= vod->oldy= event->y; 00410 vod->origkey= event->type; /* the key that triggered the operator. */ 00411 vod->use_dyn_ofs= (U.uiflag & USER_ORBIT_SELECTION) ? 1:0; 00412 copy_v3_v3(vod->ofs, rv3d->ofs); 00413 00414 if (vod->use_dyn_ofs) { 00415 /* If there's no selection, lastofs is unmodified and last value since static */ 00416 calculateTransformCenter(C, V3D_CENTROID, lastofs); 00417 negate_v3_v3(vod->dyn_ofs, lastofs); 00418 } 00419 else if (U.uiflag & USER_ORBIT_ZBUF) { 00420 00421 view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ 00422 00423 if((vod->use_dyn_ofs=ED_view3d_autodist(CTX_data_scene(C), vod->ar, vod->v3d, event->mval, vod->dyn_ofs))) { 00424 if (rv3d->is_persp) { 00425 float my_origin[3]; /* original G.vd->ofs */ 00426 float my_pivot[3]; /* view */ 00427 float dvec[3]; 00428 00429 // locals for dist correction 00430 float mat[3][3]; 00431 float upvec[3]; 00432 00433 negate_v3_v3(my_origin, rv3d->ofs); /* ofs is flipped */ 00434 00435 /* Set the dist value to be the distance from this 3d point */ 00436 /* this means youll always be able to zoom into it and panning wont go bad when dist was zero */ 00437 00438 /* remove dist value */ 00439 upvec[0] = upvec[1] = 0; 00440 upvec[2] = rv3d->dist; 00441 copy_m3_m4(mat, rv3d->viewinv); 00442 00443 mul_m3_v3(mat, upvec); 00444 sub_v3_v3v3(my_pivot, rv3d->ofs, upvec); 00445 negate_v3(my_pivot); /* ofs is flipped */ 00446 00447 /* find a new ofs value that is allong the view axis (rather than the mouse location) */ 00448 closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin); 00449 vod->dist0 = rv3d->dist = len_v3v3(my_pivot, dvec); 00450 00451 negate_v3_v3(rv3d->ofs, dvec); 00452 } 00453 negate_v3(vod->dyn_ofs); 00454 copy_v3_v3(vod->ofs, rv3d->ofs); 00455 } 00456 } 00457 00458 { 00459 /* for dolly */ 00460 float mval_f[2]; 00461 VECCOPY2D(mval_f, event->mval); 00462 ED_view3d_win_to_vector(vod->ar, mval_f, vod->mousevec); 00463 } 00464 00465 /* lookup, we dont pass on v3d to prevent confusement */ 00466 vod->grid= vod->v3d->grid; 00467 vod->far= vod->v3d->far; 00468 00469 calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec); 00470 00471 initgrabz(rv3d, -rv3d->ofs[0], -rv3d->ofs[1], -rv3d->ofs[2]); 00472 00473 vod->reverse= 1.0f; 00474 if (rv3d->persmat[2][1] < 0.0f) 00475 vod->reverse= -1.0f; 00476 00477 rv3d->rflag |= RV3D_NAVIGATING; 00478 } 00479 00480 static void viewops_data_free(bContext *C, wmOperator *op) 00481 { 00482 ARegion *ar; 00483 Paint *p = paint_get_active(CTX_data_scene(C)); 00484 00485 if(op->customdata) { 00486 ViewOpsData *vod= op->customdata; 00487 ar= vod->ar; 00488 vod->rv3d->rflag &= ~RV3D_NAVIGATING; 00489 00490 if(vod->timer) 00491 WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer); 00492 00493 MEM_freeN(vod); 00494 op->customdata= NULL; 00495 } 00496 else { 00497 ar= CTX_wm_region(C); 00498 } 00499 00500 if(p && (p->flags & PAINT_FAST_NAVIGATE)) 00501 ED_region_tag_redraw(ar); 00502 } 00503 00504 /* ************************** viewrotate **********************************/ 00505 00506 static const float thres = 0.93f; //cos(20 deg); 00507 00508 #define COS45 0.70710678118654746 00509 #define SIN45 COS45 00510 00511 static float snapquats[39][5] = { 00512 /*{q0, q1, q3, q4, view}*/ 00513 {COS45, -SIN45, 0.0, 0.0, RV3D_VIEW_FRONT}, //front 00514 {0.0, 0.0, -SIN45, -SIN45, RV3D_VIEW_BACK}, //back 00515 {1.0, 0.0, 0.0, 0.0, RV3D_VIEW_TOP}, //top 00516 {0.0, -1.0, 0.0, 0.0, RV3D_VIEW_BOTTOM}, //bottom 00517 {0.5, -0.5, -0.5, -0.5, RV3D_VIEW_RIGHT}, //left 00518 {0.5, -0.5, 0.5, 0.5, RV3D_VIEW_LEFT}, //right 00519 00520 /* some more 45 deg snaps */ 00521 {0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0}, 00522 {0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0}, 00523 {0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0}, 00524 {0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0}, 00525 {0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0}, 00526 {0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0}, 00527 {0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0}, 00528 {0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0}, 00529 {0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0}, 00530 {0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0}, 00531 {0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0}, 00532 {0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0}, 00533 {0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0}, 00534 {0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0}, 00535 {-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0}, 00536 {-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0}, 00537 {-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0}, 00538 {0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0}, 00539 {-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0}, 00540 {-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0}, 00541 {-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0}, 00542 {-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0}, 00543 {-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0}, 00544 {-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0}, 00545 {-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0}, 00546 {0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0}, 00547 {-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0}, 00548 {-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0}, 00549 {-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0}, 00550 {-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0}, 00551 {-COS45, 0.0, 0.0, SIN45, 0}, 00552 {COS45, 0.0, 0.0, SIN45, 0}, 00553 {0.0, 0.0, 0.0, 1.0, 0} 00554 }; 00555 00556 enum { 00557 VIEW_PASS= 0, 00558 VIEW_APPLY, 00559 VIEW_CONFIRM 00560 }; 00561 00562 /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ 00563 #define VIEW_MODAL_CONFIRM 1 /* used for all view operations */ 00564 #define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2 00565 #define VIEWROT_MODAL_AXIS_SNAP_DISABLE 3 00566 #define VIEWROT_MODAL_SWITCH_ZOOM 4 00567 #define VIEWROT_MODAL_SWITCH_MOVE 5 00568 #define VIEWROT_MODAL_SWITCH_ROTATE 6 00569 00570 /* called in transform_ops.c, on each regeneration of keymaps */ 00571 void viewrotate_modal_keymap(wmKeyConfig *keyconf) 00572 { 00573 static EnumPropertyItem modal_items[] = { 00574 {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, 00575 00576 {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Enable Axis Snap", ""}, 00577 {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Disable Axis Snap", ""}, 00578 00579 {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"}, 00580 {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, 00581 00582 {0, NULL, 0, NULL, NULL}}; 00583 00584 wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Rotate Modal"); 00585 00586 /* this function is called for each spacetype, only needs to add map once */ 00587 if(keymap) return; 00588 00589 keymap= WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items); 00590 00591 /* items for modal map */ 00592 WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); 00593 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); 00594 00595 WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_ENABLE); 00596 WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_DISABLE); 00597 00598 /* disabled mode switching for now, can re-implement better, later on 00599 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); 00600 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); 00601 WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); 00602 */ 00603 00604 /* assign map to operators */ 00605 WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate"); 00606 00607 } 00608 00609 static void viewrotate_apply(ViewOpsData *vod, int x, int y) 00610 { 00611 RegionView3D *rv3d= vod->rv3d; 00612 00613 rv3d->view= RV3D_VIEW_USER; /* need to reset everytime because of view snapping */ 00614 00615 if (U.flag & USER_TRACKBALL) { 00616 float phi, si, q1[4], dvec[3], newvec[3]; 00617 00618 calctrackballvec(&vod->ar->winrct, x, y, newvec); 00619 00620 sub_v3_v3v3(dvec, newvec, vod->trackvec); 00621 00622 si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]); 00623 si /= (float)(2.0 * TRACKBALLSIZE); 00624 00625 cross_v3_v3v3(q1+1, vod->trackvec, newvec); 00626 normalize_v3(q1+1); 00627 00628 /* Allow for rotation beyond the interval 00629 * [-pi, pi] */ 00630 while (si > 1.0f) 00631 si -= 2.0f; 00632 00633 /* This relation is used instead of 00634 * phi = asin(si) so that the angle 00635 * of rotation is linearly proportional 00636 * to the distance that the mouse is 00637 * dragged. */ 00638 phi = si * (float)(M_PI / 2.0); 00639 00640 q1[0]= cos(phi); 00641 mul_v3_fl(q1+1, sin(phi)); 00642 mul_qt_qtqt(rv3d->viewquat, q1, vod->oldquat); 00643 00644 if (vod->use_dyn_ofs) { 00645 /* compute the post multiplication quat, to rotate the offset correctly */ 00646 copy_qt_qt(q1, vod->oldquat); 00647 conjugate_qt(q1); 00648 mul_qt_qtqt(q1, q1, rv3d->viewquat); 00649 00650 conjugate_qt(q1); /* conj == inv for unit quat */ 00651 copy_v3_v3(rv3d->ofs, vod->ofs); 00652 sub_v3_v3(rv3d->ofs, vod->dyn_ofs); 00653 mul_qt_v3(q1, rv3d->ofs); 00654 add_v3_v3(rv3d->ofs, vod->dyn_ofs); 00655 } 00656 } 00657 else { 00658 /* New turntable view code by John Aughey */ 00659 float phi, q1[4]; 00660 float m[3][3]; 00661 float m_inv[3][3]; 00662 float xvec[3] = {1.0f, 0.0f, 0.0f}; 00663 /* Sensitivity will control how fast the viewport rotates. 0.0035 was 00664 obtained experimentally by looking at viewport rotation sensitivities 00665 on other modeling programs. */ 00666 /* Perhaps this should be a configurable user parameter. */ 00667 const float sensitivity = 0.0035f; 00668 00669 /* Get the 3x3 matrix and its inverse from the quaternion */ 00670 quat_to_mat3( m,rv3d->viewquat); 00671 invert_m3_m3(m_inv,m); 00672 00673 /* Determine the direction of the x vector (for rotating up and down) */ 00674 /* This can likely be computed directly from the quaternion. */ 00675 mul_m3_v3(m_inv,xvec); 00676 00677 /* Perform the up/down rotation */ 00678 phi = sensitivity * -(y - vod->oldy); 00679 q1[0] = cos(phi); 00680 mul_v3_v3fl(q1+1, xvec, sin(phi)); 00681 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); 00682 00683 if (vod->use_dyn_ofs) { 00684 conjugate_qt(q1); /* conj == inv for unit quat */ 00685 sub_v3_v3(rv3d->ofs, vod->dyn_ofs); 00686 mul_qt_v3(q1, rv3d->ofs); 00687 add_v3_v3(rv3d->ofs, vod->dyn_ofs); 00688 } 00689 00690 /* Perform the orbital rotation */ 00691 phi = sensitivity * vod->reverse * (x - vod->oldx); 00692 q1[0] = cos(phi); 00693 q1[1] = q1[2] = 0.0; 00694 q1[3] = sin(phi); 00695 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); 00696 00697 if (vod->use_dyn_ofs) { 00698 conjugate_qt(q1); 00699 sub_v3_v3(rv3d->ofs, vod->dyn_ofs); 00700 mul_qt_v3(q1, rv3d->ofs); 00701 add_v3_v3(rv3d->ofs, vod->dyn_ofs); 00702 } 00703 } 00704 00705 /* check for view snap */ 00706 if (vod->axis_snap){ 00707 int i; 00708 float viewquat_inv[4]; 00709 float zaxis[3]={0,0,1}; 00710 invert_qt_qt(viewquat_inv, rv3d->viewquat); 00711 00712 mul_qt_v3(viewquat_inv, zaxis); 00713 00714 for (i = 0 ; i < 39; i++){ 00715 00716 float view = (int)snapquats[i][4]; 00717 float viewquat_inv_test[4]; 00718 float zaxis_test[3]={0,0,1}; 00719 00720 invert_qt_qt(viewquat_inv_test, snapquats[i]); 00721 mul_qt_v3(viewquat_inv_test, zaxis_test); 00722 00723 if(angle_v3v3(zaxis_test, zaxis) < DEG2RADF(45/3)) { 00724 /* find the best roll */ 00725 float quat_roll[4], quat_final[4], quat_best[4]; 00726 float viewquat_align[4]; /* viewquat aligned to zaxis_test */ 00727 float viewquat_align_inv[4]; /* viewquat aligned to zaxis_test */ 00728 float best_angle = FLT_MAX; 00729 int j; 00730 00731 /* viewquat_align is the original viewquat aligned to the snapped axis 00732 * for testing roll */ 00733 rotation_between_vecs_to_quat(viewquat_align, zaxis_test, zaxis); 00734 normalize_qt(viewquat_align); 00735 mul_qt_qtqt(viewquat_align, rv3d->viewquat, viewquat_align); 00736 normalize_qt(viewquat_align); 00737 invert_qt_qt(viewquat_align_inv, viewquat_align); 00738 00739 /* find best roll */ 00740 for(j= 0; j<8; j++) { 00741 float angle; 00742 float xaxis1[3]={1,0,0}; 00743 float xaxis2[3]={1,0,0}; 00744 float quat_final_inv[4]; 00745 00746 axis_angle_to_quat(quat_roll, zaxis_test, (float)j * DEG2RADF(45.0f)); 00747 normalize_qt(quat_roll); 00748 00749 mul_qt_qtqt(quat_final, snapquats[i], quat_roll); 00750 normalize_qt(quat_final); 00751 00752 /* compare 2 vector angles to find the least roll */ 00753 invert_qt_qt(quat_final_inv, quat_final); 00754 mul_qt_v3(viewquat_align_inv, xaxis1); 00755 mul_qt_v3(quat_final_inv, xaxis2); 00756 angle= angle_v3v3(xaxis1, xaxis2); 00757 00758 if(angle <= best_angle) { 00759 best_angle= angle; 00760 copy_qt_qt(quat_best, quat_final); 00761 if(j) view= 0; /* view grid assumes certain up axis */ 00762 } 00763 } 00764 00765 copy_qt_qt(rv3d->viewquat, quat_best); 00766 rv3d->view= view; /* if we snap to a rolled camera the grid is invalid */ 00767 00768 break; 00769 } 00770 } 00771 } 00772 vod->oldx= x; 00773 vod->oldy= y; 00774 00775 /* avoid precision loss over time */ 00776 normalize_qt(rv3d->viewquat); 00777 00778 ED_view3d_camera_lock_sync(vod->v3d, rv3d); 00779 00780 ED_region_tag_redraw(vod->ar); 00781 } 00782 00783 static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) 00784 { 00785 ViewOpsData *vod= op->customdata; 00786 short event_code= VIEW_PASS; 00787 00788 /* execute the events */ 00789 if(event->type==MOUSEMOVE) { 00790 event_code= VIEW_APPLY; 00791 } 00792 else if(event->type==EVT_MODAL_MAP) { 00793 switch (event->val) { 00794 case VIEW_MODAL_CONFIRM: 00795 event_code= VIEW_CONFIRM; 00796 break; 00797 case VIEWROT_MODAL_AXIS_SNAP_ENABLE: 00798 vod->axis_snap= TRUE; 00799 event_code= VIEW_APPLY; 00800 break; 00801 case VIEWROT_MODAL_AXIS_SNAP_DISABLE: 00802 vod->axis_snap= FALSE; 00803 event_code= VIEW_APPLY; 00804 break; 00805 case VIEWROT_MODAL_SWITCH_ZOOM: 00806 WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); 00807 event_code= VIEW_CONFIRM; 00808 break; 00809 case VIEWROT_MODAL_SWITCH_MOVE: 00810 WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); 00811 event_code= VIEW_CONFIRM; 00812 break; 00813 } 00814 } 00815 else if(event->type==vod->origkey && event->val==KM_RELEASE) { 00816 event_code= VIEW_CONFIRM; 00817 } 00818 00819 if(event_code==VIEW_APPLY) { 00820 viewrotate_apply(vod, event->x, event->y); 00821 } 00822 else if (event_code==VIEW_CONFIRM) { 00823 ED_view3d_depth_tag_update(vod->rv3d); 00824 viewops_data_free(C, op); 00825 00826 return OPERATOR_FINISHED; 00827 } 00828 00829 return OPERATOR_RUNNING_MODAL; 00830 } 00831 00832 static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) 00833 { 00834 ViewOpsData *vod; 00835 RegionView3D *rv3d; 00836 00837 /* makes op->customdata */ 00838 viewops_data_create(C, op, event); 00839 vod= op->customdata; 00840 rv3d= vod->rv3d; 00841 00842 if(rv3d->viewlock) { /* poll should check but in some cases fails, see poll func for details */ 00843 viewops_data_free(C, op); 00844 return OPERATOR_PASS_THROUGH; 00845 } 00846 00847 /* switch from camera view when: */ 00848 if(rv3d->persp != RV3D_PERSP) { 00849 00850 if (U.uiflag & USER_AUTOPERSP) { 00851 if(!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { 00852 rv3d->persp= RV3D_PERSP; 00853 } 00854 } 00855 else if(rv3d->persp==RV3D_CAMOB) { 00856 00857 /* changed since 2.4x, use the camera view */ 00858 if(vod->v3d->camera) { 00859 ED_view3d_from_object(vod->v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); 00860 } 00861 00862 if(!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { 00863 rv3d->persp= rv3d->lpersp; 00864 } 00865 } 00866 ED_region_tag_redraw(vod->ar); 00867 } 00868 00869 if (event->type == MOUSEPAN) { 00870 viewrotate_apply(vod, event->prevx, event->prevy); 00871 ED_view3d_depth_tag_update(rv3d); 00872 00873 viewops_data_free(C, op); 00874 00875 return OPERATOR_FINISHED; 00876 } 00877 else if (event->type == MOUSEROTATE) { 00878 /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */ 00879 viewrotate_apply(vod, event->prevx, event->y); 00880 ED_view3d_depth_tag_update(rv3d); 00881 00882 viewops_data_free(C, op); 00883 00884 return OPERATOR_FINISHED; 00885 } 00886 else { 00887 /* add temp handler */ 00888 WM_event_add_modal_handler(C, op); 00889 00890 return OPERATOR_RUNNING_MODAL; 00891 } 00892 } 00893 00894 static int view3d_camera_active_poll(bContext *C) 00895 { 00896 if(ED_operator_view3d_active(C)) { 00897 RegionView3D *rv3d= CTX_wm_region_view3d(C); 00898 if(rv3d && rv3d->persp==RV3D_CAMOB) { 00899 return 1; 00900 } 00901 } 00902 00903 return 0; 00904 } 00905 00906 static int viewrotate_cancel(bContext *C, wmOperator *op) 00907 { 00908 viewops_data_free(C, op); 00909 00910 return OPERATOR_CANCELLED; 00911 } 00912 00913 void VIEW3D_OT_rotate(wmOperatorType *ot) 00914 { 00915 00916 /* identifiers */ 00917 ot->name= "Rotate view"; 00918 ot->description = "Rotate the view"; 00919 ot->idname= "VIEW3D_OT_rotate"; 00920 00921 /* api callbacks */ 00922 ot->invoke= viewrotate_invoke; 00923 ot->modal= viewrotate_modal; 00924 ot->poll= ED_operator_region_view3d_active; 00925 ot->cancel= viewrotate_cancel; 00926 00927 /* flags */ 00928 ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; 00929 } 00930 00931 // NDOF utility functions 00932 // (should these functions live in this file?) 00933 float ndof_to_axis_angle(struct wmNDOFMotionData* ndof, float axis[3]) 00934 { 00935 return ndof->dt * normalize_v3_v3(axis, ndof->rvec); 00936 } 00937 00938 void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]) 00939 { 00940 float axis[3]; 00941 float angle; 00942 00943 angle= ndof_to_axis_angle(ndof, axis); 00944 axis_angle_to_quat(q, axis, angle); 00945 } 00946 00947 static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) 00948 // -- "orbit" navigation (trackball/turntable) 00949 // -- zooming 00950 // -- panning in rotationally-locked views 00951 { 00952 if (event->type != NDOF_MOTION) 00953 return OPERATOR_CANCELLED; 00954 else { 00955 RegionView3D* rv3d = CTX_wm_region_view3d(C); 00956 wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; 00957 00958 rv3d->rot_angle = 0.f; // off by default, until changed later this function 00959 00960 if (ndof->progress != P_FINISHING) { 00961 const float dt = ndof->dt; 00962 00963 // tune these until everything feels right 00964 const float rot_sensitivity = 1.f; 00965 const float zoom_sensitivity = 1.f; 00966 const float pan_sensitivity = 1.f; 00967 00968 // rather have bool, but... 00969 int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec); 00970 00971 float view_inv[4]; 00972 invert_qt_qt(view_inv, rv3d->viewquat); 00973 00974 //#define DEBUG_NDOF_MOTION 00975 #ifdef DEBUG_NDOF_MOTION 00976 printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", 00977 ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); 00978 #endif 00979 00980 if (ndof->tvec[2]) { 00981 // Zoom! 00982 // velocity should be proportional to the linear velocity attained by rotational motion of same strength 00983 // [got that?] 00984 // proportional to arclength = radius * angle 00985 00986 float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tvec[2]; 00987 00988 if (U.ndof_flag & NDOF_ZOOM_INVERT) 00989 zoom_distance = -zoom_distance; 00990 00991 rv3d->dist += zoom_distance; 00992 } 00993 00994 if (rv3d->viewlock == RV3D_LOCKED) { 00995 /* rotation not allowed -- explore panning options instead */ 00996 float pan_vec[3] = {ndof->tvec[0], ndof->tvec[1], 0.0f}; 00997 mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); 00998 00999 /* transform motion from view to world coordinates */ 01000 invert_qt_qt(view_inv, rv3d->viewquat); 01001 mul_qt_v3(view_inv, pan_vec); 01002 01003 /* move center of view opposite of hand motion (this is camera mode, not object mode) */ 01004 sub_v3_v3(rv3d->ofs, pan_vec); 01005 } 01006 01007 if (has_rotation) { 01008 01009 const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES; 01010 01011 rv3d->view = RV3D_VIEW_USER; 01012 01013 if (U.flag & USER_TRACKBALL) { 01014 float rot[4]; 01015 float axis[3]; 01016 float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis); 01017 01018 if (invert) 01019 angle = -angle; 01020 01021 // transform rotation axis from view to world coordinates 01022 mul_qt_v3(view_inv, axis); 01023 01024 // update the onscreen doo-dad 01025 rv3d->rot_angle = angle; 01026 copy_v3_v3(rv3d->rot_axis, axis); 01027 01028 axis_angle_to_quat(rot, axis, angle); 01029 01030 // apply rotation 01031 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); 01032 } else { 01033 /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ 01034 float angle, rot[4]; 01035 float xvec[3] = {1,0,0}; 01036 01037 /* Determine the direction of the x vector (for rotating up and down) */ 01038 mul_qt_v3(view_inv, xvec); 01039 01040 /* Perform the up/down rotation */ 01041 angle = rot_sensitivity * dt * ndof->rvec[0]; 01042 if (invert) 01043 angle = -angle; 01044 rot[0] = cos(angle); 01045 mul_v3_v3fl(rot+1, xvec, sin(angle)); 01046 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); 01047 01048 /* Perform the orbital rotation */ 01049 angle = rot_sensitivity * dt * ndof->rvec[1]; 01050 if (invert) 01051 angle = -angle; 01052 01053 // update the onscreen doo-dad 01054 rv3d->rot_angle = angle; 01055 rv3d->rot_axis[0] = 0; 01056 rv3d->rot_axis[1] = 0; 01057 rv3d->rot_axis[2] = 1; 01058 01059 rot[0] = cos(angle); 01060 rot[1] = rot[2] = 0.0; 01061 rot[3] = sin(angle); 01062 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); 01063 } 01064 } 01065 } 01066 01067 ED_region_tag_redraw(CTX_wm_region(C)); 01068 01069 return OPERATOR_FINISHED; 01070 } 01071 } 01072 01073 void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) 01074 { 01075 /* identifiers */ 01076 ot->name = "NDOF Orbit View"; 01077 ot->description = "Explore every angle of an object using the 3D mouse."; 01078 ot->idname = "VIEW3D_OT_ndof_orbit"; 01079 01080 /* api callbacks */ 01081 ot->invoke = ndof_orbit_invoke; 01082 ot->poll = ED_operator_view3d_active; 01083 01084 /* flags */ 01085 ot->flag = 0; 01086 } 01087 01088 static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) 01089 // -- "pan" navigation 01090 // -- zoom or dolly? 01091 { 01092 if (event->type != NDOF_MOTION) 01093 return OPERATOR_CANCELLED; 01094 else { 01095 RegionView3D* rv3d = CTX_wm_region_view3d(C); 01096 wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; 01097 01098 01099 rv3d->rot_angle = 0.f; // we're panning here! so erase any leftover rotation from other operators 01100 01101 if (ndof->progress != P_FINISHING) { 01102 const float dt = ndof->dt; 01103 float view_inv[4]; 01104 #if 0 // ------------------------------------------- zoom with Z 01105 // tune these until everything feels right 01106 const float zoom_sensitivity = 1.f; 01107 const float pan_sensitivity = 1.f; 01108 01109 float pan_vec[3] = { 01110 ndof->tx, ndof->ty, 0 01111 }; 01112 01113 // "zoom in" or "translate"? depends on zoom mode in user settings? 01114 if (ndof->tz) { 01115 float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; 01116 rv3d->dist += zoom_distance; 01117 } 01118 01119 mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); 01120 #else // ------------------------------------------------------- dolly with Z 01121 float speed = 10.f; // blender units per second 01122 // ^^ this is ok for default cube scene, but should scale with.. something 01123 01124 // tune these until everything feels right 01125 const float forward_sensitivity = 1.f; 01126 const float vertical_sensitivity = 0.4f; 01127 const float lateral_sensitivity = 0.6f; 01128 01129 float pan_vec[3] = {lateral_sensitivity * ndof->tvec[0], 01130 vertical_sensitivity * ndof->tvec[1], 01131 forward_sensitivity * ndof->tvec[2] 01132 }; 01133 01134 mul_v3_fl(pan_vec, speed * dt); 01135 #endif 01136 /* transform motion from view to world coordinates */ 01137 invert_qt_qt(view_inv, rv3d->viewquat); 01138 mul_qt_v3(view_inv, pan_vec); 01139 01140 /* move center of view opposite of hand motion (this is camera mode, not object mode) */ 01141 sub_v3_v3(rv3d->ofs, pan_vec); 01142 } 01143 01144 ED_region_tag_redraw(CTX_wm_region(C)); 01145 01146 return OPERATOR_FINISHED; 01147 } 01148 } 01149 01150 void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) 01151 { 01152 /* identifiers */ 01153 ot->name = "NDOF Pan View"; 01154 ot->description = "Position your viewpoint with the 3D mouse."; 01155 ot->idname = "VIEW3D_OT_ndof_pan"; 01156 01157 /* api callbacks */ 01158 ot->invoke = ndof_pan_invoke; 01159 ot->poll = ED_operator_view3d_active; 01160 01161 /* flags */ 01162 ot->flag = 0; 01163 } 01164 01165 /* ************************ viewmove ******************************** */ 01166 01167 01168 /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ 01169 01170 /* called in transform_ops.c, on each regeneration of keymaps */ 01171 void viewmove_modal_keymap(wmKeyConfig *keyconf) 01172 { 01173 static EnumPropertyItem modal_items[] = { 01174 {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, 01175 01176 {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"}, 01177 {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, 01178 01179 {0, NULL, 0, NULL, NULL}}; 01180 01181 wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Move Modal"); 01182 01183 /* this function is called for each spacetype, only needs to add map once */ 01184 if(keymap) return; 01185 01186 keymap= WM_modalkeymap_add(keyconf, "View3D Move Modal", modal_items); 01187 01188 /* items for modal map */ 01189 WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); 01190 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); 01191 01192 /* disabled mode switching for now, can re-implement better, later on 01193 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); 01194 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); 01195 WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); 01196 */ 01197 01198 /* assign map to operators */ 01199 WM_modalkeymap_assign(keymap, "VIEW3D_OT_move"); 01200 } 01201 01202 01203 static void viewmove_apply(ViewOpsData *vod, int x, int y) 01204 { 01205 if((vod->rv3d->persp==RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { 01206 const float zoomfac= BKE_screen_view3d_zoom_to_fac((float)vod->rv3d->camzoom) * 2.0f; 01207 vod->rv3d->camdx += (vod->oldx - x)/(vod->ar->winx * zoomfac); 01208 vod->rv3d->camdy += (vod->oldy - y)/(vod->ar->winy * zoomfac); 01209 CLAMP(vod->rv3d->camdx, -1.0f, 1.0f); 01210 CLAMP(vod->rv3d->camdy, -1.0f, 1.0f); 01211 } 01212 else { 01213 float dvec[3]; 01214 float mval_f[2]; 01215 01216 mval_f[0]= x - vod->oldx; 01217 mval_f[1]= y - vod->oldy; 01218 ED_view3d_win_to_delta(vod->ar, mval_f, dvec); 01219 01220 add_v3_v3(vod->rv3d->ofs, dvec); 01221 01222 if(vod->rv3d->viewlock & RV3D_BOXVIEW) 01223 view3d_boxview_sync(vod->sa, vod->ar); 01224 } 01225 01226 vod->oldx= x; 01227 vod->oldy= y; 01228 01229 ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); 01230 01231 ED_region_tag_redraw(vod->ar); 01232 } 01233 01234 01235 static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) 01236 { 01237 01238 ViewOpsData *vod= op->customdata; 01239 short event_code= VIEW_PASS; 01240 01241 /* execute the events */ 01242 if(event->type==MOUSEMOVE) { 01243 event_code= VIEW_APPLY; 01244 } 01245 else if(event->type==EVT_MODAL_MAP) { 01246 switch (event->val) { 01247 case VIEW_MODAL_CONFIRM: 01248 event_code= VIEW_CONFIRM; 01249 break; 01250 case VIEWROT_MODAL_SWITCH_ZOOM: 01251 WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); 01252 event_code= VIEW_CONFIRM; 01253 break; 01254 case VIEWROT_MODAL_SWITCH_ROTATE: 01255 WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); 01256 event_code= VIEW_CONFIRM; 01257 break; 01258 } 01259 } 01260 else if(event->type==vod->origkey && event->val==KM_RELEASE) { 01261 event_code= VIEW_CONFIRM; 01262 } 01263 01264 if(event_code==VIEW_APPLY) { 01265 viewmove_apply(vod, event->x, event->y); 01266 } 01267 else if (event_code==VIEW_CONFIRM) { 01268 ED_view3d_depth_tag_update(vod->rv3d); 01269 01270 viewops_data_free(C, op); 01271 01272 return OPERATOR_FINISHED; 01273 } 01274 01275 return OPERATOR_RUNNING_MODAL; 01276 } 01277 01278 static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) 01279 { 01280 ViewOpsData *vod; 01281 01282 /* makes op->customdata */ 01283 viewops_data_create(C, op, event); 01284 vod= op->customdata; 01285 01286 if (event->type == MOUSEPAN) { 01287 viewmove_apply(vod, event->prevx, event->prevy); 01288 ED_view3d_depth_tag_update(vod->rv3d); 01289 01290 viewops_data_free(C, op); 01291 01292 return OPERATOR_FINISHED; 01293 } 01294 else { 01295 /* add temp handler */ 01296 WM_event_add_modal_handler(C, op); 01297 01298 return OPERATOR_RUNNING_MODAL; 01299 } 01300 } 01301 01302 static int viewmove_cancel(bContext *C, wmOperator *op) 01303 { 01304 viewops_data_free(C, op); 01305 01306 return OPERATOR_CANCELLED; 01307 } 01308 01309 void VIEW3D_OT_move(wmOperatorType *ot) 01310 { 01311 01312 /* identifiers */ 01313 ot->name= "Move view"; 01314 ot->description = "Move the view"; 01315 ot->idname= "VIEW3D_OT_move"; 01316 01317 /* api callbacks */ 01318 ot->invoke= viewmove_invoke; 01319 ot->modal= viewmove_modal; 01320 ot->poll= ED_operator_view3d_active; 01321 ot->cancel= viewmove_cancel; 01322 01323 /* flags */ 01324 ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; 01325 } 01326 01327 /* ************************ viewzoom ******************************** */ 01328 01329 /* viewdolly_modal_keymap has an exact copy of this, apply fixes to both */ 01330 /* called in transform_ops.c, on each regeneration of keymaps */ 01331 void viewzoom_modal_keymap(wmKeyConfig *keyconf) 01332 { 01333 static EnumPropertyItem modal_items[] = { 01334 {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, 01335 01336 {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, 01337 {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, 01338 01339 {0, NULL, 0, NULL, NULL}}; 01340 01341 wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Zoom Modal"); 01342 01343 /* this function is called for each spacetype, only needs to add map once */ 01344 if(keymap) return; 01345 01346 keymap= WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items); 01347 01348 /* items for modal map */ 01349 WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); 01350 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); 01351 01352 /* disabled mode switching for now, can re-implement better, later on 01353 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); 01354 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); 01355 WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); 01356 */ 01357 01358 /* assign map to operators */ 01359 WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); 01360 } 01361 01362 static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) 01363 { 01364 RegionView3D *rv3d= ar->regiondata; 01365 01366 if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) { 01367 float dvec[3]; 01368 float tvec[3]; 01369 float tpos[3]; 01370 float mval_f[2]; 01371 float new_dist; 01372 01373 negate_v3_v3(tpos, rv3d->ofs); 01374 01375 /* Project cursor position into 3D space */ 01376 initgrabz(rv3d, tpos[0], tpos[1], tpos[2]); 01377 01378 mval_f[0]= (float)(((mx - ar->winrct.xmin) * 2) - ar->winx) / 2.0f; 01379 mval_f[1]= (float)(((my - ar->winrct.ymin) * 2) - ar->winy) / 2.0f; 01380 ED_view3d_win_to_delta(ar, mval_f, dvec); 01381 01382 /* Calculate view target position for dolly */ 01383 add_v3_v3v3(tvec, tpos, dvec); 01384 negate_v3(tvec); 01385 01386 /* Offset to target position and dolly */ 01387 new_dist = rv3d->dist * dfac; 01388 01389 copy_v3_v3(rv3d->ofs, tvec); 01390 rv3d->dist = new_dist; 01391 01392 /* Calculate final offset */ 01393 madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac); 01394 } else { 01395 rv3d->dist *= dfac; 01396 } 01397 } 01398 01399 01400 static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, const short zoom_invert) 01401 { 01402 float zfac=1.0; 01403 01404 if(viewzoom==USER_ZOOM_CONT) { 01405 double time= PIL_check_seconds_timer(); 01406 float time_step= (float)(time - vod->timer_lastdraw); 01407 float fac; 01408 01409 if (U.uiflag & USER_ZOOM_HORIZ) { 01410 fac= (float)(x - vod->origx); 01411 } 01412 else { 01413 fac= (float)(y - vod->origy); 01414 } 01415 01416 if(zoom_invert) { 01417 fac= -fac; 01418 } 01419 01420 // oldstyle zoom 01421 zfac = 1.0f + ((fac / 20.0f) * time_step); 01422 vod->timer_lastdraw= time; 01423 } 01424 else if(viewzoom==USER_ZOOM_SCALE) { 01425 int ctr[2], len1, len2; 01426 // method which zooms based on how far you move the mouse 01427 01428 ctr[0] = (vod->ar->winrct.xmax + vod->ar->winrct.xmin)/2; 01429 ctr[1] = (vod->ar->winrct.ymax + vod->ar->winrct.ymin)/2; 01430 01431 len1 = (int)sqrt((ctr[0] - x)*(ctr[0] - x) + (ctr[1] - y)*(ctr[1] - y)) + 5; 01432 len2 = (int)sqrt((ctr[0] - vod->origx)*(ctr[0] - vod->origx) + (ctr[1] - vod->origy)*(ctr[1] - vod->origy)) + 5; 01433 01434 zfac = vod->dist0 * ((float)len2/len1) / vod->rv3d->dist; 01435 } 01436 else { /* USER_ZOOM_DOLLY */ 01437 float len1, len2; 01438 01439 if (U.uiflag & USER_ZOOM_HORIZ) { 01440 len1 = (vod->ar->winrct.xmax - x) + 5; 01441 len2 = (vod->ar->winrct.xmax - vod->origx) + 5; 01442 } 01443 else { 01444 len1 = (vod->ar->winrct.ymax - y) + 5; 01445 len2 = (vod->ar->winrct.ymax - vod->origy) + 5; 01446 } 01447 if (zoom_invert) { 01448 SWAP(float, len1, len2); 01449 } 01450 01451 zfac = vod->dist0 * (2.0f * ((len2/len1)-1.0f) + 1.0f) / vod->rv3d->dist; 01452 } 01453 01454 if(zfac != 1.0f && zfac*vod->rv3d->dist > 0.001f * vod->grid && 01455 zfac * vod->rv3d->dist < 10.0f * vod->far) 01456 view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy); 01457 01458 /* these limits were in old code too */ 01459 if(vod->rv3d->dist<0.001f * vod->grid) vod->rv3d->dist= 0.001f * vod->grid; 01460 if(vod->rv3d->dist>10.0f * vod->far) vod->rv3d->dist=10.0f * vod->far; 01461 01462 if(vod->rv3d->viewlock & RV3D_BOXVIEW) 01463 view3d_boxview_sync(vod->sa, vod->ar); 01464 01465 ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); 01466 01467 ED_region_tag_redraw(vod->ar); 01468 } 01469 01470 01471 static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event) 01472 { 01473 ViewOpsData *vod= op->customdata; 01474 short event_code= VIEW_PASS; 01475 01476 /* execute the events */ 01477 if (event->type == TIMER && event->customdata == vod->timer) { 01478 /* continuous zoom */ 01479 event_code= VIEW_APPLY; 01480 } 01481 else if(event->type==MOUSEMOVE) { 01482 event_code= VIEW_APPLY; 01483 } 01484 else if(event->type==EVT_MODAL_MAP) { 01485 switch (event->val) { 01486 case VIEW_MODAL_CONFIRM: 01487 event_code= VIEW_CONFIRM; 01488 break; 01489 case VIEWROT_MODAL_SWITCH_MOVE: 01490 WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); 01491 event_code= VIEW_CONFIRM; 01492 break; 01493 case VIEWROT_MODAL_SWITCH_ROTATE: 01494 WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); 01495 event_code= VIEW_CONFIRM; 01496 break; 01497 } 01498 } 01499 else if(event->type==vod->origkey && event->val==KM_RELEASE) { 01500 event_code= VIEW_CONFIRM; 01501 } 01502 01503 if(event_code==VIEW_APPLY) { 01504 viewzoom_apply(vod, event->x, event->y, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0); 01505 } 01506 else if (event_code==VIEW_CONFIRM) { 01507 ED_view3d_depth_tag_update(vod->rv3d); 01508 viewops_data_free(C, op); 01509 01510 return OPERATOR_FINISHED; 01511 } 01512 01513 return OPERATOR_RUNNING_MODAL; 01514 } 01515 01516 static int viewzoom_exec(bContext *C, wmOperator *op) 01517 { 01518 View3D *v3d; 01519 RegionView3D *rv3d; 01520 ScrArea *sa; 01521 ARegion *ar; 01522 short use_cam_zoom; 01523 01524 int delta= RNA_int_get(op->ptr, "delta"); 01525 int mx, my; 01526 01527 if(op->customdata) { 01528 ViewOpsData *vod= op->customdata; 01529 01530 sa= vod->sa; 01531 ar= vod->ar; 01532 } 01533 else { 01534 sa= CTX_wm_area(C); 01535 ar= CTX_wm_region(C); 01536 } 01537 01538 v3d= sa->spacedata.first; 01539 rv3d= ar->regiondata; 01540 01541 mx= RNA_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : ar->winx / 2; 01542 my= RNA_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2; 01543 01544 use_cam_zoom= (rv3d->persp==RV3D_CAMOB) && !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d)); 01545 01546 if(delta < 0) { 01547 /* this min and max is also in viewmove() */ 01548 if(use_cam_zoom) { 01549 rv3d->camzoom-= 10; 01550 if(rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom= RV3D_CAMZOOM_MIN; 01551 } 01552 else if(rv3d->dist < 10.0f * v3d->far) { 01553 view_zoom_mouseloc(ar, 1.2f, mx, my); 01554 } 01555 } 01556 else { 01557 if(use_cam_zoom) { 01558 rv3d->camzoom+= 10; 01559 if(rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom= RV3D_CAMZOOM_MAX; 01560 } 01561 else if(rv3d->dist> 0.001f * v3d->grid) { 01562 view_zoom_mouseloc(ar, .83333f, mx, my); 01563 } 01564 } 01565 01566 if(rv3d->viewlock & RV3D_BOXVIEW) 01567 view3d_boxview_sync(sa, ar); 01568 01569 ED_view3d_depth_tag_update(rv3d); 01570 01571 ED_view3d_camera_lock_sync(v3d, rv3d); 01572 01573 ED_region_tag_redraw(ar); 01574 01575 viewops_data_free(C, op); 01576 01577 return OPERATOR_FINISHED; 01578 } 01579 01580 /* this is an exact copy of viewzoom_modal_keymap */ 01581 /* called in transform_ops.c, on each regeneration of keymaps */ 01582 void viewdolly_modal_keymap(wmKeyConfig *keyconf) 01583 { 01584 static EnumPropertyItem modal_items[] = { 01585 {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, 01586 01587 {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, 01588 {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, 01589 01590 {0, NULL, 0, NULL, NULL}}; 01591 01592 wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Dolly Modal"); 01593 01594 /* this function is called for each spacetype, only needs to add map once */ 01595 if(keymap) return; 01596 01597 keymap= WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items); 01598 01599 /* items for modal map */ 01600 WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); 01601 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); 01602 01603 /* disabled mode switching for now, can re-implement better, later on 01604 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); 01605 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); 01606 WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); 01607 */ 01608 01609 /* assign map to operators */ 01610 WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly"); 01611 } 01612 01613 /* viewdolly_invoke() copied this function, changes here may apply there */ 01614 static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) 01615 { 01616 ViewOpsData *vod; 01617 01618 /* makes op->customdata */ 01619 viewops_data_create(C, op, event); 01620 vod= op->customdata; 01621 01622 /* if one or the other zoom position aren't set, set from event */ 01623 if (!RNA_property_is_set(op->ptr, "mx") || !RNA_property_is_set(op->ptr, "my")) 01624 { 01625 RNA_int_set(op->ptr, "mx", event->x); 01626 RNA_int_set(op->ptr, "my", event->y); 01627 } 01628 01629 if(RNA_property_is_set(op->ptr, "delta")) { 01630 viewzoom_exec(C, op); 01631 } 01632 else { 01633 if (event->type == MOUSEZOOM) { 01634 /* Bypass Zoom invert flag for track pads (pass FALSE always) */ 01635 01636 if (U.uiflag & USER_ZOOM_HORIZ) { 01637 vod->origx = vod->oldx = event->x; 01638 viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, FALSE); 01639 } 01640 else { 01641 /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */ 01642 vod->origy = vod->oldy = vod->origy + event->x - event->prevx; 01643 viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, FALSE); 01644 } 01645 ED_view3d_depth_tag_update(vod->rv3d); 01646 01647 viewops_data_free(C, op); 01648 return OPERATOR_FINISHED; 01649 } 01650 else { 01651 if(U.viewzoom == USER_ZOOM_CONT) { 01652 /* needs a timer to continue redrawing */ 01653 vod->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); 01654 vod->timer_lastdraw= PIL_check_seconds_timer(); 01655 } 01656 01657 /* add temp handler */ 01658 WM_event_add_modal_handler(C, op); 01659 01660 return OPERATOR_RUNNING_MODAL; 01661 } 01662 } 01663 return OPERATOR_FINISHED; 01664 } 01665 01666 static int viewzoom_cancel(bContext *C, wmOperator *op) 01667 { 01668 viewops_data_free(C, op); 01669 01670 return OPERATOR_CANCELLED; 01671 } 01672 01673 void VIEW3D_OT_zoom(wmOperatorType *ot) 01674 { 01675 /* identifiers */ 01676 ot->name= "Zoom View"; 01677 ot->description = "Zoom in/out in the view"; 01678 ot->idname= "VIEW3D_OT_zoom"; 01679 01680 /* api callbacks */ 01681 ot->invoke= viewzoom_invoke; 01682 ot->exec= viewzoom_exec; 01683 ot->modal= viewzoom_modal; 01684 ot->poll= ED_operator_region_view3d_active; 01685 ot->cancel= viewzoom_cancel; 01686 01687 /* flags */ 01688 ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; 01689 01690 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); 01691 RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX); 01692 RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX); 01693 } 01694 01695 01696 /* ************************ viewdolly ******************************** */ 01697 static void view_dolly_mouseloc(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac) 01698 { 01699 RegionView3D *rv3d= ar->regiondata; 01700 madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0 - dfac)); 01701 } 01702 01703 static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_invert) 01704 { 01705 float zfac=1.0; 01706 01707 { 01708 float len1, len2; 01709 01710 if (U.uiflag & USER_ZOOM_HORIZ) { 01711 len1 = (vod->ar->winrct.xmax - x) + 5; 01712 len2 = (vod->ar->winrct.xmax - vod->origx) + 5; 01713 } 01714 else { 01715 len1 = (vod->ar->winrct.ymax - y) + 5; 01716 len2 = (vod->ar->winrct.ymax - vod->origy) + 5; 01717 } 01718 if (zoom_invert) 01719 SWAP(float, len1, len2); 01720 01721 zfac = 1.0 + ((len2 - len1) * 0.01 * vod->rv3d->dist); 01722 } 01723 01724 if(zfac != 1.0f) 01725 view_dolly_mouseloc(vod->ar, vod->ofs, vod->mousevec, zfac); 01726 01727 if(vod->rv3d->viewlock & RV3D_BOXVIEW) 01728 view3d_boxview_sync(vod->sa, vod->ar); 01729 01730 ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); 01731 01732 ED_region_tag_redraw(vod->ar); 01733 } 01734 01735 01736 static int viewdolly_modal(bContext *C, wmOperator *op, wmEvent *event) 01737 { 01738 ViewOpsData *vod= op->customdata; 01739 short event_code= VIEW_PASS; 01740 01741 /* execute the events */ 01742 if(event->type==MOUSEMOVE) { 01743 event_code= VIEW_APPLY; 01744 } 01745 else if(event->type==EVT_MODAL_MAP) { 01746 switch (event->val) { 01747 case VIEW_MODAL_CONFIRM: 01748 event_code= VIEW_CONFIRM; 01749 break; 01750 case VIEWROT_MODAL_SWITCH_MOVE: 01751 WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); 01752 event_code= VIEW_CONFIRM; 01753 break; 01754 case VIEWROT_MODAL_SWITCH_ROTATE: 01755 WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); 01756 event_code= VIEW_CONFIRM; 01757 break; 01758 } 01759 } 01760 else if(event->type==vod->origkey && event->val==KM_RELEASE) { 01761 event_code= VIEW_CONFIRM; 01762 } 01763 01764 if(event_code==VIEW_APPLY) { 01765 viewdolly_apply(vod, event->x, event->y, (U.uiflag & USER_ZOOM_INVERT) != 0); 01766 } 01767 else if (event_code==VIEW_CONFIRM) { 01768 ED_view3d_depth_tag_update(vod->rv3d); 01769 viewops_data_free(C, op); 01770 01771 return OPERATOR_FINISHED; 01772 } 01773 01774 return OPERATOR_RUNNING_MODAL; 01775 } 01776 01777 static int viewdolly_exec(bContext *C, wmOperator *op) 01778 { 01779 /* View3D *v3d; */ 01780 RegionView3D *rv3d; 01781 ScrArea *sa; 01782 ARegion *ar; 01783 float mousevec[3]; 01784 01785 int delta= RNA_int_get(op->ptr, "delta"); 01786 01787 if(op->customdata) { 01788 ViewOpsData *vod= op->customdata; 01789 01790 sa= vod->sa; 01791 ar= vod->ar; 01792 copy_v3_v3(mousevec, vod->mousevec); 01793 } 01794 else { 01795 sa= CTX_wm_area(C); 01796 ar= CTX_wm_region(C); 01797 negate_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv[2]); 01798 normalize_v3(mousevec); 01799 } 01800 01801 /* v3d= sa->spacedata.first; */ /* UNUSED */ 01802 rv3d= ar->regiondata; 01803 01804 /* overwrite the mouse vector with the view direction (zoom into the center) */ 01805 if((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) { 01806 normalize_v3_v3(mousevec, rv3d->viewinv[2]); 01807 } 01808 01809 if(delta < 0) { 01810 view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 1.2f); 01811 } 01812 else { 01813 view_dolly_mouseloc(ar, rv3d->ofs, mousevec, .83333f); 01814 } 01815 01816 if(rv3d->viewlock & RV3D_BOXVIEW) 01817 view3d_boxview_sync(sa, ar); 01818 01819 ED_view3d_depth_tag_update(rv3d); 01820 ED_region_tag_redraw(ar); 01821 01822 viewops_data_free(C, op); 01823 01824 return OPERATOR_FINISHED; 01825 } 01826 01827 /* copied from viewzoom_invoke(), changes here may apply there */ 01828 static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event) 01829 { 01830 ViewOpsData *vod; 01831 01832 /* makes op->customdata */ 01833 viewops_data_create(C, op, event); 01834 vod= op->customdata; 01835 01836 /* if one or the other zoom position aren't set, set from event */ 01837 if (!RNA_property_is_set(op->ptr, "mx") || !RNA_property_is_set(op->ptr, "my")) 01838 { 01839 RNA_int_set(op->ptr, "mx", event->x); 01840 RNA_int_set(op->ptr, "my", event->y); 01841 } 01842 01843 if(RNA_property_is_set(op->ptr, "delta")) { 01844 viewdolly_exec(C, op); 01845 } 01846 else { 01847 /* overwrite the mouse vector with the view direction (zoom into the center) */ 01848 if((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) { 01849 negate_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]); 01850 normalize_v3(vod->mousevec); 01851 } 01852 01853 if (event->type == MOUSEZOOM) { 01854 /* Bypass Zoom invert flag for track pads (pass FALSE always) */ 01855 01856 if (U.uiflag & USER_ZOOM_HORIZ) { 01857 vod->origx = vod->oldx = event->x; 01858 viewdolly_apply(vod, event->prevx, event->prevy, FALSE); 01859 } 01860 else { 01861 01862 /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */ 01863 vod->origy = vod->oldy = vod->origy + event->x - event->prevx; 01864 viewdolly_apply(vod, event->prevx, event->prevy, FALSE); 01865 } 01866 ED_view3d_depth_tag_update(vod->rv3d); 01867 01868 viewops_data_free(C, op); 01869 return OPERATOR_FINISHED; 01870 } 01871 else { 01872 /* add temp handler */ 01873 WM_event_add_modal_handler(C, op); 01874 01875 return OPERATOR_RUNNING_MODAL; 01876 } 01877 } 01878 return OPERATOR_FINISHED; 01879 } 01880 01881 /* like ED_operator_region_view3d_active but check its not in ortho view */ 01882 static int viewdolly_poll(bContext *C) 01883 { 01884 RegionView3D *rv3d= CTX_wm_region_view3d(C); 01885 01886 if(rv3d) { 01887 if (rv3d->persp == RV3D_PERSP) { 01888 return 1; 01889 } 01890 else { 01891 View3D *v3d= CTX_wm_view3d(C); 01892 if (ED_view3d_camera_lock_check(v3d, rv3d)) { 01893 return 1; 01894 } 01895 } 01896 } 01897 return 0; 01898 } 01899 01900 static int viewdolly_cancel(bContext *C, wmOperator *op) 01901 { 01902 viewops_data_free(C, op); 01903 01904 return OPERATOR_CANCELLED; 01905 } 01906 01907 void VIEW3D_OT_dolly(wmOperatorType *ot) 01908 { 01909 /* identifiers */ 01910 ot->name= "Dolly view"; 01911 ot->description = "Dolly in/out in the view"; 01912 ot->idname= "VIEW3D_OT_dolly"; 01913 01914 /* api callbacks */ 01915 ot->invoke= viewdolly_invoke; 01916 ot->exec= viewdolly_exec; 01917 ot->modal= viewdolly_modal; 01918 ot->poll= viewdolly_poll; 01919 ot->cancel= viewdolly_cancel; 01920 01921 /* flags */ 01922 ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; 01923 01924 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); 01925 RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX); 01926 RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX); 01927 } 01928 01929 01930 01931 static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.4x */ 01932 { 01933 ARegion *ar= CTX_wm_region(C); 01934 View3D *v3d = CTX_wm_view3d(C); 01935 RegionView3D *rv3d= CTX_wm_region_view3d(C); 01936 Scene *scene= CTX_data_scene(C); 01937 Base *base; 01938 float *curs; 01939 const short skip_camera= ED_view3d_camera_lock_check(v3d, rv3d); 01940 01941 int center= RNA_boolean_get(op->ptr, "center"); 01942 01943 float size, min[3], max[3], afm[3]; 01944 int ok= 1, onedone=0; 01945 01946 if(center) { 01947 /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */ 01948 curs= give_cursor(scene, v3d); 01949 zero_v3(min); 01950 zero_v3(max); 01951 zero_v3(curs); 01952 } 01953 else { 01954 INIT_MINMAX(min, max); 01955 } 01956 01957 for(base= scene->base.first; base; base= base->next) { 01958 if(BASE_VISIBLE(v3d, base)) { 01959 onedone= 1; 01960 01961 if(skip_camera && base->object == v3d->camera) { 01962 continue; 01963 } 01964 01965 minmax_object(base->object, min, max); 01966 } 01967 } 01968 if(!onedone) { 01969 ED_region_tag_redraw(ar); 01970 /* TODO - should this be cancel? 01971 * I think no, because we always move the cursor, with or without 01972 * object, but in this case there is no change in the scene, 01973 * only the cursor so I choice a ED_region_tag like 01974 * smooth_view do for the center_cursor. 01975 * See bug #22640 01976 */ 01977 return OPERATOR_FINISHED; 01978 } 01979 01980 sub_v3_v3v3(afm, max, min); 01981 size= 0.7f*MAX3(afm[0], afm[1], afm[2]); 01982 if(size == 0.0f) ok= 0; 01983 01984 if(ok) { 01985 float new_dist; 01986 float new_ofs[3]; 01987 01988 new_dist = size; 01989 new_ofs[0]= -(min[0]+max[0])/2.0f; 01990 new_ofs[1]= -(min[1]+max[1])/2.0f; 01991 new_ofs[2]= -(min[2]+max[2])/2.0f; 01992 01993 // correction for window aspect ratio 01994 if(ar->winy>2 && ar->winx>2) { 01995 size= (float)ar->winx/(float)ar->winy; 01996 if(size < 1.0f) size= 1.0f/size; 01997 new_dist*= size; 01998 } 01999 02000 if ((rv3d->persp==RV3D_CAMOB) && !ED_view3d_camera_lock_check(v3d, rv3d)) { 02001 rv3d->persp= RV3D_PERSP; 02002 smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, &new_dist, NULL); 02003 } 02004 else { 02005 smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, &new_dist, NULL); 02006 } 02007 } 02008 // XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); 02009 02010 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d); 02011 02012 return OPERATOR_FINISHED; 02013 } 02014 02015 02016 void VIEW3D_OT_view_all(wmOperatorType *ot) 02017 { 02018 /* identifiers */ 02019 ot->name= "View All"; 02020 ot->description = "View all objects in scene"; 02021 ot->idname= "VIEW3D_OT_view_all"; 02022 02023 /* api callbacks */ 02024 ot->exec= view3d_all_exec; 02025 ot->poll= ED_operator_region_view3d_active; 02026 02027 /* flags */ 02028 ot->flag= 0; 02029 02030 RNA_def_boolean(ot->srna, "center", 0, "Center", ""); 02031 } 02032 02033 02034 static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) /* like a localview without local!, was centerview() in 2.4x */ 02035 { 02036 ARegion *ar= CTX_wm_region(C); 02037 View3D *v3d = CTX_wm_view3d(C); 02038 RegionView3D *rv3d= CTX_wm_region_view3d(C); 02039 Scene *scene= CTX_data_scene(C); 02040 Object *ob= OBACT; 02041 Object *obedit= CTX_data_edit_object(C); 02042 float size, min[3], max[3], afm[3]; 02043 int ok=0, ok_dist=1; 02044 const short skip_camera= ED_view3d_camera_lock_check(v3d, rv3d); 02045 02046 /* SMOOTHVIEW */ 02047 float new_ofs[3]; 02048 float new_dist; 02049 02050 INIT_MINMAX(min, max); 02051 02052 if (ob && ob->mode & OB_MODE_WEIGHT_PAINT) { 02053 /* hardcoded exception, we look for the one selected armature */ 02054 /* this is weak code this way, we should make a generic active/selection callback interface once... */ 02055 Base *base; 02056 for(base=scene->base.first; base; base= base->next) { 02057 if(TESTBASELIB(v3d, base)) { 02058 if(base->object->type==OB_ARMATURE) 02059 if(base->object->mode & OB_MODE_POSE) 02060 break; 02061 } 02062 } 02063 if(base) 02064 ob= base->object; 02065 } 02066 02067 02068 if(obedit) { 02069 ok = minmax_verts(obedit, min, max); /* only selected */ 02070 } 02071 else if(ob && (ob->mode & OB_MODE_POSE)) { 02072 if(ob->pose) { 02073 bArmature *arm= ob->data; 02074 bPoseChannel *pchan; 02075 float vec[3]; 02076 02077 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 02078 if(pchan->bone->flag & BONE_SELECTED) { 02079 if(pchan->bone->layer & arm->layer) { 02080 bPoseChannel *pchan_tx= pchan->custom_tx ? pchan->custom_tx : pchan; 02081 ok= 1; 02082 mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head); 02083 DO_MINMAX(vec, min, max); 02084 mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail); 02085 DO_MINMAX(vec, min, max); 02086 } 02087 } 02088 } 02089 } 02090 } 02091 else if (paint_facesel_test(ob)) { 02092 ok= paintface_minmax(ob, min, max); 02093 } 02094 else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { 02095 ok= PE_minmax(scene, min, max); 02096 } 02097 else { 02098 Base *base; 02099 for(base= FIRSTBASE; base; base = base->next) { 02100 if(TESTBASE(v3d, base)) { 02101 02102 if(skip_camera && base->object == v3d->camera) { 02103 continue; 02104 } 02105 02106 /* account for duplis */ 02107 if (minmax_object_duplis(scene, base->object, min, max)==0) 02108 minmax_object(base->object, min, max); /* use if duplis not found */ 02109 02110 ok= 1; 02111 } 02112 } 02113 } 02114 02115 if(ok==0) return OPERATOR_FINISHED; 02116 02117 sub_v3_v3v3(afm, max, min); 02118 size= MAX3(afm[0], afm[1], afm[2]); 02119 02120 if(!rv3d->is_persp) { 02121 if(size < 0.0001f) { /* if its a sinble point. dont even re-scale */ 02122 ok_dist= 0; 02123 } 02124 else { 02125 /* perspective should be a bit farther away to look nice */ 02126 size*= 0.7f; 02127 } 02128 } 02129 else { 02130 if(size <= v3d->near*1.5f) { 02131 size= v3d->near*1.5f; 02132 } 02133 } 02134 02135 add_v3_v3v3(new_ofs, min, max); 02136 mul_v3_fl(new_ofs, -0.5f); 02137 02138 new_dist = size; 02139 02140 /* correction for window aspect ratio */ 02141 if(ar->winy>2 && ar->winx>2) { 02142 size= (float)ar->winx/(float)ar->winy; 02143 if(size<1.0f) size= 1.0f/size; 02144 new_dist*= size; 02145 } 02146 02147 if (rv3d->persp==RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) { 02148 rv3d->persp= RV3D_PERSP; 02149 smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, &new_dist, NULL); 02150 } 02151 else { 02152 smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL); 02153 } 02154 02155 /* smooth view does viewlock RV3D_BOXVIEW copy */ 02156 02157 // XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); 02158 02159 return OPERATOR_FINISHED; 02160 } 02161 02162 void VIEW3D_OT_view_selected(wmOperatorType *ot) 02163 { 02164 02165 /* identifiers */ 02166 ot->name= "View Selected"; 02167 ot->description = "Move the view to the selection center"; 02168 ot->idname= "VIEW3D_OT_view_selected"; 02169 02170 /* api callbacks */ 02171 ot->exec= viewselected_exec; 02172 ot->poll= ED_operator_region_view3d_active; 02173 02174 /* flags */ 02175 ot->flag= 0; 02176 } 02177 02178 static int viewcenter_cursor_exec(bContext *C, wmOperator *UNUSED(op)) 02179 { 02180 View3D *v3d = CTX_wm_view3d(C); 02181 RegionView3D *rv3d= CTX_wm_region_view3d(C); 02182 Scene *scene= CTX_data_scene(C); 02183 02184 if (rv3d) { 02185 ARegion *ar= CTX_wm_region(C); 02186 02187 /* non camera center */ 02188 float new_ofs[3]; 02189 negate_v3_v3(new_ofs, give_cursor(scene, v3d)); 02190 smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, NULL, NULL); 02191 02192 /* smooth view does viewlock RV3D_BOXVIEW copy */ 02193 } 02194 02195 return OPERATOR_FINISHED; 02196 } 02197 02198 void VIEW3D_OT_view_center_cursor(wmOperatorType *ot) 02199 { 02200 /* identifiers */ 02201 ot->name= "Center View to Cursor"; 02202 ot->description= "Centers the view so that the cursor is in the middle of the view"; 02203 ot->idname= "VIEW3D_OT_view_center_cursor"; 02204 02205 /* api callbacks */ 02206 ot->exec= viewcenter_cursor_exec; 02207 ot->poll= ED_operator_view3d_active; 02208 02209 /* flags */ 02210 ot->flag= 0; 02211 } 02212 02213 static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */ 02214 { 02215 ARegion *ar= CTX_wm_region(C); 02216 RegionView3D *rv3d= CTX_wm_region_view3d(C); 02217 Scene *scene= CTX_data_scene(C); 02218 float xfac, yfac; 02219 float size[2]; 02220 02221 rv3d->camdx= rv3d->camdy= 0.0f; 02222 02223 view3d_viewborder_size_get(scene, ar, size); 02224 02225 /* 4px is just a little room from the edge of the area */ 02226 xfac= (float)ar->winx / (float)(size[0] + 4); 02227 yfac= (float)ar->winy / (float)(size[1] + 4); 02228 02229 rv3d->camzoom= BKE_screen_view3d_zoom_from_fac(MIN2(xfac, yfac)); 02230 CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); 02231 02232 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, CTX_wm_view3d(C)); 02233 02234 return OPERATOR_FINISHED; 02235 } 02236 02237 void VIEW3D_OT_view_center_camera(wmOperatorType *ot) 02238 { 02239 /* identifiers */ 02240 ot->name= "View Camera Center"; 02241 ot->description = "Center the camera view"; 02242 ot->idname= "VIEW3D_OT_view_center_camera"; 02243 02244 /* api callbacks */ 02245 ot->exec= view3d_center_camera_exec; 02246 ot->poll= view3d_camera_active_poll; 02247 02248 /* flags */ 02249 ot->flag= 0; 02250 } 02251 02252 /* ********************* Set render border operator ****************** */ 02253 02254 static int render_border_exec(bContext *C, wmOperator *op) 02255 { 02256 View3D *v3d = CTX_wm_view3d(C); 02257 ARegion *ar= CTX_wm_region(C); 02258 RegionView3D *rv3d= ED_view3d_context_rv3d(C); 02259 Scene *scene= CTX_data_scene(C); 02260 02261 rcti rect; 02262 rctf vb; 02263 02264 /* get border select values using rna */ 02265 rect.xmin= RNA_int_get(op->ptr, "xmin"); 02266 rect.ymin= RNA_int_get(op->ptr, "ymin"); 02267 rect.xmax= RNA_int_get(op->ptr, "xmax"); 02268 rect.ymax= RNA_int_get(op->ptr, "ymax"); 02269 02270 /* calculate range */ 02271 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE); 02272 02273 scene->r.border.xmin= ((float)rect.xmin-vb.xmin)/(vb.xmax-vb.xmin); 02274 scene->r.border.ymin= ((float)rect.ymin-vb.ymin)/(vb.ymax-vb.ymin); 02275 scene->r.border.xmax= ((float)rect.xmax-vb.xmin)/(vb.xmax-vb.xmin); 02276 scene->r.border.ymax= ((float)rect.ymax-vb.ymin)/(vb.ymax-vb.ymin); 02277 02278 /* actually set border */ 02279 CLAMP(scene->r.border.xmin, 0.0f, 1.0f); 02280 CLAMP(scene->r.border.ymin, 0.0f, 1.0f); 02281 CLAMP(scene->r.border.xmax, 0.0f, 1.0f); 02282 CLAMP(scene->r.border.ymax, 0.0f, 1.0f); 02283 02284 /* drawing a border surrounding the entire camera view switches off border rendering 02285 * or the border covers no pixels */ 02286 if ((scene->r.border.xmin <= 0.0f && scene->r.border.xmax >= 1.0f && 02287 scene->r.border.ymin <= 0.0f && scene->r.border.ymax >= 1.0f) || 02288 (scene->r.border.xmin == scene->r.border.xmax || 02289 scene->r.border.ymin == scene->r.border.ymax )) 02290 { 02291 scene->r.mode &= ~R_BORDER; 02292 } else { 02293 scene->r.mode |= R_BORDER; 02294 } 02295 02296 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, NULL); 02297 02298 return OPERATOR_FINISHED; 02299 02300 } 02301 02302 void VIEW3D_OT_render_border(wmOperatorType *ot) 02303 { 02304 /* identifiers */ 02305 ot->name= "Set Render Border"; 02306 ot->description = "Set the boundaries of the border render and enables border render "; 02307 ot->idname= "VIEW3D_OT_render_border"; 02308 02309 /* api callbacks */ 02310 ot->invoke= WM_border_select_invoke; 02311 ot->exec= render_border_exec; 02312 ot->modal= WM_border_select_modal; 02313 ot->cancel= WM_border_select_cancel; 02314 02315 ot->poll= view3d_camera_active_poll; 02316 02317 /* flags */ 02318 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02319 02320 /* rna */ 02321 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); 02322 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); 02323 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); 02324 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); 02325 02326 } 02327 /* ********************* Border Zoom operator ****************** */ 02328 02329 static int view3d_zoom_border_exec(bContext *C, wmOperator *op) 02330 { 02331 ARegion *ar= CTX_wm_region(C); 02332 View3D *v3d = CTX_wm_view3d(C); 02333 RegionView3D *rv3d= CTX_wm_region_view3d(C); 02334 Scene *scene= CTX_data_scene(C); 02335 02336 /* Zooms in on a border drawn by the user */ 02337 rcti rect; 02338 float dvec[3], vb[2], xscale, yscale, scale; 02339 02340 /* SMOOTHVIEW */ 02341 float new_dist; 02342 float new_ofs[3]; 02343 02344 /* ZBuffer depth vars */ 02345 bglMats mats; 02346 float depth_close= FLT_MAX; 02347 double cent[2], p[3]; 02348 02349 /* note; otherwise opengl won't work */ 02350 view3d_operator_needs_opengl(C); 02351 02352 /* get border select values using rna */ 02353 rect.xmin= RNA_int_get(op->ptr, "xmin"); 02354 rect.ymin= RNA_int_get(op->ptr, "ymin"); 02355 rect.xmax= RNA_int_get(op->ptr, "xmax"); 02356 rect.ymax= RNA_int_get(op->ptr, "ymax"); 02357 02358 /* Get Z Depths, needed for perspective, nice for ortho */ 02359 bgl_get_mats(&mats); 02360 draw_depth(scene, ar, v3d, NULL); 02361 02362 { 02363 /* avoid allocating the whole depth buffer */ 02364 ViewDepths depth_temp= {0}; 02365 02366 /* avoid view3d_update_depths() for speed. */ 02367 view3d_update_depths_rect(ar, &depth_temp, &rect); 02368 02369 /* find the closest Z pixel */ 02370 depth_close= view3d_depth_near(&depth_temp); 02371 02372 MEM_freeN(depth_temp.depths); 02373 } 02374 02375 cent[0] = (((double)rect.xmin)+((double)rect.xmax)) / 2; 02376 cent[1] = (((double)rect.ymin)+((double)rect.ymax)) / 2; 02377 02378 if (rv3d->is_persp) { 02379 double p_corner[3]; 02380 02381 /* no depths to use, we cant do anything! */ 02382 if (depth_close==FLT_MAX){ 02383 BKE_report(op->reports, RPT_ERROR, "Depth Too Large"); 02384 return OPERATOR_CANCELLED; 02385 } 02386 /* convert border to 3d coordinates */ 02387 if (( !gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) || 02388 ( !gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p_corner[0], &p_corner[1], &p_corner[2]))) 02389 return OPERATOR_CANCELLED; 02390 02391 dvec[0] = p[0]-p_corner[0]; 02392 dvec[1] = p[1]-p_corner[1]; 02393 dvec[2] = p[2]-p_corner[2]; 02394 02395 new_dist = len_v3(dvec); 02396 if(new_dist <= v3d->near * 1.5f) new_dist= v3d->near * 1.5f; 02397 02398 new_ofs[0] = -p[0]; 02399 new_ofs[1] = -p[1]; 02400 new_ofs[2] = -p[2]; 02401 02402 } else { /* othographic */ 02403 /* find the current window width and height */ 02404 vb[0] = ar->winx; 02405 vb[1] = ar->winy; 02406 02407 new_dist = rv3d->dist; 02408 02409 /* convert the drawn rectangle into 3d space */ 02410 if (depth_close!=FLT_MAX && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) { 02411 new_ofs[0] = -p[0]; 02412 new_ofs[1] = -p[1]; 02413 new_ofs[2] = -p[2]; 02414 } 02415 else { 02416 float mval_f[2]; 02417 /* We cant use the depth, fallback to the old way that dosnt set the center depth */ 02418 copy_v3_v3(new_ofs, rv3d->ofs); 02419 02420 initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]); 02421 02422 mval_f[0]= (rect.xmin + rect.xmax - vb[0]) / 2.0f; 02423 mval_f[1]= (rect.ymin + rect.ymax - vb[1]) / 2.0f; 02424 ED_view3d_win_to_delta(ar, mval_f, dvec); 02425 /* center the view to the center of the rectangle */ 02426 sub_v3_v3(new_ofs, dvec); 02427 } 02428 02429 /* work out the ratios, so that everything selected fits when we zoom */ 02430 xscale = ((rect.xmax-rect.xmin)/vb[0]); 02431 yscale = ((rect.ymax-rect.ymin)/vb[1]); 02432 scale = (xscale >= yscale)?xscale:yscale; 02433 02434 /* zoom in as required, or as far as we can go */ 02435 new_dist = ((new_dist*scale) >= 0.001f * v3d->grid)? new_dist*scale:0.001f * v3d->grid; 02436 } 02437 02438 smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, &new_dist, NULL); 02439 02440 if(rv3d->viewlock & RV3D_BOXVIEW) 02441 view3d_boxview_sync(CTX_wm_area(C), ar); 02442 02443 return OPERATOR_FINISHED; 02444 } 02445 02446 static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, wmEvent *event) 02447 { 02448 View3D *v3d= CTX_wm_view3d(C); 02449 RegionView3D *rv3d= CTX_wm_region_view3d(C); 02450 02451 /* if in camera view do not exec the operator so we do not conflict with set render border*/ 02452 if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) 02453 return WM_border_select_invoke(C, op, event); 02454 else 02455 return OPERATOR_PASS_THROUGH; 02456 } 02457 02458 void VIEW3D_OT_zoom_border(wmOperatorType *ot) 02459 { 02460 /* identifiers */ 02461 ot->name= "Border Zoom"; 02462 ot->description = "Zoom in the view to the nearest object contained in the border"; 02463 ot->idname= "VIEW3D_OT_zoom_border"; 02464 02465 /* api callbacks */ 02466 ot->invoke= view3d_zoom_border_invoke; 02467 ot->exec= view3d_zoom_border_exec; 02468 ot->modal= WM_border_select_modal; 02469 ot->cancel= WM_border_select_cancel; 02470 02471 ot->poll= ED_operator_region_view3d_active; 02472 02473 /* flags */ 02474 ot->flag= 0; 02475 02476 /* rna */ 02477 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); 02478 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); 02479 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); 02480 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); 02481 02482 } 02483 02484 /* sets the view to 1:1 camera/render-pixel */ 02485 static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar) 02486 { 02487 RegionView3D *rv3d= ar->regiondata; 02488 float size[2]; 02489 int im_width= (scene->r.size*scene->r.xsch)/100; 02490 02491 view3d_viewborder_size_get(scene, ar, size); 02492 02493 rv3d->camzoom= BKE_screen_view3d_zoom_from_fac((float)im_width/size[0]); 02494 CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); 02495 } 02496 02497 static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op)) 02498 { 02499 Scene *scene= CTX_data_scene(C); 02500 ARegion *ar= CTX_wm_region(C); 02501 02502 view3d_set_1_to_1_viewborder(scene, ar); 02503 02504 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, CTX_wm_view3d(C)); 02505 02506 return OPERATOR_FINISHED; 02507 } 02508 02509 void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot) 02510 { 02511 /* identifiers */ 02512 ot->name= "Zoom Camera 1:1"; 02513 ot->description = "Match the camera to 1:1 to the render output"; 02514 ot->idname= "VIEW3D_OT_zoom_camera_1_to_1"; 02515 02516 /* api callbacks */ 02517 ot->exec= view3d_zoom_1_to_1_camera_exec; 02518 ot->poll= view3d_camera_active_poll; 02519 02520 /* flags */ 02521 ot->flag= 0; 02522 } 02523 02524 /* ********************* Changing view operator ****************** */ 02525 02526 static EnumPropertyItem prop_view_items[] = { 02527 {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"}, 02528 {RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"}, 02529 {RV3D_VIEW_LEFT, "LEFT", 0, "Left", "View From the Left"}, 02530 {RV3D_VIEW_RIGHT, "RIGHT", 0, "Right", "View From the Right"}, 02531 {RV3D_VIEW_TOP, "TOP", 0, "Top", "View From the Top"}, 02532 {RV3D_VIEW_BOTTOM, "BOTTOM", 0, "Bottom", "View From the Bottom"}, 02533 {RV3D_VIEW_CAMERA, "CAMERA", 0, "Camera", "View From the active amera"}, 02534 {0, NULL, 0, NULL, NULL}}; 02535 02536 02537 /* would like to make this a generic function - outside of transform */ 02538 02539 static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar, float q1, float q2, float q3, float q4, short view, int perspo, int align_active) 02540 { 02541 RegionView3D *rv3d= ar->regiondata; /* no NULL check is needed, poll checks */ 02542 float new_quat[4]; 02543 02544 new_quat[0]= q1; new_quat[1]= q2; 02545 new_quat[2]= q3; new_quat[3]= q4; 02546 normalize_qt(new_quat); 02547 02548 if(align_active) { 02549 /* align to active object */ 02550 Object *obact= CTX_data_active_object(C); 02551 if (obact==NULL) { 02552 /* no active object, ignore this option */ 02553 align_active= FALSE; 02554 } 02555 else { 02556 float obact_quat[4]; 02557 float twmat[3][3]; 02558 02559 /* same as transform manipulator when normal is set */ 02560 ED_getTransformOrientationMatrix(C, twmat, FALSE); 02561 02562 mat3_to_quat( obact_quat,twmat); 02563 invert_qt(obact_quat); 02564 mul_qt_qtqt(new_quat, new_quat, obact_quat); 02565 02566 rv3d->view= view= RV3D_VIEW_USER; 02567 } 02568 } 02569 02570 if(align_active==FALSE) { 02571 /* normal operation */ 02572 if(rv3d->viewlock) { 02573 /* only pass on if */ 02574 if(rv3d->view==RV3D_VIEW_FRONT && view==RV3D_VIEW_BACK); 02575 else if(rv3d->view==RV3D_VIEW_BACK && view==RV3D_VIEW_FRONT); 02576 else if(rv3d->view==RV3D_VIEW_RIGHT && view==RV3D_VIEW_LEFT); 02577 else if(rv3d->view==RV3D_VIEW_LEFT && view==RV3D_VIEW_RIGHT); 02578 else if(rv3d->view==RV3D_VIEW_BOTTOM && view==RV3D_VIEW_TOP); 02579 else if(rv3d->view==RV3D_VIEW_TOP && view==RV3D_VIEW_BOTTOM); 02580 else return; 02581 } 02582 02583 rv3d->view= view; 02584 } 02585 02586 if(rv3d->viewlock) { 02587 ED_region_tag_redraw(ar); 02588 return; 02589 } 02590 02591 if (rv3d->persp==RV3D_CAMOB && v3d->camera) { 02592 02593 if (U.uiflag & USER_AUTOPERSP) rv3d->persp= view ? RV3D_ORTHO : RV3D_PERSP; 02594 else if(rv3d->persp==RV3D_CAMOB) rv3d->persp= perspo; 02595 02596 smooth_view(C, v3d, ar, v3d->camera, NULL, rv3d->ofs, new_quat, NULL, NULL); 02597 } 02598 else { 02599 02600 if (U.uiflag & USER_AUTOPERSP) rv3d->persp= view ? RV3D_ORTHO : RV3D_PERSP; 02601 else if(rv3d->persp==RV3D_CAMOB) rv3d->persp= perspo; 02602 02603 smooth_view(C, v3d, ar, NULL, NULL, NULL, new_quat, NULL, NULL); 02604 } 02605 02606 } 02607 02608 static int viewnumpad_exec(bContext *C, wmOperator *op) 02609 { 02610 View3D *v3d = CTX_wm_view3d(C); 02611 ARegion *ar= ED_view3d_context_region_unlock(C); 02612 RegionView3D *rv3d= ar->regiondata; /* no NULL check is needed, poll checks */ 02613 Scene *scene= CTX_data_scene(C); 02614 static int perspo=RV3D_PERSP; 02615 int viewnum, align_active, nextperspo; 02616 02617 viewnum = RNA_enum_get(op->ptr, "type"); 02618 align_active = RNA_boolean_get(op->ptr, "align_active"); 02619 02620 /* set this to zero, gets handled in axis_set_view */ 02621 if(rv3d->viewlock) 02622 align_active= 0; 02623 02624 /* Use this to test if we started out with a camera */ 02625 02626 if (rv3d->persp == RV3D_CAMOB) { 02627 nextperspo= rv3d->lpersp; 02628 } else { 02629 nextperspo= perspo; 02630 } 02631 02632 switch (viewnum) { 02633 case RV3D_VIEW_BOTTOM : 02634 axis_set_view(C, v3d, ar, 0.0, -1.0, 0.0, 0.0, viewnum, nextperspo, align_active); 02635 break; 02636 02637 case RV3D_VIEW_BACK: 02638 axis_set_view(C, v3d, ar, 0.0, 0.0, (float)-cos(M_PI/4.0), (float)-cos(M_PI/4.0), viewnum, nextperspo, align_active); 02639 break; 02640 02641 case RV3D_VIEW_LEFT: 02642 axis_set_view(C, v3d, ar, 0.5, -0.5, 0.5, 0.5, viewnum, nextperspo, align_active); 02643 break; 02644 02645 case RV3D_VIEW_TOP: 02646 axis_set_view(C, v3d, ar, 1.0, 0.0, 0.0, 0.0, viewnum, nextperspo, align_active); 02647 break; 02648 02649 case RV3D_VIEW_FRONT: 02650 axis_set_view(C, v3d, ar, (float)cos(M_PI/4.0), (float)-sin(M_PI/4.0), 0.0, 0.0, viewnum, nextperspo, align_active); 02651 break; 02652 02653 case RV3D_VIEW_RIGHT: 02654 axis_set_view(C, v3d, ar, 0.5, -0.5, -0.5, -0.5, viewnum, nextperspo, align_active); 02655 break; 02656 02657 case RV3D_VIEW_CAMERA: 02658 if(rv3d->viewlock==0) { 02659 /* lastview - */ 02660 02661 if(rv3d->persp != RV3D_CAMOB) { 02662 Object *ob= OBACT; 02663 02664 if (!rv3d->smooth_timer) { 02665 /* store settings of current view before allowing overwriting with camera view 02666 * only if we're not currently in a view transition */ 02667 copy_qt_qt(rv3d->lviewquat, rv3d->viewquat); 02668 rv3d->lview= rv3d->view; 02669 rv3d->lpersp= rv3d->persp; 02670 } 02671 02672 #if 0 02673 if(G.qual==LR_ALTKEY) { 02674 if(oldcamera && is_an_active_object(oldcamera)) { 02675 v3d->camera= oldcamera; 02676 } 02677 handle_view3d_lock(); 02678 } 02679 #endif 02680 02681 /* first get the default camera for the view lock type */ 02682 if(v3d->scenelock) { 02683 /* sets the camera view if available */ 02684 v3d->camera= scene->camera; 02685 } 02686 else { 02687 /* use scene camera if one is not set (even though we're unlocked) */ 02688 if(v3d->camera==NULL) { 02689 v3d->camera= scene->camera; 02690 } 02691 } 02692 02693 /* if the camera isnt found, check a number of options */ 02694 if(v3d->camera==NULL && ob && ob->type==OB_CAMERA) 02695 v3d->camera= ob; 02696 02697 if(v3d->camera==NULL) 02698 v3d->camera= scene_find_camera(scene); 02699 02700 /* couldnt find any useful camera, bail out */ 02701 if(v3d->camera==NULL) 02702 return OPERATOR_CANCELLED; 02703 02704 /* important these dont get out of sync for locked scenes */ 02705 if(v3d->scenelock) 02706 scene->camera= v3d->camera; 02707 02708 /* finally do snazzy view zooming */ 02709 rv3d->persp= RV3D_CAMOB; 02710 smooth_view(C, v3d, ar, NULL, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens); 02711 02712 } 02713 else{ 02714 /* return to settings of last view */ 02715 /* does smooth_view too */ 02716 axis_set_view(C, v3d, ar, rv3d->lviewquat[0], rv3d->lviewquat[1], rv3d->lviewquat[2], rv3d->lviewquat[3], rv3d->lview, rv3d->lpersp, 0); 02717 } 02718 } 02719 break; 02720 02721 default : 02722 break; 02723 } 02724 02725 if(rv3d->persp != RV3D_CAMOB) perspo= rv3d->persp; 02726 02727 return OPERATOR_FINISHED; 02728 } 02729 02730 02731 void VIEW3D_OT_viewnumpad(wmOperatorType *ot) 02732 { 02733 /* identifiers */ 02734 ot->name= "View numpad"; 02735 ot->description = "Set the view"; 02736 ot->idname= "VIEW3D_OT_viewnumpad"; 02737 02738 /* api callbacks */ 02739 ot->exec= viewnumpad_exec; 02740 ot->poll= ED_operator_rv3d_unlock_poll; 02741 02742 /* flags */ 02743 ot->flag= 0; 02744 02745 RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "The Type of view"); 02746 RNA_def_boolean(ot->srna, "align_active", 0, "Align Active", "Align to the active objects axis"); 02747 } 02748 02749 static EnumPropertyItem prop_view_orbit_items[] = { 02750 {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the Left"}, 02751 {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the Right"}, 02752 {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view Up"}, 02753 {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view Down"}, 02754 {0, NULL, 0, NULL, NULL}}; 02755 02756 static int vieworbit_exec(bContext *C, wmOperator *op) 02757 { 02758 View3D *v3d= CTX_wm_view3d(C); 02759 ARegion *ar= ED_view3d_context_region_unlock(C); 02760 RegionView3D *rv3d= ar->regiondata; /* no NULL check is needed, poll checks */ 02761 float phi, q1[4], new_quat[4]; 02762 int orbitdir; 02763 02764 orbitdir = RNA_enum_get(op->ptr, "type"); 02765 02766 if(rv3d->viewlock==0) { 02767 if((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { 02768 if(orbitdir == V3D_VIEW_STEPLEFT || orbitdir == V3D_VIEW_STEPRIGHT) { 02769 float si; 02770 /* z-axis */ 02771 phi= (float)(M_PI/360.0)*U.pad_rot_angle; 02772 if(orbitdir == V3D_VIEW_STEPRIGHT) phi= -phi; 02773 si= (float)sin(phi); 02774 q1[0]= (float)cos(phi); 02775 q1[1]= q1[2]= 0.0; 02776 q1[3]= si; 02777 mul_qt_qtqt(new_quat, rv3d->viewquat, q1); 02778 rv3d->view= RV3D_VIEW_USER; 02779 } 02780 else if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) { 02781 /* horizontal axis */ 02782 copy_v3_v3(q1+1, rv3d->viewinv[0]); 02783 02784 normalize_v3(q1+1); 02785 phi= (float)(M_PI/360.0)*U.pad_rot_angle; 02786 if(orbitdir == V3D_VIEW_STEPDOWN) phi= -phi; 02787 q1[0]= (float)cos(phi); 02788 mul_v3_fl(q1+1, sin(phi)); 02789 mul_qt_qtqt(new_quat, rv3d->viewquat, q1); 02790 rv3d->view= RV3D_VIEW_USER; 02791 } 02792 02793 smooth_view(C, CTX_wm_view3d(C), ar, NULL, NULL, NULL, new_quat, NULL, NULL); 02794 } 02795 } 02796 02797 return OPERATOR_FINISHED; 02798 } 02799 02800 void VIEW3D_OT_view_orbit(wmOperatorType *ot) 02801 { 02802 /* identifiers */ 02803 ot->name= "View Orbit"; 02804 ot->description = "Orbit the view"; 02805 ot->idname= "VIEW3D_OT_view_orbit"; 02806 02807 /* api callbacks */ 02808 ot->exec= vieworbit_exec; 02809 ot->poll= ED_operator_rv3d_unlock_poll; 02810 02811 /* flags */ 02812 ot->flag= 0; 02813 RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit"); 02814 } 02815 02816 static EnumPropertyItem prop_view_pan_items[] = { 02817 {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"}, 02818 {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"}, 02819 {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view Up"}, 02820 {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view Down"}, 02821 {0, NULL, 0, NULL, NULL}}; 02822 02823 static int viewpan_exec(bContext *C, wmOperator *op) 02824 { 02825 ARegion *ar= CTX_wm_region(C); 02826 RegionView3D *rv3d= CTX_wm_region_view3d(C); 02827 float vec[3]; 02828 float mval_f[2]= {0.0f, 0.0f}; 02829 int pandir; 02830 02831 pandir = RNA_enum_get(op->ptr, "type"); 02832 02833 initgrabz(rv3d, 0.0, 0.0, 0.0); 02834 if(pandir == V3D_VIEW_PANRIGHT) { mval_f[0]= -32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } 02835 else if(pandir == V3D_VIEW_PANLEFT) { mval_f[0]= 32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } 02836 else if(pandir == V3D_VIEW_PANUP) { mval_f[1]= -25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } 02837 else if(pandir == V3D_VIEW_PANDOWN) { mval_f[1]= 25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } 02838 add_v3_v3(rv3d->ofs, vec); 02839 02840 if(rv3d->viewlock & RV3D_BOXVIEW) 02841 view3d_boxview_sync(CTX_wm_area(C), ar); 02842 02843 ED_region_tag_redraw(ar); 02844 02845 return OPERATOR_FINISHED; 02846 } 02847 02848 void VIEW3D_OT_view_pan(wmOperatorType *ot) 02849 { 02850 /* identifiers */ 02851 ot->name= "View Pan"; 02852 ot->description = "Pan the view"; 02853 ot->idname= "VIEW3D_OT_view_pan"; 02854 02855 /* api callbacks */ 02856 ot->exec= viewpan_exec; 02857 ot->poll= ED_operator_region_view3d_active; 02858 02859 /* flags */ 02860 ot->flag= 0; 02861 RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan"); 02862 } 02863 02864 static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op)) 02865 { 02866 ARegion *ar= ED_view3d_context_region_unlock(C); 02867 RegionView3D *rv3d= ar->regiondata; /* no NULL check is needed, poll checks */ 02868 02869 if(rv3d->viewlock==0) { 02870 if(rv3d->persp!=RV3D_ORTHO) 02871 rv3d->persp=RV3D_ORTHO; 02872 else rv3d->persp=RV3D_PERSP; 02873 ED_region_tag_redraw(ar); 02874 } 02875 02876 return OPERATOR_FINISHED; 02877 02878 } 02879 02880 void VIEW3D_OT_view_persportho(wmOperatorType *ot) 02881 { 02882 /* identifiers */ 02883 ot->name= "View Persp/Ortho"; 02884 ot->description = "Switch the current view from perspective/orthographic"; 02885 ot->idname= "VIEW3D_OT_view_persportho"; 02886 02887 /* api callbacks */ 02888 ot->exec= viewpersportho_exec; 02889 ot->poll= ED_operator_rv3d_unlock_poll; 02890 02891 /* flags */ 02892 ot->flag= 0; 02893 } 02894 02895 02896 /* ******************** add background image operator **************** */ 02897 02898 static BGpic *background_image_add(bContext *C) 02899 { 02900 View3D *v3d= CTX_wm_view3d(C); 02901 02902 BGpic *bgpic= MEM_callocN(sizeof(BGpic), "Background Image"); 02903 bgpic->size= 5.0; 02904 bgpic->blend= 0.5; 02905 bgpic->iuser.fie_ima= 2; 02906 bgpic->iuser.ok= 1; 02907 bgpic->view= 0; /* 0 for all */ 02908 02909 BLI_addtail(&v3d->bgpicbase, bgpic); 02910 02911 return bgpic; 02912 } 02913 02914 static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op)) 02915 { 02916 background_image_add(C); 02917 02918 return OPERATOR_FINISHED; 02919 } 02920 02921 static int background_image_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 02922 { 02923 View3D *v3d= CTX_wm_view3d(C); 02924 Image *ima= NULL; 02925 BGpic *bgpic; 02926 char name[32]; 02927 02928 /* check input variables */ 02929 if(RNA_property_is_set(op->ptr, "filepath")) { 02930 char path[FILE_MAX]; 02931 02932 RNA_string_get(op->ptr, "filepath", path); 02933 ima= BKE_add_image_file(path); 02934 } 02935 else if(RNA_property_is_set(op->ptr, "name")) { 02936 RNA_string_get(op->ptr, "name", name); 02937 ima= (Image *)find_id("IM", name); 02938 } 02939 02940 bgpic = background_image_add(C); 02941 02942 if (ima) { 02943 bgpic->ima = ima; 02944 02945 if(ima->id.us==0) id_us_plus(&ima->id); 02946 else id_lib_extern(&ima->id); 02947 02948 if (!(v3d->flag & V3D_DISPBGPICS)) 02949 v3d->flag |= V3D_DISPBGPICS; 02950 } 02951 02952 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d); 02953 02954 return OPERATOR_FINISHED; 02955 } 02956 02957 void VIEW3D_OT_background_image_add(wmOperatorType *ot) 02958 { 02959 /* identifiers */ 02960 ot->name = "Add Background Image"; 02961 ot->description= "Add a new background image"; 02962 ot->idname = "VIEW3D_OT_background_image_add"; 02963 02964 /* api callbacks */ 02965 ot->invoke = background_image_add_invoke; 02966 ot->exec = background_image_add_exec; 02967 ot->poll = ED_operator_view3d_active; 02968 02969 /* flags */ 02970 ot->flag = 0; 02971 02972 /* properties */ 02973 RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Image name to assign."); 02974 RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file"); 02975 } 02976 02977 02978 /* ***** remove image operator ******* */ 02979 static int background_image_remove_exec(bContext *C, wmOperator *op) 02980 { 02981 View3D *vd = CTX_wm_view3d(C); 02982 int index = RNA_int_get(op->ptr, "index"); 02983 BGpic *bgpic_rem= BLI_findlink(&vd->bgpicbase, index); 02984 02985 if(bgpic_rem) { 02986 BLI_remlink(&vd->bgpicbase, bgpic_rem); 02987 if(bgpic_rem->ima) bgpic_rem->ima->id.us--; 02988 MEM_freeN(bgpic_rem); 02989 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, vd); 02990 return OPERATOR_FINISHED; 02991 } 02992 else { 02993 return OPERATOR_CANCELLED; 02994 } 02995 02996 } 02997 02998 void VIEW3D_OT_background_image_remove(wmOperatorType *ot) 02999 { 03000 /* identifiers */ 03001 ot->name = "Remove Background Image"; 03002 ot->description= "Remove a background image from the 3D view"; 03003 ot->idname = "VIEW3D_OT_background_image_remove"; 03004 03005 /* api callbacks */ 03006 ot->exec = background_image_remove_exec; 03007 ot->poll = ED_operator_view3d_active; 03008 03009 /* flags */ 03010 ot->flag = 0; 03011 03012 RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove ", 0, INT_MAX); 03013 } 03014 03015 /* ********************* set clipping operator ****************** */ 03016 03017 static void calc_clipping_plane(float clip[6][4], BoundBox *clipbb) 03018 { 03019 int val; 03020 03021 for(val=0; val<4; val++) { 03022 03023 normal_tri_v3( clip[val],clipbb->vec[val], clipbb->vec[val==3?0:val+1], clipbb->vec[val+4]); 03024 03025 clip[val][3]= 03026 - clip[val][0]*clipbb->vec[val][0] 03027 - clip[val][1]*clipbb->vec[val][1] 03028 - clip[val][2]*clipbb->vec[val][2]; 03029 } 03030 } 03031 03032 static void calc_local_clipping(float clip_local[][4], BoundBox *clipbb, float mat[][4]) 03033 { 03034 BoundBox clipbb_local; 03035 float imat[4][4]; 03036 int i; 03037 03038 invert_m4_m4(imat, mat); 03039 03040 for(i=0; i<8; i++) { 03041 mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]); 03042 } 03043 03044 calc_clipping_plane(clip_local, &clipbb_local); 03045 } 03046 03047 void ED_view3d_local_clipping(RegionView3D *rv3d, float mat[][4]) 03048 { 03049 if(rv3d->rflag & RV3D_CLIPPING) 03050 calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat); 03051 } 03052 03053 static int view3d_clipping_exec(bContext *C, wmOperator *op) 03054 { 03055 RegionView3D *rv3d= CTX_wm_region_view3d(C); 03056 ViewContext vc; 03057 bglMats mats; 03058 rcti rect; 03059 03060 rect.xmin= RNA_int_get(op->ptr, "xmin"); 03061 rect.ymin= RNA_int_get(op->ptr, "ymin"); 03062 rect.xmax= RNA_int_get(op->ptr, "xmax"); 03063 rect.ymax= RNA_int_get(op->ptr, "ymax"); 03064 03065 rv3d->rflag |= RV3D_CLIPPING; 03066 rv3d->clipbb= MEM_callocN(sizeof(BoundBox), "clipbb"); 03067 03068 /* note; otherwise opengl won't work */ 03069 view3d_operator_needs_opengl(C); 03070 03071 view3d_set_viewcontext(C, &vc); 03072 view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */ 03073 ED_view3d_calc_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect); 03074 03075 return OPERATOR_FINISHED; 03076 } 03077 03078 static int view3d_clipping_invoke(bContext *C, wmOperator *op, wmEvent *event) 03079 { 03080 RegionView3D *rv3d= CTX_wm_region_view3d(C); 03081 ARegion *ar= CTX_wm_region(C); 03082 03083 if(rv3d->rflag & RV3D_CLIPPING) { 03084 rv3d->rflag &= ~RV3D_CLIPPING; 03085 ED_region_tag_redraw(ar); 03086 if(rv3d->clipbb) MEM_freeN(rv3d->clipbb); 03087 rv3d->clipbb= NULL; 03088 return OPERATOR_FINISHED; 03089 } 03090 else { 03091 return WM_border_select_invoke(C, op, event); 03092 } 03093 } 03094 03095 /* toggles */ 03096 void VIEW3D_OT_clip_border(wmOperatorType *ot) 03097 { 03098 03099 /* identifiers */ 03100 ot->name= "Clipping Border"; 03101 ot->description = "Set the view clipping border"; 03102 ot->idname= "VIEW3D_OT_clip_border"; 03103 03104 /* api callbacks */ 03105 ot->invoke= view3d_clipping_invoke; 03106 ot->exec= view3d_clipping_exec; 03107 ot->modal= WM_border_select_modal; 03108 ot->cancel= WM_border_select_cancel; 03109 03110 ot->poll= ED_operator_region_view3d_active; 03111 03112 /* flags */ 03113 ot->flag= 0; 03114 03115 /* rna */ 03116 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); 03117 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); 03118 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); 03119 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); 03120 } 03121 03122 /* ***************** 3d cursor cursor op ******************* */ 03123 03124 /* mx my in region coords */ 03125 static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) 03126 { 03127 Scene *scene= CTX_data_scene(C); 03128 ARegion *ar= CTX_wm_region(C); 03129 View3D *v3d = CTX_wm_view3d(C); 03130 RegionView3D *rv3d= CTX_wm_region_view3d(C); 03131 float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3]; 03132 int mval[2]; 03133 // short ctrl= 0; // XXX 03134 int flip; 03135 fp= give_cursor(scene, v3d); 03136 03137 // if(obedit && ctrl) lr_click= 1; 03138 copy_v3_v3(oldcurs, fp); 03139 03140 project_int_noclip(ar, fp, mval); 03141 flip= initgrabz(rv3d, fp[0], fp[1], fp[2]); 03142 03143 /* reset the depth based on the view offset */ 03144 if(flip) { 03145 negate_v3_v3(fp, rv3d->ofs); 03146 03147 /* re initialize */ 03148 project_int_noclip(ar, fp, mval); 03149 flip= initgrabz(rv3d, fp[0], fp[1], fp[2]); 03150 } 03151 03152 if(mval[0]!=IS_CLIPPED) { 03153 short depth_used = 0; 03154 03155 if (U.uiflag & USER_ORBIT_ZBUF) { /* maybe this should be accessed some other way */ 03156 view3d_operator_needs_opengl(C); 03157 if (ED_view3d_autodist(scene, ar, v3d, event->mval, fp)) 03158 depth_used= 1; 03159 } 03160 03161 if(depth_used==0) { 03162 float mval_f[2]; 03163 VECSUB2D(mval_f, mval, event->mval); 03164 ED_view3d_win_to_delta(ar, mval_f, dvec); 03165 sub_v3_v3(fp, dvec); 03166 } 03167 } 03168 else { 03169 03170 dx= ((float)(event->mval[0]-(ar->winx/2)))*rv3d->zfac/(ar->winx/2); 03171 dy= ((float)(event->mval[1]-(ar->winy/2)))*rv3d->zfac/(ar->winy/2); 03172 03173 fz= rv3d->persmat[0][3]*fp[0]+ rv3d->persmat[1][3]*fp[1]+ rv3d->persmat[2][3]*fp[2]+ rv3d->persmat[3][3]; 03174 fz= fz/rv3d->zfac; 03175 03176 fp[0]= (rv3d->persinv[0][0]*dx + rv3d->persinv[1][0]*dy+ rv3d->persinv[2][0]*fz)-rv3d->ofs[0]; 03177 fp[1]= (rv3d->persinv[0][1]*dx + rv3d->persinv[1][1]*dy+ rv3d->persinv[2][1]*fz)-rv3d->ofs[1]; 03178 fp[2]= (rv3d->persinv[0][2]*dx + rv3d->persinv[1][2]*dy+ rv3d->persinv[2][2]*fz)-rv3d->ofs[2]; 03179 } 03180 03181 if(v3d && v3d->localvd) 03182 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d); 03183 else 03184 WM_event_add_notifier(C, NC_SCENE|NA_EDITED, scene); 03185 03186 return OPERATOR_FINISHED; 03187 } 03188 03189 void VIEW3D_OT_cursor3d(wmOperatorType *ot) 03190 { 03191 03192 /* identifiers */ 03193 ot->name= "Set 3D Cursor"; 03194 ot->description = "Set the location of the 3D cursor"; 03195 ot->idname= "VIEW3D_OT_cursor3d"; 03196 03197 /* api callbacks */ 03198 ot->invoke= set_3dcursor_invoke; 03199 03200 ot->poll= ED_operator_view3d_active; 03201 03202 /* flags */ 03203 // ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03204 03205 /* rna later */ 03206 03207 } 03208 03209 /* ***************** manipulator op ******************* */ 03210 03211 03212 static int manipulator_invoke(bContext *C, wmOperator *op, wmEvent *event) 03213 { 03214 View3D *v3d = CTX_wm_view3d(C); 03215 03216 if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH; 03217 if(!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH; 03218 03219 /* only no modifier or shift */ 03220 if(event->keymodifier != 0 && event->keymodifier != KM_SHIFT) return OPERATOR_PASS_THROUGH; 03221 03222 /* note; otherwise opengl won't work */ 03223 view3d_operator_needs_opengl(C); 03224 03225 if(0==BIF_do_manipulator(C, event, op)) 03226 return OPERATOR_PASS_THROUGH; 03227 03228 return OPERATOR_FINISHED; 03229 } 03230 03231 void VIEW3D_OT_manipulator(wmOperatorType *ot) 03232 { 03233 03234 /* identifiers */ 03235 ot->name= "3D Manipulator"; 03236 ot->description = "Manipulate selected item by axis"; 03237 ot->idname= "VIEW3D_OT_manipulator"; 03238 03239 /* api callbacks */ 03240 ot->invoke= manipulator_invoke; 03241 03242 ot->poll= ED_operator_view3d_active; 03243 03244 /* properties to pass to transform */ 03245 Transform_Properties(ot, P_CONSTRAINT); 03246 } 03247 03248 static int enable_manipulator_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 03249 { 03250 View3D *v3d = CTX_wm_view3d(C); 03251 03252 v3d->twtype=0; 03253 03254 if (RNA_boolean_get(op->ptr, "translate")) 03255 v3d->twtype |= V3D_MANIP_TRANSLATE; 03256 if (RNA_boolean_get(op->ptr, "rotate")) 03257 v3d->twtype |= V3D_MANIP_ROTATE; 03258 if (RNA_boolean_get(op->ptr, "scale")) 03259 v3d->twtype |= V3D_MANIP_SCALE; 03260 03261 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d); 03262 03263 return OPERATOR_FINISHED; 03264 } 03265 03266 void VIEW3D_OT_enable_manipulator(wmOperatorType *ot) 03267 { 03268 /* identifiers */ 03269 ot->name= "Enable 3D Manipulator"; 03270 ot->description = "Enable the transform manipulator for use"; 03271 ot->idname= "VIEW3D_OT_enable_manipulator"; 03272 03273 /* api callbacks */ 03274 ot->invoke= enable_manipulator_invoke; 03275 ot->poll= ED_operator_view3d_active; 03276 03277 /* rna later */ 03278 RNA_def_boolean(ot->srna, "translate", 0, "Translate", "Enable the translate manipulator"); 03279 RNA_def_boolean(ot->srna, "rotate", 0, "Rotate", "Enable the rotate manipulator"); 03280 RNA_def_boolean(ot->srna, "scale", 0, "Scale", "Enable the scale manipulator"); 03281 } 03282 03283 /* ************************* below the line! *********************** */ 03284 03285 03286 static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin) 03287 { 03288 ViewDepths depth_temp= {0}; 03289 rcti rect; 03290 float depth_close; 03291 03292 if(margin==0) { 03293 /* Get Z Depths, needed for perspective, nice for ortho */ 03294 rect.xmin= mval[0]; 03295 rect.ymin= mval[1]; 03296 rect.xmax= mval[0] + 1; 03297 rect.ymax= mval[1] + 1; 03298 } 03299 else { 03300 rect.xmax = mval[0] + margin; 03301 rect.ymax = mval[1] + margin; 03302 03303 rect.xmin = mval[0] - margin; 03304 rect.ymin = mval[1] - margin; 03305 } 03306 03307 view3d_update_depths_rect(ar, &depth_temp, &rect); 03308 depth_close= view3d_depth_near(&depth_temp); 03309 if(depth_temp.depths) MEM_freeN(depth_temp.depths); 03310 return depth_close; 03311 } 03312 03313 /* XXX todo Zooms in on a border drawn by the user */ 03314 int ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2], float mouse_worldloc[3] ) //, float *autodist ) 03315 { 03316 bglMats mats; /* ZBuffer depth vars */ 03317 float depth_close= FLT_MAX; 03318 double cent[2], p[3]; 03319 03320 /* Get Z Depths, needed for perspective, nice for ortho */ 03321 bgl_get_mats(&mats); 03322 draw_depth(scene, ar, v3d, NULL); 03323 03324 depth_close= view_autodist_depth_margin(ar, mval, 4); 03325 03326 if (depth_close==FLT_MAX) 03327 return 0; 03328 03329 cent[0] = (double)mval[0]; 03330 cent[1] = (double)mval[1]; 03331 03332 if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) 03333 return 0; 03334 03335 mouse_worldloc[0] = (float)p[0]; 03336 mouse_worldloc[1] = (float)p[1]; 03337 mouse_worldloc[2] = (float)p[2]; 03338 return 1; 03339 } 03340 03341 int ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, float *autodist ) 03342 { 03343 /* Get Z Depths, needed for perspective, nice for ortho */ 03344 switch(mode) { 03345 case 0: 03346 draw_depth(scene, ar, v3d, NULL); 03347 break; 03348 case 1: 03349 draw_depth_gpencil(scene, ar, v3d); 03350 break; 03351 } 03352 03353 return 1; 03354 } 03355 03356 // no 4x4 sampling, run view_autodist_init first 03357 int ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth) //, float *autodist ) 03358 { 03359 bglMats mats; /* ZBuffer depth vars, could cache? */ 03360 float depth; 03361 double cent[2], p[3]; 03362 03363 /* Get Z Depths, needed for perspective, nice for ortho */ 03364 if(force_depth) 03365 depth= *force_depth; 03366 else 03367 depth= view_autodist_depth_margin(ar, mval, margin); 03368 03369 if (depth==FLT_MAX) 03370 return 0; 03371 03372 cent[0] = (double)mval[0]; 03373 cent[1] = (double)mval[1]; 03374 03375 bgl_get_mats(&mats); 03376 if (!gluUnProject(cent[0], cent[1], depth, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) 03377 return 0; 03378 03379 mouse_worldloc[0] = (float)p[0]; 03380 mouse_worldloc[1] = (float)p[1]; 03381 mouse_worldloc[2] = (float)p[2]; 03382 return 1; 03383 } 03384 03385 int ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin, float *depth) 03386 { 03387 *depth= view_autodist_depth_margin(ar, mval, margin); 03388 03389 return (*depth==FLT_MAX) ? 0:1; 03390 } 03391 03392 static int depth_segment_cb(int x, int y, void *userData) 03393 { 03394 struct { struct ARegion *ar; int margin; float depth; } *data = userData; 03395 int mval[2]; 03396 float depth; 03397 03398 mval[0]= x; 03399 mval[1]= y; 03400 03401 depth= view_autodist_depth_margin(data->ar, mval, data->margin); 03402 03403 if(depth != FLT_MAX) { 03404 data->depth= depth; 03405 return 0; 03406 } 03407 else { 03408 return 1; 03409 } 03410 } 03411 03412 int ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth) 03413 { 03414 struct { struct ARegion *ar; int margin; float depth; } data = {NULL}; 03415 int p1[2]; 03416 int p2[2]; 03417 03418 data.ar= ar; 03419 data.margin= margin; 03420 data.depth= FLT_MAX; 03421 03422 VECCOPY2D(p1, mval_sta); 03423 VECCOPY2D(p2, mval_end); 03424 03425 plot_line_v2v2i(p1, p2, depth_segment_cb, &data); 03426 03427 *depth= data.depth; 03428 03429 return (*depth==FLT_MAX) ? 0:1; 03430 } 03431 03432 /* Gets the view trasnformation from a camera 03433 * currently dosnt take camzoom into account 03434 * 03435 * The dist is not modified for this function, if NULL its assimed zero 03436 * */ 03437 void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist) 03438 { 03439 /* Offset */ 03440 if (ofs) 03441 negate_v3_v3(ofs, mat[3]); 03442 03443 /* Quat */ 03444 if (quat) { 03445 float imat[4][4]; 03446 invert_m4_m4(imat, mat); 03447 mat4_to_quat(quat, imat); 03448 } 03449 03450 if (dist) { 03451 float nmat[3][3]; 03452 float vec[3]; 03453 03454 vec[0]= 0.0f; 03455 vec[1]= 0.0f; 03456 vec[2]= -(*dist); 03457 03458 copy_m3_m4(nmat, mat); 03459 normalize_m3(nmat); 03460 03461 mul_m3_v3(nmat, vec);; 03462 sub_v3_v3(ofs, vec); 03463 } 03464 } 03465 03466 void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], const float dist) 03467 { 03468 float iviewquat[4]= {-quat[0], quat[1], quat[2], quat[3]}; 03469 float dvec[3]= {0.0f, 0.0f, dist}; 03470 03471 quat_to_mat4(mat, iviewquat); 03472 mul_mat3_m4_v3(mat, dvec); 03473 sub_v3_v3v3(mat[3], dvec, ofs); 03474 } 03475 03476 03477 /* object -> view */ 03478 void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens) 03479 { 03480 ED_view3d_from_m4(ob->obmat, ofs, quat, dist); 03481 03482 if (lens) { 03483 ED_view3d_ob_clip_range_get(ob, lens, NULL, NULL); 03484 } 03485 } 03486 03487 /* view -> object */ 03488 void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist) 03489 { 03490 float mat[4][4]; 03491 ED_view3d_to_m4(mat, ofs, quat, dist); 03492 object_apply_mat4(ob, mat, TRUE, TRUE); 03493 }