At last... this merge should finally do the trick!
[blender.git] / source / blender / editors / transform / transform.c
index c21e3d14feced7552f8d322a383238b50a668fe3..ded6edbbb0e278ad656ac731224c63b1648543a7 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "DNA_anim_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_action_types.h"  /* for some special action-editor settings */
 #include "DNA_constraint_types.h"
@@ -59,6 +60,9 @@
 #include "DNA_userdef_types.h"
 #include "DNA_view3d_types.h"
 #include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
 
 //#include "BIF_editview.h"            /* arrows_move_cursor   */
 #include "BIF_gl.h"
 //#include "BIF_editmesh.h"
 //#include "BIF_editsima.h"
 //#include "BIF_editparticle.h"
-//#include "BIF_drawimage.h"           /* uvco_to_areaco_noclip */
-//#include "BIF_editaction.h" 
 
-#include "BKE_action.h" /* get_action_frame */
+#include "BKE_action.h"
+#include "BKE_nla.h"
 //#include "BKE_bad_level_calls.h"/* popmenu and error */
 #include "BKE_bmesh.h"
+#include "BKE_context.h"
 #include "BKE_constraint.h"
 #include "BKE_global.h"
 #include "BKE_particle.h"
 #include "BKE_utildefines.h"
 #include "BKE_context.h"
 
-//#include "BSE_drawipo.h"
-//#include "BSE_editnla_types.h"       /* for NLAWIDTH */
-//#include "BSE_editaction_types.h"
-//#include "BSE_time.h"
 //#include "BSE_view.h"
 
-#include "ED_view3d.h"
+#include "ED_image.h"
 #include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_markers.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+
 #include "UI_view2d.h"
 #include "WM_types.h"
+#include "WM_api.h"
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 
 #include "PIL_time.h"                  /* sleep                                */
 
+#include "UI_resources.h"
+
 //#include "blendef.h"
 //
 //#include "mydevice.h"
 
 #include "transform.h"
 
