Index: source/blender/makesdna/DNA_userdef_types.h =================================================================== --- source/blender/makesdna/DNA_userdef_types.h (revision 10988) +++ source/blender/makesdna/DNA_userdef_types.h (working copy) @@ -233,6 +233,7 @@ #define USER_SHOW_ROTVIEWICON 131072 #define USER_SHOW_VIEWPORTNAME 262144 #define USER_KEYINSERTNEED 524288 +#define USER_MOUSEPOSDOLLY 1048576 /* transopts */ Index: source/blender/src/space.c =================================================================== --- source/blender/src/space.c (revision 10988) +++ source/blender/src/space.c (working copy) @@ -3315,28 +3315,32 @@ &(U.viewzoom), 40, USER_ZOOM_SCALE, 0, 0, "Zooms in and out like scaling the view, mouse movements relative to center."); uiBlockSetCol(block, TH_AUTO); /* end color */ + uiDefButBitI(block, TOG, USER_MOUSEPOSDOLLY, B_DRAWINFO, "Mouse Position Dolly", + (xpos+edgsp+mpref+(2*spref)+(3*midsp)),y4,mpref,buth, + &(U.uiflag), 0, 0, 0, 0, + "Dollying to the position of the mouse."); uiBlockEndAlign(block); uiDefBut(block, LABEL,0,"View rotation:", - (xpos+(2*edgsp)+mpref+(2*spref)+(2*midsp)),y4label,mpref,buth, + (xpos+(2*edgsp)+mpref+(2*spref)+(2*midsp)),y3label,mpref,buth, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); /* mutually exclusive toggles, start color */ uiDefButBitI(block, TOG, USER_TRACKBALL, B_DRAWINFO, "Trackball", - (xpos+edgsp+mpref+(2*spref)+(3*midsp)),y3,(mpref/2),buth, + (xpos+edgsp+mpref+(2*spref)+(3*midsp)),y2,(mpref/2),buth, &(U.flag), 0, 0, 0, 0, "Allow the view to tumble freely when orbiting with the Middle Mouse Button"); uiDefButBitI(block, TOGN, USER_TRACKBALL, B_DRAWINFO, "Turntable", - (xpos+edgsp+mpref+(2*spref)+(3*midsp)+(mpref/2)),y3,(mpref/2),buth, + (xpos+edgsp+mpref+(2*spref)+(3*midsp)+(mpref/2)),y2,(mpref/2),buth, &(U.flag), 0, 0, 0, 0, "Use fixed up axis for orbiting with Middle Mouse Button"); uiBlockSetCol(block, TH_AUTO); /* end color */ uiDefButBitI(block, TOG, USER_AUTOPERSP, B_DRAWINFO, "Auto Perspective", - (xpos+edgsp+mpref+(2*spref)+(3*midsp)),y2,(mpref/2),buth, + (xpos+edgsp+mpref+(2*spref)+(3*midsp)),y1,(mpref/2),buth, &(U.uiflag), 0, 0, 0, 0, "Automatically switch between orthographic and perspective when changing from top/front/side views"); uiDefButBitI(block, TOG, USER_ORBIT_SELECTION, B_DRAWINFO, "Around Selection", - (xpos+edgsp+mpref+(2*spref)+(3*midsp)+(mpref/2)),y2,(mpref/2),buth, + (xpos+edgsp+mpref+(2*spref)+(3*midsp)+(mpref/2)),y1,(mpref/2),buth, &(U.uiflag), 0, 0, 0, 0, "Use selection as the orbiting center"); uiBlockEndAlign(block); @@ -3344,15 +3348,15 @@ uiBlockBeginAlign(block); uiDefButBitI(block, TOG, USER_SHOW_ROTVIEWICON, B_DRAWINFO, "Mini Axis", - (xpos+edgsp+(2*mpref)+(2*midsp)),y1,(mpref/3),buth, + (xpos+edgsp+(5*mpref)+(6*midsp)),y1,(mpref/3),buth, &(U.uiflag), 0, 0, 0, 0, "Show a small rotating 3D axis in the bottom left corner of the 3D View"); uiDefButS(block, NUM, B_DRAWINFO, "Size:", - (xpos+edgsp+(2*mpref)+(2*midsp)+(mpref/3)),y1,(mpref/3),buth, + ((xpos+edgsp+(5*mpref)+(6*midsp))+(mpref/3)),y1,(mpref/3),buth, &U.rvisize, 10, 64, 0, 0, "The axis icon's size"); uiDefButS(block, NUM, B_DRAWINFO, "Bright:", - (xpos+edgsp+(2*mpref)+(2*midsp)+2*(mpref/3)),y1,(mpref/3),buth, + ((xpos+edgsp+(5*mpref)+(6*midsp))+2*(mpref/3)),y1,(mpref/3),buth, &U.rvibright, 0, 10, 0, 0, "The brightness of the icon"); uiBlockEndAlign(block); Index: source/blender/src/toets.c =================================================================== --- source/blender/src/toets.c (revision 10988) +++ source/blender/src/toets.c (working copy) @@ -149,6 +149,55 @@ G.vd->view= view; } +/*WARNING: no bounds check! */ +static void do_view_dolly(float dmfac) +{ + if(U.uiflag & USER_MOUSEPOSDOLLY) { + short mco[2]; + short vb[2]; + float dvec[3]; + float tvec[3]; + float tpos[3]; + float new_dist; + + getmouseco_areawin(mco); + + /* find the current window width and height */ + vb[0] = G.vd->area->winx; + vb[1] = G.vd->area->winy; + + tpos[0] = -G.vd->ofs[0]; + tpos[1] = -G.vd->ofs[1]; + tpos[2] = -G.vd->ofs[2]; + + /* Project cursor position into 3D space */ + initgrabz(tpos[0], tpos[1], tpos[2]); + window_to_3d(dvec, mco[0]-vb[0]/2, mco[1]-vb[1]/2); + + /* Calculate view target position for dolly */ + tvec[0] = -(tpos[0] + dvec[0]); + tvec[1] = -(tpos[1] + dvec[1]); + tvec[2] = -(tpos[2] + dvec[2]); + + /* Offset to target position and dolly */ + new_dist = G.vd->dist * dmfac; + smooth_view(G.vd, tvec, NULL, &new_dist, NULL); + + /* Calculate final offset */ + dvec[0] = tvec[0] + dvec[0] * dmfac; + dvec[1] = tvec[1] + dvec[1] * dmfac; + dvec[2] = tvec[2] + dvec[2] * dmfac; + + smooth_view(G.vd, dvec, NULL, NULL, NULL); + } else { + G.vd->dist*=dmfac; + } +} + +#define VIEW_DOLLY_OUT_FACTOR (1.15f) +#define VIEW_DOLLY_IN_FACTOR (1.0f/VIEW_DOLLY_OUT_FACTOR) + + void persptoetsen(unsigned short event) { static Object *oldcamera=0; @@ -243,15 +292,20 @@ if(G.vd->persp==2) { G.vd->camzoom= MAX2(-30, G.vd->camzoom-5); } - else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f; + else if(G.vd->dist<10.0*G.vd->far) { + do_view_dolly(VIEW_DOLLY_OUT_FACTOR); + } if(G.vd->persp!=1) preview3d_event= 0; } else if(event==PADPLUSKEY) { if(G.vd->persp==2) { G.vd->camzoom= MIN2(300, G.vd->camzoom+5); } - else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f; + else if(G.vd->dist> 0.001*G.vd->grid) { + do_view_dolly(VIEW_DOLLY_IN_FACTOR); + } if(G.vd->persp!=1) preview3d_event= 0; + } else if(event==PAD5) { if (U.smooth_viewtx) {