[#19930] Nurb CV select is failing because of view clipping
[blender.git] / source / blender / editors / space_view3d / view3d_view.c
index e1a6f32aa41fd09726e8223155d5f994d2f7f82c..82b5730daa28191566a17021d8d74c4ae70ec728 100644 (file)
@@ -45,7 +45,7 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_editVert.h"
 #include "BLI_rand.h"
 #include "BKE_object.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
+#include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_screen.h"
 #include "BKE_utildefines.h"
+#include "BKE_depsgraph.h" /* for fly mode updating */
 
 #include "RE_pipeline.h"       // make_stars
 
 #include "BIF_gl.h"
+#include "BIF_glutil.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 #include "UI_resources.h"
 #include "UI_view2d.h"
 
+#include "GPU_draw.h"
+
 #include "PIL_time.h" /* smoothview */
 
-#include "view3d_intern.h"     // own include
+#if GAMEBLENDER == 1
+#include "SYS_System.h"
+#endif
 
+#include "view3d_intern.h"     // own include
 
 /* use this call when executing an operator,
    event system doesn't set for each event the
@@ -104,7 +112,7 @@ void view3d_operator_needs_opengl(const bContext *C)
 
 float *give_cursor(Scene *scene, View3D *v3d)
 {
-       if(v3d && v3d->localview) return v3d->cursor;
+       if(v3d && v3d->localvd) return v3d->cursor;
        else return scene->cursor;
 }
 
@@ -153,26 +161,26 @@ static void view_settings_from_ob(Object *ob, float *ofs, float *quat, float *di
        /* Offset */
        if (ofs) {
                VECCOPY(ofs, ob->obmat[3]);
-               VecMulf(ofs, -1.0f); /*flip the vector*/
+               mul_v3_fl(ofs, -1.0f); /*flip the vector*/
        }
        
        /* Quat */
        if (quat) {
-               Mat4CpyMat4(bmat, ob->obmat);
-               Mat4Ortho(bmat);
-               Mat4Invert(imat, bmat);
-               Mat3CpyMat4(tmat, imat);
-               Mat3ToQuat(tmat, quat);
+               copy_m4_m4(bmat, ob->obmat);
+               normalize_m4(bmat);
+               invert_m4_m4(imat, bmat);
+               copy_m3_m4(tmat, imat);
+               mat3_to_quat( quat,tmat);
        }
        
        if (dist) {
                float vec[3];
-               Mat3CpyMat4(tmat, ob->obmat);
+               copy_m3_m4(tmat, ob->obmat);
                
                vec[0]= vec[1] = 0.0;
                vec[2]= -(*dist);
-               Mat3MulVecfl(tmat, vec);
-               VecSubf(ofs, ofs, vec);
+               mul_m3_v3(tmat, vec);
+               sub_v3_v3v3(ofs, ofs, vec);
        }
        
        /* Lens */
@@ -255,10 +263,10 @@ void smooth_view(bContext *C, Object *oldcamera, Object *camera, float *ofs, flo
                                
                                VECCOPY(vec1, sms.new_quat);
                                VECCOPY(vec2, sms.orig_quat);
-                               Normalize(vec1);
-                               Normalize(vec2);
+                               normalize_v3(vec1);
+                               normalize_v3(vec2);
                                /* scale the time allowed by the rotation */
-                               sms.time_allowed *= NormalizedVecAngle2(vec1, vec2)/(M_PI/2); 
+                               sms.time_allowed *= angle_normalized_v3v3(vec1, vec2)/(M_PI/2); 
                        }
                        
                        /* original values */
@@ -277,16 +285,16 @@ void smooth_view(bContext *C, Object *oldcamera, Object *camera, float *ofs, flo
                        rv3d->view= 0;
                        
                        /* ensure it shows correct */
-                       if(sms.to_camera) rv3d->persp= V3D_PERSP;
+                       if(sms.to_camera) rv3d->persp= RV3D_PERSP;
                        
                        /* keep track of running timer! */
                        if(rv3d->sms==NULL)
                                rv3d->sms= MEM_mallocN(sizeof(struct SmoothViewStore), "smoothview v3d");
                        *rv3d->sms= sms;
                        if(rv3d->smooth_timer)
-                               WM_event_remove_window_timer(CTX_wm_window(C), rv3d->smooth_timer);
+                               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer);
                        /* TIMER1 is hardcoded in keymap */
-                       rv3d->smooth_timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER1, 1.0/30.0);      /* max 30 frs/sec */
+                       rv3d->smooth_timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/30.0);  /* max 30 frs/sec */
                        
                        return;
                }
@@ -321,7 +329,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *op, wmEvent *event)
                
                /* if we went to camera, store the original */
                if(sms->to_camera) {
-                       rv3d->persp= V3D_CAMOB;
+                       rv3d->persp= RV3D_CAMOB;
                        VECCOPY(rv3d->ofs, sms->orig_ofs);
                        QUATCOPY(rv3d->viewquat, sms->orig_quat);
                        rv3d->dist = sms->orig_dist;
@@ -338,7 +346,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *op, wmEvent *event)
                MEM_freeN(rv3d->sms);
                rv3d->sms= NULL;
                
-               WM_event_remove_window_timer(CTX_wm_window(C), rv3d->smooth_timer);
+               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer);
                rv3d->smooth_timer= NULL;
        }
        else {
@@ -353,7 +361,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *op, wmEvent *event)
                for (i=0; i<3; i++)
                        rv3d->ofs[i] = sms->new_ofs[i]*step + sms->orig_ofs[i]*step_inv;
 
-               QuatInterpol(rv3d->viewquat, sms->orig_quat, sms->new_quat, step);
+               interp_qt_qtqt(rv3d->viewquat, sms->orig_quat, sms->new_quat, step);
                
                rv3d->dist = sms->new_dist*step + sms->orig_dist*step_inv;
                v3d->lens = sms->new_lens*step + sms->orig_lens*step_inv;
@@ -370,6 +378,7 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Smooth View";
        ot->idname= "VIEW3D_OT_smoothview";
+       ot->description="The time to animate the change of view (in milliseconds)";
        
        /* api callbacks */
        ot->invoke= view3d_smoothview_invoke;
@@ -377,26 +386,32 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 }
 
-static int view3d_setcameratoview_exec(bContext *C, wmOperator *op)
+static void setcameratoview3d(View3D *v3d, RegionView3D *rv3d, Object *ob)
 {
-       View3D *v3d = CTX_wm_view3d(C);
-       RegionView3D *rv3d= CTX_wm_region_view3d(C);
-       Object *ob;
        float dvec[3];
        
-       ob= v3d->camera;
        dvec[0]= rv3d->dist*rv3d->viewinv[2][0];
        dvec[1]= rv3d->dist*rv3d->viewinv[2][1];
        dvec[2]= rv3d->dist*rv3d->viewinv[2][2];
        
        VECCOPY(ob->loc, dvec);
-       VecSubf(ob->loc, ob->loc, v3d->ofs);
+       sub_v3_v3v3(ob->loc, ob->loc, rv3d->ofs);
        rv3d->viewquat[0]= -rv3d->viewquat[0];
 
-       QuatToEul(rv3d->viewquat, ob->rot);
+       quat_to_eul( ob->rot,rv3d->viewquat);
        rv3d->viewquat[0]= -rv3d->viewquat[0];
        
        ob->recalc= OB_RECALC_OB;
+}
+
+
+static int view3d_setcameratoview_exec(bContext *C, wmOperator *op)
+{
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+
+       setcameratoview3d(v3d, rv3d, v3d->camera);
+       rv3d->persp = RV3D_CAMOB;
        
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, CTX_data_scene(C));
        
@@ -404,41 +419,86 @@ static int view3d_setcameratoview_exec(bContext *C, wmOperator *op)
 
 }
 