-/******************************** Helper functions ************************************/
-
-/* GLOBAL Wrapper Fonctions */
-
-//void BIF_drawSnap()
-//{
-//     drawSnapping(&Trans);
-//}
-
-/* ************************** Dashed help line **************************** */
-
-
-/* bad frontbuffer call... because it is used in transform after force_draw() */
-static void helpline(TransInfo *t, float *vec)
-{
-#if 0 // TRANSFORM_FIX_ME
-       float vecrot[3], cent[2];
-       short mval[2];
-       
-       VECCOPY(vecrot, vec);
-       if(t->flag & T_EDIT) {
-               Object *ob=G.obedit;
-               if(ob) Mat4MulVecfl(ob->obmat, vecrot);
-       }
-       else if(t->flag & T_POSE) {
-               Object *ob=t->poseobj;
-               if(ob) Mat4MulVecfl(ob->obmat, vecrot);
-       }
-       
-       getmouseco_areawin(mval);
-       projectFloatView(t, vecrot, cent);      // no overflow in extreme cases
-
-       persp(PERSP_WIN);
-       
-       glDrawBuffer(GL_FRONT);
-       
-       BIF_ThemeColor(TH_WIRE);
-       
-       setlinestyle(3);
-       glBegin(GL_LINE_STRIP); 
-       glVertex2sv(mval); 
-       glVertex2fv(cent); 
-       glEnd();
-       setlinestyle(0);
-       
-       persp(PERSP_VIEW);
-       bglFlush(); // flush display for frontbuffer
-       glDrawBuffer(GL_BACK);
-#endif
-}
-
-
-  
-/* ************************** INPUT FROM MOUSE *************************** */
-
-float InputScaleRatio(TransInfo *t, short mval[2]) {
-       float ratio, dx, dy;
-       if(t->flag & T_SHIFT_MOD) {
-               /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
-               dx = (float)(t->center2d[0] - t->shiftmval[0]);
-               dy = (float)(t->center2d[1] - t->shiftmval[1]);
-               ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
-               
-               dx= (float)(t->center2d[0] - mval[0]);
-               dy= (float)(t->center2d[1] - mval[1]);
-               ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
-       }
-       else {
-               dx = (float)(t->center2d[0] - mval[0]);
-               dy = (float)(t->center2d[1] - mval[1]);
-               ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
-       }
-       return ratio;
-}
-
-float InputHorizontalRatio(TransInfo *t, short mval[2]) {
-       float x, pad;
-
-       pad = t->ar->winx / 10;
-
-       if (t->flag & T_SHIFT_MOD) {
-               /* deal with Shift key by adding motion / 10 to motion before shift press */
-               x = t->shiftmval[0] + (float)(mval[0] - t->shiftmval[0]) / 10.0f;
-       }
-       else {
-               x = mval[0];
-       }
-       return (x - pad) / (t->ar->winx - 2 * pad);
-}
-
-float InputHorizontalAbsolute(TransInfo *t, short mval[2]) {
-       float vec[3];
-       if(t->flag & T_SHIFT_MOD) {
-               float dvec[3];
-               /* calculate the main translation and the precise one separate */
-               convertViewVec(t, dvec, (short)(mval[0] - t->shiftmval[0]), (short)(mval[1] - t->shiftmval[1]));
-               VecMulf(dvec, 0.1f);
-               convertViewVec(t, t->vec, (short)(t->shiftmval[0] - t->imval[0]), (short)(t->shiftmval[1] - t->imval[1]));
-               VecAddf(t->vec, t->vec, dvec);
-       }
-       else {
-               convertViewVec(t, t->vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
-       }
-       Projf(vec, t->vec, t->viewinv[0]);
-       return Inpf(t->viewinv[0], vec) * 2.0f;
-}
-
-float InputVerticalRatio(TransInfo *t, short mval[2]) {
-       float y, pad;
-
-       pad = t->ar->winy / 10;
-
-       if (t->flag & T_SHIFT_MOD) {
-               /* deal with Shift key by adding motion / 10 to motion before shift press */
-               y = t->shiftmval[1] + (float)(mval[1] - t->shiftmval[1]) / 10.0f;
-       }
-       else {
-               y = mval[0];
-       }
-       return (y - pad) / (t->ar->winy - 2 * pad);
-}
-
-float InputVerticalAbsolute(TransInfo *t, short mval[2]) {
-       float vec[3];
-       if(t->flag & T_SHIFT_MOD) {
-               float dvec[3];
-               /* calculate the main translation and the precise one separate */
-               convertViewVec(t, dvec, (short)(mval[0] - t->shiftmval[0]), (short)(mval[1] - t->shiftmval[1]));
-               VecMulf(dvec, 0.1f);
-               convertViewVec(t, t->vec, (short)(t->shiftmval[0] - t->imval[0]), (short)(t->shiftmval[1] - t->imval[1]));
-               VecAddf(t->vec, t->vec, dvec);
-       }
-       else {
-               convertViewVec(t, t->vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
-       }
-       Projf(vec, t->vec, t->viewinv[1]);
-       return Inpf(t->viewinv[1], vec) * 2.0f;
-}
-
-float InputDeltaAngle(TransInfo *t, short mval[2])
-{
-       double dx2 = mval[0] - t->center2d[0];
-       double dy2 = mval[1] - t->center2d[1];
-       double B = sqrt(dx2*dx2+dy2*dy2);
-
-       double dx1 = t->imval[0] - t->center2d[0];
-       double dy1 = t->imval[1] - t->center2d[1];
-       double A = sqrt(dx1*dx1+dy1*dy1);
-
-       double dx3 = mval[0] - t->imval[0];
-       double dy3 = mval[1] - t->imval[1];
-
-       /* use doubles here, to make sure a "1.0" (no rotation) doesnt become 9.999999e-01, which gives 0.02 for acos */
-       double deler = ((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3))
-               / (2.0 * (A*B?A*B:1.0));
-       /* (A*B?A*B:1.0f) this takes care of potential divide by zero errors */
-
-       float dphi;
-       
-       dphi = saacos((float)deler);
-       if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
-
-       /* If the angle is zero, because of lack of precision close to the 1.0 value in acos
-        * approximate the angle with the oposite side of the normalized triangle
-        * This is a good approximation here since the smallest acos value seems to be around
-        * 0.02 degree and lower values don't even have a 0.01% error compared to the approximation
-        * */   
-       if (dphi == 0)
-       {
-               double dx, dy;
-               
-               dx2 /= A;
-               dy2 /= A;
-               
-               dx1 /= B;
-               dy1 /= B;
-               
-               dx = dx1 - dx2;
-               dy = dy1 - dy2;
-               
-               dphi = sqrt(dx*dx + dy*dy);
-               if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
-       }
-       
-       if(t->flag & T_SHIFT_MOD) dphi = dphi/30.0f;
-       
-       /* if no delta angle, don't update initial position */
-       if (dphi != 0)
-       {
-               t->imval[0] = mval[0];
-               t->imval[1] = mval[1];
-       }
-       
-       return dphi;
-}
-
 /* ************************** SPACE DEPENDANT CODE **************************** */
 
 void setTransformViewMatrices(TransInfo *t)
 {
-       if(t->spacetype==SPACE_VIEW3D) {
-               View3D *v3d = t->view;
+       if(t->spacetype==SPACE_VIEW3D && t->ar->regiontype == RGN_TYPE_WINDOW) {
+               RegionView3D *rv3d = t->ar->regiondata;
                
-               Mat4CpyMat4(t->viewmat, v3d->viewmat);
-               Mat4CpyMat4(t->viewinv, v3d->viewinv);
-               Mat4CpyMat4(t->persmat, v3d->persmat);
-               Mat4CpyMat4(t->persinv, v3d->persinv);
-               t->persp = v3d->persp;
+               Mat4CpyMat4(t->viewmat, rv3d->viewmat);
+               Mat4CpyMat4(t->viewinv, rv3d->viewinv);
+               Mat4CpyMat4(t->persmat, rv3d->persmat);
+               Mat4CpyMat4(t->persinv, rv3d->persinv);
+               t->persp = rv3d->persp;
        }
        else {
                Mat4One(t->viewmat);
@@ -332,14 +144,16 @@ void setTransformViewMatrices(TransInfo *t)
 void convertViewVec(TransInfo *t, float *vec, short dx, short dy)
 {
        if (t->spacetype==SPACE_VIEW3D) {
-               window_to_3d(t->ar, t->view, vec, dx, dy);
+               if (t->ar->regiontype == RGN_TYPE_WINDOW)
+               {
+                       window_to_3d_delta(t->ar, vec, dx, dy);
+               }
        }
        else if(t->spacetype==SPACE_IMAGE) {
                View2D *v2d = t->view;
                float divx, divy, aspx, aspy;
                
-               // TRANSFORM_FIX_ME
-               //transform_aspect_ratio_tface_uv(&aspx, &aspy);
+               ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
                
                divx= v2d->mask.xmax-v2d->mask.xmin;
                divy= v2d->mask.ymax-v2d->mask.ymin;
@@ -359,29 +173,56 @@ void convertViewVec(TransInfo *t, float *vec, short dx, short dy)
                vec[1]= (v2d->cur.ymax-v2d->cur.ymin)*(dy) / (divy);
                vec[2]= 0.0f;
        }
+       else if(t->spacetype==SPACE_NODE) {
+               View2D *v2d = &t->ar->v2d;
+               float divx, divy;
+               
+               divx= v2d->mask.xmax-v2d->mask.xmin;
+               divy= v2d->mask.ymax-v2d->mask.ymin;
+               
+               vec[0]= (v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx;
+               vec[1]= (v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy;
+               vec[2]= 0.0f;
+       }
+       else if(t->spacetype==SPACE_SEQ) {
+               View2D *v2d = &t->ar->v2d;
+               float divx, divy;
+
+               divx= v2d->mask.xmax-v2d->mask.xmin;
+               divy= v2d->mask.ymax-v2d->mask.ymin;
+
+               vec[0]= (v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx;
+               vec[1]= (v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy;
+               vec[2]= 0.0f;
+       }
 }
 
 void projectIntView(TransInfo *t, float *vec, int *adr)
 {
        if (t->spacetype==SPACE_VIEW3D) {
-               project_int_noclip(t->ar, t->view, vec, adr);
+               if(t->ar->regiontype == RGN_TYPE_WINDOW)
+                       project_int_noclip(t->ar, vec, adr);
        }
        else if(t->spacetype==SPACE_IMAGE) {
                float aspx, aspy, v[2];
                
-               // TRANSFORM_FIX_ME
-               //transform_aspect_ratio_tface_uv(&aspx, &aspy);
+               ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
                v[0]= vec[0]/aspx;
                v[1]= vec[1]/aspy;
                
-               // TRANSFORM_FIX_ME
-               //uvco_to_areaco_noclip(v, adr);
+               UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1);
        }
        else if(t->spacetype==SPACE_IPO) {
-               short out[2] = {0.0f, 0.0f};
+               int out[2] = {0, 0};
                
-               // TRANSFORM_FIX_ME
-               //ipoco_to_areaco(G.v2d, vec, out);
+               UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1); 
+               adr[0]= out[0];
+               adr[1]= out[1];
+       }
+       else if(t->spacetype==SPACE_SEQ) { /* XXX not tested yet, but should work */
+               int out[2] = {0, 0};
+               
+               UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1);
                adr[0]= out[0];
                adr[1]= out[1];
        }
@@ -390,7 +231,8 @@ void projectIntView(TransInfo *t, float *vec, int *adr)
 void projectFloatView(TransInfo *t, float *vec, float *adr)
 {
        if (t->spacetype==SPACE_VIEW3D) {
-               project_float_noclip(t->ar, t->view, vec, adr);
+               if(t->ar->regiontype == RGN_TYPE_WINDOW)
+                       project_float_noclip(t->ar, vec, adr);
        }
        else if(t->spacetype==SPACE_IMAGE) {
                int a[2];
@@ -408,65 +250,54 @@ void projectFloatView(TransInfo *t, float *vec, float *adr)
        }
 }
 
-void convertVecToDisplayNum(float *vec, float *num)
+void applyAspectRatio(TransInfo *t, float *vec)
 {
-       // TRANSFORM_FIX_ME
-       TransInfo *t = NULL; //BIF_GetTransInfo();
-
-       VECCOPY(num, vec);
+       SpaceImage *sima= t->sa->spacedata.first;
 
-#if 0 // TRANSFORM_FIX_ME
        if ((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) {
                float aspx, aspy;
 
-               if((G.sima->flag & SI_COORDFLOATS)==0) {
+               if((sima->flag & SI_COORDFLOATS)==0) {
                        int width, height;
-                       transform_width_height_tface_uv(&width, &height);
+                       ED_space_image_size(sima, &width, &height);
 
-                       num[0] *= width;
-                       num[1] *= height;
+                       vec[0] *= width;
+                       vec[1] *= height;
                }
 
-               transform_aspect_ratio_tface_uv(&aspx, &aspy);
-               num[0] /= aspx;
-               num[1] /= aspy;
+               ED_space_image_uv_aspect(sima, &aspx, &aspy);
+               vec[0] /= aspx;
+               vec[1] /= aspy;
        }
-#endif
 }
 
-void convertDisplayNumToVec(float *num, float *vec)
+void removeAspectRatio(TransInfo *t, float *vec)
 {
-       // TRANSFORM_FIX_ME
-       TransInfo *t = NULL; //BIF_GetTransInfo();
+       SpaceImage *sima= t->sa->spacedata.first;
 
-       VECCOPY(vec, num);
-
-#if 0 // TRANSFORM_FIX_ME
        if ((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) {
                float aspx, aspy;
 
-               if((G.sima->flag & SI_COORDFLOATS)==0) {
+               if((sima->flag & SI_COORDFLOATS)==0) {
                        int width, height;
-                       transform_width_height_tface_uv(&width, &height);
+                       ED_space_image_size(sima, &width, &height);
 
                        vec[0] /= width;
                        vec[1] /= height;
                }
 
-               transform_aspect_ratio_tface_uv(&aspx, &aspy);
+               ED_space_image_uv_aspect(sima, &aspx, &aspy);
                vec[0] *= aspx;
                vec[1] *= aspy;
        }
-#endif
 }
 
-static void viewRedrawForce(TransInfo *t)
+static void viewRedrawForce(bContext *C, TransInfo *t)
 {
        if (t->spacetype == SPACE_VIEW3D)
        {
-               // TRANSFORM_FIX_ME
-               // need to redraw ALL 3d view
-               ED_area_tag_redraw(t->sa);
+               /* Do we need more refined tags? */             
+               WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
        }
        else if (t->spacetype == SPACE_ACTION) {
                SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
@@ -478,58 +309,38 @@ static void viewRedrawForce(TransInfo *t)
                else 
                        ED_area_tag_redraw(t->sa);
        }
-#if 0 // TRANSFORM_FIX_ME
-       else if (t->spacetype==SPACE_IMAGE) {
-               if (G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
-               else force_draw(0);
-       }
-       else if (t->spacetype == SPACE_ACTION) {
-               if (G.saction->lock) {
-                       short context;
-                       
-                       /* we ignore the pointer this function returns (not needed) */
-                       get_action_context(&context);
-                       
-                       if (context == ACTCONT_ACTION)
-                               force_draw_plus(SPACE_VIEW3D, 0);
-                       else if (context == ACTCONT_SHAPEKEY) 
-                               force_draw_all(0);
-                       else
-                               force_draw(0);
-               }
-               else {
-                       force_draw(0);
+       else if (t->spacetype == SPACE_IPO) {
+               SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+               
+               // TRANSFORM_FIX_ME
+               if (sipo->lock) {
+                       // whole window...
                }
+               else 
+                       ED_area_tag_redraw(t->sa);
        }
        else if (t->spacetype == SPACE_NLA) {
-               if (G.snla->lock)
-                       force_draw_all(0);
-               else
-                       force_draw(0);
+               ED_area_tag_redraw(t->sa); // XXX this should use a notifier instead!
        }
-       else if (t->spacetype == SPACE_IPO) {
-               /* update realtime */
-               if (G.sipo->lock) {
-                       if (G.sipo->blocktype==ID_MA || G.sipo->blocktype==ID_TE)
-                               force_draw_plus(SPACE_BUTS, 0);
-                       else if (G.sipo->blocktype==ID_CA)
-                               force_draw_plus(SPACE_VIEW3D, 0);
-                       else if (G.sipo->blocktype==ID_KE)
-                               force_draw_plus(SPACE_VIEW3D, 0);
-                       else if (G.sipo->blocktype==ID_PO)
-                               force_draw_plus(SPACE_VIEW3D, 0);
-                       else if (G.sipo->blocktype==ID_OB) 
-                               force_draw_plus(SPACE_VIEW3D, 0);
-                       else if (G.sipo->blocktype==ID_SEQ) 
-                               force_draw_plus(SPACE_SEQ, 0);
-                       else 
-                               force_draw(0);
-               }
-               else {
-                       force_draw(0);
-               }
+       else if(t->spacetype == SPACE_NODE)
+       {
+               //ED_area_tag_redraw(t->sa);
+               WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
+       }
+       else if(t->spacetype == SPACE_SEQ)
+       {
+               WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, NULL);
+       }
+       else if (t->spacetype==SPACE_IMAGE) {
+               // XXX how to deal with lock?
+#if 0
+               SpaceImage *sima= (SpaceImage*)t->sa->spacedata.first;
+               if(sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
+               else force_draw(0);
+#endif
+
+               WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, t->obedit);
        }
-#endif 
 }
 
 static void viewRedrawPost(TransInfo *t)
@@ -700,30 +511,33 @@ void transformEvent(TransInfo *t, wmEvent *event)
        float mati[3][3] = {{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}};
        char cmode = constraintModeToChar(t);
        
-       t->event = event;
-       
+       t->redraw |= handleMouseInput(t, &t->mouse, event);
+
        if (event->type == MOUSEMOVE)
        {
                t->mval[0] = event->x - t->ar->winrct.xmin;
                t->mval[1] = event->y - t->ar->winrct.ymin;
+               
+               t->redraw = 1;
+               
+               applyMouseInput(t, &t->mouse, t->mval, t->values);
        }
-
+       
        if (event->val) {
                switch (event->type){
                /* enforce redraw of transform when modifiers are used */
                case LEFTCTRLKEY:
                case RIGHTCTRLKEY:
+                       t->modifiers |= MOD_SNAP_GEARS;
                        t->redraw = 1;
                        break;
+                       
                case LEFTSHIFTKEY:
                case RIGHTSHIFTKEY:
-                       /* shift is modifier for higher resolution transform, works nice to store this mouse position */
-                       t->shiftmval[0] = event->x - t->ar->winrct.xmin;
-                       t->shiftmval[1] = event->y - t->ar->winrct.ymin;
-                       t->flag |= T_SHIFT_MOD;
+                       t->modifiers |= MOD_CONSTRAINT_PLANE;
                        t->redraw = 1;
                        break;
-                       
+
                case SPACEKEY:
                        if ((t->spacetype==SPACE_VIEW3D) && event->alt) {
 #if 0 // TRANSFORM_FIX_ME
@@ -741,7 +555,6 @@ void transformEvent(TransInfo *t, wmEvent *event)
                        }
                        break;
                        
-                       
                case MIDDLEMOUSE:
                        if ((t->flag & T_NO_CONSTRAINT)==0) {
                                /* exception for switching to dolly, or trackball, in camera view */
@@ -754,7 +567,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                        }
                                }
                                else {
-                                       t->flag |= T_MMB_PRESSED;
+                                       t->modifiers |= MOD_CONSTRAINT_SELECT;
                                        if (t->con.mode & CON_APPLY) {
                                                stopConstraint(t);
                                        }
@@ -775,6 +588,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                        break;
                case ESCKEY:
                case RIGHTMOUSE:
+                       printf("cancelled\n");
                        t->state = TRANS_CANCEL;
                        break;
                case LEFTMOUSE:
@@ -788,6 +602,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                resetTransRestrictions(t); 
                                restoreTransObjects(t);
                                initTranslation(t);
+                               initSnapping(t, NULL); // need to reinit after mode change
                                t->redraw = 1;
                        }
                        break;
@@ -797,6 +612,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                resetTransRestrictions(t); 
                                restoreTransObjects(t);
                                initResize(t);
+                               initSnapping(t, NULL); // need to reinit after mode change
                                t->redraw = 1;
                        }
                        break;
@@ -814,6 +630,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                        restoreTransObjects(t);
                                        initRotation(t);
                                }
+                               initSnapping(t, NULL); // need to reinit after mode change
                                t->redraw = 1;
                        }
                        break;
@@ -840,9 +657,9 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                                        stopConstraint(t);
                                                }
                                                else {
-                                                       if (event->keymodifier == 0)
+                                                       if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                                setUserConstraint(t, (CON_AXIS0), "along %s X");
-                                                       else if (event->keymodifier == KM_SHIFT)
+                                                       else if (t->modifiers & MOD_CONSTRAINT_PLANE)
                                                                setUserConstraint(t, (CON_AXIS1|CON_AXIS2), "locking %s X");
                                                }
                                        }
@@ -852,9 +669,9 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                                setConstraint(t, mati, (CON_AXIS0), "along X axis");
                                        }
                                        else {
-                                               if (event->keymodifier == 0)
+                                               if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                        setConstraint(t, mati, (CON_AXIS0), "along global X");
-                                               else if (event->keymodifier == KM_SHIFT)
+                                               else if (t->modifiers & MOD_CONSTRAINT_PLANE)
                                                        setConstraint(t, mati, (CON_AXIS1|CON_AXIS2), "locking global X");
                                        }
                                }
@@ -872,9 +689,9 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                                        stopConstraint(t);
                                                }
                                                else {
-                                                       if (event->keymodifier == 0)
+                                                       if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                                setUserConstraint(t, (CON_AXIS1), "along %s Y");
-                                                       else if (event->keymodifier == KM_SHIFT)
+                                                       else if (t->modifiers & MOD_CONSTRAINT_PLANE)
                                                                setUserConstraint(t, (CON_AXIS0|CON_AXIS2), "locking %s Y");
                                                }
                                        }
@@ -884,9 +701,9 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                                setConstraint(t, mati, (CON_AXIS1), "along Y axis");
                                        }
                                        else {
-                                               if (event->keymodifier == 0)
+                                               if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                        setConstraint(t, mati, (CON_AXIS1), "along global Y");
-                                               else if (event->keymodifier == KM_SHIFT)
+                                               else if (t->modifiers & MOD_CONSTRAINT_PLANE)
                                                        setConstraint(t, mati, (CON_AXIS0|CON_AXIS2), "locking global Y");
                                        }
                                }
@@ -900,31 +717,31 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                                stopConstraint(t);
                                        }
                                        else {
-                                               if (event->keymodifier == 0)
+                                               if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                        setUserConstraint(t, (CON_AXIS2), "along %s Z");
-                                               else if ((event->keymodifier == KM_SHIFT) && ((t->flag & T_2D_EDIT)==0))
+                                               else if ((t->modifiers & MOD_CONSTRAINT_PLANE) && ((t->flag & T_2D_EDIT)==0))
                                                        setUserConstraint(t, (CON_AXIS0|CON_AXIS1), "locking %s Z");
                                        }
                                }
                                else if ((t->flag & T_2D_EDIT)==0) {
-                                       if (event->keymodifier == 0)
+                                       if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                setConstraint(t, mati, (CON_AXIS2), "along global Z");
-                                       else if (event->keymodifier == KM_SHIFT)
+                                       else if (t->modifiers & MOD_CONSTRAINT_PLANE)
                                                setConstraint(t, mati, (CON_AXIS0|CON_AXIS1), "locking global Z");
                                }
                                t->redraw = 1;
                        }
                        break;
                case OKEY:
-                       if (t->flag & T_PROP_EDIT && event->keymodifier == KM_SHIFT) {
-                               G.scene->prop_mode = (G.scene->prop_mode+1)%6;
+                       if (t->flag & T_PROP_EDIT && event->shift) {
+                               t->prop_mode = (t->prop_mode + 1) % 6;
                                calculatePropRatio(t);
-                               t->redraw= 1;
+                               t->redraw = 1;
                        }
                        break;
                case PADPLUSKEY:
-                       if(event->keymodifier & KM_ALT && t->flag & T_PROP_EDIT) {
-                               t->propsize*= 1.1f;
+                       if(event->alt && t->flag & T_PROP_EDIT) {
+                               t->prop_size *= 1.1f;
                                calculatePropRatio(t);
                        }
                        t->redraw= 1;
@@ -935,15 +752,15 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                transform_autoik_update(t, 1);
                        }
                        else if(t->flag & T_PROP_EDIT) {
-                               t->propsize*= 1.1f;
+                               t->prop_size*= 1.1f;
                                calculatePropRatio(t);
                        }
                        else view_editmove(event->type);
                        t->redraw= 1;
                        break;
                case PADMINUS:
-                       if(event->keymodifier & KM_ALT && t->flag & T_PROP_EDIT) {
-                               t->propsize*= 0.90909090f;
+                       if(event->alt && t->flag & T_PROP_EDIT) {
+                               t->prop_size*= 0.90909090f;
                                calculatePropRatio(t);
                        }
                        t->redraw= 1;
@@ -954,7 +771,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                transform_autoik_update(t, -1);
                        }
                        else if (t->flag & T_PROP_EDIT) {
-                               t->propsize*= 0.90909090f;
+                               t->prop_size*= 0.90909090f;
                                calculatePropRatio(t);
                        }
                        else view_editmove(event->type);
@@ -1010,25 +827,32 @@ void transformEvent(TransInfo *t, wmEvent *event)
        }
        else {
                switch (event->type){
-               /* no redraw on release modifier keys! this makes sure you can assign the 'grid' still 
-                  after releasing modifer key */
+               case LEFTSHIFTKEY:
+               case RIGHTSHIFTKEY:
+                       t->modifiers &= ~MOD_CONSTRAINT_PLANE;
+                       t->redraw = 1;
+                       break;
+
+               case LEFTCTRLKEY:
+               case RIGHTCTRLKEY:
+                       t->modifiers &= ~MOD_SNAP_GEARS;
+                       /* no redraw on release modifier keys! this makes sure you can assign the 'grid' still 
+                          after releasing modifer key */
+                       //t->redraw = 1;
+                       break;
                case MIDDLEMOUSE:
                        if ((t->flag & T_NO_CONSTRAINT)==0) {
-                               t->flag &= ~T_MMB_PRESSED;
+                               t->modifiers &= ~MOD_CONSTRAINT_SELECT;
                                postSelectConstraint(t);
                                t->redraw = 1;
                        }
                        break;
                case LEFTMOUSE:
                case RIGHTMOUSE:
-                       if (t->options & CTX_TWEAK)
+                       if(WM_modal_tweak_exit(event, t->event_type))
+//                     if (t->options & CTX_TWEAK)
                                t->state = TRANS_CONFIRM;
                        break;
-               case LEFTSHIFTKEY:
-               case RIGHTSHIFTKEY:
-                       /* shift is modifier for higher resolution transform */
-                       t->flag &= ~T_SHIFT_MOD;
-                       break;
                }
        }
        
@@ -1048,7 +872,7 @@ int calculateTransformCenter(bContext *C, wmEvent *event, int centerMode, float
        
        t->mode = TFM_DUMMY;
 
-       initTransInfo(C, t, event);                                     // internal data, mouse, vectors
+       initTransInfo(C, t, NULL, event);                                       // internal data, mouse, vectors
 
        createTransData(C, t);                  // make TransData structs from selection
 
@@ -1076,8 +900,320 @@ int calculateTransformCenter(bContext *C, wmEvent *event, int centerMode, float
        return success;
 }
 
-void initTransform(bContext *C, TransInfo *t, int mode, int options, wmEvent *event)
+typedef enum {
+       UP,
+       DOWN,
+       LEFT,
+       RIGHT
+} ArrowDirection;
+static void drawArrow(ArrowDirection d, short offset, short length, short size)
+{
+       switch(d)
+       {
+               case LEFT:
+                       offset = -offset;
+                       length = -length;
+                       size = -size;
+               case RIGHT:
+                       glBegin(GL_LINES); 
+                       glVertex2s( offset, 0); 
+                       glVertex2s( offset + length, 0); 
+                       glVertex2s( offset + length, 0); 
+                       glVertex2s( offset + length - size, -size); 
+                       glVertex2s( offset + length, 0); 
+                       glVertex2s( offset + length - size,  size);
+                       glEnd(); 
+                       break;
+               case DOWN:
+                       offset = -offset;
+                       length = -length;
+                       size = -size;
+               case UP:
+                       glBegin(GL_LINES); 
+                       glVertex2s( 0, offset); 
+                       glVertex2s( 0, offset + length); 
+                       glVertex2s( 0, offset + length); 
+                       glVertex2s(-size, offset + length - size); 
+                       glVertex2s( 0, offset + length); 
+                       glVertex2s( size, offset + length - size);
+                       glEnd(); 
+                       break;
+       }
+}
+
+static void drawArrowHead(ArrowDirection d, short size)
 {
+       switch(d)
+       {
+               case LEFT:
+                       size = -size;
+               case RIGHT:
+                       glBegin(GL_LINES); 
+                       glVertex2s( 0, 0); 
+                       glVertex2s( -size, -size); 
+                       glVertex2s( 0, 0); 
+                       glVertex2s( -size,  size);
+                       glEnd(); 
+                       break;
+               case DOWN:
+                       size = -size;
+               case UP:
+                       glBegin(GL_LINES); 
+                       glVertex2s( 0, 0); 
+                       glVertex2s(-size, -size); 
+                       glVertex2s( 0, 0); 
+                       glVertex2s( size, -size);
+                       glEnd(); 
+                       break;
+       }
+}
+
+static void drawArc(float size, float angle_start, float angle_end, int segments)
+{
+       float delta = (angle_end - angle_start) / segments;
+       float angle;
+       
+       glBegin(GL_LINE_STRIP);
+       
+       for( angle = angle_start; angle < angle_end; angle += delta)
+       {
+               glVertex2f( cosf(angle) * size, sinf(angle) * size);
+       }
+       glVertex2f( cosf(angle_end) * size, sinf(angle_end) * size);
+       
+       glEnd();
+}
+
+void drawHelpline(const struct bContext *C, TransInfo *t)
+{
+       if (t->helpline != HLP_NONE && !(t->flag & T_USES_MANIPULATOR))
+       {
+               float vecrot[3], cent[2];
+               
+               VECCOPY(vecrot, t->center);
+               if(t->flag & T_EDIT) {
+                       Object *ob= t->obedit;
+                       if(ob) Mat4MulVecfl(ob->obmat, vecrot);
+               }
+               else if(t->flag & T_POSE) {
+                       Object *ob=t->poseobj;
+                       if(ob) Mat4MulVecfl(ob->obmat, vecrot);
+               }
+               
+               projectFloatView(t, vecrot, cent);      // no overflow in extreme cases
+       
+               glDisable(GL_DEPTH_TEST);
+
+               glMatrixMode(GL_PROJECTION);
+               glPushMatrix();
+               glMatrixMode(GL_MODELVIEW);
+               glPushMatrix();
+
+               ED_region_pixelspace(t->ar);
+               
+               switch(t->helpline)
+               {
+                       case HLP_SPRING:
+                               UI_ThemeColor(TH_WIRE);
+                               
+                               setlinestyle(3);
+                               glBegin(GL_LINE_STRIP); 
+                               glVertex2sv(t->mval); 
+                               glVertex2fv(cent); 
+                               glEnd();
+
+                               glTranslatef(t->mval[0], t->mval[1], 0);
+                               glRotatef(-180 / M_PI * atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1]), 0, 0, 1);
+
+                               setlinestyle(0);
+                               glLineWidth(3.0);
+                               drawArrow(UP, 5, 10, 5);
+                               drawArrow(DOWN, 5, 10, 5);
+                               glLineWidth(1.0);
+                               break;
+                       case HLP_HARROW:
+                               UI_ThemeColor(TH_WIRE);
+
+                               glTranslatef(t->mval[0], t->mval[1], 0);
+
+                               glLineWidth(3.0);
+                               drawArrow(RIGHT, 5, 10, 5);
+                               drawArrow(LEFT, 5, 10, 5);
+                               glLineWidth(1.0);
+                               break;
+                       case HLP_VARROW:
+                               UI_ThemeColor(TH_WIRE);
+
+                               glTranslatef(t->mval[0], t->mval[1], 0);
+
+                               glLineWidth(3.0);
+                               glBegin(GL_LINES); 
+                               drawArrow(UP, 5, 10, 5);
+                               drawArrow(DOWN, 5, 10, 5);
+                               glLineWidth(1.0);
+                               break;
+                       case HLP_ANGLE:
+                               {
+                                       float dx = t->mval[0] - cent[0], dy = t->mval[1] - cent[1];
+                                       float angle = atan2f(dy, dx);
+                                       float dist = sqrtf(dx*dx + dy*dy);
+                                       float delta_angle = MIN2(15 / dist, M_PI/4);
+                                       float spacing_angle = MIN2(5 / dist, M_PI/12);
+                                       UI_ThemeColor(TH_WIRE);
+       
+                                       setlinestyle(3);
+                                       glBegin(GL_LINE_STRIP); 
+                                       glVertex2sv(t->mval); 
+                                       glVertex2fv(cent); 
+                                       glEnd();
+                                       
+                                       glTranslatef(cent[0], cent[1], 0);
+       
+                                       setlinestyle(0);
+                                       glLineWidth(3.0);
+                                       drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
+                                       drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
+                                       
+                                       glPushMatrix();
+
+                                       glTranslatef(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
+                                       glRotatef(180 / M_PI * (angle - delta_angle), 0, 0, 1);
+                                       
+                                       drawArrowHead(DOWN, 5);
+                                       
+                                       glPopMatrix();
+
+                                       glTranslatef(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
+                                       glRotatef(180 / M_PI * (angle + delta_angle), 0, 0, 1);
+
+                                       drawArrowHead(UP, 5);
+
+                                       glLineWidth(1.0);
+                                       break;
+                               }
+                               case HLP_TRACKBALL:
+                               {
+                                       char col[3], col2[3];
+                                       UI_GetThemeColor3ubv(TH_GRID, col);
+       
+                                       glTranslatef(t->mval[0], t->mval[1], 0);
+       
+                                       glLineWidth(3.0);
+       
+                                       UI_make_axis_color(col, col2, 'x');
+                                       glColor3ubv((GLubyte *)col2);
+       
+                                       drawArrow(RIGHT, 5, 10, 5);
+                                       drawArrow(LEFT, 5, 10, 5);
+       
+                                       UI_make_axis_color(col, col2, 'y');
+                                       glColor3ubv((GLubyte *)col2);
+       
+                                       drawArrow(UP, 5, 10, 5);
+                                       drawArrow(DOWN, 5, 10, 5);
+                                       glLineWidth(1.0);
+                                       break;
+                               }
+               }
+               
+               glMatrixMode(GL_PROJECTION);
+               glPopMatrix();
+               glMatrixMode(GL_MODELVIEW);
+               glPopMatrix();
+               
+               glEnable(GL_DEPTH_TEST);
+       }
+}
+
+void drawTransform(const struct bContext *C, struct ARegion *ar, void *arg)
+{
+       TransInfo *t = arg;
+       
+       drawConstraint(C, t);
+       drawPropCircle(C, t);
+       drawSnapping(C, t);
+       drawHelpline(C, t);
+}
+
+void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
+{
+       ToolSettings *ts = CTX_data_tool_settings(C);
+       int constraint_axis[3] = {0, 0, 0};
+       int proportional = 0;
+
+       if (t->flag & T_AUTOVALUES)
+       {
+               RNA_float_set_array(op->ptr, "value", t->auto_values);
+       }
+       else
+       {
+               RNA_float_set_array(op->ptr, "value", t->values);
+       }
+
+       /* XXX convert stupid flag to enum */
+       switch(t->flag & (T_PROP_EDIT|T_PROP_CONNECTED))
+       {
+       case (T_PROP_EDIT|T_PROP_CONNECTED):
+               proportional = 2;
+               break;
+       case T_PROP_EDIT:
+               proportional = 1;
+               break;
+       default:
+               proportional = 0;
+       }
+
+       if (RNA_struct_find_property(op->ptr, "proportional"))
+       {
+               RNA_enum_set(op->ptr, "proportional", proportional);
+               RNA_enum_set(op->ptr, "proportional_editing_falloff", t->prop_mode);
+               RNA_float_set(op->ptr, "proportional_size", t->prop_size);
+       }
+
+       if (RNA_struct_find_property(op->ptr, "mirror"))
+       {
+               RNA_boolean_set(op->ptr, "mirror", t->flag & T_MIRROR);
+       }
+       
+       if (RNA_struct_find_property(op->ptr, "constraint_axis"))
+       {
+               RNA_int_set(op->ptr, "constraint_orientation", t->current_orientation);
+
+               if (t->con.mode & CON_APPLY)
+               {
+                       if (t->con.mode & CON_AXIS0) {
+                               constraint_axis[0] = 1;
+                       }
+                       if (t->con.mode & CON_AXIS1) {
+                               constraint_axis[1] = 1;
+                       }
+                       if (t->con.mode & CON_AXIS2) {
+                               constraint_axis[2] = 1;
+                       }
+               }
+
+               RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
+       }
+
+       // XXX If modal, save settings back in scene
+       if (t->flag & T_MODAL)
+       {
+               ts->prop_mode = t->prop_mode;
+               ts->proportional = proportional;
+
+               if(t->spacetype == SPACE_VIEW3D)
+               {
+                       View3D *v3d = t->view;
+                       
+                       v3d->twmode = t->current_orientation;
+               }
+       }
+}
+
+int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int mode)
+{
+       int options = 0;
+
        /* added initialize, for external calls to set stuff in TransInfo, like undo string */
 
        t->state = TRANS_RUNNING;
@@ -1086,27 +1222,34 @@ void initTransform(bContext *C, TransInfo *t, int mode, int options, wmEvent *ev
        
        t->mode = mode;
 
-       initTransInfo(C, t, event);                                     // internal data, mouse, vectors
+       if (!initTransInfo(C, t, op, event))                                    // internal data, mouse, vectors
+       {
+               return 0;
+       }
 
        if(t->spacetype == SPACE_VIEW3D)
        {
-               View3D *v3d = t->view;
                //calc_manipulator_stats(curarea);
-               Mat3CpyMat4(t->spacemtx, v3d->twmat);
-               Mat3Ortho(t->spacemtx);
+               initTransformOrientation(C, t);
+       
+               t->draw_handle = ED_region_draw_cb_activate(t->ar->type, drawTransform, t, REGION_DRAW_POST);
+       }
+       else if(t->spacetype == SPACE_IMAGE) {
+               Mat3One(t->spacemtx);
+               t->draw_handle = ED_region_draw_cb_activate(t->ar->type, drawTransform, t, REGION_DRAW_POST);
        }
        else
                Mat3One(t->spacemtx);
 
        createTransData(C, t);                  // make TransData structs from selection
 
-       initSnapping(t); // Initialize snapping data AFTER mode flags
-
        if (t->total == 0) {
                postTrans(t);
-               return;
+               return 0;
        }
 
+       initSnapping(t, op); // Initialize snapping data AFTER mode flags
+
        /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
        /* EVIL2: we gave as argument also texture space context bit... was cleared */
        /* EVIL3: extend mode for animation editors also switches modes... but is best way to avoid duplicate code */
@@ -1114,6 +1257,8 @@ void initTransform(bContext *C, TransInfo *t, int mode, int options, wmEvent *ev
        
        calculatePropRatio(t);
        calculateCenter(t);
+       
+       initMouseInput(t, &t->mouse, t->center2d, t->imval);
 
        switch (mode) {
        case TFM_TRANSLATION:
@@ -1177,8 +1322,15 @@ void initTransform(bContext *C, TransInfo *t, int mode, int options, wmEvent *ev
                initTimeScale(t);
                break;
        case TFM_TIME_EXTEND: 
-               /* now that transdata has been made, do like for TFM_TIME_TRANSLATE */
-               initTimeTranslate(t);
+               /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation
+                * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION
+                * (for Graph Editor only since it uses 'standard' transforms to get 2D movement)
+                * depending on which editor this was called from 
+                */
+               if (t->spacetype == SPACE_IPO)
+                       initTranslation(t);
+               else
+                       initTimeTranslate(t);
                break;
        case TFM_BAKE_TIME:
                initBakeTime(t);
@@ -1196,23 +1348,56 @@ void initTransform(bContext *C, TransInfo *t, int mode, int options, wmEvent *ev
                initAlign(t);
                break;
        }
-}
 
-void transformApply(TransInfo *t)
-{
-       if (1) // MOUSE MOVE
+       /* overwrite initial values if operator supplied a non-null vector */
+       if (RNA_property_is_set(op->ptr, "value"))
        {
-               if (t->flag & T_MMB_PRESSED)
-                       t->con.mode |= CON_SELECT;
-               t->redraw = 1;
+               float values[4];
+               RNA_float_get_array(op->ptr, "value", values);
+               QUATCOPY(t->values, values);
+               QUATCOPY(t->auto_values, values);
+               t->flag |= T_AUTOVALUES;
        }
+
+       /* Constraint init from operator */
+       if (RNA_struct_find_property(op->ptr, "constraint_axis") && RNA_property_is_set(op->ptr, "constraint_axis"))
+       {
+               int constraint_axis[3];
+
+               RNA_boolean_get_array(op->ptr, "constraint_axis", constraint_axis);
+
+               if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2])
+               {
+                       t->con.mode |= CON_APPLY;
+
+                       if (constraint_axis[0]) {
+                               t->con.mode |= CON_AXIS0;
+                       }
+                       if (constraint_axis[1]) {
+                               t->con.mode |= CON_AXIS1;
+                       }
+                       if (constraint_axis[2]) {
+                               t->con.mode |= CON_AXIS2;
+                       }
+                               
+                       setUserConstraint(t, t->con.mode, "%s");                
+               }
+       }
+       
+       return 1;
+}
+
+void transformApply(bContext *C, TransInfo *t)
+{
        if (t->redraw)
        {
-               // RESET MOUSE MOVE
+               if (t->modifiers & MOD_CONSTRAINT_SELECT)
+                       t->con.mode |= CON_SELECT;
 
                selectConstraint(t);
                if (t->transform) {
                        t->transform(t, t->mval);  // calls recalcData()
+                       viewRedrawForce(C, t);
                }
                t->redraw = 0;
        }
@@ -1231,41 +1416,47 @@ void transformApply(TransInfo *t)
        }
 }
 
-int transformEnd(TransInfo *t)
+int transformEnd(bContext *C, TransInfo *t)
 {
+       int exit_code = OPERATOR_RUNNING_MODAL;
+       
        if (t->state != TRANS_RUNNING)
        {
                /* handle restoring objects */
                if(t->state == TRANS_CANCEL)
+               {
+                       exit_code = OPERATOR_CANCELLED;
                        restoreTransObjects(t); // calls recalcData()
+               }
+               else
+               {
+                       exit_code = OPERATOR_FINISHED;
+               }
                
                /* free data */
                postTrans(t);
        
-               /* aftertrans does insert ipos and action channels, and clears base flags, doesnt read transdata */
+               /* aftertrans does insert keyframes, and clears base flags, doesnt read transdata */
                special_aftertrans_update(t);
        
                /* send events out for redraws */
                viewRedrawPost(t);
        
                /*  Undo as last, certainly after special_trans_update! */
-#if 0 // TRANSFORM_FIX_ME              
+
                if(t->state == TRANS_CANCEL) {
-                       if(t->undostr) BIF_undo_push(t->undostr);
+//                     if(t->undostr) ED_undo_push(C, t->undostr);
                }
                else {
-                       if(t->undostr) BIF_undo_push(t->undostr);
-                       else BIF_undo_push(transform_to_undostr(t));
+//                     if(t->undostr) ED_undo_push(C, t->undostr);
+//                     else ED_undo_push(C, transform_to_undostr(t));
                }
                t->undostr= NULL;
-#endif
-               return 1;
+
+               viewRedrawForce(C, t);
        }
        
-       t->context= NULL;
-       t->event = NULL;
-       
-       return 0;
+       return exit_code;
 }
 
 /* ************************** Manipulator init and main **************************** */
@@ -1280,8 +1471,8 @@ void initManipulator(int mode)
        Trans.mode = mode;
        
        /* automatic switch to scaling bone envelopes */
-       if(mode==TFM_RESIZE && G.obedit && G.obedit->type==OB_ARMATURE) {
-               bArmature *arm= G.obedit->data;
+       if(mode==TFM_RESIZE && t->obedit && t->obedit->type==OB_ARMATURE) {
+               bArmature *arm= t->obedit->data;
                if(arm->drawtype==ARM_ENVELOPE)
                        mode= TFM_BONE_ENVELOPE;
        }
@@ -1803,6 +1994,8 @@ void initWarp(TransInfo *t)
        t->transform = Warp;
        t->handleEvent = handleEventWarp;
        
+       initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
+
        t->idx_max = 0;
        t->num.idx_max = 0;
        t->snap[0] = 0.0f;
@@ -1810,10 +2003,6 @@ void initWarp(TransInfo *t)
        t->snap[2] = 1.0f;
        
        t->flag |= T_NO_CONSTRAINT;
-
-/* warp is done fully in view space */
-       calculateCenterCursor(t);
-       t->fac = (float)(t->center2d[0] - t->imval[0]);
        
        /* we need min/max in view space */
        for(i = 0; i < t->total; i++) {
@@ -1877,15 +2066,15 @@ int Warp(TransInfo *t, short mval[2])
        VECCOPY(cursor, curs);
        VECCOPY(gcursor, cursor);       
        if (t->flag & T_EDIT) {
-               VecSubf(cursor, cursor, G.obedit->obmat[3]);
-               VecSubf(gcursor, gcursor, G.obedit->obmat[3]);
+               VecSubf(cursor, cursor, t->obedit->obmat[3]);
+               VecSubf(gcursor, gcursor, t->obedit->obmat[3]);
                Mat3MulVecfl(t->data->smtx, gcursor);
        }
        Mat4MulVecfl(t->viewmat, cursor);
        VecSubf(cursor, cursor, t->viewmat[3]);
 
        /* amount of degrees for warp */
-       circumfac= 360.0f * InputHorizontalRatio(t, mval);
+       circumfac = 360.0f * t->values[0];
        
        if (t->customData) /* non-null value indicates reversed input */
        {
@@ -1950,10 +2139,6 @@ int Warp(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       viewRedrawForce(t);
-       
-       helpline(t, gcursor);
-       
        return 1;
 }
 
@@ -1965,6 +2150,8 @@ void initShear(TransInfo *t)
        t->transform = Shear;
        t->handleEvent = handleEventShear;
        
+       initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+       
        t->idx_max = 0;
        t->num.idx_max = 0;
        t->snap[0] = 0.0f;
@@ -1982,9 +2169,15 @@ int handleEventShear(TransInfo *t, wmEvent *event)
        {
                // Use customData pointer to signal Shear direction
                if      (t->customData == 0)
+               {
+                       initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
                        t->customData = (void*)1;
+               }
                else
+               {
+                       initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
                        t->customData = 0;
+               }
                        
                status = 1;
        }
@@ -2005,11 +2198,7 @@ int Shear(TransInfo *t, short mval[2])
        Mat3CpyMat4(persmat, t->viewmat);
        Mat3Inv(persinv, persmat);
 
-       // Custom data signals shear direction
-       if (t->customData == 0)
-               value = 0.05f * InputHorizontalAbsolute(t, mval);
-       else
-               value = 0.05f * InputVerticalAbsolute(t, mval);
+       value = 0.05f * t->values[0];
 
        snapGrid(t, &value);
 
@@ -2046,7 +2235,7 @@ int Shear(TransInfo *t, short mval[2])
                if (td->flag & TD_SKIP)
                        continue;
 
-               if (G.obedit) {
+               if (t->obedit) {
                        float mat3[3][3];
                        Mat3MulMat3(mat3, totmat, td->mtx);
                        Mat3MulMat3(tmat, td->smtx, mat3);
@@ -2070,10 +2259,6 @@ int Shear(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -2084,10 +2269,12 @@ void initResize(TransInfo *t)
        t->mode = TFM_RESIZE;
        t->transform = Resize;
        
+       initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+       
        t->flag |= T_NULL_ONE;
        t->num.flag |= NUM_NULL_ONE;
        t->num.flag |= NUM_AFFECT_ALL;
-       if (!G.obedit) {
+       if (!t->obedit) {
                t->flag |= T_NO_ZERO;
                t->num.flag |= NUM_NO_ZERO;
        }
@@ -2097,15 +2284,6 @@ void initResize(TransInfo *t)
        t->snap[0] = 0.0f;
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
-
-       t->fac = (float)sqrt(
-               (
-                       ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
-               +
-                       ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
-               ) );
-
-       if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
 }
 
 static void headerResize(TransInfo *t, float vec[3], char *str) {
@@ -2184,7 +2362,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) {
                }
                else if (t->flag & T_EDIT) {
                        
-                       if(t->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE)) {
+                       if(t->around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
                                VECCOPY(center, td->center);
                        }
                        else {
@@ -2295,16 +2473,13 @@ int Resize(TransInfo *t, short mval[2])
        char str[200];
 
        /* for manipulator, center handle, the scaling can't be done relative to center */
-       if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) {
+       if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0)
+       {
                ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]))/100.0f;
        }
-       else {
-               ratio = InputScaleRatio(t, mval);
-               
-               /* flip scale, but not for manipulator center handle */
-               if      ((t->center2d[0] - mval[0]) * (t->center2d[0] - t->imval[0]) + 
-                        (t->center2d[1] - mval[1]) * (t->center2d[1] - t->imval[1]) < 0)
-                               ratio *= -1.0f;
+       else
+       {
+               ratio = t->values[0];
        }
        
        size[0] = size[1] = size[2] = ratio;
@@ -2318,6 +2493,13 @@ int Resize(TransInfo *t, short mval[2])
 
        applySnapping(t, size);
 
+       if (t->flag & T_AUTOVALUES)
+       {
+               VECCOPY(size, t->auto_values);
+       }
+
+       VECCOPY(t->values, size);
+
        SizeToMat3(size, mat);
 
        if (t->con.applySize) {
@@ -2353,10 +2535,6 @@ int Resize(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-
        return 1;
 }
 
@@ -2369,6 +2547,8 @@ void initToSphere(TransInfo *t)
 
        t->mode = TFM_TOSPHERE;
        t->transform = ToSphere;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
 
        t->idx_max = 0;
        t->num.idx_max = 0;
@@ -2378,7 +2558,7 @@ void initToSphere(TransInfo *t)
        
        t->num.flag |= NUM_NULL_ONE | NUM_NO_NEGATIVE;
        t->flag |= T_NO_CONSTRAINT;
-
+       
        // Calculate average radius
        for(i = 0 ; i < t->total; i++, td++) {
                t->val += VecLenf(t->center, td->iloc);
@@ -2395,7 +2575,7 @@ int ToSphere(TransInfo *t, short mval[2])
        char str[64];
        TransData *td = t->data;
 
-       ratio = InputHorizontalRatio(t, mval);
+       ratio = t->values[0];
 
        snapGrid(t, &ratio);
 
@@ -2444,8 +2624,6 @@ int ToSphere(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
        return 1;
 }
 
@@ -2457,6 +2635,8 @@ void initRotation(TransInfo *t)
        t->mode = TFM_ROTATION;
        t->transform = Rotation;
        
+       initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+       
        t->ndof.axis = 16;
        /* Scale down and flip input for rotation */
        t->ndof.factor[0] = -0.2f;
@@ -2466,7 +2646,6 @@ void initRotation(TransInfo *t)
        t->snap[0] = 0.0f;
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
-       t->fac = 0;
        
        if (t->flag & T_2D_EDIT)
                t->flag |= T_NO_CONSTRAINT;
@@ -2484,7 +2663,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                }
                else {
                        /* !TODO! Make this if not rely on G */
-                       if(around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE)) {
+                       if(around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
                                center = td->center;
                        }
                }
@@ -2541,7 +2720,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                        Mat3MulVecfl(pmtx, vec);        // To Global space
                        Mat3MulVecfl(mat, vec);         // Applying rotation
                        Mat3MulVecfl(imtx, vec);        // To Local space
-       
+                       
                        VecAddf(vec, vec, center);
                        /* vec now is the location where the object has to be */
                        
@@ -2549,9 +2728,9 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                        
                        Mat3MulVecfl(pmtx, vec);        // To Global space
                        Mat3MulVecfl(td->smtx, vec);// To Pose space
-       
+                               
                        protectedTransBits(td->protectflag, vec);
-       
+                       
                        VecAddf(td->loc, td->iloc, vec);
                        
                        constraintTransLim(t, td);
@@ -2559,19 +2738,40 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                
                /* rotation */
                if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself
-                       Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
-                       
-                       Mat3ToQuat(fmat, quat); // Actual transform
-                       
-                       QuatMul(td->ext->quat, quat, td->ext->iquat);
-                       /* this function works on end result */
-                       protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+                       /* euler or quaternion? */
+                       if (td->flag & TD_USEQUAT) {
+                               Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+                               
+                               Mat3ToQuat(fmat, quat); // Actual transform
+                               
+                               QuatMul(td->ext->quat, quat, td->ext->iquat);
+                               /* this function works on end result */
+                               protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+                       }
+                       else {
+                               float eulmat[3][3];
+                               
+                               Mat3MulMat3(totmat, mat, td->mtx);
+                               Mat3MulMat3(smat, td->smtx, totmat);
+                               
+                               /* calculate the total rotatation in eulers */
+                               VECCOPY(eul, td->ext->irot);
+                               EulToMat3(eul, eulmat);
+                               
+                               /* mat = transform, obmat = bone rotation */
+                               Mat3MulMat3(fmat, smat, eulmat);
+                               
+                               Mat3ToCompatibleEul(fmat, eul, td->ext->rot);
+                               
+                               /* and apply (to end result only) */
+                               protectedRotateBits(td->protectflag, eul, td->ext->irot);
+                               VECCOPY(td->ext->rot, eul);
+                       }
                        
                        constraintRotLim(t, td);
                }
        }
        else {
-               
                if ((td->flag & TD_NO_LOC) == 0)
                {
                        /* translation */
@@ -2598,7 +2798,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
 
                /* rotation */
                if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself
-                       if(td->flag & TD_USEQUAT) {
+                       /* euler or quaternion? */
+                   if (td->flag & TD_USEQUAT) {
                                Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
                                Mat3ToQuat(fmat, quat); // Actual transform
                                
@@ -2713,9 +2914,7 @@ int Rotation(TransInfo *t, short mval[2])
        VecMulf(axis, -1.0f);
        Normalize(axis);
 
-       t->fac += InputDeltaAngle(t, mval);
-
-       final = t->fac;
+       final = t->values[0];
 
        applyNDofInput(&t->ndof, &final);
        
@@ -2751,8 +2950,9 @@ int Rotation(TransInfo *t, short mval[2])
 
        VecRotToMat3(axis, final, mat);
 
-       t->val = final;                         // used in manipulator
-       Mat3CpyMat3(t->mat, mat);       // used in manipulator
+       // TRANSFORM_FIX_ME
+//     t->values[0] = final;           // used in manipulator
+//     Mat3CpyMat3(t->mat, mat);       // used in manipulator
        
        applyRotation(t, final, axis);
        
@@ -2760,10 +2960,6 @@ int Rotation(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-
        return 1;
 }
 
@@ -2775,6 +2971,8 @@ void initTrackball(TransInfo *t)
        t->mode = TFM_TRACKBALL;
        t->transform = Trackball;
        
+       initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL);
+       
        t->ndof.axis = 40;
        /* Scale down input for rotation */
        t->ndof.factor[0] = 0.2f;
@@ -2785,7 +2983,6 @@ void initTrackball(TransInfo *t)
        t->snap[0] = 0.0f;
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
-       t->fac = 0;
        
        t->flag |= T_NO_CONSTRAINT;
 }
@@ -2831,9 +3028,8 @@ int Trackball(TransInfo *t, short mval[2])
        Normalize(axis1);
        Normalize(axis2);
        
-       /* factore has to become setting or so */
-       phi[0]= 0.01f*(float)( t->imval[1] - mval[1] );
-       phi[1]= 0.01f*(float)( mval[0] - t->imval[0] );
+       phi[0] = t->values[0];
+       phi[1] = t->values[1];
                
        applyNDofInput(&t->ndof, phi);
        
@@ -2853,11 +3049,6 @@ int Trackball(TransInfo *t, short mval[2])
        }
        else {
                sprintf(str, "Trackball: %.2f %.2f %s", 180.0*phi[0]/M_PI, 180.0*phi[1]/M_PI, t->proptext);
-       
-               if(t->flag & T_SHIFT_MOD) {
-                       if(phi[0] != 0.0) phi[0]/= 5.0f;
-                       if(phi[1] != 0.0) phi[1]/= 5.0f;
-               }
        }
 
        VecRotToMat3(axis1, phi[0], smat);
@@ -2865,7 +3056,8 @@ int Trackball(TransInfo *t, short mval[2])
        
        Mat3MulMat3(mat, smat, totmat);
        
-       Mat3CpyMat3(t->mat, mat);       // used in manipulator
+       // TRANSFORM_FIX_ME
+       //Mat3CpyMat3(t->mat, mat);     // used in manipulator
        
        applyTrackball(t, axis1, axis2, phi);
        
@@ -2873,10 +3065,6 @@ int Trackball(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       viewRedrawForce(t);
-       
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-       
        return 1;
 }
 
@@ -2886,28 +3074,17 @@ void initTranslation(TransInfo *t)
 {
        t->mode = TFM_TRANSLATION;
        t->transform = Translation;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
 
        t->idx_max = (t->flag & T_2D_EDIT)? 1: 2;
        t->num.flag = 0;
        t->num.idx_max = t->idx_max;
        
-       t->ndof.axis = 7;
+       t->ndof.axis = (t->flag & T_2D_EDIT)? 1|2: 1|2|4;
 
        if(t->spacetype == SPACE_VIEW3D) {
                View3D *v3d = t->view;
-               
-               /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d() */
-               if(t->flag & (T_EDIT|T_POSE)) {
-                       Object *ob= G.obedit?G.obedit:t->poseobj;
-                       float vec[3];
-                       
-                       VECCOPY(vec, t->center);
-                       Mat4MulVecfl(ob->obmat, vec);
-                       initgrabz(v3d, vec[0], vec[1], vec[2]);
-               }
-               else {
-                       initgrabz(v3d, t->center[0], t->center[1], t->center[2]);
-               } 
 
                t->snap[0] = 0.0f;
                t->snap[1] = v3d->gridview * 1.0f;
@@ -2928,16 +3105,18 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) {
        char tvec[60];
        char distvec[20];
        char autoik[20];
-       float dvec[3];
        float dist;
        
-       convertVecToDisplayNum(vec, dvec);
-
        if (hasNumInput(&t->num)) {
                outputNumInput(&(t->num), tvec);
                dist = VecLength(t->num.val);
        }
        else {
+               float dvec[3];
+
+               VECCOPY(dvec, vec);
+               applyAspectRatio(t, dvec);
+
                dist = VecLength(vec);
                sprintf(&tvec[0], "%.4f", dvec[0]);
                sprintf(&tvec[20], "%.4f", dvec[1]);
@@ -2950,7 +3129,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) {
                sprintf(distvec, "%.4f", dist);
                
        if(t->flag & T_AUTOIK) {
-               short chainlen= G.scene->toolsettings->autoik_chainlen;
+               short chainlen= t->settings->autoik_chainlen;
                
                if(chainlen)
                        sprintf(autoik, "AutoIK-Len: %d", chainlen);
@@ -3054,44 +3233,35 @@ int Translation(TransInfo *t, short mval[2])
        float tvec[3];
        char str[250];
        
-       if(t->flag & T_SHIFT_MOD) {
-               float dvec[3];
-               /* calculate the main translation and the precise one separate */
-               convertViewVec(t, dvec, (short)(mval[0] - t->shiftmval[0]), (short)(mval[1] - t->shiftmval[1]));
-               VecMulf(dvec, 0.1f);
-               convertViewVec(t, t->vec, (short)(t->shiftmval[0] - t->imval[0]), (short)(t->shiftmval[1] - t->imval[1]));
-               VecAddf(t->vec, t->vec, dvec);
-       }
-       else convertViewVec(t, t->vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
-
        if (t->con.mode & CON_APPLY) {
                float pvec[3] = {0.0f, 0.0f, 0.0f};
-               applySnapping(t, t->vec);
-               t->con.applyVec(t, NULL, t->vec, tvec, pvec);
-               VECCOPY(t->vec, tvec);
+               applySnapping(t, t->values);
+               t->con.applyVec(t, NULL, t->values, tvec, pvec);
+               VECCOPY(t->values, tvec);
                headerTranslation(t, pvec, str);
        }
        else {
-               applyNDofInput(&t->ndof, t->vec);
-               snapGrid(t, t->vec);
-               applyNumInput(&t->num, t->vec);
-               applySnapping(t, t->vec);
-               headerTranslation(t, t->vec, str);
+               applyNDofInput(&t->ndof, t->values);
+               snapGrid(t, t->values);
+               applyNumInput(&t->num, t->values);
+               if (hasNumInput(&t->num))
+               {
+                       removeAspectRatio(t, t->values);
+               }
+               
+               applySnapping(t, t->values);
+               headerTranslation(t, t->values, str);
        }
        
-       applyTranslation(t, t->vec);
+       applyTranslation(t, t->values);
 
-       /* evil hack - redo translation if cliiping needeed */
-       if (t->flag & T_CLIP_UV && clipUVTransform(t, t->vec, 0))
-               applyTranslation(t, t->vec);
+       /* evil hack - redo translation if clipping needed */
+       if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values, 0))
+               applyTranslation(t, t->values);
 
        recalcData(t);
 
        ED_area_headerprint(t->sa, str);
-       
-       viewRedrawForce(t);
-
-       drawSnapping(t);
 
        return 1;
 }
@@ -3101,12 +3271,14 @@ int Translation(TransInfo *t, short mval[2])
 void initShrinkFatten(TransInfo *t) 
 {
        // If not in mesh edit mode, fallback to Resize
-       if (G.obedit==NULL || G.obedit->type != OB_MESH) {
+       if (t->obedit==NULL || t->obedit->type != OB_MESH) {
                initResize(t);
        }
        else {
                t->mode = TFM_SHRINKFATTEN;
                t->transform = ShrinkFatten;
+               
+               initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
        
                t->idx_max = 0;
                t->num.idx_max = 0;
@@ -3128,7 +3300,7 @@ int ShrinkFatten(TransInfo *t, short mval[2])
        char str[64];
        TransData *td = t->data;
 
-       distance = -InputVerticalAbsolute(t, mval);
+       distance = -t->values[0];
 
        snapGrid(t, &distance);
 
@@ -3166,8 +3338,6 @@ int ShrinkFatten(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
        return 1;
 }
 
@@ -3177,6 +3347,8 @@ void initTilt(TransInfo *t)
 {
        t->mode = TFM_TILT;
        t->transform = Tilt;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
 
        t->ndof.axis = 16;
        /* Scale down and flip input for rotation */
@@ -3187,7 +3359,6 @@ void initTilt(TransInfo *t)
        t->snap[0] = 0.0f;
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
-       t->fac = 0;
        
        t->flag |= T_NO_CONSTRAINT;
 }
@@ -3202,9 +3373,7 @@ int Tilt(TransInfo *t, short mval[2])
 
        float final;
 
-       t->fac += InputDeltaAngle(t, mval);
-
-       final = t->fac;
+       final = t->values[0];
        
        applyNDofInput(&t->ndof, &final);
 
@@ -3241,16 +3410,28 @@ int Tilt(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
-       helpline (t, t->center);
-
        return 1;
 }
 
 
 /* ******************** Curve Shrink/Fatten *************** */
 
+void initCurveShrinkFatten(TransInfo *t)
+{
+       t->mode = TFM_CURVE_SHRINKFATTEN;
+       t->transform = CurveShrinkFatten;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+       
+       t->idx_max = 0;
+       t->num.idx_max = 0;
+       t->snap[0] = 0.0f;
+       t->snap[1] = 0.1f;
+       t->snap[2] = t->snap[1] * 0.1f;
+       
+       t->flag |= T_NO_CONSTRAINT;
+}
+
 int CurveShrinkFatten(TransInfo *t, short mval[2]) 
 {
        TransData *td = t->data;
@@ -3258,22 +3439,7 @@ int CurveShrinkFatten(TransInfo *t, short mval[2])
        int i;
        char str[50];
        
-       if(t->flag & T_SHIFT_MOD) {
-               /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
-               float dx= (float)(t->center2d[0] - t->shiftmval[0]);
-               float dy= (float)(t->center2d[1] - t->shiftmval[1]);
-               ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
-               
-               dx= (float)(t->center2d[0] - mval[0]);
-               dy= (float)(t->center2d[1] - mval[1]);
-               ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
-               
-       }
-       else {
-               float dx= (float)(t->center2d[0] - mval[0]);
-               float dy= (float)(t->center2d[1] - mval[1]);
-               ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
-       }
+       ratio = t->values[0];
        
        snapGrid(t, &ratio);
        
@@ -3308,33 +3474,9 @@ int CurveShrinkFatten(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       viewRedrawForce(t);
-       
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-       
        return 1;
 }
 
-void initCurveShrinkFatten(TransInfo *t)
-{
-       t->mode = TFM_CURVE_SHRINKFATTEN;
-       t->transform = CurveShrinkFatten;
-       
-       t->idx_max = 0;
-       t->num.idx_max = 0;
-       t->snap[0] = 0.0f;
-       t->snap[1] = 0.1f;
-       t->snap[2] = t->snap[1] * 0.1f;
-       
-       t->flag |= T_NO_CONSTRAINT;
-
-       t->fac = (float)sqrt( (
-                  ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
-                  +
-                  ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
-                  ) );
-}
-
 /* ************************** PUSH/PULL *************************** */
 
 void initPushPull(TransInfo *t) 
@@ -3342,6 +3484,8 @@ void initPushPull(TransInfo *t)
        t->mode = TFM_PUSHPULL;
        t->transform = PushPull;
        
+       initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+       
        t->ndof.axis = 4;
        /* Flip direction */
        t->ndof.factor[0] = -1.0f;
@@ -3362,7 +3506,7 @@ int PushPull(TransInfo *t, short mval[2])
        char str[128];
        TransData *td = t->data;
 
-       distance = InputVerticalAbsolute(t, mval);
+       distance = t->values[0];
        
        applyNDofInput(&t->ndof, &distance);
 
@@ -3417,8 +3561,6 @@ int PushPull(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
        return 1;
 }
 
@@ -3426,11 +3568,14 @@ int PushPull(TransInfo *t, short mval[2])
 
 void initBevel(TransInfo *t) 
 {
+       t->transform = Bevel;
+       t->handleEvent = handleEventBevel;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+
        t->mode = TFM_BEVEL;
        t->flag |= T_NO_CONSTRAINT;
        t->num.flag |= NUM_NO_NEGATIVE;
-       t->transform = Bevel;
-       t->handleEvent = handleEventBevel;
 
        t->idx_max = 0;
        t->num.idx_max = 0;
@@ -3493,7 +3638,7 @@ int Bevel(TransInfo *t, short mval[2])
        TransData *td = t->data;
 
        mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal";
-       distance = InputHorizontalAbsolute(t, mval)/4; /* 4 just seemed a nice value to me, nothing special */
+       distance = t->values[0] / 4; /* 4 just seemed a nice value to me, nothing special */
        
        distance = fabs(distance);
 
@@ -3529,8 +3674,6 @@ int Bevel(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
        return 1;
 }
 
@@ -3541,6 +3684,8 @@ void initBevelWeight(TransInfo *t)
        t->mode = TFM_BWEIGHT;
        t->transform = BevelWeight;
        
+       initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+       
        t->idx_max = 0;
        t->num.idx_max = 0;
        t->snap[0] = 0.0f;
@@ -3548,15 +3693,6 @@ void initBevelWeight(TransInfo *t)
        t->snap[2] = t->snap[1] * 0.1f;
        
        t->flag |= T_NO_CONSTRAINT;
-
-       t->fac = (float)sqrt(
-               (
-                       ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
-               +
-                       ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
-               ) );
-
-       if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
 }
 
 int BevelWeight(TransInfo *t, short mval[2]) 
@@ -3566,23 +3702,7 @@ int BevelWeight(TransInfo *t, short mval[2])
        int i;
        char str[50];
 
-               
-       if(t->flag & T_SHIFT_MOD) {
-               /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
-               float dx= (float)(t->center2d[0] - t->shiftmval[0]);
-               float dy= (float)(t->center2d[1] - t->shiftmval[1]);
-               weight = (float)sqrt( dx*dx + dy*dy)/t->fac;
-               
-               dx= (float)(t->center2d[0] - mval[0]);
-               dy= (float)(t->center2d[1] - mval[1]);
-               weight+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -weight);
-               
-       }
-       else {
-               float dx= (float)(t->center2d[0] - mval[0]);
-               float dy= (float)(t->center2d[1] - mval[1]);
-               weight = (float)sqrt( dx*dx + dy*dy)/t->fac;
-       }
+       weight = t->values[0];
 
        weight -= 1.0f;
        if (weight > 1.0f) weight = 1.0f;
@@ -3625,10 +3745,6 @@ int BevelWeight(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -3639,6 +3755,8 @@ void initCrease(TransInfo *t)
        t->mode = TFM_CREASE;
        t->transform = Crease;
        
+       initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+       
        t->idx_max = 0;
        t->num.idx_max = 0;
        t->snap[0] = 0.0f;
@@ -3646,15 +3764,6 @@ void initCrease(TransInfo *t)
        t->snap[2] = t->snap[1] * 0.1f;
        
        t->flag |= T_NO_CONSTRAINT;
-
-       t->fac = (float)sqrt(
-               (
-                       ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
-               +
-                       ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
-               ) );
-
-       if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
 }
 
 int Crease(TransInfo *t, short mval[2]) 
@@ -3664,23 +3773,7 @@ int Crease(TransInfo *t, short mval[2])
        int i;
        char str[50];
 
-               
-       if(t->flag & T_SHIFT_MOD) {
-               /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
-               float dx= (float)(t->center2d[0] - t->shiftmval[0]);
-               float dy= (float)(t->center2d[1] - t->shiftmval[1]);
-               crease = (float)sqrt( dx*dx + dy*dy)/t->fac;
-               
-               dx= (float)(t->center2d[0] - mval[0]);
-               dy= (float)(t->center2d[1] - mval[1]);
-               crease+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -crease);
-               
-       }
-       else {
-               float dx= (float)(t->center2d[0] - mval[0]);
-               float dy= (float)(t->center2d[1] - mval[1]);
-               crease = (float)sqrt( dx*dx + dy*dy)/t->fac;
-       }
+       crease = t->values[0];
 
        crease -= 1.0f;
        if (crease > 1.0f) crease = 1.0f;
@@ -3726,10 +3819,6 @@ int Crease(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -3740,20 +3829,14 @@ void initBoneSize(TransInfo *t)
        t->mode = TFM_BONESIZE;
        t->transform = BoneSize;
        
+       initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+       
        t->idx_max = 2;
        t->num.idx_max = 2;
        t->num.flag |= NUM_NULL_ONE;
        t->snap[0] = 0.0f;
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
-       
-       t->fac = (float)sqrt( (
-                                          ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
-                                          +
-                                          ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
-                                          ) );
-       
-       if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
 }
 
 static void headerBoneSize(TransInfo *t, float vec[3], char *str) {
@@ -3807,33 +3890,15 @@ int BoneSize(TransInfo *t, short mval[2])
        int i;
        char str[60];
        
+       // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT
        /* for manipulator, center handle, the scaling can't be done relative to center */
-       if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) {
+       if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0)
+       {
                ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]))/100.0f;
        }
-       else {
-               
-               if(t->flag & T_SHIFT_MOD) {
-                       /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
-                       float dx= (float)(t->center2d[0] - t->shiftmval[0]);
-                       float dy= (float)(t->center2d[1] - t->shiftmval[1]);
-                       ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
-                       
-                       dx= (float)(t->center2d[0] - mval[0]);
-                       dy= (float)(t->center2d[1] - mval[1]);
-                       ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
-                       
-               }
-               else {
-                       float dx= (float)(t->center2d[0] - mval[0]);
-                       float dy= (float)(t->center2d[1] - mval[1]);
-                       ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
-               }
-               
-               /* flip scale, but not for manipulator center handle */
-               if      ((t->center2d[0] - mval[0]) * (t->center2d[0] - t->imval[0]) + 
-                        (t->center2d[1] - mval[1]) * (t->center2d[1] - t->imval[1]) < 0)
-                       ratio *= -1.0f;
+       else
+       {
+               ratio = t->values[0];
        }
        
        size[0] = size[1] = size[2] = ratio;
@@ -3869,10 +3934,6 @@ int BoneSize(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       viewRedrawForce(t);
-       
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-       
        return 1;
 }
 
@@ -3884,6 +3945,8 @@ void initBoneEnvelope(TransInfo *t)
        t->mode = TFM_BONE_ENVELOPE;
        t->transform = BoneEnvelope;
        
+       initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+       
        t->idx_max = 0;
        t->num.idx_max = 0;
        t->snap[0] = 0.0f;
@@ -3891,14 +3954,6 @@ void initBoneEnvelope(TransInfo *t)
        t->snap[2] = t->snap[1] * 0.1f;
 
        t->flag |= T_NO_CONSTRAINT;
-
-       t->fac = (float)sqrt( (
-                                                  ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
-                                                  +
-                                                  ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
-                                                  ) );
-       
-       if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
 }
 
 int BoneEnvelope(TransInfo *t, short mval[2]) 
@@ -3908,22 +3963,7 @@ int BoneEnvelope(TransInfo *t, short mval[2])
        int i;
        char str[50];
        
-       if(t->flag & T_SHIFT_MOD) {
-               /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
-               float dx= (float)(t->center2d[0] - t->shiftmval[0]);
-               float dy= (float)(t->center2d[1] - t->shiftmval[1]);
-               ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
-               
-               dx= (float)(t->center2d[0] - mval[0]);
-               dy= (float)(t->center2d[1] - mval[1]);
-               ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
-               
-       }
-       else {
-               float dx= (float)(t->center2d[0] - mval[0]);
-               float dy= (float)(t->center2d[1] - mval[1]);
-               ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
-       }
+       ratio = t->values[0];
        
        snapGrid(t, &ratio);
        
@@ -3960,10 +4000,6 @@ int BoneEnvelope(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       viewRedrawForce(t);
-       
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-       
        return 1;
 }
 
@@ -3974,6 +4010,8 @@ void initBoneRoll(TransInfo *t)
 {
        t->mode = TFM_BONE_ROLL;
        t->transform = BoneRoll;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
 
        t->idx_max = 0;
        t->num.idx_max = 0;
@@ -3981,8 +4019,6 @@ void initBoneRoll(TransInfo *t)
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
        
-       t->fac = 0.0f;
-       
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -3994,9 +4030,7 @@ int BoneRoll(TransInfo *t, short mval[2])
 
        float final;
 
-       t->fac += InputDeltaAngle(t, mval);
-
-       final = t->fac;
+       final = t->values[0];
 
        snapGrid(t, &final);
 
@@ -4030,10 +4064,6 @@ int BoneRoll(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-
        return 1;
 }
 
@@ -4041,13 +4071,14 @@ int BoneRoll(TransInfo *t, short mval[2])
 
 void initBakeTime(TransInfo *t) 
 {
+       t->transform = BakeTime;
+       initMouseInputMode(t, &t->mouse, INPUT_NONE);
+       
        t->idx_max = 0;
        t->num.idx_max = 0;
        t->snap[0] = 0.0f;
        t->snap[1] = 1.0f;
        t->snap[2] = t->snap[1] * 0.1f;
-       t->transform = BakeTime;
-       t->fac = 0.1f;
 }
 
 int BakeTime(TransInfo *t, short mval[2]) 
@@ -4056,15 +4087,16 @@ int BakeTime(TransInfo *t, short mval[2])
        float time;
        int i;
        char str[50];
-
+       
+       float fac = 0.1f;
                
-       if(t->flag & T_SHIFT_MOD) {
+       if(t->mouse.precision) {
                /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
-               time= (float)(t->center2d[0] - t->shiftmval[0])*t->fac;
-               time+= 0.1f*((float)(t->center2d[0]*t->fac - mval[0]) -time);
+               time= (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac;
+               time+= 0.1f*((float)(t->center2d[0]*fac - mval[0]) -time);
        }
        else {
-               time = (float)(t->center2d[0] - mval[0])*t->fac;
+               time = (float)(t->center2d[0] - mval[0])*fac;
        }
 
        snapGrid(t, &time);
@@ -4108,10 +4140,6 @@ int BakeTime(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       viewRedrawForce(t);
-
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -4119,12 +4147,13 @@ int BakeTime(TransInfo *t, short mval[2])
 
 void initMirror(TransInfo *t) 
 {
+       t->transform = Mirror;
+       initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
        t->flag |= T_NULL_ONE;
-       if (!G.obedit) {
+       if (!t->obedit) {
                t->flag |= T_NO_ZERO;
        }
-       
-       t->transform = Mirror;
 }
 
 int Mirror(TransInfo *t, short mval[2]) 
@@ -4165,8 +4194,6 @@ int Mirror(TransInfo *t, short mval[2])
                recalcData(t);
        
                ED_area_headerprint(t->sa, str);
-       
-               viewRedrawForce(t);
        }
        else
        {
@@ -4187,8 +4214,6 @@ int Mirror(TransInfo *t, short mval[2])
                recalcData(t);
        
                ED_area_headerprint(t->sa, "Select a mirror axis (X, Y, Z)");
-       
-               viewRedrawForce(t);
        }
 
        return 1;
@@ -4201,6 +4226,8 @@ void initAlign(TransInfo *t)
        t->flag |= T_NO_CONSTRAINT;
        
        t->transform = Align;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_NONE);
 }
 
 int Align(TransInfo *t, short mval[2])
@@ -4227,7 +4254,7 @@ int Align(TransInfo *t, short mval[2])
                        VECCOPY(t->center, td->center);
                }
                else {
-                       if(G.scene->selectmode & SCE_SELECT_FACE) {
+                       if(t->settings->selectmode & SCE_SELECT_FACE) {
                                VECCOPY(t->center, td->center);
                        }
                }
@@ -4253,6 +4280,7 @@ int Align(TransInfo *t, short mval[2])
 
 /* ---------------- Special Helpers for Various Settings ------------- */
 
+
 /* This function returns the snapping 'mode' for Animation Editors only 
  * We cannot use the standard snapping due to NLA-strip scaling complexities.
  */
@@ -4265,65 +4293,31 @@ static short getAnimEdit_SnapMode(TransInfo *t)
        if (t->spacetype == SPACE_ACTION) {
                SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
                
-               if (saction) {
-                       switch (saction->autosnap) {
-                       case SACTSNAP_OFF:
-                               if (t->event->ctrl) 
-                                       autosnap= SACTSNAP_STEP;
-                               else if (t->event->shift)
-                                       autosnap= SACTSNAP_FRAME;
-                               else if (t->event->alt)
-                                       autosnap= SACTSNAP_MARKER;
-                               else
-                                       autosnap= SACTSNAP_OFF;
-                               break;
-                       case SACTSNAP_STEP:
-                               autosnap= (t->event->ctrl)? SACTSNAP_OFF: SACTSNAP_STEP;
-                               break;
-                       case SACTSNAP_FRAME:
-                               autosnap= (t->event->shift)? SACTSNAP_OFF: SACTSNAP_FRAME;
-                               break;
-                       case SACTSNAP_MARKER:
-                               autosnap= (t->event->alt)? SACTSNAP_OFF: SACTSNAP_MARKER;
-                               break;
-                       }
-               }
+               if (saction)
+                       autosnap= saction->autosnap;
+       }
+       else if (t->spacetype == SPACE_IPO) {
+               SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+               
+               if (sipo)
+                       autosnap= sipo->autosnap;
        }
        else if (t->spacetype == SPACE_NLA) {
                SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first;
                
-               if (snla) {
-                       switch (snla->autosnap) {
-                       case SACTSNAP_OFF:
-                               if (t->event->ctrl) 
-                                       autosnap= SACTSNAP_STEP;
-                               else if (t->event->shift)
-                                       autosnap= SACTSNAP_FRAME;
-                               else if (t->event->alt)
-                                       autosnap= SACTSNAP_MARKER;
-                               else
-                                       autosnap= SACTSNAP_OFF;
-                               break;
-                       case SACTSNAP_STEP:
-                               autosnap= (t->event->ctrl)? SACTSNAP_OFF: SACTSNAP_STEP;
-                               break;
-                       case SACTSNAP_FRAME:
-                               autosnap= (t->event->shift)? SACTSNAP_OFF: SACTSNAP_FRAME;
-                               break;
-                       case SACTSNAP_MARKER:
-                               autosnap= (t->event->alt)? SACTSNAP_OFF: SACTSNAP_MARKER;
-                               break;
-                       }
-               }
+               if (snla)
+                       autosnap= snla->autosnap;
        }
        else {
-               if (t->event->ctrl) 
-                       autosnap= SACTSNAP_STEP;
-               else if (t->event->shift)
-                       autosnap= SACTSNAP_FRAME;
-               else if (t->event->alt)
-                       autosnap= SACTSNAP_MARKER;
-               else
+               // TRANSFORM_FIX_ME This needs to use proper defines for t->modifiers
+//             // FIXME: this still toggles the modes...
+//             if (ctrl) 
+//                     autosnap= SACTSNAP_STEP;
+//             else if (shift)
+//                     autosnap= SACTSNAP_FRAME;
+//             else if (alt)
+//                     autosnap= SACTSNAP_MARKER;
+//             else
                        autosnap= SACTSNAP_OFF;
        }
        
@@ -4360,7 +4354,7 @@ static short getAnimEdit_DrawTime(TransInfo *t)
 /* This function is used by Animation Editor specific transform functions to do 
  * the Snap Keyframe to Nearest Frame/Marker
  */
-static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short autosnap)
+static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, short autosnap)
 {
        /* snap key to nearest frame? */
        if (autosnap == SACTSNAP_FRAME) {
@@ -4370,8 +4364,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short
                double val;
                
                /* convert frame to nla-action time (if needed) */
-               if (ob
-                       val= get_action_frame_inv(ob, *(td->val));
+               if (adt
+                       val= BKE_nla_tweakedit_remap(adt, *(td->val), 1);
                else
                        val= *(td->val);
                
@@ -4382,8 +4376,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short
                        val= (float)( floor(val+0.5f) );
                        
                /* convert frame out of nla-action time */
-               if (ob)
-                       *(td->val)= get_action_frame(ob, val);
+               if (adt)
+                       *(td->val)= BKE_nla_tweakedit_remap(adt, val, 0);
                else
                        *(td->val)= val;
        }
@@ -4392,18 +4386,18 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short
                float val;
                
                /* convert frame to nla-action time (if needed) */
-               if (ob
-                       val= get_action_frame_inv(ob, *(td->val));
+               if (adt
+                       val= BKE_nla_tweakedit_remap(adt, *(td->val), 1);
                else
                        val= *(td->val);
                
                /* snap to nearest marker */
-               // XXX missing function!
-               //val= (float)find_nearest_marker_time(val);
+               // TODO: need some more careful checks for where data comes from
+               val= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, val);
                
                /* convert frame out of nla-action time */
-               if (ob)
-                       *(td->val)= get_action_frame(ob, val);
+               if (adt)
+                       *(td->val)= BKE_nla_tweakedit_remap(adt, val, 0);
                else
                        *(td->val)= val;
        }
@@ -4415,6 +4409,8 @@ void initTimeTranslate(TransInfo *t)
 {
        t->mode = TFM_TIME_TRANSLATE;
        t->transform = TimeTranslate;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_NONE);
 
        /* num-input has max of (n-1) */
        t->idx_max = 0;
@@ -4439,7 +4435,7 @@ static void headerTimeTranslate(TransInfo *t, char *str)
                const short autosnap= getAnimEdit_SnapMode(t);
                const short doTime = getAnimEdit_DrawTime(t);
                const double secf= FPS;
-               float val= t->fac;
+               float val = t->values[0];
                
                /* apply snapping + frame->seconds conversions */
                if (autosnap == SACTSNAP_STEP) {
@@ -4474,14 +4470,15 @@ static void applyTimeTranslate(TransInfo *t, float sval)
        
        /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
        for (i = 0 ; i < t->total; i++, td++) {
-               /* it is assumed that td->ob is a pointer to the object,
+               /* it is assumed that td->extra is a pointer to the AnimData,
                 * whose active action is where this keyframe comes from 
+                * (this is only valid when not in NLA)
                 */
-               Object *ob= td->ob;
+               AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL;
                
-               /* check if any need to apply nla-scaling */
-               if (ob) {
-                       deltax = t->fac;
+               /* check if any need to apply nla-mapping */
+               if (adt) {
+                       deltax = t->values[0];
                        
                        if (autosnap == SACTSNAP_STEP) {
                                if (doTime) 
@@ -4490,12 +4487,12 @@ static void applyTimeTranslate(TransInfo *t, float sval)
                                        deltax= (float)( floor(deltax + 0.5f) );
                        }
                        
-                       val = get_action_frame_inv(ob, td->ival);
+                       val = BKE_nla_tweakedit_remap(adt, td->ival, 1);
                        val += deltax;
-                       *(td->val) = get_action_frame(ob, val);
+                       *(td->val) = BKE_nla_tweakedit_remap(adt, val, 0);
                }
                else {
-                       deltax = val = t->fac;
+                       deltax = val = t->values[0];
                        
                        if (autosnap == SACTSNAP_STEP) {
                                if (doTime)
@@ -4508,7 +4505,7 @@ static void applyTimeTranslate(TransInfo *t, float sval)
                }
                
                /* apply nearest snapping */
-               doAnimEdit_SnapFrame(t, td, ob, autosnap);
+               doAnimEdit_SnapFrame(t, td, adt, autosnap);
        }
 }
 
@@ -4523,12 +4520,12 @@ int TimeTranslate(TransInfo *t, short mval[2])
        UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
        
        /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
-       t->fac= cval[0] - sval[0];
+       t->values[0] = cval[0] - sval[0];
        
        /* handle numeric-input stuff */
-       t->vec[0] = t->fac;
+       t->vec[0] = t->values[0];
        applyNumInput(&t->num, &t->vec[0]);
-       t->fac = t->vec[0];
+       t->values[0] = t->vec[0];
        headerTimeTranslate(t, str);
        
        applyTimeTranslate(t, sval[0]);
@@ -4536,8 +4533,6 @@ int TimeTranslate(TransInfo *t, short mval[2])
        recalcData(t);
 
        ED_area_headerprint(t->sa, str);
-       
-       viewRedrawForce(t);
 
        return 1;
 }
@@ -4557,6 +4552,8 @@ void initTimeSlide(TransInfo *t)
        t->mode = TFM_TIME_SLIDE;
        t->transform = TimeSlide;
        t->flag |= T_FREE_CUSTOMDATA;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_NONE);
 
        /* num-input has max of (n-1) */
        t->idx_max = 0;
@@ -4578,7 +4575,7 @@ static void headerTimeSlide(TransInfo *t, float sval, char *str)
        else {
                float minx= *((float *)(t->customData));
                float maxx= *((float *)(t->customData) + 1);
-               float cval= t->fac;
+               float cval= t->values[0];
                float val;
                        
                val= 2.0f*(cval-sval) / (maxx-minx);
@@ -4601,22 +4598,23 @@ static void applyTimeSlide(TransInfo *t, float sval)
        /* set value for drawing black line */
        if (t->spacetype == SPACE_ACTION) {
                SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
-               float cvalf = t->fac;
+               float cvalf = t->values[0];
                
                saction->timeslide= cvalf;
        }
        
        /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
        for (i = 0 ; i < t->total; i++, td++) {
-               /* it is assumed that td->ob is a pointer to the object,
+               /* it is assumed that td->extra is a pointer to the AnimData,
                 * whose active action is where this keyframe comes from 
+                * (this is only valid when not in NLA)
                 */
-               Object *ob= td->ob;
-               float cval = t->fac;
+               AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+               float cval = t->values[0];
                
-               /* apply scaling to necessary values */
-               if (ob)
-                       cval= get_action_frame(ob, cval);
+               /* apply NLA-mapping to necessary values */
+               if (adt)
+                       cval= BKE_nla_tweakedit_remap(adt, cval, 0);
                
                /* only apply to data if in range */
                if ((sval > minx) && (sval < maxx)) {
@@ -4648,13 +4646,13 @@ int TimeSlide(TransInfo *t, short mval[2])
        UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
        UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
        
-       /* t->fac stores cval[0], which is the current mouse-pointer location (in frames) */
-       t->fac= cval[0];
+       /* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */
+       t->values[0] = cval[0];
        
        /* handle numeric-input stuff */
        t->vec[0] = 2.0f*(cval[0]-sval[0]) / (maxx-minx);
        applyNumInput(&t->num, &t->vec[0]);
-       t->fac = (maxx-minx) * t->vec[0] / 2.0 + sval[0];
+       t->values[0] = (maxx-minx) * t->vec[0] / 2.0 + sval[0];
        
        headerTimeSlide(t, sval[0], str);
        applyTimeSlide(t, sval[0]);
@@ -4662,8 +4660,6 @@ int TimeSlide(TransInfo *t, short mval[2])
        recalcData(t);
 
        ED_area_headerprint(t->sa, str);
-       
-       viewRedrawForce(t);
 
        return 1;
 }
@@ -4674,6 +4670,9 @@ void initTimeScale(TransInfo *t)
 {
        t->mode = TFM_TIME_SCALE;
        t->transform = TimeScale;
+       
+       initMouseInputMode(t, &t->mouse, INPUT_NONE);
+       t->helpline = HLP_SPRING; /* set manually because we don't use a predefined input */
 
        t->flag |= T_NULL_ONE;
        t->num.flag |= NUM_NULL_ONE;
@@ -4694,7 +4693,7 @@ static void headerTimeScale(TransInfo *t, char *str) {
        if (hasNumInput(&t->num))
                outputNumInput(&(t->num), tvec);
        else
-               sprintf(&tvec[0], "%.4f", t->fac);
+               sprintf(&tvec[0], "%.4f", t->values[0]);
                
        sprintf(str, "ScaleX: %s", &tvec[0]);
 }
@@ -4710,12 +4709,13 @@ static void applyTimeScale(TransInfo *t) {
        
        
        for (i = 0 ; i < t->total; i++, td++) {
-               /* it is assumed that td->ob is a pointer to the object,
+               /* it is assumed that td->extra is a pointer to the AnimData,
                 * whose active action is where this keyframe comes from 
+                * (this is only valid when not in NLA)
                 */
-               Object *ob= td->ob;
+               AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL;
                float startx= CFRA;
-               float fac= t->fac;
+               float fac= t->values[0];
                
                if (autosnap == SACTSNAP_STEP) {
                        if (doTime)
@@ -4724,9 +4724,9 @@ static void applyTimeScale(TransInfo *t) {
                                fac= (float)( floor(fac + 0.5f) );
                }
                
-               /* check if any need to apply nla-scaling */
-               if (ob)
-                       startx= get_action_frame(ob, startx);
+               /* check if any need to apply nla-mapping */
+               if (adt)
+                       startx= BKE_nla_tweakedit_remap(adt, startx, 0);
                        
                /* now, calculate the new value */
                *(td->val) = td->ival - startx;
@@ -4734,7 +4734,7 @@ static void applyTimeScale(TransInfo *t) {
                *(td->val) += startx;
                
                /* apply nearest snapping */
-               doAnimEdit_SnapFrame(t, td, ob, autosnap);
+               doAnimEdit_SnapFrame(t, td, adt, autosnap);
        }
 }
 
@@ -4748,27 +4748,15 @@ int TimeScale(TransInfo *t, short mval[2])
        sval= t->imval[0];
        cval= mval[0];
        
-       // XXX ewww... we need a better factor!
-#if 0 // TRANSFORM_FIX_ME              
-       switch (t->spacetype) {
-               case SPACE_ACTION:
-                       width= ACTWIDTH;
-                       break;
-               case SPACE_NLA:
-                       width= NLAWIDTH;
-                       break;
-       }
-#endif
-       
        /* calculate scaling factor */
        startx= sval-(width/2+(t->ar->winx)/2);
        deltax= cval-(width/2+(t->ar->winx)/2);
-       t->fac = deltax / startx;
+       t->values[0] = deltax / startx;
        
        /* handle numeric-input stuff */
-       t->vec[0] = t->fac;
+       t->vec[0] = t->values[0];
        applyNumInput(&t->num, &t->vec[0]);
-       t->fac = t->vec[0];
+       t->values[0] = t->vec[0];
        headerTimeScale(t, str);
        
        applyTimeScale(t);
@@ -4776,8 +4764,6 @@ int TimeScale(TransInfo *t, short mval[2])
        recalcData(t);
 
        ED_area_headerprint(t->sa, str);
-       
-       viewRedrawForce(t);
 
        return 1;
 }