At last... this merge should finally do the trick!
[blender.git] / source / blender / editors / transform / transform.c
index a630277c87af272f5f217542d41f89c45efe7cfd..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"
 //#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_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_util.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 "PIL_time.h"                  /* sleep                                */
 
+#include "UI_resources.h"
+
 //#include "blendef.h"
 //
 //#include "mydevice.h"
 
 #include "transform.h"
 
-/* ************************** 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= t->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
-}
-
 /* ************************** SPACE DEPENDANT CODE **************************** */
 
 void setTransformViewMatrices(TransInfo *t)
 {
-       if(t->spacetype==SPACE_VIEW3D) {
+       if(t->spacetype==SPACE_VIEW3D && t->ar->regiontype == RGN_TYPE_WINDOW) {
                RegionView3D *rv3d = t->ar->regiondata;
                
                Mat4CpyMat4(t->viewmat, rv3d->viewmat);
@@ -186,15 +144,16 @@ void setTransformViewMatrices(TransInfo *t)
 void convertViewVec(TransInfo *t, float *vec, short dx, short dy)
 {
        if (t->spacetype==SPACE_VIEW3D) {
-               window_to_3d_delta(t->ar, 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);
-               aspx= aspy= 1.0f;
+               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;
@@ -221,6 +180,17 @@ void convertViewVec(TransInfo *t, float *vec, short dx, short dy)
                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;
@@ -230,18 +200,17 @@ void convertViewVec(TransInfo *t, float *vec, short dx, short dy)
 void projectIntView(TransInfo *t, float *vec, int *adr)
 {
        if (t->spacetype==SPACE_VIEW3D) {
-               project_int_noclip(t->ar, 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) {
                int out[2] = {0, 0};
@@ -250,12 +219,20 @@ void projectIntView(TransInfo *t, float *vec, int *adr)
                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];
+       }
 }
 
 void projectFloatView(TransInfo *t, float *vec, float *adr)
 {
        if (t->spacetype==SPACE_VIEW3D) {
-               project_float_noclip(t->ar, 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];
@@ -273,54 +250,46 @@ void projectFloatView(TransInfo *t, float *vec, float *adr)
        }
 }
 
-void convertVecToDisplayNum(float *vec, float *num)
+void applyAspectRatio(TransInfo *t, float *vec)
 {
-       VECCOPY(num, vec);
-
-#if 0 // TRANSFORM_FIX_ME
-       TransInfo *t = BIF_GetTransInfo();
+       SpaceImage *sima= t->sa->spacedata.first;
 
        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)
 {
-       VECCOPY(vec, num);
-
-#if 0 // TRANSFORM_FIX_ME
-       TransInfo *t = BIF_GetTransInfo();
+       SpaceImage *sima= t->sa->spacedata.first;
 
        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(bContext *C, TransInfo *t)
@@ -340,63 +309,38 @@ static void viewRedrawForce(bContext *C, TransInfo *t)
                else 
                        ED_area_tag_redraw(t->sa);
        }
+       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) {
+               ED_area_tag_redraw(t->sa); // XXX this should use a notifier instead!
+       }
        else if(t->spacetype == SPACE_NODE)
        {
                //ED_area_tag_redraw(t->sa);
                WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
        }
-#if 0 // TRANSFORM_FIX_ME
+       else if(t->spacetype == SPACE_SEQ)
+       {
+               WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, NULL);
+       }
        else if (t->spacetype==SPACE_IMAGE) {
-               if (G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
+               // 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);
        }
-       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_NLA) {
-               if (G.snla->lock)
-                       force_draw_all(0);
-               else
-                       force_draw(0);
-       }
-       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);
-               }
-       }
-#endif 
 }
 
 static void viewRedrawPost(TransInfo *t)
@@ -658,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;
@@ -667,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;
@@ -684,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;
@@ -786,15 +733,15 @@ void transformEvent(TransInfo *t, wmEvent *event)
                        }
                        break;
                case OKEY:
-                       if (t->flag & T_PROP_EDIT && event->keymodifier == KM_SHIFT) {
-                               t->scene->prop_mode = (t->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;
@@ -805,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;
@@ -824,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);
@@ -902,7 +849,8 @@ void transformEvent(TransInfo *t, wmEvent *event)
                        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;
                }
@@ -924,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
 
@@ -952,34 +900,319 @@ int calculateTransformCenter(bContext *C, wmEvent *event, int centerMode, float
        return success;
 }
 
+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(t);
-       drawPropCircle(t);
-       drawSnapping(t);
+       drawConstraint(C, t);
+       drawPropCircle(C, t);
+       drawSnapping(C, t);
+       drawHelpline(C, t);
 }
 
 void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
 {
-       short twmode= (t->spacetype==SPACE_VIEW3D)? ((View3D*)t->view)->twmode: V3D_MANIP_GLOBAL;
+       ToolSettings *ts = CTX_data_tool_settings(C);
+       int constraint_axis[3] = {0, 0, 0};
+       int proportional = 0;
 
-       RNA_int_set(op->ptr, "mode", t->mode);
-       RNA_int_set(op->ptr, "options", t->options);
-       RNA_float_set_array(op->ptr, "values", t->values);
+       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);
+       }
        
-       RNA_int_set(op->ptr, "constraint_mode", t->con.mode);
-       RNA_int_set(op->ptr, "constraint_orientation", twmode);
-       RNA_float_set_array(op->ptr, "constraint_matrix", (float*)t->con.mtx);
+       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;
+               }
+       }
 }
 
-void initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
+int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int mode)
 {
-       int mode    = RNA_int_get(op->ptr, "mode");
-       int options = RNA_int_get(op->ptr, "options");
-       float values[4];
+       int options = 0;
 
        /* added initialize, for external calls to set stuff in TransInfo, like undo string */
 
@@ -989,17 +1222,20 @@ void initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
        
        t->mode = mode;
 
-       initTransInfo(C, t, event);                                     // internal data, mouse, vectors
-       
-       initTransformOrientation(C, t);
+       if (!initTransInfo(C, t, op, event))                                    // internal data, mouse, vectors
+       {
+               return 0;
+       }
 
        if(t->spacetype == SPACE_VIEW3D)
        {
-               RegionView3D *rv3d = t->ar->regiondata;
                //calc_manipulator_stats(curarea);
-               Mat3CpyMat4(t->spacemtx, rv3d->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
@@ -1007,13 +1243,13 @@ void initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
 
        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 */
@@ -1086,8 +1322,15 @@ void initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
                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);
@@ -1105,28 +1348,43 @@ void initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
                initAlign(t);
                break;
        }
-       
-       RNA_float_get_array(op->ptr, "values", values);
-       
+
        /* overwrite initial values if operator supplied a non-null vector */
-       if (!QuatIsNul(values))
+       if (RNA_property_is_set(op->ptr, "value"))
        {
-               QUATCOPY(t->values, values); /* vec-4 */
+               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"))
        {
-               t->con.mode = RNA_int_get(op->ptr, "constraint_mode");
-               
-               if (t->con.mode & CON_APPLY)
+               int constraint_axis[3];
+
+               RNA_boolean_get_array(op->ptr, "constraint_axis", constraint_axis);
+
+               if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2])
                {
-                       //int options = RNA_int_get(op->ptr, "options");
-                       RNA_float_get_array(op->ptr, "constraint_matrix", (float*)t->spacemtx);
-                       
+                       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)
@@ -1178,7 +1436,7 @@ int transformEnd(bContext *C, TransInfo *t)
                /* 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 */
@@ -1187,11 +1445,11 @@ int transformEnd(bContext *C, TransInfo *t)
                /*  Undo as last, certainly after special_trans_update! */
 
                if(t->state == TRANS_CANCEL) {
-                       if(t->undostr) ED_undo_push(C, t->undostr);
+//                     if(t->undostr) ED_undo_push(C, t->undostr);
                }
                else {
-                       if(t->undostr) ED_undo_push(C, t->undostr);
-                       else ED_undo_push(C, 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;
 
@@ -1745,7 +2003,7 @@ void initWarp(TransInfo *t)
        t->snap[2] = 1.0f;
        
        t->flag |= T_NO_CONSTRAINT;
-
+       
        /* we need min/max in view space */
        for(i = 0; i < t->total; i++) {
                float center[3];
@@ -1881,8 +2139,6 @@ int Warp(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       helpline(t, gcursor);
-       
        return 1;
 }
 
@@ -2003,8 +2259,6 @@ int Shear(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -2108,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 && (t->scene->selectmode & SCE_SELECT_FACE)) {
+                       if(t->around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
                                VECCOPY(center, td->center);
                        }
                        else {
@@ -2239,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) {
@@ -2274,8 +2535,6 @@ int Resize(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-
        return 1;
 }
 
@@ -2299,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);
@@ -2404,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 && (t->scene->selectmode & SCE_SELECT_FACE)) {
+                       if(around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
                                center = td->center;
                        }
                }
@@ -2461,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 */
                        
@@ -2469,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);
@@ -2479,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 */
@@ -2518,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
                                
@@ -2679,8 +2960,6 @@ int Rotation(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-
        return 1;
 }
 
@@ -2786,8 +3065,6 @@ int Trackball(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-       
        return 1;
 }
 
@@ -2828,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]);
@@ -2850,7 +3129,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) {
                sprintf(distvec, "%.4f", dist);
                
        if(t->flag & T_AUTOIK) {
-               short chainlen= t->scene->toolsettings->autoik_chainlen;
+               short chainlen= t->settings->autoik_chainlen;
                
                if(chainlen)
                        sprintf(autoik, "AutoIK-Len: %d", chainlen);
@@ -2965,6 +3244,11 @@ int Translation(TransInfo *t, short mval[2])
                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);
        }
