RNA
[blender.git] / source / blender / editors / space_view3d / view3d_edit.c
index 5ac774afadbcb36908fd0124235191c4820a676e..79173d3fec72fd50af9e739aea423a9ee52d436c 100644 (file)
@@ -6,7 +6,7 @@
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. 
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,7 +20,7 @@
  * The Original Code is Copyright (C) 2008 Blender Foundation.
  * All rights reserved.
  *
- * 
+ *
  * Contributor(s): Blender Foundation
  *
  * ***** END GPL LICENSE BLOCK *****
@@ -32,6 +32,7 @@
 #include <float.h>
 
 #include "DNA_action_types.h"
+#include "DNA_armature_types.h"
 #include "DNA_camera_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_object_types.h"
 
 #include "BKE_action.h"
 #include "BKE_context.h"
+#include "BKE_depsgraph.h"
 #include "BKE_object.h"
 #include "BKE_global.h"
+#include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_screen.h"
 #include "BKE_utildefines.h"
 #include "BIF_retopo.h"
 
 #include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
 
+#include "ED_particle.h"
+#include "ED_space_api.h"
 #include "ED_screen.h"
+#include "ED_types.h"
 
 #include "UI_interface.h"
 #include "UI_resources.h"
 
 /* ********************** view3d_edit: view manipulations ********************* */
 
-#define TRACKBALLSIZE  (1.1)
+/* ********************* box view support ***************** */
+
+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];
+       int val;
+       
+       /* create bounding box */
+       for(ar= sa->regionbase.first; ar; ar= ar->next) {
+               if(ar->regiontype==RGN_TYPE_WINDOW) {
+                       RegionView3D *rv3d= ar->regiondata;
+                       
+                       if(rv3d->viewlock & RV3D_BOXCLIP) {
+                               if(ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM)) {
+                                       if(ar->winx>ar->winy) x1= rv3d->dist;
+                                       else x1= ar->winx*rv3d->dist/ar->winy;
+                                       
+                                       if(ar->winx>ar->winy) y1= ar->winy*rv3d->dist/ar->winx;
+                                       else y1= rv3d->dist;
+                                       
+                                       ofs[0]= rv3d->ofs[0];
+                                       ofs[1]= rv3d->ofs[1];
+                               }
+                               else if(ELEM(rv3d->view, V3D_VIEW_FRONT, V3D_VIEW_BACK)) {
+                                       ofs[2]= rv3d->ofs[2];
+                                       
+                                       if(ar->winx>ar->winy) z1= ar->winy*rv3d->dist/ar->winx;
+                                       else z1= rv3d->dist;
+                               }
+                       }
+               }
+       }
+       
+       for(val=0; val<8; val++) {
+               if(ELEM4(val, 0, 3, 4, 7))
+                       bb->vec[val][0]= -x1 - ofs[0];
+               else
+                       bb->vec[val][0]=  x1 - ofs[0];
+               
+               if(ELEM4(val, 0, 1, 4, 5))
+                       bb->vec[val][1]= -y1 - ofs[1];
+               else
+                       bb->vec[val][1]=  y1 - ofs[1];
+               
+               if(val > 3)
+                       bb->vec[val][2]= -z1 - ofs[2];
+               else
+                       bb->vec[val][2]=  z1 - ofs[2];
+       }       
+       
+       /* 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]);
+       
+       /* then plane equations */
+       for(val=0; val<5; val++) {
+               clip[val][3]= - clip[val][0]*bb->vec[val][0] - clip[val][1]*bb->vec[val][1] - clip[val][2]*bb->vec[val][2];
+       }
+       clip[5][3]= - clip[5][0]*bb->vec[0][0] - clip[5][1]*bb->vec[0][1] - clip[5][2]*bb->vec[0][2];
+       
+       /* create bounding box */
+       for(ar= sa->regionbase.first; ar; ar= ar->next) {
+               if(ar->regiontype==RGN_TYPE_WINDOW) {
+                       RegionView3D *rv3d= ar->regiondata;
+                       
+                       if(rv3d->viewlock & RV3D_BOXCLIP) {
+                               rv3d->rflag |= RV3D_CLIPPING;
+                               memcpy(rv3d->clip, clip, sizeof(clip));
+                       }
+               }
+       }
+       MEM_freeN(bb);
+}
+
+/* sync center/zoom view of region to others, for view transforms */
+static void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
+{
+       ARegion *artest;
+       RegionView3D *rv3d= ar->regiondata;
+       
+       for(artest= sa->regionbase.first; artest; artest= artest->next) {
+               if(artest!=ar && artest->regiontype==RGN_TYPE_WINDOW) {
+                       RegionView3D *rv3dtest= artest->regiondata;
+                       
+                       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))
+                                               rv3dtest->ofs[0]= rv3d->ofs[0];
+                                       else if( ELEM(rv3dtest->view, V3D_VIEW_RIGHT, V3D_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))
+                                               rv3dtest->ofs[0]= rv3d->ofs[0];
+                                       else if( ELEM(rv3dtest->view, V3D_VIEW_RIGHT, V3D_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))
+                                               rv3dtest->ofs[1]= rv3d->ofs[1];
+                                       if( ELEM(rv3dtest->view, V3D_VIEW_FRONT, V3D_VIEW_BACK))
+                                               rv3dtest->ofs[2]= rv3d->ofs[2];
+                               }
+                               
+                               ED_region_tag_redraw(artest);
+                       }
+               }
+       }
+       view3d_boxview_clip(sa);
+}
+
+/* for home, center etc */
+void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
+{
+       ARegion *artest;
+       RegionView3D *rv3d= ar->regiondata;
+       
+       for(artest= sa->regionbase.first; artest; artest= artest->next) {
+               if(artest!=ar && artest->regiontype==RGN_TYPE_WINDOW) {
+                       RegionView3D *rv3dtest= artest->regiondata;
+                       
+                       if(rv3dtest->viewlock) {
+                               rv3dtest->dist= rv3d->dist;
+                               VECCOPY(rv3dtest->ofs, rv3d->ofs);
+                               ED_region_tag_redraw(artest);
+                       }
+               }
+       }
+       view3d_boxview_clip(sa);
+}
+
+/* ************************** init for view ops **********************************/
+
+typedef struct ViewOpsData {
+       ScrArea *sa;
+       ARegion *ar;
+       RegionView3D *rv3d;
 
-/* the central math in this function was copied from trackball.cpp, sample code from the 
-   Developers Toolbox series by SGI. */
+       float oldquat[4];
+       float trackvec[3];
+       float ofs[3], obofs[3];
+       float reverse, dist0;
+       float grid, far;
+       
+       int origx, origy, oldx, oldy;
+       int origkey;
+
+} ViewOpsData;
 
-/* trackball: better one than a full spherical solution */
+#define TRACKBALLSIZE  (1.1)
 
-void calctrackballvecfirst(rcti *area, short *mval, float *vec)
+static void calctrackballvec(rcti *rect, int mx, int my, float *vec)
 {
        float x, y, radius, d, z, t;
-       
+
        radius= TRACKBALLSIZE;
-       
+
        /* normalize x and y */
-       x= (area->xmax + area->xmin)/2 -mval[0];
-       x/= (float)((area->xmax - area->xmin)/2);
-       y= (area->ymax + area->ymin)/2 -mval[1];
-       y/= (float)((area->ymax - area->ymin)/2);
-       
+       x= (rect->xmax + rect->xmin)/2 - mx;
+       x/= (float)((rect->xmax - rect->xmin)/4);
+       y= (rect->ymax + rect->ymin)/2 - my;
+       y/= (float)((rect->ymax - rect->ymin)/2);
+
        d = sqrt(x*x + y*y);
        if (d < radius*M_SQRT1_2)       /* Inside sphere */
                z = sqrt(radius*radius - d*d);
@@ -103,55 +266,1676 @@ void calctrackballvecfirst(rcti *area, short *mval, float *vec)
                z = t*t / d;
        }
 