+int view3d_setcameratoview_poll(bContext *C)
+{
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+
+       if (v3d==NULL || v3d->camera==NULL)     return 0;
+       if (rv3d && rv3d->viewlock != 0)                return 0;
+       return 1;
+}
+
 void VIEW3D_OT_setcameratoview(wmOperatorType *ot)
 {
        
        /* identifiers */
        ot->name= "Align Camera To View";
+       ot->description= "Set camera view to active view.";
        ot->idname= "VIEW3D_OT_camera_to_view";
        
        /* api callbacks */
        ot->exec= view3d_setcameratoview_exec;  
-       ot->poll= ED_operator_view3d_active;
+       ot->poll= view3d_setcameratoview_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
+{
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       Scene *scene= CTX_data_scene(C);
+       
+       if(BASACT) {
+               rv3d->persp= RV3D_CAMOB;
+               v3d->camera= OBACT;
+               if(v3d->scenelock)
+                       scene->camera= OBACT;
+               smooth_view(C, NULL, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens);
+       }
+       
+       WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT|ND_DRAW, CTX_data_scene(C));
+       
+       return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_setobjectascamera(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Set Active Object as Camera";
+       ot->description= "Set the active object as the active camera for this view or scene.";
+       ot->idname= "VIEW3D_OT_object_as_camera";
+       
+       /* api callbacks */
+       ot->exec= view3d_setobjectascamera_exec;        
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 /* ********************************** */
 
 /* create intersection coordinates in view Z direction at mouse coordinates */
-void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_end[3])
+void viewline(ARegion *ar, View3D *v3d, float mval[2], float ray_start[3], float ray_end[3])
 {
        RegionView3D *rv3d= ar->regiondata;
        float vec[4];
        
-       if(rv3d->persp != V3D_ORTHO){
+       if(rv3d->persp != RV3D_ORTHO){
                vec[0]= 2.0f * mval[0] / ar->winx - 1;
                vec[1]= 2.0f * mval[1] / ar->winy - 1;
                vec[2]= -1.0f;
                vec[3]= 1.0f;
                
-               Mat4MulVec4fl(rv3d->persinv, vec);
-               VecMulf(vec, 1.0f / vec[3]);
+               mul_m4_v4(rv3d->persinv, vec);
+               mul_v3_fl(vec, 1.0f / vec[3]);
                
                VECCOPY(ray_start, rv3d->viewinv[3]);
                VECSUB(vec, vec, ray_start);
-               Normalize(vec);
+               normalize_v3(vec);
                
                VECADDFAC(ray_start, rv3d->viewinv[3], vec, v3d->near);
                VECADDFAC(ray_end, rv3d->viewinv[3], vec, v3d->far);
@@ -449,7 +509,7 @@ void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float
                vec[2] = 0.0f;
                vec[3] = 1.0f;
                
-               Mat4MulVec4fl(rv3d->persinv, vec);
+               mul_m4_v4(rv3d->persinv, vec);
                
                VECADDFAC(ray_start, vec, rv3d->viewinv[2],  1000.0f);
                VECADDFAC(ray_end, vec, rv3d->viewinv[2], -1000.0f);
@@ -457,13 +517,13 @@ void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float
 }
 
 /* create intersection ray in view Z direction at mouse coordinates */
-void viewray(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_normal[3])
+void viewray(ARegion *ar, View3D *v3d, float mval[2], float ray_start[3], float ray_normal[3])
 {
        float ray_end[3];
        
        viewline(ar, v3d, mval, ray_start, ray_end);
-       VecSubf(ray_normal, ray_end, ray_start);
-       Normalize(ray_normal);
+       sub_v3_v3v3(ray_normal, ray_end, ray_start);
+       normalize_v3(ray_normal);
 }
 
 
@@ -480,7 +540,10 @@ void initgrabz(RegionView3D *rv3d, float x, float y, float z)
        /* Negative zfac means x, y, z was behind the camera (in perspective).
                * This gives flipped directions, so revert back to ok default case.
        */
-       if (rv3d->zfac < 0.0f) rv3d->zfac = 1.0f;
+       // NOTE: I've changed this to flip zfac to be positive again for now so that GPencil draws ok
+       //      -- Aligorith, 2009Aug31
+       //if (rv3d->zfac < 0.0f) rv3d->zfac = 1.0f;
+       if (rv3d->zfac < 0.0f) rv3d->zfac= -rv3d->zfac;
 }
 
 /* always call initgrabz */
@@ -538,10 +601,22 @@ void view3d_get_object_project_mat(RegionView3D *rv3d, Object *ob, float pmat[4]
 {
        float vmat[4][4];
        
-       Mat4MulMat4(vmat, ob->obmat, rv3d->viewmat);
-       Mat4MulMat4(pmat, vmat, rv3d->winmat);
+       mul_m4_m4m4(vmat, ob->obmat, rv3d->viewmat);
+       mul_m4_m4m4(pmat, vmat, rv3d->winmat);
 }
 
+/* Uses window coordinates (x,y) and depth component z to find a point in
+   modelspace */
+void view3d_unproject(bglMats *mats, float out[3], const short x, const short y, const float z)
+{
+       double ux, uy, uz;
+
+        gluUnProject(x,y,z, mats->modelview, mats->projection,
+                    (GLint *)mats->viewport, &ux, &uy, &uz );
+       out[0] = ux;
+       out[1] = uy;
+       out[2] = uz;
+}
 
 /* use above call to get projecting mat */
 void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
@@ -552,7 +627,7 @@ void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
        VECCOPY(vec4, vec);
        vec4[3]= 1.0;
        
-       Mat4MulVec4fl(mat, vec4);
+       mul_m4_v4(mat, vec4);
        
        if( vec4[3]>FLT_EPSILON ) {
                adr[0] = (float)(ar->winx/2.0f)+(ar->winx/2.0f)*vec4[0]/vec4[3];        
@@ -573,12 +648,12 @@ int boundbox_clip(RegionView3D *rv3d, float obmat[][4], BoundBox *bb)
        if(bb==NULL) return 1;
        if(bb->flag & OB_BB_DISABLED) return 1;
        
-       Mat4MulMat4(mat, obmat, rv3d->persmat);
+       mul_m4_m4m4(mat, obmat, rv3d->persmat);
        
        for(a=0; a<8; a++) {
                VECCOPY(vec, bb->vec[a]);
                vec[3]= 1.0;
-               Mat4MulVec4fl(mat, vec);
+               mul_m4_v4(mat, vec);
                max= vec[3];
                min= -vec[3];
                
@@ -605,13 +680,13 @@ void project_short(ARegion *ar, float *vec, short *adr)   /* clips */
        adr[0]= IS_CLIPPED;
        
        if(rv3d->rflag & RV3D_CLIPPING) {
-               if(view3d_test_clipping(rv3d, vec))
+               if(view3d_test_clipping(rv3d, vec, 0))
                        return;
        }
        
        VECCOPY(vec4, vec);
        vec4[3]= 1.0;
-       Mat4MulVec4fl(rv3d->persmat, vec4);
+       mul_m4_v4(rv3d->persmat, vec4);
        
        if( vec4[3]>BL_NEAR_CLIP ) {    /* 0.001 is the NEAR clipping cutoff for picking */
                fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
@@ -637,7 +712,7 @@ void project_int(ARegion *ar, float *vec, int *adr)
        VECCOPY(vec4, vec);
        vec4[3]= 1.0;
        
-       Mat4MulVec4fl(rv3d->persmat, vec4);
+       mul_m4_v4(rv3d->persmat, vec4);
        
        if( vec4[3]>BL_NEAR_CLIP ) {    /* 0.001 is the NEAR clipping cutoff for picking */
                fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
@@ -661,7 +736,7 @@ void project_int_noclip(ARegion *ar, float *vec, int *adr)
        VECCOPY(vec4, vec);
        vec4[3]= 1.0;
        
-       Mat4MulVec4fl(rv3d->persmat, vec4);
+       mul_m4_v4(rv3d->persmat, vec4);
        
        if( fabs(vec4[3]) > BL_NEAR_CLIP ) {
                fx = (ar->winx/2)*(1 + vec4[0]/vec4[3]);
@@ -686,7 +761,7 @@ void project_short_noclip(ARegion *ar, float *vec, short *adr)
        VECCOPY(vec4, vec);
        vec4[3]= 1.0;
        
-       Mat4MulVec4fl(rv3d->persmat, vec4);
+       mul_m4_v4(rv3d->persmat, vec4);
        
        if( vec4[3]>BL_NEAR_CLIP ) {    /* 0.001 is the NEAR clipping cutoff for picking */
                fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
@@ -712,7 +787,7 @@ void project_float(ARegion *ar, float *vec, float *adr)
        VECCOPY(vec4, vec);
        vec4[3]= 1.0;
        
-       Mat4MulVec4fl(rv3d->persmat, vec4);
+       mul_m4_v4(rv3d->persmat, vec4);
        
        if( vec4[3]>BL_NEAR_CLIP ) {
                adr[0] = (float)(ar->winx/2.0)+(ar->winx/2.0)*vec4[0]/vec4[3];  
@@ -728,7 +803,7 @@ void project_float_noclip(ARegion *ar, float *vec, float *adr)
        VECCOPY(vec4, vec);
        vec4[3]= 1.0;
        
-       Mat4MulVec4fl(rv3d->persmat, vec4);
+       mul_m4_v4(rv3d->persmat, vec4);
        
        if( fabs(vec4[3]) > BL_NEAR_CLIP ) {
                adr[0] = (float)(ar->winx/2.0)+(ar->winx/2.0)*vec4[0]/vec4[3];  
@@ -745,7 +820,7 @@ int get_view3d_ortho(View3D *v3d, RegionView3D *rv3d)
 {
   Camera *cam;
   
-  if(rv3d->persp==V3D_CAMOB) {
+  if(rv3d->persp==RV3D_CAMOB) {
       if(v3d->camera && v3d->camera->type==OB_CAMERA) {
           cam= v3d->camera->data;
 
@@ -758,7 +833,7 @@ int get_view3d_ortho(View3D *v3d, RegionView3D *rv3d)
           return 0;
   }
   
-  if(rv3d->persp==V3D_ORTHO)
+  if(rv3d->persp==RV3D_ORTHO)
       return 1;
 
   return 0;
@@ -777,7 +852,7 @@ int get_view3d_viewplane(View3D *v3d, RegionView3D *rv3d, int winxi, int winyi,
        *clipsta= v3d->near;
        *clipend= v3d->far;
        
-       if(rv3d->persp==V3D_CAMOB) {
+       if(rv3d->persp==RV3D_CAMOB) {
                if(v3d->camera) {
                        if(v3d->camera->type==OB_LAMP ) {
                                Lamp *la;
@@ -800,7 +875,7 @@ int get_view3d_viewplane(View3D *v3d, RegionView3D *rv3d, int winxi, int winyi,
                }
        }
        
-       if(rv3d->persp==V3D_ORTHO) {
+       if(rv3d->persp==RV3D_ORTHO) {
                if(winx>winy) x1= -rv3d->dist;
                else x1= -winx*rv3d->dist/winy;
                x2= -x1;
@@ -815,7 +890,7 @@ int get_view3d_viewplane(View3D *v3d, RegionView3D *rv3d, int winxi, int winyi,
        }
        else {
                /* fac for zoom, also used for camdx */
-               if(rv3d->persp==V3D_CAMOB) {
+               if(rv3d->persp==RV3D_CAMOB) {
                        fac= (1.41421+( (float)rv3d->camzoom )/50.0);
                        fac*= fac;
                }
@@ -926,15 +1001,15 @@ static void obmat_to_viewmat(View3D *v3d, RegionView3D *rv3d, Object *ob, short
        
        rv3d->view= 0; /* dont show the grid */
        
-       Mat4CpyMat4(bmat, ob->obmat);
-       Mat4Ortho(bmat);
-       Mat4Invert(rv3d->viewmat, bmat);
+       copy_m4_m4(bmat, ob->obmat);
+       normalize_m4(bmat);
+       invert_m4_m4(rv3d->viewmat, bmat);
        
        /* view quat calculation, needed for add object */
-       Mat3CpyMat4(tmat, rv3d->viewmat);
+       copy_m3_m4(tmat, rv3d->viewmat);
        if (smooth) {
                float new_quat[4];
-               if (rv3d->persp==V3D_CAMOB && v3d->camera) {
+               if (rv3d->persp==RV3D_CAMOB && v3d->camera) {
                        /* were from a camera view */
                        
                        float orig_ofs[3];
@@ -943,22 +1018,22 @@ static void obmat_to_viewmat(View3D *v3d, RegionView3D *rv3d, Object *ob, short
                        VECCOPY(orig_ofs, rv3d->ofs);
                        
                        /* Switch from camera view */
-                       Mat3ToQuat(tmat, new_quat);
+                       mat3_to_quat( new_quat,tmat);
                        
-                       rv3d->persp=V3D_PERSP;
+                       rv3d->persp=RV3D_PERSP;
                        rv3d->dist= 0.0;
                        
                        view_settings_from_ob(v3d->camera, rv3d->ofs, NULL, NULL, &v3d->lens);
                        smooth_view(NULL, NULL, NULL, orig_ofs, new_quat, &orig_dist, &orig_lens); // XXX
                        
-                       rv3d->persp=V3D_CAMOB; /* just to be polite, not needed */
+                       rv3d->persp=RV3D_CAMOB; /* just to be polite, not needed */
                        
                } else {
-                       Mat3ToQuat(tmat, new_quat);
+                       mat3_to_quat( new_quat,tmat);
                        smooth_view(NULL, NULL, NULL, NULL, new_quat, NULL, NULL); // XXX
                }
        } else {
-               Mat3ToQuat(tmat, rv3d->viewquat);
+               mat3_to_quat( rv3d->viewquat,tmat);
        }
 }
 
@@ -967,27 +1042,27 @@ static void obmat_to_viewmat(View3D *v3d, RegionView3D *rv3d, Object *ob, short
 static void view3d_viewlock(RegionView3D *rv3d)
 {
        switch(rv3d->view) {
-       case V3D_VIEW_BOTTOM :
+       case RV3D_VIEW_BOTTOM :
                QUATSET(rv3d->viewquat,0.0, -1.0, 0.0, 0.0);
                break;
                
-       case V3D_VIEW_BACK:
+       case RV3D_VIEW_BACK:
                QUATSET(rv3d->viewquat,0.0, 0.0, (float)-cos(M_PI/4.0), (float)-cos(M_PI/4.0));
                break;
                
-       case V3D_VIEW_LEFT:
+       case RV3D_VIEW_LEFT:
                QUATSET(rv3d->viewquat,0.5, -0.5, 0.5, 0.5);
                break;
                
-       case V3D_VIEW_TOP:
+       case RV3D_VIEW_TOP:
                QUATSET(rv3d->viewquat,1.0, 0.0, 0.0, 0.0);
                break;
                
-       case V3D_VIEW_FRONT:
+       case RV3D_VIEW_FRONT:
                QUATSET(rv3d->viewquat,(float)cos(M_PI/4.0), (float)-sin(M_PI/4.0), 0.0, 0.0);
                break;
                
-       case V3D_VIEW_RIGHT:
+       case RV3D_VIEW_RIGHT:
                QUATSET(rv3d->viewquat, 0.5, -0.5, -0.5, -0.5);
                break;
        }
@@ -996,13 +1071,13 @@ static void view3d_viewlock(RegionView3D *rv3d)
 /* dont set windows active in in here, is used by renderwin too */
 void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d)
 {
-       if(rv3d->persp==V3D_CAMOB) {        /* obs/camera */
+       if(rv3d->persp==RV3D_CAMOB) {       /* obs/camera */
                if(v3d->camera) {
                        where_is_object(scene, v3d->camera);    
                        obmat_to_viewmat(v3d, rv3d, v3d->camera, 0);
                }
                else {
-                       QuatToMat4(rv3d->viewquat, rv3d->viewmat);
+                       quat_to_mat4( rv3d->viewmat,rv3d->viewquat);
                        rv3d->viewmat[3][2]-= rv3d->dist;
                }
        }
@@ -1011,8 +1086,8 @@ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d)
                if(rv3d->viewlock)
                        view3d_viewlock(rv3d);
                
-               QuatToMat4(rv3d->viewquat, rv3d->viewmat);
-               if(rv3d->persp==V3D_PERSP) rv3d->viewmat[3][2]-= rv3d->dist;
+               quat_to_mat4( rv3d->viewmat,rv3d->viewquat);
+               if(rv3d->persp==RV3D_PERSP) rv3d->viewmat[3][2]-= rv3d->dist;
                if(v3d->ob_centre) {
                        Object *ob= v3d->ob_centre;
                        float vec[3];
@@ -1022,12 +1097,12 @@ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d)
                                bPoseChannel *pchan= get_pose_channel(ob->pose, v3d->ob_centre_bone);
                                if(pchan) {
                                        VECCOPY(vec, pchan->pose_mat[3]);
-                                       Mat4MulVecfl(ob->obmat, vec);
+                                       mul_m4_v3(ob->obmat, vec);
                                }
                        }
-                       i_translate(-vec[0], -vec[1], -vec[2], rv3d->viewmat);
+                       translate_m4( rv3d->viewmat,-vec[0], -vec[1], -vec[2]);
                }
-               else i_translate(rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2], rv3d->viewmat);
+               else translate_m4( rv3d->viewmat,rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
        }
 }
 
@@ -1061,7 +1136,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
        }
        
        setwinmatrixview3d(ar, v3d, &rect);
-       Mat4MulMat4(vc->rv3d->persmat, vc->rv3d->viewmat, vc->rv3d->winmat);
+       mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->viewmat, vc->rv3d->winmat);
        
        if(v3d->drawtype > OB_WIRE) {
                v3d->zbuf= TRUE;
@@ -1111,11 +1186,11 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
                                                
                                                for(dob= lb->first; dob; dob= dob->next) {
                                                        tbase.object= dob->ob;
-                                                       Mat4CpyMat4(dob->ob->obmat, dob->mat);
+                                                       copy_m4_m4(dob->ob->obmat, dob->mat);
                                                        
                                                        draw_object(scene, ar, v3d, &tbase, DRAW_PICKING|DRAW_CONSTCOLOR);
                                                        
-                                                       Mat4CpyMat4(dob->ob->obmat, dob->omat);
+                                                       copy_m4_m4(dob->ob->obmat, dob->omat);
                                                }
                                                free_object_duplilist(lb);
                                        }
@@ -1131,7 +1206,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
        
        G.f &= ~G_PICKSEL;
        setwinmatrixview3d(ar, v3d, NULL);
-       Mat4MulMat4(vc->rv3d->persmat, vc->rv3d->viewmat, vc->rv3d->winmat);
+       mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->viewmat, vc->rv3d->winmat);
        
        if(v3d->drawtype > OB_WIRE) {
                v3d->zbuf= 0;
@@ -1249,7 +1324,7 @@ static void initlocalview(Scene *scene, ScrArea *sa)
 
                                rv3d->dist= size;
                                /* perspective should be a bit farther away to look nice */
-                               if(rv3d->persp==V3D_ORTHO)
+                               if(rv3d->persp==RV3D_ORTHO)
                                        rv3d->dist*= 0.7;
 
                                // correction for window aspect ratio
@@ -1259,7 +1334,7 @@ static void initlocalview(Scene *scene, ScrArea *sa)
                                        rv3d->dist*= asp;
                                }
                                
-                               if (rv3d->persp==V3D_CAMOB) rv3d->persp= V3D_PERSP;
+                               if (rv3d->persp==RV3D_CAMOB) rv3d->persp= RV3D_PERSP;
                                
                                v3d->cursor[0]= -rv3d->ofs[0];
                                v3d->cursor[1]= -rv3d->ofs[1];
@@ -1280,7 +1355,6 @@ static void initlocalview(Scene *scene, ScrArea *sa)
                                base->object->lay= base->lay;
                        }
                }               
-               v3d->localview= 0;
        }
 
 }
@@ -1302,7 +1376,6 @@ static void restore_localviewdata(ScrArea *sa, int free)
        if(free) {
                MEM_freeN(v3d->localvd);
                v3d->localvd= NULL;
-               v3d->localview= 0;
        }
        
        for(ar= sa->regionbase.first; ar; ar= ar->next) {
@@ -1374,6 +1447,7 @@ void VIEW3D_OT_localview(wmOperatorType *ot)
        
        /* identifiers */
        ot->name= "Local View";
+       ot->description= "Toggle display of selected object(s) separately and centered in view.";
        ot->idname= "VIEW3D_OT_localview";
        
        /* api callbacks */
@@ -1382,6 +1456,1005 @@ void VIEW3D_OT_localview(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 }
 
+#if GAMEBLENDER == 1
+
+static ListBase queue_back;
+static void SaveState(bContext *C)
+{
+       wmWindow *win= CTX_wm_window(C);
+       Object *obact = CTX_data_active_object(C);
+       
+       glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+       if(obact && obact->mode & OB_MODE_TEXTURE_PAINT)
+               GPU_paint_set_mipmap(1);
+       
+       queue_back= win->queue;
+       
+       win->queue.first= win->queue.last= NULL;
+       
+       //XXX waitcursor(1);
+}
+
+static void RestoreState(bContext *C)
+{
+       wmWindow *win= CTX_wm_window(C);
+       Object *obact = CTX_data_active_object(C);
+       
+       if(obact && obact->mode & OB_MODE_TEXTURE_PAINT)
+               GPU_paint_set_mipmap(0);
+
+       //XXX curarea->win_swap = 0;
+       //XXX curarea->head_swap=0;
+       //XXX allqueue(REDRAWVIEW3D, 1);
+       //XXX allqueue(REDRAWBUTSALL, 0);
+       //XXX reset_slowparents();
+       //XXX waitcursor(0);
+       //XXX G.qual= 0;
+       
+       win->queue= queue_back;
+       
+       GPU_state_init();
+
+       glPopAttrib();
+}
+
+/* was space_set_commmandline_options in 2.4x */
+void game_set_commmandline_options(GameData *gm)
+{
+       SYS_SystemHandle syshandle;
+       int test;
+
+       if ( (syshandle = SYS_GetSystem()) ) {
+               /* User defined settings */
+               test= (U.gameflags & USER_DISABLE_SOUND);
+               /* if user already disabled audio at the command-line, don't re-enable it */
+               if (test)
+                       SYS_WriteCommandLineInt(syshandle, "noaudio", test);
+
+               test= (U.gameflags & USER_DISABLE_MIPMAP);
+               GPU_set_mipmap(!test);
+               SYS_WriteCommandLineInt(syshandle, "nomipmap", test);
+
+               /* File specific settings: */
+               /* Only test the first one. These two are switched
+                * simultaneously. */
+               test= (gm->flag & GAME_SHOW_FRAMERATE);
+               SYS_WriteCommandLineInt(syshandle, "show_framerate", test);
+               SYS_WriteCommandLineInt(syshandle, "show_profile", test);
+
+               test = (gm->flag & GAME_SHOW_DEBUG_PROPS);
+               SYS_WriteCommandLineInt(syshandle, "show_properties", test);
+
+               test= (gm->flag & GAME_SHOW_PHYSICS);
+               SYS_WriteCommandLineInt(syshandle, "show_physics", test);
+
+               test= (gm->flag & GAME_ENABLE_ALL_FRAMES);
+               SYS_WriteCommandLineInt(syshandle, "fixedtime", test);
+
+//             a= (G.fileflags & G_FILE_GAME_TO_IPO);
+//             SYS_WriteCommandLineInt(syshandle, "game2ipo", a);
+
+               test= (gm->flag & GAME_IGNORE_DEPRECATION_WARNINGS);
+               SYS_WriteCommandLineInt(syshandle, "ignore_deprecation_warnings", test);
+
+               test= (gm->matmode == GAME_MAT_MULTITEX);
+               SYS_WriteCommandLineInt(syshandle, "blender_material", test);
+               test= (gm->matmode == GAME_MAT_GLSL);
+               SYS_WriteCommandLineInt(syshandle, "blender_glsl_material", test);
+               test= (gm->flag & GAME_DISPLAY_LISTS);
+               SYS_WriteCommandLineInt(syshandle, "displaylists", test);
+
+
+       }
+}
+
+/* maybe we need this defined somewhere else */
+extern void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing);
+
+#endif // GAMEBLENDER == 1
+
+int game_engine_poll(bContext *C)
+{
+       return CTX_data_mode_enum(C)==CTX_MODE_OBJECT ? 1:0;
+}
+
+int ED_view3d_context_activate(bContext *C)
+{
+       bScreen *sc= CTX_wm_screen(C);
+       ScrArea *sa= CTX_wm_area(C);
+       ARegion *ar;
+       RegionView3D *rv3d;
+
+       if(sa->spacetype != SPACE_VIEW3D)
+               for(sa=sc->areabase.first; sa; sa= sa->next)
+                       if(sa->spacetype==SPACE_VIEW3D)
+                               break;
+
+       if(!sa)
+               return 0;
+       
+       for(ar=sa->regionbase.first; ar; ar=ar->next)
+               if(ar->regiontype == RGN_TYPE_WINDOW)
+                       break;
+       
+       if(!ar)
+               return 0;
+       
+       // bad context switch ..
+       CTX_wm_area_set(C, sa);
+       CTX_wm_region_set(C, ar);
+       rv3d= ar->regiondata;
+
+       return 1;
+}
+
+static int game_engine_exec(bContext *C, wmOperator *unused)
+{
+#if GAMEBLENDER == 1
+       Scene *startscene = CTX_data_scene(C);
+       ScrArea *sa, *prevsa= CTX_wm_area(C);
+       ARegion *ar, *prevar= CTX_wm_region(C);
+       RegionView3D *rv3d;
+       rcti cam_frame;
+
+       // bad context switch ..
+       if(!ED_view3d_context_activate(C))
+               return OPERATOR_CANCELLED;
+       
+       rv3d= CTX_wm_region_view3d(C);
+       sa= CTX_wm_area(C);
+       ar= CTX_wm_region(C);
+
+       view3d_operator_needs_opengl(C);
+       
+       game_set_commmandline_options(&startscene->gm);
+
+       if(rv3d->persp==RV3D_CAMOB && startscene->gm.framing.type == SCE_GAMEFRAMING_BARS && startscene->gm.stereoflag != STEREO_DOME) { /* Letterbox */
+               rctf cam_framef;
+               calc_viewborder(startscene, ar, CTX_wm_view3d(C), &cam_framef);
+               cam_frame.xmin = cam_framef.xmin + ar->winrct.xmin;
+               cam_frame.xmax = cam_framef.xmax + ar->winrct.xmin;
+               cam_frame.ymin = cam_framef.ymin + ar->winrct.ymin;
+               cam_frame.ymax = cam_framef.ymax + ar->winrct.ymin;
+               BLI_isect_rcti(&ar->winrct, &cam_frame, &cam_frame);
+       }
+       else {
+               cam_frame.xmin = ar->winrct.xmin;
+               cam_frame.xmax = ar->winrct.xmax;
+               cam_frame.ymin = ar->winrct.ymin;
+               cam_frame.ymax = ar->winrct.ymax;
+       }
+
+
+       SaveState(C);
+       StartKetsjiShell(C, ar, &cam_frame, 1);
+       RestoreState(C);
+       
+       CTX_wm_region_set(C, prevar);
+       CTX_wm_area_set(C, prevsa);
+
+       //XXX restore_all_scene_cfra(scene_cfra_store);
+       set_scene_bg(startscene);
+       //XXX scene_update_for_newframe(G.scene, G.scene->lay);
+       
+#else
+       printf("GameEngine Disabled\n");
+#endif
+       ED_area_tag_redraw(CTX_wm_area(C));
+       return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_game_start(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Start Game Engine";
+       ot->description= "Start game engine.";
+       ot->idname= "VIEW3D_OT_game_start";
+       
+       /* api callbacks */
+       ot->exec= game_engine_exec;
+       
+       ot->poll= game_engine_poll;
+}
+
+
+/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
+#define FLY_MODAL_CANCEL                       1
+#define FLY_MODAL_CONFIRM                      2
+#define FLY_MODAL_ACCELERATE           3
+#define FLY_MODAL_DECELERATE           4
+#define FLY_MODAL_PAN_ENABLE           5
+#define FLY_MODAL_PAN_DISABLE          6
+#define FLY_MODAL_DIR_FORWARD          7
+#define FLY_MODAL_DIR_BACKWARD         8
+#define FLY_MODAL_DIR_LEFT                     9
+#define FLY_MODAL_DIR_RIGHT                    10
+#define FLY_MODAL_DIR_UP                       11
+#define FLY_MODAL_DIR_DOWN                     12
+#define FLY_MODAL_AXIS_LOCK_X          13
+#define FLY_MODAL_AXIS_LOCK_Z          14
+#define FLY_MODAL_PRECISION_ENABLE     15
+#define FLY_MODAL_PRECISION_DISABLE    16
+
+/* called in transform_ops.c, on each regeneration of keymaps  */
+void fly_modal_keymap(wmKeyConfig *keyconf)
+{
+       static EnumPropertyItem modal_items[] = {
+       {FLY_MODAL_CANCEL,      "CANCEL", 0, "Cancel", ""},
+       {FLY_MODAL_CONFIRM,     "CONFIRM", 0, "Confirm", ""},
+       {FLY_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
+       {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
+
+       {FLY_MODAL_PAN_ENABLE,  "PAN_ENABLE", 0, "Pan Enable", ""},
+       {FLY_MODAL_PAN_DISABLE, "PAN_DISABLE", 0, "Pan Disable", ""},
+
+       {FLY_MODAL_DIR_FORWARD, "FORWARD", 0, "Fly Forward", ""},
+       {FLY_MODAL_DIR_BACKWARD,"BACKWARD", 0, "Fly Backward", ""},
+       {FLY_MODAL_DIR_LEFT,    "LEFT", 0, "Fly Left", ""},
+       {FLY_MODAL_DIR_RIGHT,   "RIGHT", 0, "Fly Right", ""},
+       {FLY_MODAL_DIR_UP,              "UP", 0, "Fly Up", ""},
+       {FLY_MODAL_DIR_DOWN,    "DOWN", 0, "Fly Down", ""},
+
+       {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"},
+       {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"},
+
+       {FLY_MODAL_PRECISION_ENABLE,    "PRECISION_ENABLE", 0, "Precision Enable", ""},
+       {FLY_MODAL_PRECISION_DISABLE,   "PRECISION_DISABLE", 0, "Precision Disable", ""},
+
+       {0, NULL, 0, NULL, NULL}};
+
+       wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Fly Modal");
+
+       /* this function is called for each spacetype, only needs to add map once */
+       if(keymap) return;
+
+       keymap= WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items);
+
+       /* items for modal map */
+       WM_modalkeymap_add_item(keymap, ESCKEY,    KM_PRESS, KM_ANY, 0, FLY_MODAL_CANCEL);
+       WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_ANY, KM_ANY, 0, FLY_MODAL_CANCEL);
+
+       WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, FLY_MODAL_CONFIRM);
+       WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, FLY_MODAL_CONFIRM);
+       WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, FLY_MODAL_CONFIRM);
+
+       WM_modalkeymap_add_item(keymap, PADPLUSKEY, KM_PRESS, 0, 0, FLY_MODAL_ACCELERATE);
+       WM_modalkeymap_add_item(keymap, PADMINUS, KM_PRESS, 0, 0, FLY_MODAL_DECELERATE);
+       WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, FLY_MODAL_ACCELERATE);
+       WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, FLY_MODAL_DECELERATE);
+
+       WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, KM_ANY, 0, FLY_MODAL_PAN_ENABLE);
+       WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, FLY_MODAL_PAN_DISABLE); /* XXX - Bug in the event system, middle mouse release doesnt work */
+
+       /* WASD */
+       WM_modalkeymap_add_item(keymap, WKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_FORWARD);
+       WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_BACKWARD);
+       WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_LEFT);
+       WM_modalkeymap_add_item(keymap, DKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_RIGHT);
+       WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_UP);
+       WM_modalkeymap_add_item(keymap, FKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_DOWN);
+
+       WM_modalkeymap_add_item(keymap, XKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_X);
+       WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_Z);
+
+       WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, FLY_MODAL_PRECISION_ENABLE);
+       WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, FLY_MODAL_PRECISION_DISABLE);
+
+       /* assign map to operators */
+       WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly");
+
+}
+
+typedef struct FlyInfo {
+       /* context stuff */
+       RegionView3D *rv3d;
+       View3D *v3d;
+       ARegion *ar;
+       Scene *scene;
+
+       wmTimer *timer; /* needed for redraws */
+
+       short state;
+       short use_precision;
+       short redraw;
+       short mval[2];
+
+       /* fly state state */
+       float speed; /* the speed the view is moving per redraw */
+       short axis; /* Axis index to move allong by default Z to move allong the view */
+       short pan_view; /* when true, pan the view instead of rotating */
+
+       /* relative view axis locking - xlock, zlock
+       0; disabled
+       1; enabled but not checking because mouse hasnt moved outside the margin since locking was checked an not needed
+          when the mouse moves, locking is set to 2 so checks are done.
+       2; mouse moved and checking needed, if no view altering is donem its changed back to 1 */
+       short xlock, zlock;
+       float xlock_momentum, zlock_momentum; /* nicer dynamics */
+       float grid; /* world scale 1.0 default */
+
+       /* backup values */
+       float dist_backup; /* backup the views distance since we use a zero dist for fly mode */
+       float ofs_backup[3]; /* backup the views offset incase the user cancels flying in non camera mode */
+       float rot_backup[4]; /* backup the views quat incase the user cancels flying in non camera mode. (quat for view, eul for camera) */
+       short persp_backup; /* remember if were ortho or not, only used for restoring the view if it was a ortho view */
+
+       /* compare between last state */
+       double time_lastwheel; /* used to accelerate when using the mousewheel a lot */
+       double time_lastdraw; /* time between draws */
+
+       /* use for some lag */
+       float dvec_prev[3]; /* old for some lag */
+
+} FlyInfo;
+
+/* FlyInfo->state */
+#define FLY_RUNNING            0
+#define FLY_CANCEL             1
+#define FLY_CONFIRM            2
+
+int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event)
+{
+       float upvec[3]; // tmp
+       float mat[3][3];
+
+       fly->rv3d= CTX_wm_region_view3d(C);
+       fly->v3d = CTX_wm_view3d(C);
+       fly->ar = CTX_wm_region(C);
+       fly->scene= CTX_data_scene(C);
+
+       if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) {
+               BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
+               return FALSE;
+       }
+
+       if(fly->v3d->ob_centre) {
+               BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view is locked to an object");
+               return FALSE;
+       }
+
+       if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->constraints.first) {
+               BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints");
+               return FALSE;
+       }
+
+       fly->state= FLY_RUNNING;
+       fly->speed= 0.0f;
+       fly->axis= 2;
+       fly->pan_view= FALSE;
+       fly->xlock= FALSE;
+       fly->zlock= TRUE;
+       fly->xlock_momentum=0.0f;
+       fly->zlock_momentum=0.0f;
+       fly->grid= 1.0f;
+       fly->use_precision= 0;
+
+       fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f;
+
+       fly->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+
+
+       /* we have to rely on events to give proper mousecoords after a warp_pointer */
+//XXX2.5       warp_pointer(cent_orig[0], cent_orig[1]);
+       //fly->mval[0]= (fly->sa->winx)/2;
+       //fly->mval[1]= (fly->sa->winy)/2;
+
+       fly->mval[0] = event->x - fly->ar->winrct.xmin;
+       fly->mval[1] = event->y - fly->ar->winrct.ymin;
+
+
+       fly->time_lastdraw= fly->time_lastwheel= PIL_check_seconds_timer();
+
+       fly->rv3d->rflag |= RV3D_FLYMODE; /* so we draw the corner margins */
+
+       /* detect weather to start with Z locking */
+       upvec[0]=1.0f; upvec[1]=0.0f; upvec[2]=0.0f;
+       copy_m3_m4(mat, fly->rv3d->viewinv);
+       mul_m3_v3(mat, upvec);
+       if (fabs(upvec[2]) < 0.1)
+               fly->zlock = 1;
+       upvec[0]=0; upvec[1]=0; upvec[2]=0;
+
+       fly->persp_backup= fly->rv3d->persp;
+       fly->dist_backup= fly->rv3d->dist;
+       if (fly->rv3d->persp==RV3D_CAMOB) {
+               /* store the origoinal camera loc and rot */
+               VECCOPY(fly->ofs_backup, fly->v3d->camera->loc);
+               VECCOPY(fly->rot_backup, fly->v3d->camera->rot);
+
+               where_is_object(fly->scene, fly->v3d->camera);
+               VECCOPY(fly->rv3d->ofs, fly->v3d->camera->obmat[3]);
+               mul_v3_fl(fly->rv3d->ofs, -1.0f); /*flip the vector*/
+
+               fly->rv3d->dist=0.0;
+               fly->rv3d->viewbut=0;
+
+               /* used for recording */
+//XXX2.5               if(v3d->camera->ipoflag & OB_ACTION_OB)
+//XXX2.5                       actname= "Object";
+
+       } else {
+               /* perspective or ortho */
+               if (fly->rv3d->persp==RV3D_ORTHO)
+                       fly->rv3d->persp= RV3D_PERSP; /*if ortho projection, make perspective */
+               QUATCOPY(fly->rot_backup, fly->rv3d->viewquat);
+               VECCOPY(fly->ofs_backup, fly->rv3d->ofs);
+               fly->rv3d->dist= 0.0;
+
+               upvec[2]= fly->dist_backup; /*x and y are 0*/
+               mul_m3_v3(mat, upvec);
+               sub_v3_v3v3(fly->rv3d->ofs, fly->rv3d->ofs, upvec);
+               /*Done with correcting for the dist*/
+       }
+
+       return 1;
+}
+
+static int flyEnd(bContext *C, FlyInfo *fly)
+{
+       RegionView3D *rv3d= fly->rv3d;
+       View3D *v3d = fly->v3d;
+
+       float upvec[3];
+
+       if(fly->state == FLY_RUNNING)
+               return OPERATOR_RUNNING_MODAL;
+
+       WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer);
+
+       rv3d->dist= fly->dist_backup;
+
+       if (fly->state == FLY_CANCEL) {
+       /* Revert to original view? */
+               if (fly->persp_backup==RV3D_CAMOB) { /* a camera view */
+                       rv3d->viewbut=1;
+                       VECCOPY(v3d->camera->loc, fly->ofs_backup);
+                       VECCOPY(v3d->camera->rot, fly->rot_backup);
+                       DAG_id_flush_update(&v3d->camera->id, OB_RECALC_OB);
+               } else {
+                       /* Non Camera we need to reset the view back to the original location bacause the user canceled*/
+                       QUATCOPY(rv3d->viewquat, fly->rot_backup);
+                       VECCOPY(rv3d->ofs, fly->ofs_backup);
+                       rv3d->persp= fly->persp_backup;
+               }
+       }
+       else if (fly->persp_backup==RV3D_CAMOB) {       /* camera */
+               float mat3[3][3];
+               copy_m3_m4(mat3, v3d->camera->obmat);
+               mat3_to_compatible_eul( v3d->camera->rot, fly->rot_backup,mat3);
+
+               DAG_id_flush_update(&v3d->camera->id, OB_RECALC_OB);
+#if 0 //XXX2.5
+               if (IS_AUTOKEY_MODE(NORMAL)) {
+                       allqueue(REDRAWIPO, 0);
+                       allspace(REMAKEIPO, 0);
+                       allqueue(REDRAWNLA, 0);
+                       allqueue(REDRAWTIME, 0);
+               }
+#endif
+       }
+       else { /* not camera */
+               /* Apply the fly mode view */
+               /*restore the dist*/
+               float mat[3][3];
+               upvec[0]= upvec[1]= 0;
+               upvec[2]= fly->dist_backup; /*x and y are 0*/
+               copy_m3_m4(mat, rv3d->viewinv);
+               mul_m3_v3(mat, upvec);
+               add_v3_v3v3(rv3d->ofs, rv3d->ofs, upvec);
+               /*Done with correcting for the dist */
+       }
+
+       rv3d->rflag &= ~RV3D_FLYMODE;
+//XXX2.5       BIF_view3d_previewrender_signal(fly->sa, PR_DBASE|PR_DISPRECT); /* not working at the moment not sure why */
+
+
+       if(fly->state == FLY_CONFIRM) {
+               MEM_freeN(fly);
+               return OPERATOR_FINISHED;
+       }
+
+       MEM_freeN(fly);
+       return OPERATOR_CANCELLED;
+}
+
+void flyEvent(FlyInfo *fly, wmEvent *event)
+{
+       if (event->type == TIMER) {
+               fly->redraw = 1;
+       }
+       else if (event->type == MOUSEMOVE) {
+               fly->mval[0] = event->x - fly->ar->winrct.xmin;
+               fly->mval[1] = event->y - fly->ar->winrct.ymin;
+       } /* handle modal keymap first */
+       else if (event->type == EVT_MODAL_MAP) {
+               switch (event->val) {
+                       case FLY_MODAL_CANCEL:
+                               fly->state = FLY_CANCEL;
+                               break;
+                       case FLY_MODAL_CONFIRM:
+                               fly->state = FLY_CONFIRM;
+                               break;
+
+                       case FLY_MODAL_ACCELERATE:
+                       {
+                               double time_currwheel;
+                               float time_wheel;
+
+                               time_currwheel= PIL_check_seconds_timer();
+                               time_wheel = (float)(time_currwheel - fly->time_lastwheel);
+                               fly->time_lastwheel = time_currwheel;
+                               /*printf("Wheel %f\n", time_wheel);*/
+                               /*Mouse wheel delays range from 0.5==slow to 0.01==fast*/
+                               time_wheel = 1+ (10 - (20*MIN2(time_wheel, 0.5))); /* 0-0.5 -> 0-5.0 */
+
+                               if (fly->speed<0.0f) fly->speed= 0.0f;
+                               else {
+                                       if (event->shift)
+                                               fly->speed+= fly->grid*time_wheel*0.1;
+                                       else
+                                               fly->speed+= fly->grid*time_wheel;
+                               }
+                               break;
+                       }
+                       case FLY_MODAL_DECELERATE:
+                       {
+                               double time_currwheel;
+                               float time_wheel;
+
+                               time_currwheel= PIL_check_seconds_timer();
+                               time_wheel = (float)(time_currwheel - fly->time_lastwheel);
+                               fly->time_lastwheel = time_currwheel;
+                               time_wheel = 1+ (10 - (20*MIN2(time_wheel, 0.5))); /* 0-0.5 -> 0-5.0 */
+
+                               if (fly->speed>0) fly->speed=0;
+                               else {
+                                       if (event->shift)
+                                               fly->speed-= fly->grid*time_wheel*0.1;
+                                       else
+                                               fly->speed-= fly->grid*time_wheel;
+                               }
+                               break;
+                       }
+                       case FLY_MODAL_PAN_ENABLE:
+                               fly->pan_view= TRUE;
+                               break;
+                       case FLY_MODAL_PAN_DISABLE:
+//XXX2.5               warp_pointer(cent_orig[0], cent_orig[1]);
+                               fly->pan_view= FALSE;
+                               break;
+
+                               /* impliment WASD keys */
+                       case FLY_MODAL_DIR_FORWARD:
+                               if (fly->speed < 0.0f) fly->speed= -fly->speed; /* flip speed rather then stopping, game like motion */
+                               else fly->speed += fly->grid; /* increse like mousewheel if were alredy moving in that difection*/
+                               fly->axis= 2;
+                               break;
+                       case FLY_MODAL_DIR_BACKWARD:
+                               if (fly->speed>0) fly->speed= -fly->speed;
+                               else fly->speed -= fly->grid;
+                               fly->axis= 2;
+                               break;
+                       case FLY_MODAL_DIR_LEFT:
+                               if (fly->speed < 0.0f) fly->speed= -fly->speed;
+                               fly->axis= 0;
+                               break;
+                       case FLY_MODAL_DIR_RIGHT:
+                               if (fly->speed > 0.0f) fly->speed= -fly->speed;
+                               fly->axis= 0;
+                               break;
+
+                       case FLY_MODAL_DIR_UP:
+                               if (fly->speed < 0.0f) fly->speed= -fly->speed;
+                               fly->axis= 1;
+                               break;
+
+                       case FLY_MODAL_DIR_DOWN:
+                               if (fly->speed > 0.0f) fly->speed= -fly->speed;
+                               fly->axis= 1;
+                               break;
+
+                       case FLY_MODAL_AXIS_LOCK_X:
+                               if (fly->xlock) fly->xlock=0;
+                               else {
+                                       fly->xlock = 2;
+                                       fly->xlock_momentum = 0.0;
+                               }
+                               break;
+                       case FLY_MODAL_AXIS_LOCK_Z:
+                               if (fly->zlock) fly->zlock=0;
+                               else {
+                                       fly->zlock = 2;
+                                       fly->zlock_momentum = 0.0;
+                               }
+                               break;
+
+                       case FLY_MODAL_PRECISION_ENABLE:
+                               fly->use_precision= TRUE;
+                               break;
+                       case FLY_MODAL_PRECISION_DISABLE:
+                               fly->use_precision= FALSE;
+                               break;
+
+               }
+       }
+}
+
+//int fly_exec(bContext *C, wmOperator *op)
+int flyApply(FlyInfo *fly)
+{
+       /*
+       fly mode - Shift+F
+       a fly loop where the user can move move the view as if they are flying
+       */
+       RegionView3D *rv3d= fly->rv3d;
+       View3D *v3d = fly->v3d;
+       ARegion *ar = fly->ar;
+       Scene *scene= fly->scene;
+
+       float mat[3][3], /* 3x3 copy of the view matrix so we can move allong the view axis */
+       dvec[3]={0,0,0}, /* this is the direction thast added to the view offset per redraw */
+
+       /* Camera Uprighting variables */
+       upvec[3]={0,0,0}, /* stores the view's up vector */
+
+       moffset[2], /* mouse offset from the views center */
+       tmp_quat[4]; /* used for rotating the view */
+
+       int cent_orig[2], /* view center */
+//XXX- can avoid using //      cent[2], /* view center modified */
+       xmargin, ymargin; /* x and y margin are define the safe area where the mouses movement wont rotate the view */
+       unsigned char
+       apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/
+
+       /* for recording */
+#if 0 //XXX2.5 todo, get animation recording working again.
+       int playing_anim = 0; //XXX has_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM);
+       int cfra = -1; /*so the first frame always has a key added */
+       char *actname="";
+#endif
+       /* the dist defines a vector that is infront of the offset
+       to rotate the view about.
+       this is no good for fly mode because we
+       want to rotate about the viewers center.
+       but to correct the dist removal we must
+       alter offset so the view doesn't jump. */
+
+       xmargin= ar->winx/20.0f;
+       ymargin= ar->winy/20.0f;
+
+       cent_orig[0]= ar->winrct.xmin + ar->winx/2;
+       cent_orig[1]= ar->winrct.ymin + ar->winy/2;
+
+       {
+
+               /* mouse offset from the center */
+               moffset[0]= fly->mval[0]- ar->winx/2;
+               moffset[1]= fly->mval[1]- ar->winy/2;
+
+               /* enforce a view margin */
+               if (moffset[0]>xmargin)                 moffset[0]-=xmargin;
+               else if (moffset[0] < -xmargin) moffset[0]+=xmargin;
+               else                                                    moffset[0]=0;
+
+               if (moffset[1]>ymargin)                 moffset[1]-=ymargin;
+               else if (moffset[1] < -ymargin) moffset[1]+=ymargin;
+               else                                                    moffset[1]=0;
+
+
+               /* scale the mouse movement by this value - scales mouse movement to the view size
+                * moffset[0]/(ar->winx-xmargin*2) - window size minus margin (same for y)
+                *
+                * the mouse moves isnt linear */
+
+               if(moffset[0]) {
+                       moffset[0] /= ar->winx - (xmargin*2);
+                       moffset[0] *= fabs(moffset[0]);
+               }
+
+               if(moffset[1]) {
+                       moffset[1] /= ar->winy - (ymargin*2);
+                       moffset[1] *= fabs(moffset[1]);
+               }
+
+               /* Should we redraw? */
+               if(fly->speed != 0.0f || moffset[0] || moffset[1] || fly->zlock || fly->xlock || dvec[0] || dvec[1] || dvec[2] ) {
+                       float dvec_tmp[3];
+                       double time_current, time_redraw; /*time how fast it takes for us to redraw, this is so simple scenes dont fly too fast */
+                       float time_redraw_clamped;
+
+                       time_current= PIL_check_seconds_timer();
+                       time_redraw= (float)(time_current - fly->time_lastdraw);
+                       time_redraw_clamped= MIN2(0.05f, time_redraw); /* clamt the redraw time to avoid jitter in roll correction */
+                       fly->time_lastdraw= time_current;
+                       /*fprintf(stderr, "%f\n", time_redraw);*/ /* 0.002 is a small redraw 0.02 is larger */
+
+                       /* Scale the time to use shift to scale the speed down- just like
+                       shift slows many other areas of blender down */
+                       if (fly->use_precision)
+                               fly->speed= fly->speed * (1.0f-time_redraw_clamped);
+
+                       copy_m3_m4(mat, rv3d->viewinv);
+
+                       if (fly->pan_view==TRUE) {
+                               /* pan only */
+                               dvec_tmp[0]= -moffset[0];
+                               dvec_tmp[1]= -moffset[1];
+                               dvec_tmp[2]= 0;
+
+                               if (fly->use_precision) {
+                                       dvec_tmp[0] *= 0.1;
+                                       dvec_tmp[1] *= 0.1;
+                               }
+
+                               mul_m3_v3(mat, dvec_tmp);
+                               mul_v3_fl(dvec_tmp, time_redraw*200.0 * fly->grid);
+
+                       } else {
+                               float roll; /* similar to the angle between the camera's up and the Z-up, but its very rough so just roll*/
+
+                               /* rotate about the X axis- look up/down */
+                               if (moffset[1]) {
+                                       upvec[0]=1;
+                                       upvec[1]=0;
+                                       upvec[2]=0;
+                                       mul_m3_v3(mat, upvec);
+                                       axis_angle_to_quat( tmp_quat, upvec, (float)moffset[1]*-time_redraw*20); /* Rotate about the relative up vec */
+                                       mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+                                       if (fly->xlock) fly->xlock = 2; /*check for rotation*/
+                                       if (fly->zlock) fly->zlock = 2;
+                                       fly->xlock_momentum= 0.0f;
+                               }
+
+                               /* rotate about the Y axis- look left/right */
+                               if (moffset[0]) {
+
+                                       /* if we're upside down invert the moffset */
+                                       upvec[0]=0;
+                                       upvec[1]=1;
+                                       upvec[2]=0;
+                                       mul_m3_v3(mat, upvec);
+
+                                       if(upvec[2] < 0.0f)
+                                               moffset[0]= -moffset[0];
+
+                                       /* make the lock vectors */
+                                       if (fly->zlock) {
+                                               upvec[0]=0;
+                                               upvec[1]=0;
+                                               upvec[2]=1;
+                                       } else {
+                                               upvec[0]=0;
+                                               upvec[1]=1;
+                                               upvec[2]=0;
+                                               mul_m3_v3(mat, upvec);
+                                       }
+
+                                       axis_angle_to_quat( tmp_quat, upvec, (float)moffset[0]*time_redraw*20); /* Rotate about the relative up vec */
+                                       mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+                                       if (fly->xlock) fly->xlock = 2;/*check for rotation*/
+                                       if (fly->zlock) fly->zlock = 2;
+                               }
+
+                               if (fly->zlock==2) {
+                                       upvec[0]=1;
+                                       upvec[1]=0;
+                                       upvec[2]=0;
+                                       mul_m3_v3(mat, upvec);
+
+                                       /*make sure we have some z rolling*/
+                                       if (fabs(upvec[2]) > 0.00001f) {
+                                               roll= upvec[2]*5;
+                                               upvec[0]=0; /*rotate the view about this axis*/
+                                               upvec[1]=0;
+                                               upvec[2]=1;
+
+                                               mul_m3_v3(mat, upvec);
+                                               axis_angle_to_quat( tmp_quat, upvec, roll*time_redraw_clamped*fly->zlock_momentum*0.1); /* Rotate about the relative up vec */
+                                               mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+                                               fly->zlock_momentum += 0.05f;
+                                       } else {
+                                               fly->zlock=1; /* dont check until the view rotates again */
+                                               fly->zlock_momentum= 0.0f;
+                                       }
+                               }
+
+                               if (fly->xlock==2 && moffset[1]==0) { /*only apply xcorrect when mouse isnt applying x rot*/
+                                       upvec[0]=0;
+                                       upvec[1]=0;
+                                       upvec[2]=1;
+                                       mul_m3_v3(mat, upvec);
+                                       /*make sure we have some z rolling*/
+                                       if (fabs(upvec[2]) > 0.00001) {
+                                               roll= upvec[2] * -5;
+
+                                               upvec[0]= 1.0f; /*rotate the view about this axis*/
+                                               upvec[1]= 0.0f;
+                                               upvec[2]= 0.0f;
+
+                                               mul_m3_v3(mat, upvec);
+
+                                               axis_angle_to_quat( tmp_quat, upvec, roll*time_redraw_clamped*fly->xlock_momentum*0.1f); /* Rotate about the relative up vec */
+                                               mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+                                               fly->xlock_momentum += 0.05f;
+                                       } else {
+                                               fly->xlock=1; /* see above */
+                                               fly->xlock_momentum= 0.0f;
+                                       }
+                               }
+
+
+                               if (apply_rotation) {
+                                       /* Normal operation */
+                                       /* define dvec, view direction vector */
+                                       dvec_tmp[0]= dvec_tmp[1]= dvec_tmp[2]= 0.0f;
+                                       /* move along the current axis */
+                                       dvec_tmp[fly->axis]= 1.0f;
+
+                                       mul_m3_v3(mat, dvec_tmp);
+
+                                       mul_v3_fl(dvec_tmp, fly->speed * time_redraw * 0.25f);
+                               }
+                       }
+
+                       /* impose a directional lag */
+                       interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f/(1.0f+(time_redraw*5.0f))));
+
+                       if (rv3d->persp==RV3D_CAMOB) {
+                               if (v3d->camera->protectflag & OB_LOCK_LOCX)
+                                       dvec[0] = 0.0;
+                               if (v3d->camera->protectflag & OB_LOCK_LOCY)
+                                       dvec[1] = 0.0;
+                               if (v3d->camera->protectflag & OB_LOCK_LOCZ)
+                                       dvec[2] = 0.0;
+                       }
+
+                       add_v3_v3v3(rv3d->ofs, rv3d->ofs, dvec);
+#if 0 //XXX2.5
+                       if (fly->zlock && fly->xlock)
+                               headerprint("FlyKeys  Speed:(+/- | Wheel),  Upright Axis:X  on/Z on,   Slow:Shift,  Direction:WASDRF,  Ok:LMB,  Pan:MMB,  Cancel:RMB");
+                       else if (fly->zlock)
+                               headerprint("FlyKeys  Speed:(+/- | Wheel),  Upright Axis:X off/Z on,   Slow:Shift,  Direction:WASDRF,  Ok:LMB,  Pan:MMB,  Cancel:RMB");
+                       else if (fly->xlock)
+                               headerprint("FlyKeys  Speed:(+/- | Wheel),  Upright Axis:X  on/Z off,  Slow:Shift,  Direction:WASDRF,  Ok:LMB,  Pan:MMB,  Cancel:RMB");
+                       else
+                               headerprint("FlyKeys  Speed:(+/- | Wheel),  Upright Axis:X off/Z off,  Slow:Shift,  Direction:WASDRF,  Ok:LMB,  Pan:MMB,  Cancel:RMB");
+#endif
+
+//XXX2.5                       do_screenhandlers(G.curscreen); /* advance the next frame */
+
+                       /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */
+                       if (rv3d->persp==RV3D_CAMOB) {
+                               rv3d->persp= RV3D_PERSP; /*set this so setviewmatrixview3d uses the ofs and quat instead of the camera */
+                               setviewmatrixview3d(scene, v3d, rv3d);
+
+                               setcameratoview3d(v3d, rv3d, v3d->camera);
+
+                               {       //XXX - some reason setcameratoview3d doesnt copy, shouldnt not be needed!
+                                       VECCOPY(v3d->camera->loc, rv3d->ofs);
+                                       negate_v3(v3d->camera->loc);
+                               }
+
+                               rv3d->persp= RV3D_CAMOB;
+#if 0 //XXX2.5
+                               /* record the motion */
+                               if (IS_AUTOKEY_MODE(NORMAL) && (!playing_anim || cfra != G.scene->r.cfra)) {
+                                       cfra = G.scene->r.cfra;
+
+                                       if (fly->xlock || fly->zlock || moffset[0] || moffset[1]) {
+                                               insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_ROT_X, 0);
+                                               insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_ROT_Y, 0);
+                                               insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_ROT_Z, 0);
+                                       }
+                                       if (fly->speed) {
+                                               insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_LOC_X, 0);
+                                               insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_LOC_Y, 0);
+                                               insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_LOC_Z, 0);
+                                       }
+                               }
+#endif
+                       }
+//XXX2.5                       scrarea_do_windraw(curarea);
+//XXX2.5                       screen_swapbuffers();
+               } else
+                       /*were not redrawing but we need to update the time else the view will jump */
+                       fly->time_lastdraw= PIL_check_seconds_timer();
+               /* end drawing */
+               VECCOPY(fly->dvec_prev, dvec);
+       }
+
+/* moved to flyEnd() */
+
+       return OPERATOR_FINISHED;
+}
+
+
+
+static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       FlyInfo *fly;
+
+       if(rv3d->viewlock)
+               return OPERATOR_CANCELLED;
+
+       fly= MEM_callocN(sizeof(FlyInfo), "FlyOperation");
+
+       op->customdata= fly;
+
+       if(initFlyInfo(C, fly, op, event)==FALSE) {
+               MEM_freeN(op->customdata);
+               return OPERATOR_CANCELLED;
+       }
+
+       flyEvent(fly, event);
+
+       WM_event_add_modal_handler(C, op);
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+static int fly_cancel(bContext *C, wmOperator *op)
+{
+       FlyInfo *fly = op->customdata;
+
+       fly->state = FLY_CANCEL;
+       flyEnd(C, fly);
+       op->customdata= NULL;
+
+       return OPERATOR_CANCELLED;
+}
+
+static int fly_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       int exit_code;
+
+       FlyInfo *fly = op->customdata;
+
+       fly->redraw= 0;
+
+       flyEvent(fly, event);
+
+       if(event->type==TIMER)
+               flyApply(fly);
+
+       if(fly->redraw) {;
+               ED_region_tag_redraw(CTX_wm_region(C));
+       }
+
+       exit_code = flyEnd(C, fly);
+
+       if(exit_code!=OPERATOR_RUNNING_MODAL)
+               ED_region_tag_redraw(CTX_wm_region(C));
+
+       return exit_code;
+}
+
+void VIEW3D_OT_fly(wmOperatorType *ot)
+{
+
+       /* identifiers */
+       ot->name= "Fly Navigation";
+       ot->description= "Interactively fly around the scene.";
+       ot->idname= "VIEW3D_OT_fly";
+
+       /* api callbacks */
+       ot->invoke= fly_invoke;
+       ot->cancel= fly_cancel;
+       ot->modal= fly_modal;
+       ot->poll= ED_operator_view3d_active;
+
+       /* flags */
+       ot->flag= OPTYPE_BLOCKING;
+
+}
+
 /* ************************************** */
 
 void view3d_align_axis_to_vector(View3D *v3d, RegionView3D *rv3d, int axisidx, float vec[3])
