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