-       vec[0]= x;
-       vec[1]= y;
-       vec[2]= -z;             /* yah yah! */
+       vec[0]= x;
+       vec[1]= y;
+       vec[2]= -z;             /* yah yah! */
+}
+
+
+static void viewops_data(bContext *C, wmOperator *op, wmEvent *event)
+{
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d;
+       ViewOpsData *vod= MEM_callocN(sizeof(ViewOpsData), "viewops data");
+
+       /* store data */
+       op->customdata= vod;
+       vod->sa= CTX_wm_area(C);
+       vod->ar= CTX_wm_region(C);
+       vod->rv3d= rv3d= vod->ar->regiondata;
+       vod->dist0= rv3d->dist;
+       QUATCOPY(vod->oldquat, rv3d->viewquat);
+       vod->origx= vod->oldx= event->x;
+       vod->origy= vod->oldy= event->y;
+       vod->origkey= event->type;
+       
+       /* lookup, we dont pass on v3d to prevent confusement */
+       vod->grid= v3d->grid;
+       vod->far= v3d->far;
+       
+       calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec);
+
+       initgrabz(rv3d, -rv3d->ofs[0], -rv3d->ofs[1], -rv3d->ofs[2]);
+
+       vod->reverse= 1.0f;
+       if (rv3d->persmat[2][1] < 0.0f)
+               vod->reverse= -1.0f;
+
+}
+
+/* ************************** viewrotate **********************************/
+
+static const float thres = 0.93f; //cos(20 deg);
+
+#define COS45 0.70710678118654746
+#define SIN45 COS45
+
+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
+
+       /* some more 45 deg snaps */
+{0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0},
+{0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0, 0},
+{0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0, 0},
+{0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0, 0},
+{0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0, 0},
+{0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0, 0},
+{0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0, 0},
+{0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0, 0},
+{0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0, 0},
+{0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0, 0},
+{0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0, 0},
+{0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0, 0},
+{0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0, 0},
+{0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0, 0},
+{-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0, 0},
+{-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0, 0},
+{-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0, 0},
+{0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0, 0},
+{-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0, 0},
+{-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0, 0},
+{-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0, 0},
+{-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0, 0},
+{-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0, 0},
+{-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0, 0},
+{-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0, 0},
+{0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0, 0},
+{-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0, 0},
+{-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0, 0},
+{-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0, 0},
+{-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0, 0},
+{-COS45, 0.0, 0.0, SIN45, 0, 0},
+{COS45, 0.0, 0.0, SIN45, 0, 0},
+{0.0, 0.0, 0.0, 1.0, 0, 0}
+};
+
+
+static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
+{
+       RegionView3D *rv3d= vod->rv3d;
+       int use_sel= 0; /* XXX */
+
+       rv3d->view= 0; /* need to reset everytime because of view snapping */
+
+       if (U.flag & USER_TRACKBALL) {
+               float phi, si, q1[4], dvec[3], newvec[3];
+
+               calctrackballvec(&vod->ar->winrct, x, y, newvec);
+
+               VecSubf(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);
+
+               /* Allow for rotation beyond the interval
+                       * [-pi, pi] */
+               while (si > 1.0)
+                       si -= 2.0;
+
+               /* This relation is used instead of
+                       * phi = asin(si) so that the angle
+                       * of rotation is linearly proportional
+                       * to the distance that the mouse is
+                       * dragged. */
+               phi = si * M_PI / 2.0;
+
+               si= sin(phi);
+               q1[0]= cos(phi);
+               q1[1]*= si;
+               q1[2]*= si;
+               q1[3]*= si;
+               QuatMul(rv3d->viewquat, q1, vod->oldquat);
+
+               if (use_sel) {
+                       /* compute the post multiplication quat, to rotate the offset correctly */
+                       QUATCOPY(q1, vod->oldquat);
+                       QuatConj(q1);
+                       QuatMul(q1, q1, rv3d->viewquat);
+
+                       QuatConj(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);
+               }
+       }
+       else {
+               /* New turntable view code by John Aughey */
+               float si, phi, q1[4];
+               float m[3][3];
+               float m_inv[3][3];
+               float xvec[3] = {1,0,0};
+               /* Sensitivity will control how fast the viewport rotates.  0.0035 was
+                       obtained experimentally by looking at viewport rotation sensitivities
+                       on other modeling programs. */
+               /* Perhaps this should be a configurable user parameter. */
+               const float sensitivity = 0.0035;
+
+               /* Get the 3x3 matrix and its inverse from the quaternion */
+               QuatToMat3(rv3d->viewquat, m);
+               Mat3Inv(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);
+
+               /* Perform the up/down rotation */
+               phi = sensitivity * -(y - vod->oldy);
+               si = sin(phi);
+               q1[0] = cos(phi);
+               q1[1] = si * xvec[0];
+               q1[2] = si * xvec[1];
+               q1[3] = si * xvec[2];
+               QuatMul(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);
+               }
+
+               /* Perform the orbital rotation */
+               phi = sensitivity * vod->reverse * (x - vod->oldx);
+               q1[0] = cos(phi);
+               q1[1] = q1[2] = 0.0;
+               q1[3] = sin(phi);
+               QuatMul(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);
+               }
+       }
+
+       /* check for view snap */
+       if (ctrl){
+               int i;
+               float viewmat[3][3];
+
+
+               QuatToMat3(rv3d->viewquat, viewmat);
+
+               for (i = 0 ; i < 39; i++){
+                       float snapmat[3][3];
+                       float view = (int)snapquats[i][4];
+
+                       QuatToMat3(snapquats[i], snapmat);
+
+                       if ((Inpf(snapmat[0], viewmat[0]) > thres) &&
+                               (Inpf(snapmat[1], viewmat[1]) > thres) &&
+                               (Inpf(snapmat[2], viewmat[2]) > thres)){
+
+                               QUATCOPY(rv3d->viewquat, snapquats[i]);
+
+                               rv3d->view = view;
+
+                               break;
+                       }
+               }
+       }
+       vod->oldx= x;
+       vod->oldy= y;
+
+       ED_region_tag_redraw(vod->ar);
+}
+
+static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       ViewOpsData *vod= op->customdata;
+
+       /* execute the events */
+       switch(event->type) {
+               case MOUSEMOVE:
+                       viewrotate_apply(vod, event->x, event->y, event->ctrl);
+                       break;
+
+               default:
+                       if(event->type==vod->origkey && event->val==0) {
+                               request_depth_update(CTX_wm_region_view3d(C));
+
+                               MEM_freeN(vod);
+                               op->customdata= NULL;
+
+                               return OPERATOR_FINISHED;
+                       }
+       }
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       ViewOpsData *vod;
+
+       if(rv3d->viewlock)
+               return OPERATOR_CANCELLED;
+       
+       /* makes op->customdata */
+       viewops_data(C, op, event);
+       vod= op->customdata;
+
+       /* switch from camera view when: */
+       if(vod->rv3d->persp != V3D_PERSP) {
+
+               if (U.uiflag & USER_AUTOPERSP)
+                       vod->rv3d->persp= V3D_PERSP;
+               else if(vod->rv3d->persp==V3D_CAMOB)
+                       vod->rv3d->persp= V3D_PERSP;
+               ED_region_tag_redraw(vod->ar);
+       }
+
+       /* add temp handler */
+       WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+
+void VIEW3D_OT_viewrotate(wmOperatorType *ot)
+{
+
+       /* identifiers */
+       ot->name= "Rotate view";
+       ot->description = "Rotate the view.";
+       ot->idname= "VIEW3D_OT_viewrotate";
+
+       /* api callbacks */
+       ot->invoke= viewrotate_invoke;
+       ot->modal= viewrotate_modal;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+}
+
+/* ************************ viewmove ******************************** */
+
+static void viewmove_apply(ViewOpsData *vod, int x, int y)
+{
+       if(vod->rv3d->persp==V3D_CAMOB) {
+               float max= (float)MAX2(vod->ar->winx, vod->ar->winy);
+
+               vod->rv3d->camdx += (vod->oldx - x)/(max);
+               vod->rv3d->camdy += (vod->oldy - y)/(max);
+               CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
+               CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
+// XXX         preview3d_event= 0;
+       }
+       else {
+               float dvec[3];
+
+               window_to_3d_delta(vod->ar, dvec, x-vod->oldx, y-vod->oldy);
+               VecAddf(vod->rv3d->ofs, vod->rv3d->ofs, dvec);
+               
+               if(vod->rv3d->viewlock & RV3D_BOXVIEW)
+                       view3d_boxview_sync(vod->sa, vod->ar);
+       }
+
+       vod->oldx= x;
+       vod->oldy= y;
+
+       ED_region_tag_redraw(vod->ar);
+}
+
+
+static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       ViewOpsData *vod= op->customdata;
+
+       /* execute the events */
+       switch(event->type) {
+               case MOUSEMOVE:
+                       viewmove_apply(vod, event->x, event->y);
+                       break;
+
+               default:
+                       if(event->type==vod->origkey && event->val==0) {
+                               request_depth_update(CTX_wm_region_view3d(C));
+
+                               MEM_freeN(vod);
+                               op->customdata= NULL;
+
+                               return OPERATOR_FINISHED;
+                       }
+       }
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+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);
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+
+void VIEW3D_OT_viewmove(wmOperatorType *ot)
+{
+
+       /* identifiers */
+       ot->name= "Move view";
+       ot->description = "Move the view.";
+       ot->idname= "VIEW3D_OT_viewmove";
+
+       /* api callbacks */
+       ot->invoke= viewmove_invoke;
+       ot->modal= viewmove_modal;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+}
+
+/* ************************ viewzoom ******************************** */
+
+static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
+{
+       RegionView3D *rv3d= ar->regiondata;
+       
+       if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+               float dvec[3];
+               float tvec[3];
+               float tpos[3];
+               float new_dist;
+               short vb[2], mouseloc[2];
+
+               mouseloc[0]= mx - ar->winrct.xmin;
+               mouseloc[1]= my - ar->winrct.ymin;
+
+               /* find the current window width and height */
+               vb[0] = ar->winx;
+               vb[1] = ar->winy;
+
+               tpos[0] = -rv3d->ofs[0];
+               tpos[1] = -rv3d->ofs[1];
+               tpos[2] = -rv3d->ofs[2];
+
+               /* Project cursor position into 3D space */
+               initgrabz(rv3d, tpos[0], tpos[1], tpos[2]);
+               window_to_3d_delta(ar, dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2);
+
+               /* 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 = rv3d->dist * dfac;
+
+               VECCOPY(rv3d->ofs, tvec);
+               rv3d->dist = new_dist;
+
+               /* Calculate final offset */
+               dvec[0] = tvec[0] + dvec[0] * dfac;
+               dvec[1] = tvec[1] + dvec[1] * dfac;
+               dvec[2] = tvec[2] + dvec[2] * dfac;
+
+               VECCOPY(rv3d->ofs, dvec);
+       } else {
+               rv3d->dist *= dfac;
+       }
+}
+
+
+static void viewzoom_apply(ViewOpsData *vod, int x, int y)
+{
+       float zfac=1.0;
+
+       if(U.viewzoom==USER_ZOOM_CONT) {
+               // oldstyle zoom
+               zfac = 1.0+(float)(vod->origx - x + vod->origy - y)/1000.0;
+       }
+       else if(U.viewzoom==USER_ZOOM_SCALE) {
+               int ctr[2], len1, len2;
+               // method which zooms based on how far you move the mouse
+
+               ctr[0] = (vod->ar->winrct.xmax + vod->ar->winrct.xmin)/2;
+               ctr[1] = (vod->ar->winrct.ymax + vod->ar->winrct.ymin)/2;
+
+               len1 = (int)sqrt((ctr[0] - x)*(ctr[0] - x) + (ctr[1] - y)*(ctr[1] - y)) + 5;
+               len2 = (int)sqrt((ctr[0] - vod->origx)*(ctr[0] - vod->origx) + (ctr[1] - vod->origy)*(ctr[1] - vod->origy)) + 5;
+
+               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;
+               zfac = vod->dist0 * (2.0*((len2/len1)-1.0) + 1.0) / vod->rv3d->dist;
+       }
+
+       if(zfac != 1.0 && zfac*vod->rv3d->dist > 0.001*vod->grid &&
+                               zfac*vod->rv3d->dist < 10.0*vod->far)
+               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)) {
+               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);
+       } 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;
+
+       if(vod->rv3d->viewlock & RV3D_BOXVIEW)
+               view3d_boxview_sync(vod->sa, vod->ar);
+
+       ED_region_tag_redraw(vod->ar);
+}
+
+
+static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       ViewOpsData *vod= op->customdata;
+
+       /* execute the events */
+       switch(event->type) {
+               case MOUSEMOVE:
+                       viewzoom_apply(vod, event->x, event->y);
+                       break;
+
+               default:
+                       if(event->type==vod->origkey && event->val==0) {
+                               request_depth_update(CTX_wm_region_view3d(C));
+
+                               MEM_freeN(vod);
+                               op->customdata= NULL;
+
+                               return OPERATOR_FINISHED;
+                       }
+       }
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+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");
+
+       if(delta < 0) {
+               /* this min and max is also in viewmove() */
+               if(rv3d->persp==V3D_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->persp==V3D_CAMOB) {
+                       rv3d->camzoom+= 10;
+                       if(rv3d->camzoom>300) rv3d->camzoom= 300;
+               }
+               else if(rv3d->dist> 0.001*v3d->grid) rv3d->dist*=.83333f;
+       }
+
+       if(rv3d->viewlock & RV3D_BOXVIEW)
+               view3d_boxview_sync(CTX_wm_area(C), CTX_wm_region(C));
+       
+       request_depth_update(CTX_wm_region_view3d(C));
+       ED_region_tag_redraw(CTX_wm_region(C));
+
+       return OPERATOR_FINISHED;
+}
+
+static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       int delta= RNA_int_get(op->ptr, "delta");
+
+       if(delta) {
+               viewzoom_exec(C, op);
+       }
+       else {
+               /* makes op->customdata */
+               viewops_data(C, op, event);
+
+               /* add temp handler */
+               WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+               return OPERATOR_RUNNING_MODAL;
+       }
+       return OPERATOR_FINISHED;
+}
+
+
+void VIEW3D_OT_zoom(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Zoom view";
+       ot->description = "Zoom in/out in the view.";
+       ot->idname= "VIEW3D_OT_zoom";
+
+       /* api callbacks */
+       ot->invoke= viewzoom_invoke;
+       ot->exec= viewzoom_exec;
+       ot->modal= viewzoom_modal;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+       
+       RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+}
+
+static int viewhome_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.4x */
+{
+       ARegion *ar= CTX_wm_region(C);
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       Scene *scene= CTX_data_scene(C);
+       Base *base;
+
+       int center= RNA_boolean_get(op->ptr, "center");
+
+       float size, min[3], max[3], afm[3];
+       int ok= 1, onedone=0;
+
+       if(center) {
+               min[0]= min[1]= min[2]= 0.0f;
+               max[0]= max[1]= max[2]= 0.0f;
+       }
+       else {
+               INIT_MINMAX(min, max);
+       }
+
+       for(base= scene->base.first; base; base= base->next) {
+               if(base->lay & v3d->lay) {
+                       onedone= 1;
+                       minmax_object(base->object, min, max);
+               }
+       }
+       if(!onedone) return OPERATOR_FINISHED; /* TODO - should this be cancel? */
+
+       afm[0]= (max[0]-min[0]);
+       afm[1]= (max[1]-min[1]);
+       afm[2]= (max[2]-min[2]);
+       size= 0.7f*MAX3(afm[0], afm[1], afm[2]);
+       if(size==0.0) ok= 0;
+
+       if(ok) {
+               float new_dist;
+               float new_ofs[3];
+
+               new_dist = size;
+               new_ofs[0]= -(min[0]+max[0])/2.0f;
+               new_ofs[1]= -(min[1]+max[1])/2.0f;
+               new_ofs[2]= -(min[2]+max[2])/2.0f;
+
+               // correction for window aspect ratio
+               if(ar->winy>2 && ar->winx>2) {
+                       size= (float)ar->winx/(float)ar->winy;
+                       if(size<1.0) size= 1.0f/size;
+                       new_dist*= size;
+               }
+
+               if (rv3d->persp==V3D_CAMOB) {
+                       rv3d->persp= V3D_PERSP;
+                       smooth_view(C, NULL, v3d->camera, new_ofs, NULL, &new_dist, NULL); 
+               }
+       }
+// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
+       
+       if(rv3d->viewlock & RV3D_BOXVIEW)
+               view3d_boxview_copy(CTX_wm_area(C), ar);
+
+       return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_viewhome(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "View home";
+       ot->description = "View all objects in scene.";
+       ot->idname= "VIEW3D_OT_viewhome";
+
+       /* api callbacks */
+       ot->exec= viewhome_exec;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+       
+       RNA_def_boolean(ot->srna, "center", 0, "Center", "");
+}
+
+static int viewcenter_exec(bContext *C, wmOperator *op) /* like a localview without local!, was centerview() in 2.4x */
+{
+       ARegion *ar= CTX_wm_region(C);
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= OBACT;
+       Object *obedit= CTX_data_edit_object(C);
+       float size, min[3], max[3], afm[3];
+       int ok=0;
+
+       /* SMOOTHVIEW */
+       float new_ofs[3];
+       float new_dist;
+
+       INIT_MINMAX(min, max);
+
+       if (G.f & G_WEIGHTPAINT) {
+               /* hardcoded exception, we look for the one selected armature */
+               /* this is weak code this way, we should make a generic active/selection callback interface once... */
+               Base *base;
+               for(base=scene->base.first; base; base= base->next) {
+                       if(TESTBASELIB(v3d, base)) {
+                               if(base->object->type==OB_ARMATURE)
+                                       if(base->object->flag & OB_POSEMODE)
+                                               break;
+                       }
+               }
+               if(base)
+                       ob= base->object;
+       }
+
+
+       if(obedit) {
+               ok = minmax_verts(obedit, min, max);    /* only selected */
+       }
+       else if(ob && (ob->flag & OB_POSEMODE)) {
+               if(ob->pose) {
+                       bArmature *arm= ob->data;
+                       bPoseChannel *pchan;
+                       float vec[3];
+
+                       for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                               if(pchan->bone->flag & BONE_SELECTED) {
+                                       if(pchan->bone->layer & arm->layer) {
+                                               ok= 1;
+                                               VECCOPY(vec, pchan->pose_head);
+                                               Mat4MulVecfl(ob->obmat, vec);
+                                               DO_MINMAX(vec, min, max);
+                                               VECCOPY(vec, pchan->pose_tail);
+                                               Mat4MulVecfl(ob->obmat, vec);
+                                               DO_MINMAX(vec, min, max);
+                                       }
+                               }
+                       }
+               }
+       }
+       else if (FACESEL_PAINT_TEST) {
+// XXX         ok= minmax_tface(min, max);
+       }
+       else if (G.f & G_PARTICLEEDIT) {
+               ok= PE_minmax(scene, min, max);
+       }
+       else {
+               Base *base= FIRSTBASE;
+               while(base) {
+                       if(TESTBASE(v3d, base))  {
+                               minmax_object(base->object, min, max);
+                               /* account for duplis */
+                               minmax_object_duplis(scene, base->object, min, max);
+
+                               ok= 1;
+                       }
+                       base= base->next;
+               }
+       }
+
+       if(ok==0) return OPERATOR_FINISHED;
+
+       afm[0]= (max[0]-min[0]);
+       afm[1]= (max[1]-min[1]);
+       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)
+               size*= 0.7;
+       
+       if(size <= v3d->near*1.5f) size= v3d->near*1.5f;
+
+       new_ofs[0]= -(min[0]+max[0])/2.0f;
+       new_ofs[1]= -(min[1]+max[1])/2.0f;
+       new_ofs[2]= -(min[2]+max[2])/2.0f;
+
+       new_dist = size;
+
+       /* correction for window aspect ratio */
+       if(ar->winy>2 && ar->winx>2) {
+               size= (float)ar->winx/(float)ar->winy;
+               if(size<1.0f) size= 1.0f/size;
+               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;
+               smooth_view(C, v3d->camera, NULL, new_ofs, NULL, &new_dist, NULL);
+       } 
+       else {
+               smooth_view(C, NULL, NULL, new_ofs, NULL, &new_dist, NULL);
+       }
+
+// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
+       if(rv3d->viewlock & RV3D_BOXVIEW)
+               view3d_boxview_copy(CTX_wm_area(C), ar);
+
+       return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_viewcenter(wmOperatorType *ot)
+{
+
+       /* identifiers */
+       ot->name= "View center";
+       ot->description = "Move the view to the selection center.";
+       ot->idname= "VIEW3D_OT_viewcenter";
+
+       /* api callbacks */
+       ot->exec= viewcenter_exec;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+}
+
+/* ********************* Set render border operator ****************** */
+
+static int render_border_exec(bContext *C, wmOperator *op)
+{
+       View3D *v3d = CTX_wm_view3d(C);
+       ARegion *ar= CTX_wm_region(C);
+       Scene *scene= CTX_data_scene(C);
+       
+       rcti rect;
+       rctf vb;
+       
+       /* get border select values using rna */
+       rect.xmin= RNA_int_get(op->ptr, "xmin");
+       rect.ymin= RNA_int_get(op->ptr, "ymin");
+       rect.xmax= RNA_int_get(op->ptr, "xmax");
+       rect.ymax= RNA_int_get(op->ptr, "ymax");
+       
+       /* calculate range */
+       calc_viewborder(scene, ar, v3d, &vb);
+
+       scene->r.border.xmin= ((float)rect.xmin-vb.xmin)/(vb.xmax-vb.xmin);
+       scene->r.border.ymin= ((float)rect.ymin-vb.ymin)/(vb.ymax-vb.ymin);
+       scene->r.border.xmax= ((float)rect.xmax-vb.xmin)/(vb.xmax-vb.xmin);
+       scene->r.border.ymax= ((float)rect.ymax-vb.ymin)/(vb.ymax-vb.ymin);
+       
+       /* actually set border */       
+       CLAMP(scene->r.border.xmin, 0.0, 1.0);
+       CLAMP(scene->r.border.ymin, 0.0, 1.0);
+       CLAMP(scene->r.border.xmax, 0.0, 1.0);
+       CLAMP(scene->r.border.ymax, 0.0, 1.0);
+               
+       /* drawing a border surrounding the entire camera view switches off border rendering
+        * or the border covers no pixels */
+       if ((scene->r.border.xmin <= 0.0 && scene->r.border.xmax >= 1.0 &&
+               scene->r.border.ymin <= 0.0 && scene->r.border.ymax >= 1.0) ||
+          (scene->r.border.xmin == scene->r.border.xmax ||
+               scene->r.border.ymin == scene->r.border.ymax ))
+       {
+               scene->r.mode &= ~R_BORDER;
+       } else {
+               scene->r.mode |= R_BORDER;
+       }
+       
+       return OPERATOR_FINISHED;
+
+}
+
+static int view3d_render_border_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       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);     
+       else return OPERATOR_PASS_THROUGH;
+}
+
+void VIEW3D_OT_render_border(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Set Render Border";
+       ot->description = "Set the boundries of the border render and enables border render .";
+       ot->idname= "VIEW3D_OT_render_border";
+
+       /* api callbacks */
+       ot->invoke= view3d_render_border_invoke;
+       ot->exec= render_border_exec;
+       ot->modal= WM_border_select_modal;
+       
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* rna */
+       RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+}
+/* ********************* Border Zoom operator ****************** */
+
+static int view3d_border_zoom_exec(bContext *C, wmOperator *op)
+{
+       ARegion *ar= CTX_wm_region(C);
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       Scene *scene= CTX_data_scene(C);
+       
+       /* Zooms in on a border drawn by the user */
+       rcti rect;
+       float dvec[3], vb[2], xscale, yscale, scale;
+
+       /* SMOOTHVIEW */
+       float new_dist;
+       float new_ofs[3];
+
+       /* ZBuffer depth vars */
+       bglMats mats;
+       float depth, depth_close= MAXFLOAT;
+       int had_depth = 0;
+       double cent[2],  p[3];
+       int xs, ys;
+       
+       /* note; otherwise opengl won't work */
+       view3d_operator_needs_opengl(C);
+       
+       /* get border select values using rna */
+       rect.xmin= RNA_int_get(op->ptr, "xmin");
+       rect.ymin= RNA_int_get(op->ptr, "ymin");
+       rect.xmax= RNA_int_get(op->ptr, "xmax");
+       rect.ymax= RNA_int_get(op->ptr, "ymax");
+       
+       /* Get Z Depths, needed for perspective, nice for ortho */
+       bgl_get_mats(&mats);
+       draw_depth(scene, ar, v3d, NULL);
+
+       /* force updating */
+       if (rv3d->depths) {
+               had_depth = 1;
+               rv3d->depths->damaged = 1;
+       }
+
+       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;
+
+       /* 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 (had_depth==0) {
+               MEM_freeN(rv3d->depths->depths);
+               rv3d->depths->depths = NULL;
+       }
+       rv3d->depths->damaged = 1;
+
+       cent[0] = (((double)rect.xmin)+((double)rect.xmax)) / 2;
+       cent[1] = (((double)rect.ymin)+((double)rect.ymax)) / 2;
+
+       if (rv3d->persp==V3D_PERSP) {
+               double p_corner[3];
+
+               /* no depths to use, we cant do anything! */
+               if (depth_close==MAXFLOAT){
+                       BKE_report(op->reports, RPT_ERROR, "Depth Too Large");
+                       return OPERATOR_CANCELLED;
+               }
+               /* convert border to 3d coordinates */
+               if ((   !gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) ||
+                       (       !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])))
+                       return OPERATOR_CANCELLED;
+
+               dvec[0] = p[0]-p_corner[0];
+               dvec[1] = p[1]-p_corner[1];
+               dvec[2] = p[2]-p_corner[2];
+
+               new_dist = VecLength(dvec);
+               if(new_dist <= v3d->near*1.5) new_dist= v3d->near*1.5;
+
+               new_ofs[0] = -p[0];
+               new_ofs[1] = -p[1];
+               new_ofs[2] = -p[2];
+
+       } else { /* othographic */
+               /* find the current window width and height */
+               vb[0] = ar->winx;
+               vb[1] = ar->winy;
+
+               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])) {
+                       new_ofs[0] = -p[0];
+                       new_ofs[1] = -p[1];
+                       new_ofs[2] = -p[2];
+               } else {
+                       /* We cant use the depth, fallback to the old way that dosnt set the center depth */
+                       new_ofs[0] = rv3d->ofs[0];
+                       new_ofs[1] = rv3d->ofs[1];
+                       new_ofs[2] = rv3d->ofs[2];
+
+                       initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]);
+
+                       window_to_3d_delta(ar, dvec, (rect.xmin+rect.xmax-vb[0])/2, (rect.ymin+rect.ymax-vb[1])/2);
+                       /* center the view to the center of the rectangle */
+                       VecSubf(new_ofs, new_ofs, dvec);
+               }
+
+               /* work out the ratios, so that everything selected fits when we zoom */
+               xscale = ((rect.xmax-rect.xmin)/vb[0]);
+               yscale = ((rect.ymax-rect.ymin)/vb[1]);
+               scale = (xscale >= yscale)?xscale:yscale;
+
+               /* zoom in as required, or as far as we can go */
+               new_dist = ((new_dist*scale) >= 0.001*v3d->grid)? new_dist*scale:0.001*v3d->grid;
+       }
+
+       smooth_view(C, NULL, NULL, new_ofs, NULL, &new_dist, NULL);
+       
+       if(rv3d->viewlock & RV3D_BOXVIEW)
+               view3d_boxview_sync(CTX_wm_area(C), ar);
+       
+       return OPERATOR_FINISHED;
+}
+
+static int view3d_border_zoom_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) 
+               return WM_border_select_invoke(C, op, event);   
+       else 
+               return OPERATOR_PASS_THROUGH;
+}
+
+void VIEW3D_OT_zoom_border(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Border Zoom";
+       ot->description = "Zoom in the view to the nearest object contained in the border.";
+       ot->idname= "VIEW3D_OT_zoom_border";
+
+       /* api callbacks */
+       ot->invoke= view3d_border_zoom_invoke;
+       ot->exec= view3d_border_zoom_exec;
+       ot->modal= WM_border_select_modal;
+       
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+       
+       /* rna */
+       RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+}
+/* ********************* 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"},
+       {0, NULL, 0, NULL, NULL}};
+
+static void axis_set_view(bContext *C, float q1, float q2, float q3, float q4, short view, int perspo)
+{
+       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(rv3d->viewlock) {
+               ED_region_tag_redraw(CTX_wm_region(C));
+               return;
+       }
+
+       if (rv3d->persp==V3D_CAMOB && v3d->camera) {
+
+               if (U.uiflag & USER_AUTOPERSP) rv3d->persp= V3D_ORTHO;
+               else if(rv3d->persp==V3D_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;
+
+               smooth_view(C, NULL, NULL, NULL, new_quat, NULL, NULL);
+       }
+
+}
+
+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;
+
+       viewnum = RNA_enum_get(op->ptr, "type");
+
+       /* Use this to test if we started out with a camera */
+
+       switch (viewnum) {
+               case V3D_VIEW_BOTTOM :
+                       axis_set_view(C, 0.0, -1.0, 0.0, 0.0, viewnum, perspo);
+                       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);
+                       break;
+
+               case V3D_VIEW_LEFT:
+                       axis_set_view(C, 0.5, -0.5, 0.5, 0.5, viewnum, perspo);
+                       break;
+
+               case V3D_VIEW_TOP:
+                       axis_set_view(C, 1.0, 0.0, 0.0, 0.0, viewnum, perspo);
+                       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);
+                       break;
+
+               case V3D_VIEW_RIGHT:
+                       axis_set_view(C, 0.5, -0.5, -0.5, -0.5, viewnum, perspo);
+                       break;
+
+               case V3D_VIEW_CAMERA:
+                       if(rv3d->viewlock==0) {
+                               /* lastview -  */
+
+                               if(rv3d->persp != V3D_CAMOB) {
+                                       /* store settings of current view before allowing overwriting with camera view */
+                                       QUATCOPY(rv3d->lviewquat, rv3d->viewquat);
+                                       rv3d->lview= rv3d->view;
+                                       rv3d->lpersp= rv3d->persp;
+                                       
+       #if 0
+                                       if(G.qual==LR_ALTKEY) {
+                                               if(oldcamera && is_an_active_object(oldcamera)) {
+                                                       v3d->camera= oldcamera;
+                                               }
+                                               handle_view3d_lock();
+                                       }
+       #endif
+                                       
+                                       if(BASACT) {
+                                               /* check both G.vd as G.scene cameras */
+                                               if((v3d->camera==NULL || scene->camera==NULL) && OBACT->type==OB_CAMERA) {
+                                                       v3d->camera= OBACT;
+                                                       /*handle_view3d_lock();*/
+                                               }
+                                       }
+                                       
+                                       if(v3d->camera==NULL) {
+                                               v3d->camera= scene_find_camera(scene);
+                                               /*handle_view3d_lock();*/
+                                       }
+                                       rv3d->persp= V3D_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);
+                               }
+                       }
+                       break;
+
+               default :
+                       break;
+       }
+
+       if(rv3d->persp != V3D_CAMOB) perspo= rv3d->persp;
+
+       return OPERATOR_FINISHED;
+}
+void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "View numpad";
+       ot->description = "Set the view.";
+       ot->idname= "VIEW3D_OT_viewnumpad";
+
+       /* api callbacks */
+       ot->exec= viewnumpad_exec;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+       
+       RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "The Type of view");
+}
+
+static EnumPropertyItem prop_view_orbit_items[] = {
+       {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the Left"},
+       {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the Right"},
+       {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view Up"},
+       {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view Down"},
+       {0, NULL, 0, NULL, NULL}};
+
+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];           
+       int orbitdir;
+
+       orbitdir = RNA_enum_get(op->ptr, "type");
+       
+       if(rv3d->viewlock==0) {
+
+               if(rv3d->persp != V3D_CAMOB) {
+                       if(orbitdir == V3D_VIEW_STEPLEFT || orbitdir == V3D_VIEW_STEPRIGHT) {
+                               /* z-axis */
+                               phi= (float)(M_PI/360.0)*U.pad_rot_angle;
+                               if(orbitdir == V3D_VIEW_STEPRIGHT) phi= -phi;
+                               si= (float)sin(phi);
+                               q1[0]= (float)cos(phi);
+                               q1[1]= q1[2]= 0.0;
+                               q1[3]= si;
+                               QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+                               rv3d->view= 0;
+                       }
+                       if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) {
+                               /* horizontal axis */
+                               VECCOPY(q1+1, rv3d->viewinv[0]);
+
+                               Normalize(q1+1);
+                               phi= (float)(M_PI/360.0)*U.pad_rot_angle;
+                               if(orbitdir == V3D_VIEW_STEPDOWN) phi= -phi;
+                               si= (float)sin(phi);
+                               q1[0]= (float)cos(phi);
+                               q1[1]*= si;
+                               q1[2]*= si;
+                               q1[3]*= si;
+                               QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+                               rv3d->view= 0;
+                       }
+                       ED_region_tag_redraw(ar);
+               }
+       }
+
+       return OPERATOR_FINISHED;       
+}
+
+void VIEW3D_OT_view_orbit(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "View Orbit";
+       ot->description = "Orbit the view.";
+       ot->idname= "VIEW3D_OT_view_orbit";
+
+       /* api callbacks */
+       ot->exec= vieworbit_exec;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+       RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
+}
+
+static EnumPropertyItem prop_view_pan_items[] = {
+       {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"},
+       {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"},
+       {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view Up"},
+       {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view Down"},
+       {0, NULL, 0, NULL, NULL}};
+
+static int viewpan_exec(bContext *C, wmOperator *op)
+{
+       ARegion *ar= CTX_wm_region(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);    
+       float vec[3];   
+       int pandir;
+
+       pandir = RNA_enum_get(op->ptr, "type");
+       
+       initgrabz(rv3d, 0.0, 0.0, 0.0);
+
+       if(pandir == V3D_VIEW_PANRIGHT) window_to_3d_delta(ar, vec, -32, 0);
+       else if(pandir == V3D_VIEW_PANLEFT) window_to_3d_delta(ar, vec, 32, 0);
+       else if(pandir == V3D_VIEW_PANUP) window_to_3d_delta(ar, vec, 0, -25);
+       else if(pandir == V3D_VIEW_PANDOWN) window_to_3d_delta(ar, vec, 0, 25);
+       rv3d->ofs[0]+= vec[0];
+       rv3d->ofs[1]+= vec[1];
+       rv3d->ofs[2]+= vec[2];
+
+       if(rv3d->viewlock & RV3D_BOXVIEW)
+               view3d_boxview_sync(CTX_wm_area(C), ar);
+
+       ED_region_tag_redraw(ar);
+
+       return OPERATOR_FINISHED;       
+}
+
+void VIEW3D_OT_view_pan(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "View Pan";
+       ot->description = "Pan the view.";
+       ot->idname= "VIEW3D_OT_view_pan";
+
+       /* api callbacks */
+       ot->exec= viewpan_exec;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+       RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
+}
+
+static int viewpersportho_exec(bContext *C, wmOperator *op)
+{
+       ARegion *ar= CTX_wm_region(C);
+       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;
+               ED_region_tag_redraw(ar);
+       }
+
+       return OPERATOR_FINISHED;
+       
+}
+
+void VIEW3D_OT_view_persportho(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "View persp/ortho";
+       ot->description = "Switch the current view from perspective/orthographic.";
+       ot->idname= "VIEW3D_OT_view_persportho";
+
+       /* api callbacks */
+       ot->exec= viewpersportho_exec;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+}
+
+
+/* ********************* set clipping operator ****************** */
+
+static int view3d_clipping_exec(bContext *C, wmOperator *op)
+{
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       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");
+       rect.xmax= RNA_int_get(op->ptr, "xmax");
+       rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+       rv3d->rflag |= RV3D_CLIPPING;
+       rv3d->clipbb= MEM_callocN(sizeof(BoundBox), "clipbb");
+
+       /* 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]);
+
+               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;
+}
+
+static int view3d_clipping_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       ARegion *ar= CTX_wm_region(C);
+
+       if(rv3d->rflag & RV3D_CLIPPING) {
+               rv3d->rflag &= ~RV3D_CLIPPING;
+               ED_region_tag_redraw(ar);
+               if(rv3d->clipbb) MEM_freeN(rv3d->clipbb);
+               rv3d->clipbb= NULL;
+               return OPERATOR_FINISHED;
+       }
+       else {
+               return WM_border_select_invoke(C, op, event);
+       }
+}
+
+/* toggles */
+void VIEW3D_OT_clipping(wmOperatorType *ot)
+{
+
+       /* identifiers */
+       ot->name= "Clipping Border";
+       ot->description = "Set the view clipping border.";
+       ot->idname= "VIEW3D_OT_clipping";
+
+       /* api callbacks */
+       ot->invoke= view3d_clipping_invoke;
+       ot->exec= view3d_clipping_exec;
+       ot->modal= WM_border_select_modal;
+
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER;
+       
+       /* rna */
+       RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+       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= OPTYPE_REGISTER;
+       
+       /* 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 */
+static int set_3dcursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       Scene *scene= CTX_data_scene(C);
+       ARegion *ar= CTX_wm_region(C);
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3];
+       short mx, my, mval[2];
+//     short ctrl= 0; // XXX
+       
+       fp= give_cursor(scene, v3d);
+       
+//     if(obedit && ctrl) lr_click= 1;
+       VECCOPY(oldcurs, fp);
+       
+       mx= event->x - ar->winrct.xmin;
+       my= event->y - ar->winrct.ymin;
+       project_short_noclip(ar, fp, mval);
+       
+       initgrabz(rv3d, fp[0], fp[1], fp[2]);
+       
+       if(mval[0]!=IS_CLIPPED) {
+               
+               window_to_3d_delta(ar, dvec, mval[0]-mx, mval[1]-my);
+               VecSubf(fp, fp, dvec);
+       }
+       else {
+               
+               dx= ((float)(mx-(ar->winx/2)))*rv3d->zfac/(ar->winx/2);
+               dy= ((float)(my-(ar->winy/2)))*rv3d->zfac/(ar->winy/2);
+               
+               fz= rv3d->persmat[0][3]*fp[0]+ rv3d->persmat[1][3]*fp[1]+ rv3d->persmat[2][3]*fp[2]+ rv3d->persmat[3][3];
+               fz= fz/rv3d->zfac;
+               
+               fp[0]= (rv3d->persinv[0][0]*dx + rv3d->persinv[1][0]*dy+ rv3d->persinv[2][0]*fz)-rv3d->ofs[0];
+               fp[1]= (rv3d->persinv[0][1]*dx + rv3d->persinv[1][1]*dy+ rv3d->persinv[2][1]*fz)-rv3d->ofs[1];
+               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));
+       
+       /* prevent other mouse ops to fail */
+       return OPERATOR_PASS_THROUGH;
+}
+
+void VIEW3D_OT_cursor3d(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Set 3D Cursor";
+       ot->description = "Set the location of the 3D cursor.";
+       ot->idname= "VIEW3D_OT_cursor3d";
+       
+       /* api callbacks */
+       ot->invoke= set_3dcursor_invoke;
+       
+       ot->poll= ED_operator_view3d_active;
+       
+       /* rna later */
+
+}
+
+
+/* ************************* below the line! *********************** */
+
+
+/* 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;
+       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);
+       draw_depth(scene, ar, v3d, NULL);
+
+       /* force updating */
+       if (rv3d->depths) {
+               had_depth = 1;
+               rv3d->depths->damaged = 1;
+       }
+
+       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;
+
+       /* 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)
+               return 0;
 
-       if( fabs(vec[2])>fabs(vec[1]) && fabs(vec[2])>fabs(vec[0]) ) {
-               vec[0]= 0.0;
-               vec[1]= 0.0;
-               if(vec[2]>0.0) vec[2]= 1.0; else vec[2]= -1.0;
-       }
-       else if( fabs(vec[1])>fabs(vec[0]) && fabs(vec[1])>fabs(vec[2]) ) {
-               vec[0]= 0.0;
-               vec[2]= 0.0;
-               if(vec[1]>0.0) vec[1]= 1.0; else vec[1]= -1.0;
-       }
-       else  {
-               vec[1]= 0.0;
-               vec[2]= 0.0;
-               if(vec[0]>0.0) vec[0]= 1.0; else vec[0]= -1.0;
+       if (had_depth==0) {
+               MEM_freeN(rv3d->depths->depths);
+               rv3d->depths->depths = NULL;
        }
-}
+       rv3d->depths->damaged = 1;
 
-void calctrackballvec(rcti *area, short *mval, float *vec)
-{
-       float x, y, radius, d, z, t;
-       
-       radius= TRACKBALLSIZE;
-       
-       /* x en y normalizeren */
-       x= (area->xmax + area->xmin)/2 -mval[0];
-       x/= (float)((area->xmax - area->xmin)/4);
-       y= (area->ymax + area->ymin)/2 -mval[1];
-       y/= (float)((area->ymax - area->ymin)/2);
-       
-       d = sqrt(x*x + y*y);
-       if (d < radius*M_SQRT1_2)       /* Inside sphere */
-               z = sqrt(radius*radius - d*d);
-       else
-       {                       /* On hyperbola */
-               t = radius / M_SQRT2;
-               z = t*t / d;
-       }
+       cent[0] = (double)mval[0];
+       cent[1] = (double)mval[1];
 
-       vec[0]= x;
-       vec[1]= y;
-       vec[2]= -z;             /* yah yah! */
+       if (!gluUnProject(cent[0], cent[1], depth_close, 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;
 }
 
 
+
+/* ********************* NDOF ************************ */
+/* note: this code is confusing and unclear... (ton) */
+/* **************************************************** */
+
 // ndof scaling will be moved to user setting.
 // In the mean time this is just a place holder.
 
@@ -171,7 +1955,7 @@ void calctrackballvec(rcti *area, short *mval, float *vec)
 // and up to +/- 1000 if set to maximum
 // because i remove the scaling by delta,
 // which was a bad idea as it depend of the system
-// speed and os, i changed the scaling values, but 
+// speed and os, i changed the scaling values, but
 // those are still not ok
 
 
@@ -188,7 +1972,7 @@ void filterNDOFvalues(float *sbval)
 {
        int i=0;
        float max  = 0.0;
-       
+
        for (i =0; i<6;i++)
                if (fabs(sbval[i]) > max)
                        max = fabs(sbval[i]);
@@ -197,8 +1981,8 @@ void filterNDOFvalues(float *sbval)
                        sbval[i]=0.0;
 }
 
-// statics for controlling v3d->dist corrections.
-// viewmoveNDOF zeros and adjusts v3d->ofs.
+// statics for controlling rv3d->dist corrections.
+// viewmoveNDOF zeros and adjusts rv3d->ofs.
 // viewmove restores based on dz_flag state.
 
 int dz_flag = 0;
@@ -206,6 +1990,7 @@ float m_dist;
 
 void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
 {
+       RegionView3D *rv3d= ar->regiondata;
     int i;
     float phi;
     float dval[7];
@@ -256,10 +2041,10 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
        // until the first draw and doesn't update the menu
        // to reflect persp mode.
 
-       v3d->persp = V3D_PERSP;
+       rv3d->persp = V3D_PERSP;
 
 
-       // Correct the distance jump if v3d->dist != 0
+       // Correct the distance jump if rv3d->dist != 0
 
        // This is due to a side effect of the original
        // mouse view rotation code. The rotation point is
@@ -271,15 +2056,15 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
        // movement devices must subtract this from their
        // view transformations.
 
-       if(v3d->dist != 0.0) {
+       if(rv3d->dist != 0.0) {
                dz_flag = 1;
-               m_dist = v3d->dist;
+               m_dist = rv3d->dist;
                upvec[0] = upvec[1] = 0;
-               upvec[2] = v3d->dist;
-               Mat3CpyMat4(mat, v3d->viewinv);
+               upvec[2] = rv3d->dist;
+               Mat3CpyMat4(mat, rv3d->viewinv);
                Mat3MulVecfl(mat, upvec);
-               VecSubf(v3d->ofs, v3d->ofs, upvec);
-               v3d->dist = 0.0;
+               VecSubf(rv3d->ofs, rv3d->ofs, upvec);
+               rv3d->dist = 0.0;
        }
 
 
@@ -292,7 +2077,7 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
 
        // rotate device x and y by view z
 
-       Mat3CpyMat4(mat, v3d->viewinv);
+       Mat3CpyMat4(mat, rv3d->viewinv);
        mat[2][2] = 0.0f;
        Mat3MulVecfl(mat, rvec);
 
@@ -301,7 +2086,7 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
        phi = Normalize(rvec);
        if(phi != 0) {
                VecRotToQuat(rvec,phi,q1);
-               QuatMul(v3d->viewquat, v3d->viewquat, q1);
+               QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
        }
 
 
@@ -314,13 +2099,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, v3d->viewinv);
+       Mat3CpyMat4(mat, rv3d->viewinv);
        mat[2][2] = 0.0f;
        Mat3MulVecfl(mat, tvec);
 
        // translate the view
 
-       VecSubf(v3d->ofs, v3d->ofs, tvec);
+       VecSubf(rv3d->ofs, rv3d->ofs, tvec);
 
 
        /*----------------------------------------------------
@@ -332,596 +2117,56 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
 // XXX BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT);
 }
 
-/* Zooms in on a border drawn by the user */
-static int view_autodist(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist )
-{
-       rcti rect;
-       /* ZBuffer depth vars */
-       bglMats mats;
-       float depth, depth_close= MAXFLOAT;
-       int had_depth = 0;
-       double cent[2],  p[3];
-       int xs, ys;
-       
-// XXX         getmouseco_areawin(mval);
-       
-// XXX persp(PERSP_VIEW);
-       
-       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);
-       draw_depth(C, scene, ar, v3d, NULL);
-       
-       /* force updating */
-       if (v3d->depths) {
-               had_depth = 1;
-               v3d->depths->damaged = 1;
-       }
-       
-       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 >= v3d->depths->w) rect.xmax = v3d->depths->w-1;
-       if (rect.ymax >= v3d->depths->h) rect.ymax = v3d->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= v3d->depths->depths[ys*v3d->depths->w+xs];
-                       if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) {
-                               if (depth_close > depth) {
-                                       depth_close = depth;
-                               }
-                       }
-               }
-       }
-       
-       if (depth_close==MAXFLOAT)
-               return 0;
-               
-       if (had_depth==0) {
-               MEM_freeN(v3d->depths->depths);
-               v3d->depths->depths = NULL;
-       }
-       v3d->depths->damaged = 1;
-       
-       cent[0] = (double)mval[0];
-       cent[1] = (double)mval[1];
-       
-       if (!gluUnProject(cent[0], cent[1], depth_close, 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;
-}
-
-static void view_zoom_mouseloc(ARegion *ar, View3D *v3d, float dfac, short *mouseloc)
-{
-       if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
-               short vb[2];
-               float dvec[3];
-               float tvec[3];
-               float tpos[3];
-               float new_dist;
-               
-               /* find the current window width and height */
-               vb[0] = ar->winx;
-               vb[1] = ar->winy;
-               
-               tpos[0] = -v3d->ofs[0];
-               tpos[1] = -v3d->ofs[1];
-               tpos[2] = -v3d->ofs[2];
-               
-               /* Project cursor position into 3D space */
-               initgrabz(v3d, tpos[0], tpos[1], tpos[2]);
-               window_to_3d(ar, v3d, dvec, mouseloc[0]-vb[0]/2, mouseloc[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 = v3d->dist * dfac;
-               
-               VECCOPY(v3d->ofs, tvec);
-               v3d->dist = new_dist;
-               
-               /* Calculate final offset */
-               dvec[0] = tvec[0] + dvec[0] * dfac;
-               dvec[1] = tvec[1] + dvec[1] * dfac;
-               dvec[2] = tvec[2] + dvec[2] * dfac;
-               
-               VECCOPY(v3d->ofs, dvec);
-       } else {
-               v3d->dist *= dfac;
-       }
-}
-
-
-#define COS45 0.70710678118654746
-#define SIN45 COS45
-
-void viewmove(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, int mode)
-{
-       static float lastofs[3] = {0,0,0};
-       Object *ob = OBACT;
-       float firstvec[3], newvec[3], dvec[3];
-       float reverse, oldquat[4], q1[4], si, phi, dist0;
-       float ofs[3], obofs[3]= {0.0f, 0.0f, 0.0f};
-       int firsttime=1;
-       short mvalball[2], mval[2], mvalo[2], mval_area[2], mvali[2];
-       short use_sel = 0;
-       short preview3d_event= 1;
-       
-       // locals for dist correction
-       float mat[3][3];
-       float upvec[3];
-
-               /* 3D window may not be defined */
-       if( !v3d ) {
-               fprintf( stderr, "v3d == NULL in viewmove()\n" );
-               return;
-       }
-       
-       // dist correction from other movement devices  
-       if((dz_flag)||v3d->dist==0) {
-               dz_flag = 0;
-               v3d->dist = m_dist;
-               upvec[0] = upvec[1] = 0;
-               upvec[2] = v3d->dist;
-               Mat3CpyMat4(mat, v3d->viewinv);
-               Mat3MulVecfl(mat, upvec);
-               VecAddf(v3d->ofs, v3d->ofs, upvec);
-       }
-               
-       /* sometimes this routine is called from headerbuttons */
-
-// XXX areawinset(ar->win);
-       
-       QUATCOPY(oldquat, v3d->viewquat);
-       
-// XXX getmouseco_areawin(mval_area);  /* for zoom to mouse loc */
-// XXX getmouseco_sc(mvali);           /* work with screen coordinates because of trackball function */
-       mvalball[0]= mvalo[0] = mvali[0];                       /* needed for turntable to work */
-       mvalball[1]= mvalo[1] = mvali[1];
-       dist0= v3d->dist;
-       
-       calctrackballvec(&ar->winrct, mvalo, firstvec);
-
-       /* cumultime(0); */
-
-       if(!G.obedit && (G.f & G_SCULPTMODE) && ob && v3d->pivot_last) {
-               use_sel= 1;
-               VecCopyf(ofs, v3d->ofs);
-
-// XXX         VecCopyf(obofs, sculpt_data()->pivot);
-               Mat4MulVecfl(ob->obmat, obofs);
-               obofs[0]= -obofs[0];
-               obofs[1]= -obofs[1];
-               obofs[2]= -obofs[2];
-       }
-       else if (U.uiflag & USER_ORBIT_SELECTION) {
-               use_sel = 1;
-               
-               VECCOPY(ofs, v3d->ofs);
-               
-               /* If there's no selection, lastofs is unmodified and last value since static */
-// XXX         calculateTransformCenter(V3D_CENTROID, lastofs);
-               
-               VECCOPY(obofs, lastofs);
-               VecMulf(obofs, -1.0f);
-       }
-       else if (U.uiflag & USER_ORBIT_ZBUF) {
-               if ((use_sel= view_autodist(C, scene, ar, v3d, mval, obofs))) {
-                       if (v3d->persp==V3D_PERSP) {
-                               float my_origin[3]; /* original v3d->ofs */
-                               float my_pivot[3]; /* view */
-                               
-                               VECCOPY(my_origin, v3d->ofs);
-                               VecMulf(my_origin, -1.0f);                              /* 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] = v3d->dist;
-                               Mat3CpyMat4(mat, v3d->viewinv);
-                               Mat3MulVecfl(mat, upvec);
-                               VecSubf(my_pivot, v3d->ofs, upvec);
-                               VecMulf(my_pivot, -1.0f);                               /* ofs is flipped */
-                               
-                               /* find a new ofs value that is allong the view axis (rather then the mouse location) */
-                               lambda_cp_line_ex(obofs, my_pivot, my_origin, dvec);
-                               dist0 = v3d->dist = VecLenf(my_pivot, dvec);
-                               
-                               VecMulf(dvec, -1.0f);
-                               VECCOPY(v3d->ofs, dvec);
-                       }
-                       VecMulf(obofs, -1.0f);
-                       VECCOPY(ofs, v3d->ofs);
-               } else {
-                       ofs[0] = ofs[1] = ofs[2] = 0.0f;
-               }
-       }
-       else
-               ofs[0] = ofs[1] = ofs[2] = 0.0f;
-       
-       initgrabz(v3d, -v3d->ofs[0], -v3d->ofs[1], -v3d->ofs[2]);
-       
-       reverse= 1.0f;
-       if (v3d->persmat[2][1] < 0.0f)
-               reverse= -1.0f;
-
-       while(TRUE) {
-// XXX                 getmouseco_sc(mval);
-               
-               if(     (mode==2 && U.viewzoom==USER_ZOOM_CONT) || /* continues zoom always update */
-                        mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { /* mouse moved, so update */
-                       
-                       if(firsttime) {
-                               
-                               firsttime= 0;
-                               /* are we translating, rotating or zooming? */
-                               if(mode==0) {
-// XXX                                 if(v3d->view!=0) scrarea_queue_headredraw(ar);  /*for button */
-                               }
-                               if(v3d->persp==V3D_CAMOB && mode!=1 && v3d->camera) {
-                                       v3d->persp= V3D_PERSP;
-// XXX                                 scrarea_do_windraw(ar);
-// XXX                                 scrarea_queue_headredraw(ar);
-                               }
-                       }
-
-                       if(mode==0) {   /* view rotate */
-                               v3d->view= 0; /* need to reset everytime because of view snapping */
-               
-                               if (U.uiflag & USER_AUTOPERSP) v3d->persp= V3D_PERSP;
-
-                               if (U.flag & USER_TRACKBALL) mvalball[0]= mval[0];
-                               mvalball[1]= mval[1];
-                               
-                               calctrackballvec(&ar->winrct, mvalball, newvec);
-                               
-                               VecSubf(dvec, newvec, firstvec);
-                               
-                               si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]);
-                               si/= (2.0*TRACKBALLSIZE);
-                       
-                               if (U.flag & USER_TRACKBALL) {
-                                       Crossf(q1+1, firstvec, newvec);
-       
-                                       Normalize(q1+1);
-       
-                                       /* Allow for rotation beyond the interval
-                                        * [-pi, pi] */
-                                       while (si > 1.0)
-                                               si -= 2.0;
-               
-                                       /* This relation is used instead of
-                                        * phi = asin(si) so that the angle
-                                        * of rotation is linearly proportional
-                                        * to the distance that the mouse is
-                                        * dragged. */
-                                       phi = si * M_PI / 2.0;
-               
-                                       si= sin(phi);
-                                       q1[0]= cos(phi);
-                                       q1[1]*= si;
-                                       q1[2]*= si;
-                                       q1[3]*= si;     
-                                       QuatMul(v3d->viewquat, q1, oldquat);
-
-                                       if (use_sel) {
-                                               /* compute the post multiplication quat, to rotate the offset correctly */
-                                               QUATCOPY(q1, oldquat);
-                                               QuatConj(q1);
-                                               QuatMul(q1, q1, v3d->viewquat);
-
-                                               QuatConj(q1); /* conj == inv for unit quat */
-                                               VECCOPY(v3d->ofs, ofs);
-                                               VecSubf(v3d->ofs, v3d->ofs, obofs);
-                                               QuatMulVecf(q1, v3d->ofs);
-                                               VecAddf(v3d->ofs, v3d->ofs, obofs);
-                                       }
-                               } else {
-                                       /* New turntable view code by John Aughey */
-
-                                       float m[3][3];
-                                       float m_inv[3][3];
-                                       float xvec[3] = {1,0,0};
-                                       /* Sensitivity will control how fast the viewport rotates.  0.0035 was
-                                          obtained experimentally by looking at viewport rotation sensitivities
-                                          on other modeling programs. */
-                                       /* Perhaps this should be a configurable user parameter. */
-                                       const float sensitivity = 0.0035;
-
-                                       /* Get the 3x3 matrix and its inverse from the quaternion */
-                                       QuatToMat3(v3d->viewquat, m);
-                                       Mat3Inv(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);
-
-                                       /* Perform the up/down rotation */
-                                       phi = sensitivity * -(mval[1] - mvalo[1]);
-                                       si = sin(phi);
-                                       q1[0] = cos(phi);
-                                       q1[1] = si * xvec[0];
-                                       q1[2] = si * xvec[1];
-                                       q1[3] = si * xvec[2];
-                                       QuatMul(v3d->viewquat, v3d->viewquat, q1);
-
-                                       if (use_sel) {
-                                               QuatConj(q1); /* conj == inv for unit quat */
-                                               VecSubf(v3d->ofs, v3d->ofs, obofs);
-                                               QuatMulVecf(q1, v3d->ofs);
-                                               VecAddf(v3d->ofs, v3d->ofs, obofs);
-                                       }
-
-                                       /* Perform the orbital rotation */
-                                       phi = sensitivity * reverse * (mval[0] - mvalo[0]);
-                                       q1[0] = cos(phi);
-                                       q1[1] = q1[2] = 0.0;
-                                       q1[3] = sin(phi);
-                                       QuatMul(v3d->viewquat, v3d->viewquat, q1);
-
-                                       if (use_sel) {
-                                               QuatConj(q1);
-                                               VecSubf(v3d->ofs, v3d->ofs, obofs);
-                                               QuatMulVecf(q1, v3d->ofs);
-                                               VecAddf(v3d->ofs, v3d->ofs, obofs);
-                                       }
-                               }
-                               
-                               /* check for view snap */
-                               if (G.qual==LR_CTRLKEY){
-                                       int i;
-                                       float viewmat[3][3];
-
-                                       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, 1, 0},  //front
-                                               {0.0, 0.0, -SIN45, -SIN45, 1, 1}, //back
-                                               {1.0, 0.0, 0.0, 0.0, 7, 0},       //top
-                                               {0.0, -1.0, 0.0, 0.0, 7, 1},      //bottom
-                                               {0.5, -0.5, -0.5, -0.5, 3, 0},    //left
-                                               {0.5, -0.5, 0.5, 0.5, 3, 1},      //right
-                                               
-                                               /* some more 45 deg snaps */
-                                               {0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0},
-                                               {0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0, 0},
-                                               {0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0, 0},
-                                               {0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0, 0},
-                                               {0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0, 0},
-                                               {0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0, 0},
-                                               {0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0, 0},
-                                               {0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0, 0},
-                                               {0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0, 0},
-                                               {0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0, 0},
-                                               {0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0, 0},
-                                               {0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0, 0},
-                                               {0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0, 0},
-                                               {0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0, 0},
-                                               {-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0, 0},
-                                               {-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0, 0},
-                                               {-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0, 0},
-                                               {0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0, 0},
-                                               {-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0, 0},
-                                               {-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0, 0},
-                                               {-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0, 0},
-                                               {-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0, 0},
-                                               {-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0, 0},
-                                               {-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0, 0},
-                                               {-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0, 0},
-                                               {0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0, 0},
-                                               {-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0, 0},
-                                               {-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0, 0},
-                                               {-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0, 0},
-                                               {-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0, 0},
-                                               {-COS45, 0.0, 0.0, SIN45, 0, 0},
-                                               {COS45, 0.0, 0.0, SIN45, 0, 0},
-                                               {0.0, 0.0, 0.0, 1.0, 0, 0}
-                                       };
-
-                                       QuatToMat3(v3d->viewquat, viewmat);
-
-                                       for (i = 0 ; i < 39; i++){
-                                               float snapmat[3][3];
-                                               float view = (int)snapquats[i][4];
-                                               float oposite_dir = (int)snapquats[i][5];
-                                               
-                                               QuatToMat3(snapquats[i], snapmat);
-                                               
-                                               if ((Inpf(snapmat[0], viewmat[0]) > thres) &&
-                                                       (Inpf(snapmat[1], viewmat[1]) > thres) &&
-                                                       (Inpf(snapmat[2], viewmat[2]) > thres)){
-                                                       
-                                                       QUATCOPY(v3d->viewquat, snapquats[i]);
-                                                       
-                                                       v3d->view = view;
-                                                       if (view){
-                                                               if (oposite_dir){
-                                                                       v3d->flag2 |= V3D_OPP_DIRECTION_NAME;
-                                                               }else{
-                                                                       v3d->flag2 &= ~V3D_OPP_DIRECTION_NAME;
-                                                               }
-                                                       }
-                                                       
-                                                       break;
-                                               }
-                                       }
-                               }
-                       }
-                       else if(mode==1) {      /* translate */
-                               if(v3d->persp==V3D_CAMOB) {
-                                       float max= (float)MAX2(ar->winx, ar->winy);
-
-                                       v3d->camdx += (mvalo[0]-mval[0])/(max);
-                                       v3d->camdy += (mvalo[1]-mval[1])/(max);
-                                       CLAMP(v3d->camdx, -1.0f, 1.0f);
-                                       CLAMP(v3d->camdy, -1.0f, 1.0f);
-                                       preview3d_event= 0;
-                               }
-                               else {
-                                       window_to_3d(ar, v3d, dvec, mval[0]-mvalo[0], mval[1]-mvalo[1]);
-                                       VecAddf(v3d->ofs, v3d->ofs, dvec);
-                               }
-                       }
-                       else if(mode==2) {
-                               float zfac=1.0;
-
-                               /* use initial value (do not use mvalo (that is used to detect mouse moviments)) */
-                               mvalo[0] = mvali[0];
-                               mvalo[1] = mvali[1];
-                               
-                               if(U.viewzoom==USER_ZOOM_CONT) {
-                                       // oldstyle zoom
-                                       zfac = 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0;
-                               }
-                               else if(U.viewzoom==USER_ZOOM_SCALE) {
-                                       int ctr[2], len1, len2;
-                                       // method which zooms based on how far you move the mouse
-                                       
-                                       ctr[0] = (ar->winrct.xmax + ar->winrct.xmin)/2;
-                                       ctr[1] = (ar->winrct.ymax + ar->winrct.ymin)/2;
-                                       
-                                       len1 = (int)sqrt((ctr[0] - mval[0])*(ctr[0] - mval[0]) + (ctr[1] - mval[1])*(ctr[1] - mval[1])) + 5;
-                                       len2 = (int)sqrt((ctr[0] - mvalo[0])*(ctr[0] - mvalo[0]) + (ctr[1] - mvalo[1])*(ctr[1] - mvalo[1])) + 5;
-                                       
-                                       zfac = dist0 * ((float)len2/len1) / v3d->dist;
-                               }
-                               else {  /* USER_ZOOM_DOLLY */
-                                       float len1 = (ar->winrct.ymax - mval[1]) + 5;
-                                       float len2 = (ar->winrct.ymax - mvalo[1]) + 5;
-                                       zfac = dist0 * (2.0*((len2/len1)-1.0) + 1.0) / v3d->dist;
-                               }
-
-                               if(zfac != 1.0 && zfac*v3d->dist > 0.001*v3d->grid && 
-                                       zfac*v3d->dist < 10.0*v3d->far)
-                                       view_zoom_mouseloc(ar, v3d, zfac, mval_area);
-                               
-                               
-                               if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (v3d->persp==V3D_PERSP)) {
-                                       /* Secret apricot feature, translate the view when in continues mode */
-                                       upvec[0] = upvec[1] = 0;
-                                       upvec[2] = (dist0 - v3d->dist) * v3d->grid;
-                                       v3d->dist = dist0;
-                                       Mat3CpyMat4(mat, v3d->viewinv);
-                                       Mat3MulVecfl(mat, upvec);
-                                       VecAddf(v3d->ofs, v3d->ofs, upvec);
-                               } else {
-                                       /* these limits are in toets.c too */
-                                       if(v3d->dist<0.001*v3d->grid) v3d->dist= 0.001*v3d->grid;
-                                       if(v3d->dist>10.0*v3d->far) v3d->dist=10.0*v3d->far;
-                               }
-                               
-                               if(v3d->persp==V3D_ORTHO || v3d->persp==V3D_CAMOB) preview3d_event= 0;
-                       }
-                       
-                       
-                       
-                       mvalo[0]= mval[0];
-                       mvalo[1]= mval[1];
-
-// XXX                 if(G.f & G_PLAYANIM) inner_play_anim_loop(0, 0);
-
-                       /* If in retopo paint mode, update lines */
-                       if(retopo_mesh_paint_check() && v3d->retopo_view_data) {
-                               v3d->retopo_view_data->queue_matrix_update= 1;
-                               retopo_paint_view_update(v3d);
-                       }
-
-//     XXX             scrarea_do_windraw(ar);
-// XXX                 screen_swapbuffers();
-               }
-               else {
-//                     short val;
-//                     unsigned short event;
-                       /* we need to empty the queue... when you do this very long it overflows */
-// XX                  while(qtest()) event= extern_qread(&val);
-                       
-// XXX                 BIF_wait_for_statechange();
-               }
-               
-               /* this in the end, otherwise get_mbut does not work on a PC... */
-// XXX         if( !(get_mbut() & (L_MOUSE|M_MOUSE))) break;
-       }
-
-       if(v3d->depths) v3d->depths->damaged= 1;
-// XXX retopo_queue_updates(v3d);
-// XXX allqueue(REDRAWVIEW3D, 0);
-
-// XXX if(preview3d_event) 
-//             BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT);
-//     else
-//             BIF_view3d_previewrender_signal(ar, PR_PROJECTED);
-
-}
-
-void viewmoveNDOF(Scene *scene, View3D *v3d, int mode)
+void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
 {
-    float fval[7];
-    float dvec[3];
-    float sbadjust = 1.0f;
-    float len;
+       RegionView3D *rv3d= ar->regiondata;
+       float fval[7];
+       float dvec[3];
+       float sbadjust = 1.0f;
+       float len;
        short use_sel = 0;
        Object *ob = OBACT;
-    float m[3][3];
-    float m_inv[3][3];
-    float xvec[3] = {1,0,0};
-    float yvec[3] = {0,-1,0};
-    float zvec[3] = {0,0,1};
+       float m[3][3];
+       float m_inv[3][3];
+       float xvec[3] = {1,0,0};
+       float yvec[3] = {0,-1,0};
+       float zvec[3] = {0,0,1};
        float phi, si;
-    float q1[4];
-    float obofs[3];
-    float reverse;
-    //float diff[4];
-    float d, curareaX, curareaY;
-    float mat[3][3];
-    float upvec[3];
+       float q1[4];
+       float obofs[3];
+       float reverse;
+       //float diff[4];
+       float d, curareaX, curareaY;
+       float mat[3][3];
+       float upvec[3];
 
     /* Sensitivity will control how fast the view rotates.  The value was
      * obtained experimentally by tweaking until the author didn't get dizzy watching.
-     * Perhaps this should be a configurable user parameter. 
+     * Perhaps this should be a configurable user parameter.
      */
-    float psens = 0.005f * (float) U.ndof_pan;   /* pan sensitivity */
-    float rsens = 0.005f * (float) U.ndof_rotate;  /* rotate sensitivity */
-    float zsens = 0.3f;   /* zoom sensitivity */
+       float psens = 0.005f * (float) U.ndof_pan;   /* pan sensitivity */
+       float rsens = 0.005f * (float) U.ndof_rotate;  /* rotate sensitivity */
+       float zsens = 0.3f;   /* zoom sensitivity */
 
-    const float minZoom = -30.0f;
-    const float maxZoom = 300.0f;
+       const float minZoom = -30.0f;
+       const float maxZoom = 300.0f;
 
        //reset view type
-       v3d->view = 0;
+       rv3d->view = 0;
 //printf("passing here \n");
 //
-       if (G.obedit==NULL && ob && !(ob->flag & OB_POSEMODE)) {
+       if (scene->obedit==NULL && ob && !(ob->flag & OB_POSEMODE)) {
                use_sel = 1;
        }
 
-    if((dz_flag)||v3d->dist==0) {
+       if((dz_flag)||rv3d->dist==0) {
                dz_flag = 0;
-               v3d->dist = m_dist;
+               rv3d->dist = m_dist;
                upvec[0] = upvec[1] = 0;
-               upvec[2] = v3d->dist;
-               Mat3CpyMat4(mat, v3d->viewinv);
+               upvec[2] = rv3d->dist;
+               Mat3CpyMat4(mat, rv3d->viewinv);
                Mat3MulVecfl(mat, upvec);
-               VecAddf(v3d->ofs, v3d->ofs, upvec);
+               VecAddf(rv3d->ofs, rv3d->ofs, upvec);
        }
 
     /*----------------------------------------------------
@@ -932,7 +2177,7 @@ void viewmoveNDOF(Scene *scene, View3D *v3d, int mode)
 
     /*----------------------------------------------------
      * record how much time has passed. clamp at 10 Hz
-     * pretend the previous frame occured at the clamped time 
+     * pretend the previous frame occured at the clamped time
      */
 //    now = PIL_check_seconds_timer();
  //   frametime = (now - prevTime);
@@ -946,29 +2191,28 @@ void viewmoveNDOF(Scene *scene, View3D *v3d, int mode)
 // XXX    getndof(fval);
        if (v3d->ndoffilter)
                filterNDOFvalues(fval);
-       
-       
+
+
     // put scaling back here, was previously in ghostwinlay
-    fval[0] = fval[0] * (1.0f/600.0f);
-    fval[1] = fval[1] * (1.0f/600.0f);
-    fval[2] = fval[2] * (1.0f/1100.0f);
-    fval[3] = fval[3] * 0.00005f;
-    fval[4] =-fval[4] * 0.00005f;
-    fval[5] = fval[5] * 0.00005f;
-    fval[6] = fval[6] / 1000000.0f;
-                       
+       fval[0] = fval[0] * (1.0f/600.0f);
+       fval[1] = fval[1] * (1.0f/600.0f);
+       fval[2] = fval[2] * (1.0f/1100.0f);
+       fval[3] = fval[3] * 0.00005f;
+       fval[4] =-fval[4] * 0.00005f;
+       fval[5] = fval[5] * 0.00005f;
+       fval[6] = fval[6] / 1000000.0f;
+
     // scale more if not in perspective mode
-    if (v3d->persp == V3D_ORTHO) {
-        fval[0] = fval[0] * 0.05f;
-        fval[1] = fval[1] * 0.05f;
-        fval[2] = fval[2] * 0.05f;
-        fval[3] = fval[3] * 0.9f;
-        fval[4] = fval[4] * 0.9f;
-        fval[5] = fval[5] * 0.9f;
-        zsens *= 8;
-    }
-                       
-       
+       if (rv3d->persp == V3D_ORTHO) {
+               fval[0] = fval[0] * 0.05f;
+               fval[1] = fval[1] * 0.05f;
+               fval[2] = fval[2] * 0.05f;
+               fval[3] = fval[3] * 0.9f;
+               fval[4] = fval[4] * 0.9f;
+               fval[5] = fval[5] * 0.9f;
+               zsens *= 8;
+       }
+
     /* set object offset */
        if (ob) {
                obofs[0] = -ob->obmat[3][0];
@@ -976,7 +2220,7 @@ void viewmoveNDOF(Scene *scene, View3D *v3d, int mode)
                obofs[2] = -ob->obmat[3][2];
        }
        else {
-               VECCOPY(obofs, v3d->ofs);
+               VECCOPY(obofs, rv3d->ofs);
        }
 
     /* calc an adjustment based on distance from camera
@@ -984,38 +2228,38 @@ void viewmoveNDOF(Scene *scene, View3D *v3d, int mode)
      d = 1.0f;
 
 /*    if (ob) {
-        VecSubf(diff, obofs, v3d->ofs);
+        VecSubf(diff, obofs, rv3d->ofs);
         d = VecLength(diff);
     }
 */
 
-    reverse = (v3d->persmat[2][1] < 0.0f) ? -1.0f : 1.0f;
+    reverse = (rv3d->persmat[2][1] < 0.0f) ? -1.0f : 1.0f;
 
     /*----------------------------------------------------
-     * ndof device pan 
+     * ndof device pan
      */
     psens *= 1.0f + d;
     curareaX = sbadjust * psens * fval[0];
     curareaY = sbadjust * psens * fval[1];
-    dvec[0] = curareaX * v3d->persinv[0][0] + curareaY * v3d->persinv[1][0];
-    dvec[1] = curareaX * v3d->persinv[0][1] + curareaY * v3d->persinv[1][1];
-    dvec[2] = curareaX * v3d->persinv[0][2] + curareaY * v3d->persinv[1][2];
-    VecAddf(v3d->ofs, v3d->ofs, dvec);
+    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);
 
     /*----------------------------------------------------
-     * ndof device dolly 
+     * ndof device dolly
      */
     len = zsens * sbadjust * fval[2];
 
-    if (v3d->persp==V3D_CAMOB) {
-        if(v3d->persp==V3D_CAMOB) { /* This is stupid, please fix - TODO */
-            v3d->camzoom+= 10.0f * -len;
+    if (rv3d->persp==V3D_CAMOB) {
+        if(rv3d->persp==V3D_CAMOB) { /* This is stupid, please fix - TODO */
+            rv3d->camzoom+= 10.0f * -len;
         }
-        if (v3d->camzoom < minZoom) v3d->camzoom = minZoom;
-        else if (v3d->camzoom > maxZoom) v3d->camzoom = maxZoom;
+        if (rv3d->camzoom < minZoom) rv3d->camzoom = minZoom;
+        else if (rv3d->camzoom > maxZoom) rv3d->camzoom = maxZoom;
     }
-    else if ((v3d->dist> 0.001*v3d->grid) && (v3d->dist<10.0*v3d->far)) {
-        v3d->dist*=(1.0 + len);
+    else if ((rv3d->dist> 0.001*v3d->grid) && (rv3d->dist<10.0*v3d->far)) {
+        rv3d->dist*=(1.0 + len);
     }
 
 
@@ -1025,7 +2269,7 @@ void viewmoveNDOF(Scene *scene, View3D *v3d, int mode)
      */
 
     /* Get the 3x3 matrix and its inverse from the quaternion */
-    QuatToMat3(v3d->viewquat, m);
+    QuatToMat3(rv3d->viewquat, m);
     Mat3Inv(m_inv,m);
 
     /* Determine the direction of the x vector (for rotating up and down) */
@@ -1041,38 +2285,38 @@ void viewmoveNDOF(Scene *scene, View3D *v3d, int mode)
     q1[1] = si * xvec[0];
     q1[2] = si * xvec[1];
     q1[3] = si * xvec[2];
-    QuatMul(v3d->viewquat, v3d->viewquat, q1);
+    QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
 
     if (use_sel) {
         QuatConj(q1); /* conj == inv for unit quat */
         VecSubf(v3d->ofs, v3d->ofs, obofs);
-        QuatMulVecf(q1, v3d->ofs);
-        VecAddf(v3d->ofs, v3d->ofs, obofs);
+        QuatMulVecf(q1, rv3d->ofs);
+        VecAddf(rv3d->ofs, rv3d->ofs, obofs);
     }
 
     /* Perform the orbital rotation */
-    /* Perform the orbital rotation 
+    /* Perform the orbital rotation
        If the seen Up axis is parallel to the zoom axis, rotation should be
-       achieved with a pure Roll motion (no Spin) on the device. When you start 
-       to tilt, moving from Top to Side view, Spinning will increasingly become 
-       more relevant while the Roll component will decrease. When a full 
+       achieved with a pure Roll motion (no Spin) on the device. When you start
+       to tilt, moving from Top to Side view, Spinning will increasingly become
+       more relevant while the Roll component will decrease. When a full
        Side view is reached, rotations around the world's Up axis are achieved
        with a pure Spin-only motion.  In other words the control of the spinning
        around the world's Up axis should move from the device's Spin axis to the
-       device's Roll axis depending on the orientation of the world's Up axis 
+       device's Roll axis depending on the orientation of the world's Up axis
        relative to the screen. */
     //phi = sbadjust * rsens * reverse * fval[4];  /* spin the knob, y axis */
     phi = sbadjust * rsens * (yvec[2] * fval[4] + zvec[2] * fval[5]);
     q1[0] = cos(phi);
     q1[1] = q1[2] = 0.0;
     q1[3] = sin(phi);
-    QuatMul(v3d->viewquat, v3d->viewquat, q1);
+    QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
 
     if (use_sel) {
         QuatConj(q1);
-        VecSubf(v3d->ofs, v3d->ofs, obofs);
-        QuatMulVecf(q1, v3d->ofs);
-        VecAddf(v3d->ofs, v3d->ofs, obofs);
+        VecSubf(rv3d->ofs, rv3d->ofs, obofs);
+        QuatMulVecf(q1, rv3d->ofs);
+        VecAddf(rv3d->ofs, rv3d->ofs, obofs);
     }
 
     /*----------------------------------------------------