@@ -1393,27 +2466,27 @@ void view3d_align_axis_to_vector(View3D *v3d, RegionView3D *rv3d, int axisidx, f
        else alignaxis[-axisidx-1]= -1.0;
        
        VECCOPY(norm, vec);
-       Normalize(norm);
+       normalize_v3(norm);
        
-       angle= (float)acos(Inpf(alignaxis, norm));
-       Crossf(axis, alignaxis, norm);
-       VecRotToQuat(axis, -angle, new_quat);
+       angle= (float)acos(dot_v3v3(alignaxis, norm));
+       cross_v3_v3v3(axis, alignaxis, norm);
+       axis_angle_to_quat( new_quat,axis, -angle);
        
        rv3d->view= 0;
        
-       if (rv3d->persp==V3D_CAMOB && v3d->camera) {
+       if (rv3d->persp==RV3D_CAMOB && v3d->camera) {
                /* switch out of camera view */
                float orig_ofs[3];
                float orig_dist= rv3d->dist;
                float orig_lens= v3d->lens;
                
                VECCOPY(orig_ofs, rv3d->ofs);
-               rv3d->persp= V3D_PERSP;
+               rv3d->persp= RV3D_PERSP;
                rv3d->dist= 0.0;
                view_settings_from_ob(v3d->camera, rv3d->ofs, NULL, NULL, &v3d->lens);
                smooth_view(NULL, NULL, NULL, orig_ofs, new_quat, &orig_dist, &orig_lens); // XXX
        } else {
-               if (rv3d->persp==V3D_CAMOB) rv3d->persp= V3D_PERSP; /* switch out of camera mode */
+               if (rv3d->persp==RV3D_CAMOB) rv3d->persp= RV3D_PERSP; /* switch out of camera mode */
                smooth_view(NULL, NULL, NULL, NULL, new_quat, NULL, NULL); // XXX
        }
 }