Multitouch trackpad 2 fingers gestures implementation
[blender-staging.git] / source / blender / editors / space_view3d / view3d_edit.c
index a7ea19e49f90f13b422ecf20f494fabbc7c05451..288918c3c1e9f0a39c2c2afe4597a6b5b7b4c8f2 100644 (file)
@@ -46,7 +46,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_rand.h"
 
 #include "BKE_action.h"
@@ -94,7 +94,7 @@ static void view3d_boxview_clip(ScrArea *sa)
        ARegion *ar;
        BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb");
        float clip[6][4];
-       float x1= 0.0f, y1= 0.0f, z1= 0.0f, ofs[3];
+       float x1= 0.0f, y1= 0.0f, z1= 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f};
        int val;
 
        /* create bounding box */
@@ -103,7 +103,7 @@ static void view3d_boxview_clip(ScrArea *sa)
                        RegionView3D *rv3d= ar->regiondata;
 
                        if(rv3d->viewlock & RV3D_BOXCLIP) {
-                               if(ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM)) {
+                               if(ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
                                        if(ar->winx>ar->winy) x1= rv3d->dist;
                                        else x1= ar->winx*rv3d->dist/ar->winy;
 
@@ -113,7 +113,7 @@ static void view3d_boxview_clip(ScrArea *sa)
                                        ofs[0]= rv3d->ofs[0];
                                        ofs[1]= rv3d->ofs[1];
                                }
-                               else if(ELEM(rv3d->view, V3D_VIEW_FRONT, V3D_VIEW_BACK)) {
+                               else if(ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
                                        ofs[2]= rv3d->ofs[2];
 
                                        if(ar->winx>ar->winy) z1= ar->winy*rv3d->dist/ar->winx;
@@ -141,12 +141,12 @@ static void view3d_boxview_clip(ScrArea *sa)
        }
 
        /* normals for plane equations */
-       CalcNormFloat(bb->vec[0], bb->vec[1], bb->vec[4], clip[0]);
-       CalcNormFloat(bb->vec[1], bb->vec[2], bb->vec[5], clip[1]);
-       CalcNormFloat(bb->vec[2], bb->vec[3], bb->vec[6], clip[2]);
-       CalcNormFloat(bb->vec[3], bb->vec[0], bb->vec[7], clip[3]);
-       CalcNormFloat(bb->vec[4], bb->vec[5], bb->vec[6], clip[4]);
-       CalcNormFloat(bb->vec[0], bb->vec[2], bb->vec[1], clip[5]);
+       normal_tri_v3( clip[0],bb->vec[0], bb->vec[1], bb->vec[4]);
+       normal_tri_v3( clip[1],bb->vec[1], bb->vec[2], bb->vec[5]);
+       normal_tri_v3( clip[2],bb->vec[2], bb->vec[3], bb->vec[6]);
+       normal_tri_v3( clip[3],bb->vec[3], bb->vec[0], bb->vec[7]);
+       normal_tri_v3( clip[4],bb->vec[4], bb->vec[5], bb->vec[6]);
+       normal_tri_v3( clip[5],bb->vec[0], bb->vec[2], bb->vec[1]);
 
        /* then plane equations */
        for(val=0; val<5; val++) {
@@ -181,22 +181,22 @@ static void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
                        if(rv3dtest->viewlock) {
                                rv3dtest->dist= rv3d->dist;
 
-                               if( ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM) ) {
-                                       if( ELEM(rv3dtest->view, V3D_VIEW_FRONT, V3D_VIEW_BACK))
+                               if( ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ) {
+                                       if( ELEM(rv3dtest->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK))
                                                rv3dtest->ofs[0]= rv3d->ofs[0];
-                                       else if( ELEM(rv3dtest->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT))
+                                       else if( ELEM(rv3dtest->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
                                                rv3dtest->ofs[1]= rv3d->ofs[1];
                                }
-                               else if( ELEM(rv3d->view, V3D_VIEW_FRONT, V3D_VIEW_BACK) ) {
-                                       if( ELEM(rv3dtest->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM))
+                               else if( ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK) ) {
+                                       if( ELEM(rv3dtest->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
                                                rv3dtest->ofs[0]= rv3d->ofs[0];
-                                       else if( ELEM(rv3dtest->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT))
+                                       else if( ELEM(rv3dtest->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
                                                rv3dtest->ofs[2]= rv3d->ofs[2];
                                }
-                               else if( ELEM(rv3d->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT) ) {
-                                       if( ELEM(rv3dtest->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM))
+                               else if( ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ) {
+                                       if( ELEM(rv3dtest->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
                                                rv3dtest->ofs[1]= rv3d->ofs[1];
-                                       if( ELEM(rv3dtest->view, V3D_VIEW_FRONT, V3D_VIEW_BACK))
+                                       if( ELEM(rv3dtest->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK))
                                                rv3dtest->ofs[2]= rv3d->ofs[2];
                                }
 
@@ -234,14 +234,22 @@ typedef struct ViewOpsData {
        ARegion *ar;
        RegionView3D *rv3d;
 
+       /* needed for continuous zoom */
+       wmTimer *timer;
+       double timer_lastdraw;
+
        float oldquat[4];
        float trackvec[3];
-       float ofs[3], obofs[3];
        float reverse, dist0;
        float grid, far;
+       short axis_snap; /* view rotate only */
+
+       /* use for orbit selection and auto-dist */
+       float ofs[3], dyn_ofs[3];
+       short use_dyn_ofs;
 
        int origx, origy, oldx, oldy;
-       int origkey;
+       int origkey; /* the key that triggered the operator */
 
 } ViewOpsData;
 
@@ -274,8 +282,9 @@ static void calctrackballvec(rcti *rect, int mx, int my, float *vec)
 }
 
 
-static void viewops_data(bContext *C, wmOperator *op, wmEvent *event)
+static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event)
 {
+       static float lastofs[3] = {0,0,0};
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d;
        ViewOpsData *vod= MEM_callocN(sizeof(ViewOpsData), "viewops data");
@@ -289,7 +298,58 @@ static void viewops_data(bContext *C, wmOperator *op, wmEvent *event)
        QUATCOPY(vod->oldquat, rv3d->viewquat);
        vod->origx= vod->oldx= event->x;
        vod->origy= vod->oldy= event->y;
-       vod->origkey= event->type;
+       vod->origkey= event->type; /* the key that triggered the operator.  */
+       vod->use_dyn_ofs= (U.uiflag & USER_ORBIT_SELECTION) ? 1:0;
+
+       if (vod->use_dyn_ofs) {
+               VECCOPY(vod->ofs, rv3d->ofs);
+               /* If there's no selection, lastofs is unmodified and last value since static */
+               calculateTransformCenter(C, V3D_CENTROID, lastofs);
+               VECCOPY(vod->dyn_ofs, lastofs);
+               mul_v3_fl(vod->dyn_ofs, -1.0f);
+       }
+       else if (U.uiflag & USER_ORBIT_ZBUF) {
+
+               view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
+
+               if((vod->use_dyn_ofs=view_autodist(CTX_data_scene(C), vod->ar, v3d, event->mval, vod->dyn_ofs))) {
+                       if (rv3d->persp==RV3D_PERSP) {
+                               float my_origin[3]; /* original G.vd->ofs */
+                               float my_pivot[3]; /* view */
+                               float dvec[3];
+
+                               // locals for dist correction
+                               float mat[3][3];
+                               float upvec[3];
+
+                               VECCOPY(my_origin, rv3d->ofs);
+                               negate_v3(my_origin);                           /* ofs is flipped */
+
+                               /* Set the dist value to be the distance from this 3d point */
+                               /* this means youll always be able to zoom into it and panning wont go bad when dist was zero */
+
+                               /* remove dist value */
+                               upvec[0] = upvec[1] = 0;
+                               upvec[2] = rv3d->dist;
+                               copy_m3_m4(mat, rv3d->viewinv);
+
+                               mul_m3_v3(mat, upvec);
+                               sub_v3_v3v3(my_pivot, rv3d->ofs, upvec);
+                               negate_v3(my_pivot);                            /* ofs is flipped */
+
+                               /* find a new ofs value that is allong the view axis (rather then the mouse location) */
+                               closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin);
+                               vod->dist0 = rv3d->dist = len_v3v3(my_pivot, dvec);
+
+                               negate_v3(dvec);
+                               VECCOPY(rv3d->ofs, dvec);
+                       }
+                       negate_v3(vod->dyn_ofs);
+                       VECCOPY(vod->ofs, rv3d->ofs);
+               } else {
+                       vod->ofs[0] = vod->ofs[1] = vod->ofs[2] = 0.0f;
+               }
+       }
 
        /* lookup, we dont pass on v3d to prevent confusement */
        vod->grid= v3d->grid;
@@ -303,6 +363,24 @@ static void viewops_data(bContext *C, wmOperator *op, wmEvent *event)
        if (rv3d->persmat[2][1] < 0.0f)
                vod->reverse= -1.0f;
 
+       rv3d->rflag |= RV3D_NAVIGATING;
+}
+
+static void viewops_data_free(bContext *C, wmOperator *op)
+{
+       Paint *p = paint_get_active(CTX_data_scene(C));
+       ViewOpsData *vod= op->customdata;
+
+       vod->rv3d->rflag &= ~RV3D_NAVIGATING;
+
+       if(p && (p->flags & PAINT_FAST_NAVIGATE))
+               ED_region_tag_redraw(vod->ar);
+
+       if(vod->timer)
+               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), vod->timer);
+
+       MEM_freeN(vod);
+       op->customdata= NULL;
 }
 
 /* ************************** viewrotate **********************************/
@@ -314,12 +392,12 @@ static const float thres = 0.93f; //cos(20 deg);
 
 static float snapquats[39][6] = {
        /*{q0, q1, q3, q4, view, oposite_direction}*/
-{COS45, -SIN45, 0.0, 0.0, V3D_VIEW_FRONT, 0},  //front
-{0.0, 0.0, -SIN45, -SIN45, V3D_VIEW_BACK, 0}, //back
-{1.0, 0.0, 0.0, 0.0, V3D_VIEW_TOP, 0},       //top
-{0.0, -1.0, 0.0, 0.0, V3D_VIEW_BOTTOM, 0},      //bottom
-{0.5, -0.5, -0.5, -0.5, V3D_VIEW_LEFT, 0},    //left
-{0.5, -0.5, 0.5, 0.5, V3D_VIEW_RIGHT, 0},      //right
+{COS45, -SIN45, 0.0, 0.0, RV3D_VIEW_FRONT, 0},  //front
+{0.0, 0.0, -SIN45, -SIN45, RV3D_VIEW_BACK, 0}, //back
+{1.0, 0.0, 0.0, 0.0, RV3D_VIEW_TOP, 0},       //top
+{0.0, -1.0, 0.0, 0.0, RV3D_VIEW_BOTTOM, 0},      //bottom
+{0.5, -0.5, -0.5, -0.5, RV3D_VIEW_LEFT, 0},    //left
+{0.5, -0.5, 0.5, 0.5, RV3D_VIEW_RIGHT, 0},      //right
 
        /* some more 45 deg snaps */
 {0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0},
@@ -357,11 +435,60 @@ static float snapquats[39][6] = {
 {0.0, 0.0, 0.0, 1.0, 0, 0}
 };
 
+enum {
+       VIEW_PASS= 0,
+       VIEW_APPLY,
+       VIEW_CONFIRM
+};
+
+/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
+#define VIEW_MODAL_CONFIRM                             1 /* used for all view operations */
+#define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2
+#define VIEWROT_MODAL_AXIS_SNAP_DISABLE        3
+#define VIEWROT_MODAL_SWITCH_ZOOM              4
+#define VIEWROT_MODAL_SWITCH_MOVE              5
+#define VIEWROT_MODAL_SWITCH_ROTATE            6
+
+/* called in transform_ops.c, on each regeneration of keymaps  */
+void viewrotate_modal_keymap(wmKeyConfig *keyconf)
+{
+       static EnumPropertyItem modal_items[] = {
+       {VIEW_MODAL_CONFIRM,    "CONFIRM", 0, "Cancel", ""},
+
+       {VIEWROT_MODAL_AXIS_SNAP_ENABLE,        "AXIS_SNAP_ENABLE", 0, "Enable Axis Snap", ""},
+       {VIEWROT_MODAL_AXIS_SNAP_DISABLE,       "AXIS_SNAP_DISABLE", 0, "Disable Axis Snap", ""},
+               
+       {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
+       {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+
+       {0, NULL, 0, NULL, NULL}};
+
+       wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Rotate Modal");
+
+       /* this function is called for each spacetype, only needs to add map once */
+       if(keymap) return;
+
+       keymap= WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items);
+
+       /* items for modal map */
+       WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+       WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+
+       WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_ENABLE);
+       WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_DISABLE);
+
+       WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+       WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+       
+       /* assign map to operators */
+       WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
+
+}
 
-static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
+static void viewrotate_apply(ViewOpsData *vod, int x, int y)
 {
        RegionView3D *rv3d= vod->rv3d;
-       int use_sel= 0; /* XXX */
 
        rv3d->view= 0; /* need to reset everytime because of view snapping */
 
@@ -370,13 +497,13 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
 
                calctrackballvec(&vod->ar->winrct, x, y, newvec);
 
-               VecSubf(dvec, newvec, vod->trackvec);
+               sub_v3_v3v3(dvec, newvec, vod->trackvec);
 
                si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]);
                si/= (2.0*TRACKBALLSIZE);
 
-               Crossf(q1+1, vod->trackvec, newvec);
-               Normalize(q1+1);
+               cross_v3_v3v3(q1+1, vod->trackvec, newvec);
+               normalize_v3(q1+1);
 
                /* Allow for rotation beyond the interval
                        * [-pi, pi] */
@@ -395,19 +522,19 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
                q1[1]*= si;
                q1[2]*= si;
                q1[3]*= si;
-               QuatMul(rv3d->viewquat, q1, vod->oldquat);
+               mul_qt_qtqt(rv3d->viewquat, q1, vod->oldquat);
 
-               if (use_sel) {
+               if (vod->use_dyn_ofs) {
                        /* compute the post multiplication quat, to rotate the offset correctly */
                        QUATCOPY(q1, vod->oldquat);
-                       QuatConj(q1);
-                       QuatMul(q1, q1, rv3d->viewquat);
+                       conjugate_qt(q1);
+                       mul_qt_qtqt(q1, q1, rv3d->viewquat);
 
-                       QuatConj(q1); /* conj == inv for unit quat */
+                       conjugate_qt(q1); /* conj == inv for unit quat */
                        VECCOPY(rv3d->ofs, vod->ofs);
-                       VecSubf(rv3d->ofs, rv3d->ofs, vod->obofs);
-                       QuatMulVecf(q1, rv3d->ofs);
-                       VecAddf(rv3d->ofs, rv3d->ofs, vod->obofs);
+                       sub_v3_v3v3(rv3d->ofs, rv3d->ofs, vod->dyn_ofs);
+                       mul_qt_v3(q1, rv3d->ofs);
+                       add_v3_v3v3(rv3d->ofs, rv3d->ofs, vod->dyn_ofs);
                }
        }
        else {
@@ -423,12 +550,12 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
                const float sensitivity = 0.0035;
 
                /* Get the 3x3 matrix and its inverse from the quaternion */
-               QuatToMat3(rv3d->viewquat, m);
-               Mat3Inv(m_inv,m);
+               quat_to_mat3( m,rv3d->viewquat);
+               invert_m3_m3(m_inv,m);
 
                /* Determine the direction of the x vector (for rotating up and down) */
-               /* This can likely be compuated directly from the quaternion. */
-               Mat3MulVecfl(m_inv,xvec);
+               /* This can likely be computed directly from the quaternion. */
+               mul_m3_v3(m_inv,xvec);
 
                /* Perform the up/down rotation */
                phi = sensitivity * -(y - vod->oldy);
@@ -437,13 +564,13 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
                q1[1] = si * xvec[0];
                q1[2] = si * xvec[1];
                q1[3] = si * xvec[2];
-               QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+               mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
 
-               if (use_sel) {
-                       QuatConj(q1); /* conj == inv for unit quat */
-                       VecSubf(rv3d->ofs, rv3d->ofs, vod->obofs);
-                       QuatMulVecf(q1, rv3d->ofs);
-                       VecAddf(rv3d->ofs, rv3d->ofs, vod->obofs);
+               if (vod->use_dyn_ofs) {
+                       conjugate_qt(q1); /* conj == inv for unit quat */
+                       sub_v3_v3v3(rv3d->ofs, rv3d->ofs, vod->dyn_ofs);
+                       mul_qt_v3(q1, rv3d->ofs);
+                       add_v3_v3v3(rv3d->ofs, rv3d->ofs, vod->dyn_ofs);
                }
 
                /* Perform the orbital rotation */
@@ -451,33 +578,33 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
                q1[0] = cos(phi);
                q1[1] = q1[2] = 0.0;
                q1[3] = sin(phi);
-               QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+               mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
 
-               if (use_sel) {
-                       QuatConj(q1);
-                       VecSubf(rv3d->ofs, rv3d->ofs, vod->obofs);
-                       QuatMulVecf(q1, rv3d->ofs);
-                       VecAddf(rv3d->ofs, rv3d->ofs, vod->obofs);
+               if (vod->use_dyn_ofs) {
+                       conjugate_qt(q1);
+                       sub_v3_v3v3(rv3d->ofs, rv3d->ofs, vod->dyn_ofs);
+                       mul_qt_v3(q1, rv3d->ofs);
+                       add_v3_v3v3(rv3d->ofs, rv3d->ofs, vod->dyn_ofs);
                }
        }
 
        /* check for view snap */
-       if (ctrl){
+       if (vod->axis_snap){
                int i;
                float viewmat[3][3];
 
 
-               QuatToMat3(rv3d->viewquat, viewmat);
+               quat_to_mat3( viewmat,rv3d->viewquat);
 
                for (i = 0 ; i < 39; i++){
                        float snapmat[3][3];
                        float view = (int)snapquats[i][4];
 
-                       QuatToMat3(snapquats[i], snapmat);
+                       quat_to_mat3( snapmat,snapquats[i]);
 
-                       if ((Inpf(snapmat[0], viewmat[0]) > thres) &&
-                               (Inpf(snapmat[1], viewmat[1]) > thres) &&
-                               (Inpf(snapmat[2], viewmat[2]) > thres)){
+                       if ((dot_v3v3(snapmat[0], viewmat[0]) > thres) &&
+                               (dot_v3v3(snapmat[1], viewmat[1]) > thres) &&
+                               (dot_v3v3(snapmat[2], viewmat[2]) > thres)){
 
                                QUATCOPY(rv3d->viewquat, snapquats[i]);
 
@@ -496,23 +623,47 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
 static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
        ViewOpsData *vod= op->customdata;
+       short event_code= VIEW_PASS;
 
        /* execute the events */
-       switch(event->type) {
-               case MOUSEMOVE:
-                       viewrotate_apply(vod, event->x, event->y, event->ctrl);
-                       break;
-
-               default:
-                       /* origkey may be zero when invoked from a button */
-                       if(ELEM3(event->type, ESCKEY, LEFTMOUSE, RIGHTMOUSE) || (event->type==vod->origkey && event->val==0)) {
-                               request_depth_update(CTX_wm_region_view3d(C));
+       if(event->type==MOUSEMOVE) {
+               event_code= VIEW_APPLY;
+       }
+       else if(event->type==EVT_MODAL_MAP) {
+               switch (event->val) {
+                       case VIEW_MODAL_CONFIRM:
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_AXIS_SNAP_ENABLE:
+                               vod->axis_snap= TRUE;
+                               event_code= VIEW_APPLY;
+                               break;
+                       case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
+                               vod->axis_snap= FALSE;
+                               event_code= VIEW_APPLY;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_ZOOM:
+                               WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_MOVE:
+                               WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+               }
+       }
+       else if(event->type==vod->origkey && event->val==KM_RELEASE) {
+               event_code= VIEW_CONFIRM;
+       }
 
-                               MEM_freeN(vod);
-                               op->customdata= NULL;
+       if(event_code==VIEW_APPLY) {
+               viewrotate_apply(vod, event->x, event->y);
+       }
+       else if (event_code==VIEW_CONFIRM) {
+               request_depth_update(CTX_wm_region_view3d(C));
+               viewops_data_free(C, op);
 
-                               return OPERATOR_FINISHED;
-                       }
+               return OPERATOR_FINISHED;
        }
 
        return OPERATOR_RUNNING_MODAL;
@@ -527,48 +678,112 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
                return OPERATOR_CANCELLED;
 
        /* makes op->customdata */
-       viewops_data(C, op, event);
+       viewops_data_create(C, op, event);
        vod= op->customdata;
 
        /* switch from camera view when: */
-       if(vod->rv3d->persp != V3D_PERSP) {
+       if(vod->rv3d->persp != RV3D_PERSP) {
 
                if (U.uiflag & USER_AUTOPERSP)
-                       vod->rv3d->persp= V3D_PERSP;
-               else if(vod->rv3d->persp==V3D_CAMOB)
-                       vod->rv3d->persp= V3D_PERSP;
+                       vod->rv3d->persp= RV3D_PERSP;
+               else if(vod->rv3d->persp==RV3D_CAMOB)
+                       vod->rv3d->persp= RV3D_PERSP;
                ED_region_tag_redraw(vod->ar);
        }
+       
+       if (event->type == MOUSEPAN) {
+               viewrotate_apply(vod, event->prevx, event->prevy);
+               request_depth_update(CTX_wm_region_view3d(C));
+               
+               viewops_data_free(C, op);
+               
+               return OPERATOR_FINISHED;
+       }
+       else if (event->type == MOUSEROTATE) {
+               /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
+               viewrotate_apply(vod, event->prevx, event->y);
+               request_depth_update(CTX_wm_region_view3d(C));
+               
+               viewops_data_free(C, op);
+               
+               return OPERATOR_FINISHED;
+       }
+       else {          
+               /* add temp handler */
+               WM_event_add_modal_handler(C, op);
 
-       /* add temp handler */
-       WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
-
-       return OPERATOR_RUNNING_MODAL;
+               return OPERATOR_RUNNING_MODAL;
+       }
 }
 
+static int ED_operator_view3d_rotate(bContext *C)
+{
+       if (!ED_operator_view3d_active(C)) {
+               return 0;
+       } else {
+               RegionView3D *rv3d= CTX_wm_region_view3d(C);
+               /* rv3d is null in menus, but it's ok when the menu is clicked on */
+               /* XXX of course, this doesn't work with quadview
+                * Maybe having exec return PASSTHROUGH would be better than polling here
+                * Poll functions are full of problems anyway.
+                * */
+               return rv3d == NULL || rv3d->viewlock == 0;
+       }
+}
 
-void VIEW3D_OT_viewrotate(wmOperatorType *ot)
+void VIEW3D_OT_rotate(wmOperatorType *ot)
 {
 
        /* identifiers */
        ot->name= "Rotate view";
        ot->description = "Rotate the view.";
-       ot->idname= "VIEW3D_OT_viewrotate";
+       ot->idname= "VIEW3D_OT_rotate";
 
        /* api callbacks */
        ot->invoke= viewrotate_invoke;
        ot->modal= viewrotate_modal;
-       ot->poll= ED_operator_view3d_active;
+       ot->poll= ED_operator_view3d_rotate;
 
        /* flags */
-       ot->flag= OPTYPE_BLOCKING;
+       ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
 }
 
 /* ************************ viewmove ******************************** */
 
+
+/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
+
+/* called in transform_ops.c, on each regeneration of keymaps  */
+void viewmove_modal_keymap(wmKeyConfig *keyconf)
+{
+       static EnumPropertyItem modal_items[] = {
+       {VIEW_MODAL_CONFIRM,    "CONFIRM", 0, "Confirm", ""},
+
+       {0, NULL, 0, NULL, NULL}};
+
+       wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Move Modal");
+
+       /* this function is called for each spacetype, only needs to add map once */
+       if(keymap) return;
+
+       keymap= WM_modalkeymap_add(keyconf, "View3D Move Modal", modal_items);
+
+       /* items for modal map */
+       WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+       WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+
+       WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+       WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+       
+       /* assign map to operators */
+       WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
+}
+
+
 static void viewmove_apply(ViewOpsData *vod, int x, int y)
 {
-       if(vod->rv3d->persp==V3D_CAMOB) {
+       if(vod->rv3d->persp==RV3D_CAMOB) {
                float max= (float)MAX2(vod->ar->winx, vod->ar->winy);
 
                vod->rv3d->camdx += (vod->oldx - x)/(max);
@@ -581,7 +796,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
                float dvec[3];
 
                window_to_3d_delta(vod->ar, dvec, x-vod->oldx, y-vod->oldy);
-               VecAddf(vod->rv3d->ofs, vod->rv3d->ofs, dvec);
+               add_v3_v3v3(vod->rv3d->ofs, vod->rv3d->ofs, dvec);
 
                if(vod->rv3d->viewlock & RV3D_BOXVIEW)
                        view3d_boxview_sync(vod->sa, vod->ar);
@@ -596,24 +811,42 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
 
 static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
+
        ViewOpsData *vod= op->customdata;
+       short event_code= VIEW_PASS;
 
        /* execute the events */
-       switch(event->type) {
-               case MOUSEMOVE:
-                       viewmove_apply(vod, event->x, event->y);
-                       break;
+       if(event->type==MOUSEMOVE) {
+               event_code= VIEW_APPLY;
+       }
+       else if(event->type==EVT_MODAL_MAP) {
+               switch (event->val) {
+                       case VIEW_MODAL_CONFIRM:
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_ZOOM:
+                               WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_ROTATE:
+                               WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+               }
+       }
+       else if(event->type==vod->origkey && event->val==KM_RELEASE) {
+               event_code= VIEW_CONFIRM;
+       }
 
-               default:
-                       /* origkey may be zero when invoked from a button */
-                       if(ELEM3(event->type, ESCKEY, LEFTMOUSE, RIGHTMOUSE) || (event->type==vod->origkey && event->val==0)) {
-                               request_depth_update(CTX_wm_region_view3d(C));
+       if(event_code==VIEW_APPLY) {
+               viewmove_apply(vod, event->x, event->y);
+       }
+       else if (event_code==VIEW_CONFIRM) {
+               request_depth_update(CTX_wm_region_view3d(C));
 
-                               MEM_freeN(vod);
-                               op->customdata= NULL;
+               viewops_data_free(C, op);
 
-                               return OPERATOR_FINISHED;
-                       }
+               return OPERATOR_FINISHED;
        }
 
        return OPERATOR_RUNNING_MODAL;
@@ -622,22 +855,32 @@ static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
 static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        /* makes op->customdata */
-       viewops_data(C, op, event);
-
-       /* add temp handler */
-       WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+       viewops_data_create(C, op, event);
+
+       if (event->type == MOUSEPAN) {
+               ViewOpsData *vod= op->customdata;
+               viewmove_apply(vod, event->prevx, event->prevy);
+               request_depth_update(CTX_wm_region_view3d(C));
+               
+               viewops_data_free(C, op);               
+               
+               return OPERATOR_FINISHED;
+       }
+       else {
+               /* add temp handler */
+               WM_event_add_modal_handler(C, op);
 
-       return OPERATOR_RUNNING_MODAL;
+               return OPERATOR_RUNNING_MODAL;
+       }
 }
 
-
-void VIEW3D_OT_viewmove(wmOperatorType *ot)
+void VIEW3D_OT_move(wmOperatorType *ot)
 {
 
        /* identifiers */
        ot->name= "Move view";
        ot->description = "Move the view.";
-       ot->idname= "VIEW3D_OT_viewmove";
+       ot->idname= "VIEW3D_OT_move";
 
        /* api callbacks */
        ot->invoke= viewmove_invoke;
@@ -645,11 +888,38 @@ void VIEW3D_OT_viewmove(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_BLOCKING;
+       ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
 }
 
 /* ************************ viewzoom ******************************** */
 
+/* called in transform_ops.c, on each regeneration of keymaps  */
+void viewzoom_modal_keymap(wmKeyConfig *keyconf)
+{
+       static EnumPropertyItem modal_items[] = {
+       {VIEW_MODAL_CONFIRM,    "CONFIRM", 0, "Confirm", ""},
+
+       {0, NULL, 0, NULL, NULL}};
+
+       wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Zoom Modal");
+
+       /* this function is called for each spacetype, only needs to add map once */
+       if(keymap) return;
+
+       keymap= WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items);
+
+       /* items for modal map */
+       WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+       WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+
+       WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+       WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+       
+       /* assign map to operators */
+       WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
+}
+
 static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
 {
        RegionView3D *rv3d= ar->regiondata;
@@ -699,15 +969,19 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
 }
 
 
-static void viewzoom_apply(ViewOpsData *vod, int x, int y)
+static void viewzoom_apply(ViewOpsData *vod, int x, int y, short viewzoom)
 {
        float zfac=1.0;
 
-       if(U.viewzoom==USER_ZOOM_CONT) {
+       if(viewzoom==USER_ZOOM_CONT) {
+               double time= PIL_check_seconds_timer();
+               float time_step= (float)(time - vod->timer_lastdraw);
+
                // oldstyle zoom
-               zfac = 1.0+(float)(vod->origx - x + vod->origy - y)/1000.0;
+               zfac = 1.0f + (((float)(vod->origx - x + vod->origy - y)/20.0) * time_step);
+               vod->timer_lastdraw= time;
        }
-       else if(U.viewzoom==USER_ZOOM_SCALE) {
+       else if(viewzoom==USER_ZOOM_SCALE) {
                int ctr[2], len1, len2;
                // method which zooms based on how far you move the mouse
 
@@ -720,8 +994,19 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y)
                zfac = vod->dist0 * ((float)len2/len1) / vod->rv3d->dist;
        }
        else {  /* USER_ZOOM_DOLLY */
-               float len1 = (vod->ar->winrct.ymax - y) + 5;
-               float len2 = (vod->ar->winrct.ymax - vod->origy) + 5;
+               float len1, len2;
+               
+               if (U.uiflag & USER_ZOOM_DOLLY_HORIZ) {
+                       len1 = (vod->ar->winrct.xmax - x) + 5;
+                       len2 = (vod->ar->winrct.xmax - vod->origx) + 5;
+               }
+               else {
+                       len1 = (vod->ar->winrct.ymax - y) + 5;
+                       len2 = (vod->ar->winrct.ymax - vod->origy) + 5;
+               }
+               if (U.uiflag & USER_ZOOM_INVERT)
+                       SWAP(float, len1, len2);
+               
                zfac = vod->dist0 * (2.0*((len2/len1)-1.0) + 1.0) / vod->rv3d->dist;
        }
 
@@ -730,23 +1015,23 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y)
                view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy);
 
 
-       if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (vod->rv3d->persp==V3D_PERSP)) {
+       if ((U.uiflag & USER_ORBIT_ZBUF) && (viewzoom==USER_ZOOM_CONT) && (vod->rv3d->persp==RV3D_PERSP)) {
                float upvec[3], mat[3][3];
 
                /* Secret apricot feature, translate the view when in continues mode */
                upvec[0] = upvec[1] = 0.0f;
                upvec[2] = (vod->dist0 - vod->rv3d->dist) * vod->grid;
                vod->rv3d->dist = vod->dist0;
-               Mat3CpyMat4(mat, vod->rv3d->viewinv);
-               Mat3MulVecfl(mat, upvec);
-               VecAddf(vod->rv3d->ofs, vod->rv3d->ofs, upvec);
+               copy_m3_m4(mat, vod->rv3d->viewinv);
+               mul_m3_v3(mat, upvec);
+               add_v3_v3v3(vod->rv3d->ofs, vod->rv3d->ofs, upvec);
        } else {
                /* these limits were in old code too */
                if(vod->rv3d->dist<0.001*vod->grid) vod->rv3d->dist= 0.001*vod->grid;
                if(vod->rv3d->dist>10.0*vod->far) vod->rv3d->dist=10.0*vod->far;
        }
 
-// XXX if(vod->rv3d->persp==V3D_ORTHO || vod->rv3d->persp==V3D_CAMOB) preview3d_event= 0;
+// XXX if(vod->rv3d->persp==RV3D_ORTHO || vod->rv3d->persp==RV3D_CAMOB) preview3d_event= 0;
 
        if(vod->rv3d->viewlock & RV3D_BOXVIEW)
                view3d_boxview_sync(vod->sa, vod->ar);
@@ -758,23 +1043,42 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y)
 static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
        ViewOpsData *vod= op->customdata;
+       short event_code= VIEW_PASS;
 
        /* execute the events */
-       switch(event->type) {
-               case MOUSEMOVE:
-                       viewzoom_apply(vod, event->x, event->y);
-                       break;
-
-               default:
-                       /* origkey may be zero when invoked from a button */
-                       if(ELEM3(event->type, ESCKEY, LEFTMOUSE, RIGHTMOUSE) || (event->type==vod->origkey && event->val==0)) {
-                               request_depth_update(CTX_wm_region_view3d(C));
+       if (event->type == TIMER && event->customdata == vod->timer) {
+               event_code= VIEW_APPLY;
+       }
+       else if(event->type==MOUSEMOVE) {
+               event_code= VIEW_APPLY;
+       }
+       else if(event->type==EVT_MODAL_MAP) {
+               switch (event->val) {
+                       case VIEW_MODAL_CONFIRM:
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_MOVE:
+                               WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_ROTATE:
+                               WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+               }
+       }
+       else if(event->type==vod->origkey && event->val==KM_RELEASE) {
+               event_code= VIEW_CONFIRM;
+       }
 
-                               MEM_freeN(vod);
-                               op->customdata= NULL;
+       if(event_code==VIEW_APPLY) {
+               viewzoom_apply(vod, event->x, event->y, U.viewzoom);
+       }
+       else if (event_code==VIEW_CONFIRM) {
+               request_depth_update(CTX_wm_region_view3d(C));
+               viewops_data_free(C, op);
 
-                               return OPERATOR_FINISHED;
-                       }
+               return OPERATOR_FINISHED;
        }
 
        return OPERATOR_RUNNING_MODAL;
@@ -785,21 +1089,27 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
        int delta= RNA_int_get(op->ptr, "delta");
+       int mx = RNA_int_get(op->ptr, "mx");
+       int my = RNA_int_get(op->ptr, "my");
 
        if(delta < 0) {
                /* this min and max is also in viewmove() */
-               if(rv3d->persp==V3D_CAMOB) {
+               if(rv3d->persp==RV3D_CAMOB) {
                        rv3d->camzoom-= 10;
                        if(rv3d->camzoom<-30) rv3d->camzoom= -30;
                }
-               else if(rv3d->dist<10.0*v3d->far) rv3d->dist*=1.2f;
+               else if(rv3d->dist<10.0*v3d->far) {
+                       view_zoom_mouseloc(CTX_wm_region(C), 1.2f, mx, my);
+               }
        }
        else {
-               if(rv3d->persp==V3D_CAMOB) {
+               if(rv3d->persp==RV3D_CAMOB) {
                        rv3d->camzoom+= 10;
                        if(rv3d->camzoom>300) rv3d->camzoom= 300;
                }
-               else if(rv3d->dist> 0.001*v3d->grid) rv3d->dist*=.83333f;
+               else if(rv3d->dist> 0.001*v3d->grid) {
+                       view_zoom_mouseloc(CTX_wm_region(C), .83333f, mx, my);
+               }
        }
 
        if(rv3d->viewlock & RV3D_BOXVIEW)
@@ -814,18 +1124,53 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
 static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        int delta= RNA_int_get(op->ptr, "delta");
+       
+       /* if one or the other zoom position aren't set, set from event */
+       if (!RNA_property_is_set(op->ptr, "mx") || !RNA_property_is_set(op->ptr, "my"))
+       {
+               RNA_int_set(op->ptr, "mx", event->x);
+               RNA_int_set(op->ptr, "my", event->y);
+       }
 
        if(delta) {
                viewzoom_exec(C, op);
        }
        else {
+               ViewOpsData *vod;
+
                /* makes op->customdata */
-               viewops_data(C, op, event);
+               viewops_data_create(C, op, event);
 
-               /* add temp handler */
-               WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+               vod= op->customdata;
 
-               return OPERATOR_RUNNING_MODAL;
+               if (event->type == MOUSEZOOM) {
+                       if (U.uiflag & USER_ZOOM_INVERT) /* Bypass Zoom invert flag */
+                               SWAP(int, event->x, event->prevx);
+
+                       if (U.uiflag & USER_ZOOM_DOLLY_HORIZ) {
+                               vod->origx = vod->oldx = event->x;
+                               viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY);
+                       }
+                       else {
+                               
+                               /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
+                               vod->origy = vod->oldy = event->x;
+                               viewzoom_apply(vod, event->x, event->prevx, USER_ZOOM_DOLLY);
+                       }
+                       request_depth_update(CTX_wm_region_view3d(C));
+                       
+                       viewops_data_free(C, op);
+                       return OPERATOR_FINISHED;
+               }
+               else {
+                       vod->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+                       vod->timer_lastdraw= PIL_check_seconds_timer();
+
+                       /* add temp handler */
+                       WM_event_add_modal_handler(C, op);
+
+                       return OPERATOR_RUNNING_MODAL;
+               }
        }
        return OPERATOR_FINISHED;
 }
@@ -845,9 +1190,11 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_BLOCKING;
+       ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
 
        RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
+       RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX);
 }
 
 static int viewhome_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.4x */
@@ -906,8 +1253,8 @@ static int viewhome_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.
                        new_dist*= size;
                }
 
-               if (rv3d->persp==V3D_CAMOB) {
-                       rv3d->persp= V3D_PERSP;
+               if (rv3d->persp==RV3D_CAMOB) {
+                       rv3d->persp= RV3D_PERSP;
                        smooth_view(C, NULL, v3d->camera, new_ofs, NULL, &new_dist, NULL);
                }
         else {
@@ -925,7 +1272,7 @@ static int viewhome_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.
 void VIEW3D_OT_view_all(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "View home";
+       ot->name= "View All";
        ot->description = "View all objects in scene.";
        ot->idname= "VIEW3D_OT_view_all";
 
@@ -986,10 +1333,10 @@ static int viewcenter_exec(bContext *C, wmOperator *op) /* like a localview with
                                        if(pchan->bone->layer & arm->layer) {
                                                ok= 1;
                                                VECCOPY(vec, pchan->pose_head);
-                                               Mat4MulVecfl(ob->obmat, vec);
+                                               mul_m4_v3(ob->obmat, vec);
                                                DO_MINMAX(vec, min, max);
                                                VECCOPY(vec, pchan->pose_tail);
-                                               Mat4MulVecfl(ob->obmat, vec);
+                                               mul_m4_v3(ob->obmat, vec);
                                                DO_MINMAX(vec, min, max);
                                        }
                                }
@@ -1023,7 +1370,7 @@ static int viewcenter_exec(bContext *C, wmOperator *op) /* like a localview with
        afm[2]= (max[2]-min[2]);
        size= MAX3(afm[0], afm[1], afm[2]);
        /* perspective should be a bit farther away to look nice */
-       if(rv3d->persp==V3D_ORTHO)
+       if(rv3d->persp==RV3D_ORTHO)
                size*= 0.7;
 
        if(size <= v3d->near*1.5f) size= v3d->near*1.5f;
@@ -1041,12 +1388,8 @@ static int viewcenter_exec(bContext *C, wmOperator *op) /* like a localview with
                new_dist*= size;
        }
 
-       v3d->cursor[0]= -new_ofs[0];
-       v3d->cursor[1]= -new_ofs[1];
-       v3d->cursor[2]= -new_ofs[2];
-
-       if (rv3d->persp==V3D_CAMOB) {
-               rv3d->persp= V3D_PERSP;
+       if (rv3d->persp==RV3D_CAMOB) {
+               rv3d->persp= RV3D_PERSP;
                smooth_view(C, v3d->camera, NULL, new_ofs, NULL, &new_dist, NULL);
        }
        else {
@@ -1064,7 +1407,7 @@ void VIEW3D_OT_view_center(wmOperatorType *ot)
 {
 
        /* identifiers */
-       ot->name= "View center";
+       ot->name= "View Selected";
        ot->description = "Move the view to the selection center.";
        ot->idname= "VIEW3D_OT_view_center";
 
@@ -1076,6 +1419,51 @@ void VIEW3D_OT_view_center(wmOperatorType *ot)
        ot->flag= 0;
 }
 
+static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
+{
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       Scene *scene= CTX_data_scene(C);
+       
+       if (rv3d) {
+               if (rv3d->persp==RV3D_CAMOB) {
+                       /* center the camera offset */
+                       rv3d->camdx= rv3d->camdy= 0.0;
+               }
+               else {
+                       /* non camera center */
+                       float *curs= give_cursor(scene, v3d);
+                       float new_ofs[3];
+                       
+                       new_ofs[0]= -curs[0];
+                       new_ofs[1]= -curs[1];
+                       new_ofs[2]= -curs[2];
+                       
+                       smooth_view(C, NULL, NULL, new_ofs, NULL, NULL, NULL);
+               }
+               
+               if (rv3d->viewlock & RV3D_BOXVIEW)
+                       view3d_boxview_copy(CTX_wm_area(C), CTX_wm_region(C));
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Center View to Cursor";
+       ot->description= "Centers the view so that the cursor is in the middle of the view.";
+       ot->idname= "VIEW3D_OT_view_center_cursor";
+       
+       /* api callbacks */
+       ot->exec= viewcenter_cursor_exec;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= 0;
+}
+
 /* ********************* Set render border operator ****************** */
 
 static int render_border_exec(bContext *C, wmOperator *op)
@@ -1118,6 +1506,8 @@ static int render_border_exec(bContext *C, wmOperator *op)
        } else {
                scene->r.mode |= R_BORDER;
        }
+       
+       WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, NULL);
 
        return OPERATOR_FINISHED;
 
@@ -1128,7 +1518,7 @@ static int view3d_render_border_invoke(bContext *C, wmOperator *op, wmEvent *eve
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
 
        /* if not in camera view do not exec the operator*/
-       if (rv3d->persp == V3D_CAMOB) return WM_border_select_invoke(C, op, event);
+       if (rv3d->persp == RV3D_CAMOB) return WM_border_select_invoke(C, op, event);
        else return OPERATOR_PASS_THROUGH;
 }
 
@@ -1175,7 +1565,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
 
        /* ZBuffer depth vars */
        bglMats mats;
-       float depth, depth_close= MAXFLOAT;
+       float depth, depth_close= FLT_MAX;
        int had_depth = 0;
        double cent[2],  p[3];
        int xs, ys;
@@ -1228,11 +1618,11 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
        cent[0] = (((double)rect.xmin)+((double)rect.xmax)) / 2;
        cent[1] = (((double)rect.ymin)+((double)rect.ymax)) / 2;
 
-       if (rv3d->persp==V3D_PERSP) {
+       if (rv3d->persp==RV3D_PERSP) {
                double p_corner[3];
 
                /* no depths to use, we cant do anything! */
-               if (depth_close==MAXFLOAT){
+               if (depth_close==FLT_MAX){
                        BKE_report(op->reports, RPT_ERROR, "Depth Too Large");
                        return OPERATOR_CANCELLED;
                }
@@ -1245,7 +1635,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
                dvec[1] = p[1]-p_corner[1];
                dvec[2] = p[2]-p_corner[2];
 
-               new_dist = VecLength(dvec);
+               new_dist = len_v3(dvec);
                if(new_dist <= v3d->near*1.5) new_dist= v3d->near*1.5;
 
                new_ofs[0] = -p[0];
@@ -1260,7 +1650,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
                new_dist = rv3d->dist;
 
                /* convert the drawn rectangle into 3d space */
-               if (depth_close!=MAXFLOAT && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) {
+               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])) {
                        new_ofs[0] = -p[0];
                        new_ofs[1] = -p[1];
                        new_ofs[2] = -p[2];
@@ -1274,7 +1664,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
 
                        window_to_3d_delta(ar, dvec, (rect.xmin+rect.xmax-vb[0])/2, (rect.ymin+rect.ymax-vb[1])/2);
                        /* center the view to the center of the rectangle */
-                       VecSubf(new_ofs, new_ofs, dvec);
+                       sub_v3_v3v3(new_ofs, new_ofs, dvec);
                }
 
                /* work out the ratios, so that everything selected fits when we zoom */
@@ -1299,7 +1689,7 @@ static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, wmEvent *event
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
 
        /* if in camera view do not exec the operator so we do not conflict with set render border*/
-       if (rv3d->persp != V3D_CAMOB)
+       if (rv3d->persp != RV3D_CAMOB)
                return WM_border_select_invoke(C, op, event);
        else
                return OPERATOR_PASS_THROUGH;
@@ -1333,53 +1723,81 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
 /* ********************* Changing view operator ****************** */
 
 static EnumPropertyItem prop_view_items[] = {
-       {V3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"},
-       {V3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"},
-       {V3D_VIEW_LEFT, "LEFT", 0, "Left", "View From the Left"},
-       {V3D_VIEW_RIGHT, "RIGHT", 0, "Right", "View From the Right"},
-       {V3D_VIEW_TOP, "TOP", 0, "Top", "View From the Top"},
-       {V3D_VIEW_BOTTOM, "BOTTOM", 0, "Bottom", "View From the Bottom"},
-       {V3D_VIEW_CAMERA, "CAMERA", 0, "Camera", "View From the active amera"},
+       {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"},
+       {RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"},
+       {RV3D_VIEW_LEFT, "LEFT", 0, "Left", "View From the Left"},
+       {RV3D_VIEW_RIGHT, "RIGHT", 0, "Right", "View From the Right"},
+       {RV3D_VIEW_TOP, "TOP", 0, "Top", "View From the Top"},
+       {RV3D_VIEW_BOTTOM, "BOTTOM", 0, "Bottom", "View From the Bottom"},
+       {RV3D_VIEW_CAMERA, "CAMERA", 0, "Camera", "View From the active amera"},
        {0, NULL, 0, NULL, NULL}};
 
-static void axis_set_view(bContext *C, float q1, float q2, float q3, float q4, short view, int perspo)
+
+/* would like to make this a generic function - outside of transform */
+
+static void axis_set_view(bContext *C, float q1, float q2, float q3, float q4, short view, int perspo, int align_active)
 {
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
        float new_quat[4];
 
-       if(rv3d->viewlock) {
-               /* only pass on if */
-               if(rv3d->view==V3D_VIEW_FRONT && view==V3D_VIEW_BACK);
-               else if(rv3d->view==V3D_VIEW_BACK && view==V3D_VIEW_FRONT);
-               else if(rv3d->view==V3D_VIEW_RIGHT && view==V3D_VIEW_LEFT);
-               else if(rv3d->view==V3D_VIEW_LEFT && view==V3D_VIEW_RIGHT);
-               else if(rv3d->view==V3D_VIEW_BOTTOM && view==V3D_VIEW_TOP);
-               else if(rv3d->view==V3D_VIEW_TOP && view==V3D_VIEW_BOTTOM);
-               else return;
-       }
-
        new_quat[0]= q1; new_quat[1]= q2;
        new_quat[2]= q3; new_quat[3]= q4;
 
-       rv3d->view= view;
+       if(align_active) {
+               /* align to active object */
+               Object *obact= CTX_data_active_object(C);
+               if (obact==NULL) {
+                       /* no active object, ignore this option */
+                       align_active= FALSE;
+               }
+               else {
+                       float obact_quat[4];
+                       float twmat[3][3];
+
+                       /* same as transform manipulator when normal is set */
+                       ED_getTransformOrientationMatrix(C, twmat, TRUE);
+
+                       mat3_to_quat( obact_quat,twmat);
+                       invert_qt(obact_quat);
+                       mul_qt_qtqt(new_quat, new_quat, obact_quat);
+
+                       rv3d->view= view= 0;
+               }
+       }
+
+       if(align_active==FALSE) {
+               /* normal operation */
+               if(rv3d->viewlock) {
+                       /* only pass on if */
+                       if(rv3d->view==RV3D_VIEW_FRONT && view==RV3D_VIEW_BACK);
+                       else if(rv3d->view==RV3D_VIEW_BACK && view==RV3D_VIEW_FRONT);
+                       else if(rv3d->view==RV3D_VIEW_RIGHT && view==RV3D_VIEW_LEFT);
+                       else if(rv3d->view==RV3D_VIEW_LEFT && view==RV3D_VIEW_RIGHT);
+                       else if(rv3d->view==RV3D_VIEW_BOTTOM && view==RV3D_VIEW_TOP);
+                       else if(rv3d->view==RV3D_VIEW_TOP && view==RV3D_VIEW_BOTTOM);
+                       else return;
+               }
+
+               rv3d->view= view;
+       }
 
        if(rv3d->viewlock) {
                ED_region_tag_redraw(CTX_wm_region(C));
                return;
        }
 
-       if (rv3d->persp==V3D_CAMOB && v3d->camera) {
+       if (rv3d->persp==RV3D_CAMOB && v3d->camera) {
 
-               if (U.uiflag & USER_AUTOPERSP) rv3d->persp= V3D_ORTHO;
-               else if(rv3d->persp==V3D_CAMOB) rv3d->persp= perspo;
+               if (U.uiflag & USER_AUTOPERSP) rv3d->persp= RV3D_ORTHO;
+               else if(rv3d->persp==RV3D_CAMOB) rv3d->persp= perspo;
 
                smooth_view(C, v3d->camera, NULL, rv3d->ofs, new_quat, NULL, NULL);
        }
        else {
 
-               if (U.uiflag & USER_AUTOPERSP) rv3d->persp= V3D_ORTHO;
-               else if(rv3d->persp==V3D_CAMOB) rv3d->persp= perspo;
+               if (U.uiflag & USER_AUTOPERSP) rv3d->persp= RV3D_ORTHO;
+               else if(rv3d->persp==RV3D_CAMOB) rv3d->persp= perspo;
 
                smooth_view(C, NULL, NULL, NULL, new_quat, NULL, NULL);
        }
@@ -1391,43 +1809,51 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
        Scene *scene= CTX_data_scene(C);
-       static int perspo=V3D_PERSP;
-       int viewnum;
+       static int perspo=RV3D_PERSP;
+       int viewnum, align_active, nextperspo;
 
        viewnum = RNA_enum_get(op->ptr, "type");
+       align_active = RNA_boolean_get(op->ptr, "align_active");
+
 
        /* Use this to test if we started out with a camera */
 
+       if (rv3d->persp == RV3D_CAMOB) {
+               nextperspo= rv3d->lpersp;
+       } else {
+               nextperspo= perspo;
+       }
+
        switch (viewnum) {
-               case V3D_VIEW_BOTTOM :
-                       axis_set_view(C, 0.0, -1.0, 0.0, 0.0, viewnum, perspo);
+               case RV3D_VIEW_BOTTOM :
+                       axis_set_view(C, 0.0, -1.0, 0.0, 0.0, viewnum, nextperspo, align_active);
                        break;
 
-               case V3D_VIEW_BACK:
-                       axis_set_view(C, 0.0, 0.0, (float)-cos(M_PI/4.0), (float)-cos(M_PI/4.0), viewnum, perspo);
+               case RV3D_VIEW_BACK:
+                       axis_set_view(C, 0.0, 0.0, (float)-cos(M_PI/4.0), (float)-cos(M_PI/4.0), viewnum, nextperspo, align_active);
                        break;
 
-               case V3D_VIEW_LEFT:
-                       axis_set_view(C, 0.5, -0.5, 0.5, 0.5, viewnum, perspo);
+               case RV3D_VIEW_LEFT:
+                       axis_set_view(C, 0.5, -0.5, 0.5, 0.5, viewnum, nextperspo, align_active);
                        break;
 
-               case V3D_VIEW_TOP:
-                       axis_set_view(C, 1.0, 0.0, 0.0, 0.0, viewnum, perspo);
+               case RV3D_VIEW_TOP:
+                       axis_set_view(C, 1.0, 0.0, 0.0, 0.0, viewnum, nextperspo, align_active);
                        break;
 
-               case V3D_VIEW_FRONT:
-                       axis_set_view(C, (float)cos(M_PI/4.0), (float)-sin(M_PI/4.0), 0.0, 0.0, viewnum, perspo);
+               case RV3D_VIEW_FRONT:
+                       axis_set_view(C, (float)cos(M_PI/4.0), (float)-sin(M_PI/4.0), 0.0, 0.0, viewnum, nextperspo, align_active);
                        break;
 
-               case V3D_VIEW_RIGHT:
-                       axis_set_view(C, 0.5, -0.5, -0.5, -0.5, viewnum, perspo);
+               case RV3D_VIEW_RIGHT:
+                       axis_set_view(C, 0.5, -0.5, -0.5, -0.5, viewnum, nextperspo, align_active);
                        break;
 
-               case V3D_VIEW_CAMERA:
+               case RV3D_VIEW_CAMERA:
                        if(rv3d->viewlock==0) {
                                /* lastview -  */
 
-                               if(rv3d->persp != V3D_CAMOB) {
+                               if(rv3d->persp != RV3D_CAMOB) {
                                        /* store settings of current view before allowing overwriting with camera view */
                                        QUATCOPY(rv3d->lviewquat, rv3d->viewquat);
                                        rv3d->lview= rv3d->view;
@@ -1454,14 +1880,14 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
                                                v3d->camera= scene_find_camera(scene);
                                                /*handle_view3d_lock();*/
                                        }
-                                       rv3d->persp= V3D_CAMOB;
+                                       rv3d->persp= RV3D_CAMOB;
                                        smooth_view(C, NULL, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens);
 
                                }
                                else{
                                        /* return to settings of last view */
                                        /* does smooth_view too */
-                                       axis_set_view(C, rv3d->lviewquat[0], rv3d->lviewquat[1], rv3d->lviewquat[2], rv3d->lviewquat[3], rv3d->lview, rv3d->lpersp);
+                                       axis_set_view(C, rv3d->lviewquat[0], rv3d->lviewquat[1], rv3d->lviewquat[2], rv3d->lviewquat[3], rv3d->lview, rv3d->lpersp, 0);
                                }
                        }
                        break;
@@ -1470,7 +1896,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
                        break;
        }
 
-       if(rv3d->persp != V3D_CAMOB) perspo= rv3d->persp;
+       if(rv3d->persp != RV3D_CAMOB) perspo= rv3d->persp;
 
        return OPERATOR_FINISHED;
 }
@@ -1489,6 +1915,7 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
        ot->flag= 0;
 
        RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "The Type of view");
+       RNA_def_boolean(ot->srna, "align_active", 0, "Align Active", "Align to the active objects axis");
 }
 
 static EnumPropertyItem prop_view_orbit_items[] = {
@@ -1500,16 +1927,15 @@ static EnumPropertyItem prop_view_orbit_items[] = {
 
 static int vieworbit_exec(bContext *C, wmOperator *op)
 {
-       ARegion *ar= CTX_wm_region(C);
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
-       float phi, si, q1[4];
+       float phi, si, q1[4], new_quat[4];
        int orbitdir;
 
        orbitdir = RNA_enum_get(op->ptr, "type");
 
        if(rv3d->viewlock==0) {
 
-               if(rv3d->persp != V3D_CAMOB) {
+               if(rv3d->persp != RV3D_CAMOB) {
                        if(orbitdir == V3D_VIEW_STEPLEFT || orbitdir == V3D_VIEW_STEPRIGHT) {
                                /* z-axis */
                                phi= (float)(M_PI/360.0)*U.pad_rot_angle;
@@ -1518,14 +1944,14 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
                                q1[0]= (float)cos(phi);
                                q1[1]= q1[2]= 0.0;
                                q1[3]= si;
-                               QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+                               mul_qt_qtqt(new_quat, rv3d->viewquat, q1);
                                rv3d->view= 0;
                        }
-                       if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) {
+                       else if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) {
                                /* horizontal axis */
                                VECCOPY(q1+1, rv3d->viewinv[0]);
 
-                               Normalize(q1+1);
+                               normalize_v3(q1+1);
                                phi= (float)(M_PI/360.0)*U.pad_rot_angle;
                                if(orbitdir == V3D_VIEW_STEPDOWN) phi= -phi;
                                si= (float)sin(phi);
@@ -1533,10 +1959,11 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
                                q1[1]*= si;
                                q1[2]*= si;
                                q1[3]*= si;
-                               QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+                               mul_qt_qtqt(new_quat, rv3d->viewquat, q1);
                                rv3d->view= 0;
                        }
-                       ED_region_tag_redraw(ar);
+
+                       smooth_view(C, NULL, NULL, NULL, new_quat, NULL, NULL);
                }
        }
 
@@ -1552,7 +1979,7 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
 
        /* api callbacks */
        ot->exec= vieworbit_exec;
-       ot->poll= ED_operator_view3d_active;
+       ot->poll= ED_operator_view3d_rotate;
 
        /* flags */
        ot->flag= 0;
@@ -1615,9 +2042,9 @@ static int viewpersportho_exec(bContext *C, wmOperator *op)
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
 
        if(rv3d->viewlock==0) {
-               if(rv3d->persp!=V3D_ORTHO)
-                       rv3d->persp=V3D_ORTHO;
-               else rv3d->persp=V3D_PERSP;
+               if(rv3d->persp!=RV3D_ORTHO)
+                       rv3d->persp=RV3D_ORTHO;
+               else rv3d->persp=RV3D_PERSP;
                ED_region_tag_redraw(ar);
        }
 
@@ -1628,7 +2055,7 @@ static int viewpersportho_exec(bContext *C, wmOperator *op)
 void VIEW3D_OT_view_persportho(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "View persp/ortho";
+       ot->name= "View Persp/Ortho";
        ot->description = "Switch the current view from perspective/orthographic.";
        ot->idname= "VIEW3D_OT_view_persportho";
 
@@ -1643,15 +2070,48 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
 
 /* ********************* set clipping operator ****************** */
 
+static void calc_clipping_plane(float clip[6][4], BoundBox *clipbb)
+{
+       int val;
+
+       for(val=0; val<4; val++) {
+
+               normal_tri_v3( clip[val],clipbb->vec[val], clipbb->vec[val==3?0:val+1], clipbb->vec[val+4]);
+
+               clip[val][3]=
+                       - clip[val][0]*clipbb->vec[val][0]
+                       - clip[val][1]*clipbb->vec[val][1]
+                       - clip[val][2]*clipbb->vec[val][2];
+       }
+}
+
+static void calc_local_clipping(float clip_local[][4], BoundBox *clipbb, float mat[][4])
+{
+       BoundBox clipbb_local;
+       float imat[4][4];
+       int i;
+
+       invert_m4_m4(imat, mat);
+
+       for(i=0; i<8; i++) {
+               mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]);
+       }
+
+       calc_clipping_plane(clip_local, &clipbb_local);
+}
+
+void ED_view3d_local_clipping(RegionView3D *rv3d, float mat[][4])
+{
+       if(rv3d->rflag & RV3D_CLIPPING)
+               calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat);
+}
+
 static int view3d_clipping_exec(bContext *C, wmOperator *op)
 {
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       ViewContext vc;
+       bglMats mats;
        rcti rect;
-       double mvmatrix[16];
-       double projmatrix[16];
-       double xs, ys, p[3];
-       GLint viewport[4];
-       short val;
 
        rect.xmin= RNA_int_get(op->ptr, "xmin");
        rect.ymin= RNA_int_get(op->ptr, "ymin");
@@ -1664,44 +2124,10 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
        /* note; otherwise opengl won't work */
        view3d_operator_needs_opengl(C);
 
-       /* Get the matrices needed for gluUnProject */
-       glGetIntegerv(GL_VIEWPORT, viewport);
-       glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
-       glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
-
-       /* near zero floating point values can give issues with gluUnProject
-               in side view on some implementations */
-       if(fabs(mvmatrix[0]) < 1e-6) mvmatrix[0]= 0.0;
-       if(fabs(mvmatrix[5]) < 1e-6) mvmatrix[5]= 0.0;
-
-       /* Set up viewport so that gluUnProject will give correct values */
-       viewport[0] = 0;
-       viewport[1] = 0;
-
-       /* four clipping planes and bounding volume */
-       /* first do the bounding volume */
-       for(val=0; val<4; val++) {
-
-               xs= (val==0||val==3)?rect.xmin:rect.xmax;
-               ys= (val==0||val==1)?rect.ymin:rect.ymax;
-
-               gluUnProject(xs, ys, 0.0, mvmatrix, projmatrix, viewport, &p[0], &p[1], &p[2]);
-               VECCOPY(rv3d->clipbb->vec[val], p);
-
-               gluUnProject(xs, ys, 1.0, mvmatrix, projmatrix, viewport, &p[0], &p[1], &p[2]);
-               VECCOPY(rv3d->clipbb->vec[4+val], p);
-       }
-
-       /* then plane equations */
-       for(val=0; val<4; val++) {
-
-               CalcNormFloat(rv3d->clipbb->vec[val], rv3d->clipbb->vec[val==3?0:val+1], rv3d->clipbb->vec[val+4],
-                                         rv3d->clip[val]);
+       view3d_set_viewcontext(C, &vc);
+       view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */
+       view3d_calculate_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect);
 
-               rv3d->clip[val][3]= - rv3d->clip[val][0]*rv3d->clipbb->vec[val][0]
-                       - rv3d->clip[val][1]*rv3d->clipbb->vec[val][1]
-                       - rv3d->clip[val][2]*rv3d->clipbb->vec[val][2];
-       }
        return OPERATOR_FINISHED;
 }
 
@@ -1748,57 +2174,6 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
        RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
 }
 
-/* ********************* draw type operator ****************** */
-
-static int view3d_drawtype_exec(bContext *C, wmOperator *op)
-{
-       View3D *v3d = CTX_wm_view3d(C);
-       int dt, dt_alt;
-
-       dt  = RNA_int_get(op->ptr, "draw_type");
-       dt_alt = RNA_int_get(op->ptr, "draw_type_alternate");
-
-       if (dt_alt != -1) {
-               if (v3d->drawtype == dt)
-                       v3d->drawtype = dt_alt;
-               else
-                       v3d->drawtype = dt;
-       }
-       else
-               v3d->drawtype = dt;
-
-       ED_area_tag_redraw(CTX_wm_area(C));
-
-       return OPERATOR_FINISHED;
-}
-
-static int view3d_drawtype_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       return view3d_drawtype_exec(C, op);
-}
-
-/* toggles */
-void VIEW3D_OT_drawtype(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Change draw type";
-       ot->description = "Change the draw type of the view.";
-       ot->idname= "VIEW3D_OT_drawtype";
-
-       /* api callbacks */
-       ot->invoke= view3d_drawtype_invoke;
-       ot->exec= view3d_drawtype_exec;
-
-       ot->poll= ED_operator_view3d_active;
-
-       /* flags */
-       ot->flag= 0;
-
-       /* rna XXX should become enum */
-       RNA_def_int(ot->srna, "draw_type", 0, INT_MIN, INT_MAX, "Draw Type", "", INT_MIN, INT_MAX);
-       RNA_def_int(ot->srna, "draw_type_alternate", -1, INT_MIN, INT_MAX, "Draw Type Alternate", "", INT_MIN, INT_MAX);
-}
-
 /* ***************** 3d cursor cursor op ******************* */
 
 /* mx my in region coords */
@@ -1826,7 +2201,7 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
        if(mval[0]!=IS_CLIPPED) {
 
                window_to_3d_delta(ar, dvec, mval[0]-mx, mval[1]-my);
-               VecSubf(fp, fp, dvec);
+               sub_v3_v3v3(fp, fp, dvec);
        }
        else {
 
@@ -1841,17 +2216,12 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
                fp[2]= (rv3d->persinv[0][2]*dx + rv3d->persinv[1][2]*dy+ rv3d->persinv[2][2]*fz)-rv3d->ofs[2];
        }
 
-//     if(lr_click) {
-               // XXX          if(obedit->type==OB_MESH) add_click_mesh();
-               //              else if ELEM(obedit->type, OB_CURVE, OB_SURF) addvert_Nurb(0);
-               //              else if (obedit->type==OB_ARMATURE) addvert_armature();
-//             VECCOPY(fp, oldcurs);
-//     }
-       // XXX notifier for scene */
-       ED_area_tag_redraw(CTX_wm_area(C));
+       if(v3d && v3d->localvd)
+               WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
+       else
+               WM_event_add_notifier(C, NC_SCENE|NA_EDITED, scene);
 
-       /* prevent other mouse ops to fail */
-       return OPERATOR_PASS_THROUGH;
+       return OPERATOR_FINISHED;
 }
 
 void VIEW3D_OT_cursor3d(wmOperatorType *ot)
@@ -1866,7 +2236,10 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
        ot->invoke= set_3dcursor_invoke;
 
        ot->poll= ED_operator_view3d_active;
-
+    
+       /* flags */
+//     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+    
        /* rna later */
 
 }
@@ -1881,6 +2254,9 @@ static int manipulator_invoke(bContext *C, wmOperator *op, wmEvent *event)
        if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH;
        if(!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH;
 
+       /* only no modifier or shift */
+       if(event->keymodifier != 0 && event->keymodifier != KM_SHIFT) return OPERATOR_PASS_THROUGH;
+
        /* note; otherwise opengl won't work */
        view3d_operator_needs_opengl(C);
 
@@ -1895,7 +2271,7 @@ void VIEW3D_OT_manipulator(wmOperatorType *ot)
 
        /* identifiers */
        ot->name= "3D Manipulator";
-       ot->description = "";
+       ot->description = "Manipulate selected item by axis.";
        ot->idname= "VIEW3D_OT_manipulator";
 
        /* api callbacks */
@@ -1912,22 +2288,66 @@ void VIEW3D_OT_manipulator(wmOperatorType *ot)
 /* ************************* below the line! *********************** */
 
 
+static float view_autodist_depth_margin(ARegion *ar, short *mval, int margin)
+{
+       RegionView3D *rv3d= ar->regiondata;
+       float depth= FLT_MAX;
+
+       if(margin==0) {
+               if (mval[0] < 0) return 0;
+               if (mval[1] < 0) return 0;
+               if (mval[0] >= rv3d->depths->w) return 0;
+               if (mval[1] >= rv3d->depths->h) return 0;
+
+               /* Get Z Depths, needed for perspective, nice for ortho */
+               depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]];
+               if(depth >= rv3d->depths->depth_range[1] || depth <= rv3d->depths->depth_range[0]) {
+                       depth= FLT_MAX;
+               }
+       }
+       else {
+               rcti rect;
+               float depth_close= FLT_MAX;
+               int xs, ys;
+
+               rect.xmax = mval[0] + margin;
+               rect.ymax = mval[1] + margin;
+
+               rect.xmin = mval[0] - margin;
+               rect.ymin = mval[1] - margin;
+
+               /* Constrain rect to depth bounds */
+               if (rect.xmin < 0) rect.xmin = 0;
+               if (rect.ymin < 0) rect.ymin = 0;
+               if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1;
+               if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1;
+
+               /* Find the closest Z pixel */
+               for (xs=rect.xmin; xs < rect.xmax; xs++) {
+                       for (ys=rect.ymin; ys < rect.ymax; ys++) {
+                               depth= rv3d->depths->depths[ys*rv3d->depths->w+xs];
+                               if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) {
+                                       if (depth_close > depth) {
+                                               depth_close = depth;
+                                       }
+                               }
+                       }
+               }
+
+               depth= depth_close;
+       }
+
+       return depth;
+}
+
 /* XXX todo Zooms in on a border drawn by the user */
 int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist )
 {
        RegionView3D *rv3d= ar->regiondata;
        bglMats mats; /* ZBuffer depth vars */
-       rcti rect;
-       float depth, depth_close= MAXFLOAT;
+       float depth_close= FLT_MAX;
        int had_depth = 0;
        double cent[2],  p[3];
-       int xs, ys;
-
-       rect.xmax = mval[0] + 4;
-       rect.ymax = mval[1] + 4;
-
-       rect.xmin = mval[0] - 4;
-       rect.ymin = mval[1] - 4;
 
        /* Get Z Depths, needed for perspective, nice for ortho */
        bgl_get_mats(&mats);
@@ -1941,25 +2361,9 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou
 
        view3d_update_depths(ar, v3d);
 
-       /* Constrain rect to depth bounds */
-       if (rect.xmin < 0) rect.xmin = 0;
-       if (rect.ymin < 0) rect.ymin = 0;
-       if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1;
-       if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1;
+       depth_close= view_autodist_depth_margin(ar, mval, 4);
 
-       /* Find the closest Z pixel */
-       for (xs=rect.xmin; xs < rect.xmax; xs++) {
-               for (ys=rect.ymin; ys < rect.ymax; ys++) {
-                       depth= rv3d->depths->depths[ys*rv3d->depths->w+xs];
-                       if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) {
-                               if (depth_close > depth) {
-                                       depth_close = depth;
-                               }
-                       }
-               }
-       }
-
-       if (depth_close==MAXFLOAT)
+       if (depth_close==FLT_MAX)
                return 0;
 
        if (had_depth==0) {
@@ -1980,7 +2384,65 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou
        return 1;
 }
 
+int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, float *autodist )
+{
+       RegionView3D *rv3d= ar->regiondata;
+
+       /* Get Z Depths, needed for perspective, nice for ortho */
+       switch(mode) {
+       case 0:
+               draw_depth(scene, ar, v3d, NULL);
+               break;
+       case 1:
+               draw_depth_gpencil(scene, ar, v3d);
+               break;
+       }
+
+       /* force updating */
+       if (rv3d->depths) {
+               rv3d->depths->damaged = 1;
+       }
+
+       view3d_update_depths(ar, v3d);
+       return 1;
+}
+
+// no 4x4 sampling, run view_autodist_init first
+int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], int margin, float *force_depth) //, float *autodist )
+{
+       bglMats mats; /* ZBuffer depth vars, could cache? */
+       float depth;
+       double cent[2],  p[3];
+
+       /* Get Z Depths, needed for perspective, nice for ortho */
+       if(force_depth)
+               depth= *force_depth;
+       else
+               depth= view_autodist_depth_margin(ar, mval, margin);
+
+       if (depth==FLT_MAX)
+               return 0;
+
+       cent[0] = (double)mval[0];
+       cent[1] = (double)mval[1];
+
+       bgl_get_mats(&mats);
+       if (!gluUnProject(cent[0], cent[1], depth, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
+               return 0;
+
+       mouse_worldloc[0] = (float)p[0];
+       mouse_worldloc[1] = (float)p[1];
+       mouse_worldloc[2] = (float)p[2];
+       return 1;
+}
+
+int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *depth)
+{
+       *depth= view_autodist_depth_margin(ar, mval, margin);
 
+       return (*depth==FLT_MAX) ? 0:1;
+               return 0;
+}
 
 /* ********************* NDOF ************************ */
 /* note: this code is confusing and unclear... (ton) */
@@ -2091,7 +2553,7 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
        // until the first draw and doesn't update the menu
        // to reflect persp mode.
 
-       rv3d->persp = V3D_PERSP;
+       rv3d->persp = RV3D_PERSP;
 
 
        // Correct the distance jump if rv3d->dist != 0
@@ -2111,9 +2573,9 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
                m_dist = rv3d->dist;
                upvec[0] = upvec[1] = 0;
                upvec[2] = rv3d->dist;
-               Mat3CpyMat4(mat, rv3d->viewinv);
-               Mat3MulVecfl(mat, upvec);
-               VecSubf(rv3d->ofs, rv3d->ofs, upvec);
+               copy_m3_m4(mat, rv3d->viewinv);
+               mul_m3_v3(mat, upvec);
+               sub_v3_v3v3(rv3d->ofs, rv3d->ofs, upvec);
                rv3d->dist = 0.0;
        }
 
@@ -2127,16 +2589,16 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
 
        // rotate device x and y by view z
 
-       Mat3CpyMat4(mat, rv3d->viewinv);
+       copy_m3_m4(mat, rv3d->viewinv);
        mat[2][2] = 0.0f;
-       Mat3MulVecfl(mat, rvec);
+       mul_m3_v3(mat, rvec);
 
        // rotate the view
 
-       phi = Normalize(rvec);
+       phi = normalize_v3(rvec);
        if(phi != 0) {
-               VecRotToQuat(rvec,phi,q1);
-               QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+               axis_angle_to_quat(q1,rvec,phi);
+               mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
        }
 
 
@@ -2149,13 +2611,13 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
        // the next three lines rotate the x and y translation coordinates
        // by the current z axis angle
 
-       Mat3CpyMat4(mat, rv3d->viewinv);
+       copy_m3_m4(mat, rv3d->viewinv);
        mat[2][2] = 0.0f;
-       Mat3MulVecfl(mat, tvec);
+       mul_m3_v3(mat, tvec);
 
        // translate the view
 
-       VecSubf(rv3d->ofs, rv3d->ofs, tvec);
+       sub_v3_v3v3(rv3d->ofs, rv3d->ofs, tvec);
 
 
        /*----------------------------------------------------
@@ -2214,9 +2676,9 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
                rv3d->dist = m_dist;
                upvec[0] = upvec[1] = 0;
                upvec[2] = rv3d->dist;
-               Mat3CpyMat4(mat, rv3d->viewinv);
-               Mat3MulVecfl(mat, upvec);
-               VecAddf(rv3d->ofs, rv3d->ofs, upvec);
+               copy_m3_m4(mat, rv3d->viewinv);
+               mul_m3_v3(mat, upvec);
+               add_v3_v3v3(rv3d->ofs, rv3d->ofs, upvec);
        }
 
     /*----------------------------------------------------
@@ -2253,7 +2715,7 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
        fval[6] = fval[6] / 1000000.0f;
 
     // scale more if not in perspective mode
-       if (rv3d->persp == V3D_ORTHO) {
+       if (rv3d->persp == RV3D_ORTHO) {
                fval[0] = fval[0] * 0.05f;
                fval[1] = fval[1] * 0.05f;
                fval[2] = fval[2] * 0.05f;
@@ -2278,8 +2740,8 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
      d = 1.0f;
 
 /*    if (ob) {
-        VecSubf(diff, obofs, rv3d->ofs);
-        d = VecLength(diff);
+        sub_v3_v3v3(diff, obofs, rv3d->ofs);
+        d = len_v3(diff);
     }
 */
 
@@ -2294,15 +2756,15 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
     dvec[0] = curareaX * rv3d->persinv[0][0] + curareaY * rv3d->persinv[1][0];
     dvec[1] = curareaX * rv3d->persinv[0][1] + curareaY * rv3d->persinv[1][1];
     dvec[2] = curareaX * rv3d->persinv[0][2] + curareaY * rv3d->persinv[1][2];
-    VecAddf(rv3d->ofs, rv3d->ofs, dvec);
+    add_v3_v3v3(rv3d->ofs, rv3d->ofs, dvec);
 
     /*----------------------------------------------------
      * ndof device dolly
      */
     len = zsens * sbadjust * fval[2];
 
-    if (rv3d->persp==V3D_CAMOB) {
-        if(rv3d->persp==V3D_CAMOB) { /* This is stupid, please fix - TODO */
+    if (rv3d->persp==RV3D_CAMOB) {
+        if(rv3d->persp==RV3D_CAMOB) { /* This is stupid, please fix - TODO */
             rv3d->camzoom+= 10.0f * -len;
         }
         if (rv3d->camzoom < minZoom) rv3d->camzoom = minZoom;
@@ -2319,14 +2781,14 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
      */
 
     /* Get the 3x3 matrix and its inverse from the quaternion */
-    QuatToMat3(rv3d->viewquat, m);
-    Mat3Inv(m_inv,m);
+    quat_to_mat3( m,rv3d->viewquat);
+    invert_m3_m3(m_inv,m);
 
     /* Determine the direction of the x vector (for rotating up and down) */
     /* This can likely be compuated directly from the quaternion. */
-    Mat3MulVecfl(m_inv,xvec);
-    Mat3MulVecfl(m_inv,yvec);
-    Mat3MulVecfl(m_inv,zvec);
+    mul_m3_v3(m_inv,xvec);
+    mul_m3_v3(m_inv,yvec);
+    mul_m3_v3(m_inv,zvec);
 
     /* Perform the up/down rotation */
     phi = sbadjust * rsens * /*0.5f * */ fval[3]; /* spin vertically half as fast as horizontally */
@@ -2335,13 +2797,13 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
     q1[1] = si * xvec[0];
     q1[2] = si * xvec[1];
     q1[3] = si * xvec[2];
-    QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+    mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
 
     if (use_sel) {
-        QuatConj(q1); /* conj == inv for unit quat */
-        VecSubf(v3d->ofs, v3d->ofs, obofs);
-        QuatMulVecf(q1, rv3d->ofs);
-        VecAddf(rv3d->ofs, rv3d->ofs, obofs);
+        conjugate_qt(q1); /* conj == inv for unit quat */
+        sub_v3_v3v3(rv3d->ofs, rv3d->ofs, obofs);
+        mul_qt_v3(q1, rv3d->ofs);
+        add_v3_v3v3(rv3d->ofs, rv3d->ofs, obofs);
     }
 
     /* Perform the orbital rotation */
@@ -2360,13 +2822,13 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
     q1[0] = cos(phi);
     q1[1] = q1[2] = 0.0;
     q1[3] = sin(phi);
-    QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+    mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
 
     if (use_sel) {
-        QuatConj(q1);
-        VecSubf(rv3d->ofs, rv3d->ofs, obofs);
-        QuatMulVecf(q1, rv3d->ofs);
-        VecAddf(rv3d->ofs, rv3d->ofs, obofs);
+        conjugate_qt(q1);
+        sub_v3_v3v3(rv3d->ofs, rv3d->ofs, obofs);
+        mul_qt_v3(q1, rv3d->ofs);
+        add_v3_v3v3(rv3d->ofs, rv3d->ofs, obofs);
     }
 
     /*----------------------------------------------------