@@ -2979,8 +3263,6 @@ int Translation(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       drawSnapping(t);
-
        return 1;
 }
 
@@ -3128,8 +3410,6 @@ int Tilt(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -3194,8 +3474,6 @@ int CurveShrinkFatten(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-       
        return 1;
 }
 
@@ -3467,8 +3745,6 @@ int BevelWeight(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -3543,8 +3819,6 @@ int Crease(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -3660,8 +3934,6 @@ int BoneSize(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-       
        return 1;
 }
 
@@ -3728,8 +4000,6 @@ int BoneEnvelope(TransInfo *t, short mval[2])
        
        ED_area_headerprint(t->sa, str);
        
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-       
        return 1;
 }
 
@@ -3794,8 +4064,6 @@ int BoneRoll(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
-
        return 1;
 }
 
@@ -3872,8 +4140,6 @@ int BakeTime(TransInfo *t, short mval[2])
 
        ED_area_headerprint(t->sa, str);
 
-       helpline (t, t->center);
-
        return 1;
 }
 
@@ -3988,7 +4254,7 @@ int Align(TransInfo *t, short mval[2])
                        VECCOPY(t->center, td->center);
                }
                else {
-                       if(t->scene->selectmode & SCE_SELECT_FACE) {
+                       if(t->settings->selectmode & SCE_SELECT_FACE) {
                                VECCOPY(t->center, td->center);
                        }
                }
@@ -4088,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) {
@@ -4098,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);
                
@@ -4110,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;
        }
@@ -4120,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;
        }
@@ -4204,13 +4470,14 @@ 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) {
+               /* check if any need to apply nla-mapping */
+               if (adt) {
                        deltax = t->values[0];
                        
                        if (autosnap == SACTSNAP_STEP) {
@@ -4220,9 +4487,9 @@ 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->values[0];
@@ -4238,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);
        }
 }
 
@@ -4338,15 +4605,16 @@ static void applyTimeSlide(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;
                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)) {
@@ -4404,6 +4672,7 @@ void initTimeScale(TransInfo *t)
        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;
@@ -4440,10 +4709,11 @@ 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->values[0];
                
@@ -4454,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;
@@ -4464,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);
        }
 }
 
@@ -4478,18 +4748,6 @@ 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);