commit from r27250 to fix bug #21433, broke local axis rotation for pose bones and...
[blender.git] / source / blender / editors / transform / transform.c
index 3f4839a7d7202dd02a5bbdae5909f74160cc6dd3..e4639b268de3328b5271ebe724b64a805ec7d531 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 
 #include "transform.h"
 
+void drawTransformApply(const struct bContext *C, struct ARegion *ar, void *arg);
+
 /* ************************** SPACE DEPENDANT CODE **************************** */
 
 void setTransformViewMatrices(TransInfo *t)
 {
-       if(t->spacetype==SPACE_VIEW3D && t->ar->regiontype == RGN_TYPE_WINDOW) {
+       if(t->spacetype==SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
                RegionView3D *rv3d = t->ar->regiondata;
 
                copy_m4_m4(t->viewmat, rv3d->viewmat);
@@ -217,7 +219,7 @@ void projectIntView(TransInfo *t, float *vec, int *adr)
 
                UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1);
        }
-       else if(ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) {
+       else if(ELEM3(t->spacetype, SPACE_IPO, SPACE_NLA, SPACE_ACTION)) {
                int out[2] = {0, 0};
 
                UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1);
@@ -297,7 +299,7 @@ void removeAspectRatio(TransInfo *t, float *vec)
        }
 }
 
-static void viewRedrawForce(bContext *C, TransInfo *t)
+static void viewRedrawForce(const bContext *C, TransInfo *t)
 {
        if (t->spacetype == SPACE_VIEW3D)
        {
@@ -305,8 +307,10 @@ static void viewRedrawForce(bContext *C, TransInfo *t)
                WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
                
                /* for realtime animation record - send notifiers recognised by animation editors */
+               // XXX: is this notifier a lame duck?
                if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
                        WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
+               
        }
        else if (t->spacetype == SPACE_ACTION) {
                //SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
@@ -339,7 +343,13 @@ static void viewRedrawForce(bContext *C, TransInfo *t)
 static void viewRedrawPost(TransInfo *t)
 {
        ED_area_headerprint(t->sa, NULL);
-
+       
+       if(t->spacetype == SPACE_VIEW3D) {
+               /* if autokeying is enabled, send notifiers that keyframes were added */
+               if (IS_AUTOKEY_ON(t->scene))
+                       WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
+       }
+       
 #if 0 // TRANSFORM_FIX_ME
        if(t->spacetype==SPACE_VIEW3D) {
                allqueue(REDRAWBUTSOBJECT, 0);
@@ -450,69 +460,31 @@ static void view_editmove(unsigned short event)
 #endif
 }
 
-#if 0
-static char *transform_to_undostr(TransInfo *t)
-{
-       switch (t->mode) {
-               case TFM_TRANSLATION:
-                       return "Translate";
-               case TFM_ROTATION:
-                       return "Rotate";
-               case TFM_RESIZE:
-                       return "Scale";
-               case TFM_TOSPHERE:
-                       return "To Sphere";
-               case TFM_SHEAR:
-                       return "Shear";
-               case TFM_WARP:
-                       return "Warp";
-               case TFM_SHRINKFATTEN:
-                       return "Shrink/Fatten";
-               case TFM_TILT:
-                       return "Tilt";
-               case TFM_TRACKBALL:
-                       return "Trackball";
-               case TFM_PUSHPULL:
-                       return "Push/Pull";
-               case TFM_BEVEL:
-                       return "Bevel";
-               case TFM_BWEIGHT:
-                       return "Bevel Weight";
-               case TFM_CREASE:
-                       return "Crease";
-               case TFM_BONESIZE:
-                       return "Bone Width";
-               case TFM_BONE_ENVELOPE:
-                       return "Bone Envelope";
-               case TFM_TIME_TRANSLATE:
-                       return "Translate Anim. Data";
-               case TFM_TIME_SCALE:
-                       return "Scale Anim. Data";
-               case TFM_TIME_SLIDE:
-                       return "Time Slide";
-               case TFM_BAKE_TIME:
-                       return "Key Time";
-               case TFM_MIRROR:
-                       return "Mirror";
-       }
-       return "Transform";
-}
-#endif
-
 /* ************************************************* */
 
 /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-#define TFM_MODAL_CANCEL                       1
-#define TFM_MODAL_CONFIRM                      2
-#define TFM_MODAL_TRANSLATE                    3
-#define TFM_MODAL_ROTATE                       4
-#define TFM_MODAL_RESIZE                       5
-#define TFM_MODAL_SNAP_GEARS           6
-#define TFM_MODAL_SNAP_GEARS_OFF       7
-#define TFM_MODAL_SNAP_GEARS_TOGGLE    8
+#define TFM_MODAL_CANCEL               1
+#define TFM_MODAL_CONFIRM              2
+#define TFM_MODAL_TRANSLATE            3
+#define TFM_MODAL_ROTATE               4
+#define TFM_MODAL_RESIZE               5
+#define TFM_MODAL_SNAP_INV_ON  6
+#define TFM_MODAL_SNAP_INV_OFF 7
+#define TFM_MODAL_SNAP_TOGGLE  8
+#define TFM_MODAL_AXIS_X               9
+#define TFM_MODAL_AXIS_Y               10
+#define TFM_MODAL_AXIS_Z               11
+#define TFM_MODAL_PLANE_X              12
+#define TFM_MODAL_PLANE_Y              13
+#define TFM_MODAL_PLANE_Z              14
+#define TFM_MODAL_CONS_OFF             15
+#define TFM_MODAL_ADD_SNAP             16
+#define TFM_MODAL_REMOVE_SNAP  17
+/*     18 and 19 used by numinput, defined in transform.h
+ * */
 
 /* called in transform_ops.c, on each regeneration of keymaps */
-void transform_modal_keymap(wmKeyConfig *keyconf)
+wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf)
 {
        static EnumPropertyItem modal_items[] = {
        {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
@@ -520,15 +492,26 @@ void transform_modal_keymap(wmKeyConfig *keyconf)
        {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Translate", ""},
        {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""},
        {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""},
-       {TFM_MODAL_SNAP_GEARS, "SNAP_GEARS", 0, "Snap On", ""},
-       {TFM_MODAL_SNAP_GEARS_OFF, "SNAP_GEARS_OFF", 0, "Snap Off", ""},
-       {TFM_MODAL_SNAP_GEARS_TOGGLE, "SNAP_GEARS_TOGGLE", 0, "Snap Toggle", ""},
+       {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Invert Snap On", ""},
+       {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Invert Snap Off", ""},
+       {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""},
+       {TFM_MODAL_AXIS_X, "AXIS_X", 0, "Orientation X axis", ""},
+       {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Orientation Y axis", ""},
+       {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Orientation Z axis", ""},
+       {TFM_MODAL_PLANE_X, "PLANE_X", 0, "Orientation X plane", ""},
+       {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Orientation Y plane", ""},
+       {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Orientation Z plane", ""},
+       {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Remove Constraints", ""},
+       {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""},
+       {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""},
+       {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""},
+       {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""},
        {0, NULL, 0, NULL, NULL}};
        
        wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "Transform Modal Map");
        
        /* this function is called for each spacetype, only needs to add map once */
-       if(keymap) return;
+       if(keymap) return NULL;
        
        keymap= WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items);
        
@@ -542,37 +525,38 @@ void transform_modal_keymap(wmKeyConfig *keyconf)
        WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE);
        WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, 0, 0, TFM_MODAL_RESIZE);
        
-       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_SNAP_GEARS_TOGGLE);
-       
-       /* assign map to operators */
-       WM_modalkeymap_assign(keymap, "TFM_OT_transform");
-       WM_modalkeymap_assign(keymap, "TFM_OT_translate");
-       WM_modalkeymap_assign(keymap, "TFM_OT_rotate");
-       WM_modalkeymap_assign(keymap, "TFM_OT_tosphere");
-       WM_modalkeymap_assign(keymap, "TFM_OT_resize");
-       WM_modalkeymap_assign(keymap, "TFM_OT_shear");
-       WM_modalkeymap_assign(keymap, "TFM_OT_warp");
-       WM_modalkeymap_assign(keymap, "TFM_OT_shrink_fatten");
-       WM_modalkeymap_assign(keymap, "TFM_OT_tilt");
-       WM_modalkeymap_assign(keymap, "TFM_OT_trackball");
-       WM_modalkeymap_assign(keymap, "TFM_OT_mirror");
-       WM_modalkeymap_assign(keymap, "TFM_OT_edge_slide");
+       WM_modalkeymap_add_item(keymap, TABKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_SNAP_TOGGLE);
+
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_SNAP_INV_ON);
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_SNAP_INV_OFF);
+       
+       WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, 0, 0, TFM_MODAL_ADD_SNAP);
+       WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, KM_ALT, 0, TFM_MODAL_REMOVE_SNAP);
+
+       WM_modalkeymap_add_item(keymap, UPARROWKEY, KM_PRESS, 0, 0, NUM_MODAL_INCREMENT_UP);
+       WM_modalkeymap_add_item(keymap, DOWNARROWKEY, KM_PRESS, 0, 0, NUM_MODAL_INCREMENT_DOWN);
+
+       return keymap;
 }
 
 
-void transformEvent(TransInfo *t, wmEvent *event)
+int 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);
+       int handled = 1;
 
        t->redraw |= handleMouseInput(t, &t->mouse, event);
 
        if (event->type == MOUSEMOVE)
        {
+               if (t->modifiers & MOD_CONSTRAINT_SELECT)
+                       t->con.mode |= CON_SELECT;
+
                t->mval[0] = event->x - t->ar->winrct.xmin;
                t->mval[1] = event->y - t->ar->winrct.ymin;
 
-               t->redraw = 1;
+               t->redraw |= TREDRAW_SOFT;
 
                if (t->state == TRANS_STARTING) {
                    t->state = TRANS_RUNNING;
@@ -597,7 +581,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                        restoreTransObjects(t);
                                        initTranslation(t);
                                        initSnapping(t, NULL); // need to reinit after mode change
-                                       t->redraw = 1;
+                                       t->redraw |= TREDRAW_HARD;
                                }
                                break;
                        case TFM_MODAL_ROTATE:
@@ -615,7 +599,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                                initRotation(t);
                                        }
                                        initSnapping(t, NULL); // need to reinit after mode change
-                                       t->redraw = 1;
+                                       t->redraw |= TREDRAW_HARD;
                                }
                                break;
                        case TFM_MODAL_RESIZE:
@@ -625,23 +609,119 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                        restoreTransObjects(t);
                                        initResize(t);
                                        initSnapping(t, NULL); // need to reinit after mode change
-                                       t->redraw = 1;
+                                       t->redraw |= TREDRAW_HARD;
                                }
                                break;
                                
-                       case TFM_MODAL_SNAP_GEARS:
-                               t->modifiers |= MOD_SNAP_GEARS;
-                               t->redraw = 1;
+                       case TFM_MODAL_SNAP_INV_ON:
+                               t->modifiers |= MOD_SNAP_INVERT;
+                               t->redraw |= TREDRAW_HARD;
+                               break;
+                       case TFM_MODAL_SNAP_INV_OFF:
+                               t->modifiers &= ~MOD_SNAP_INVERT;
+                               t->redraw |= TREDRAW_HARD;
+                               break;
+                       case TFM_MODAL_SNAP_TOGGLE:
+                               t->modifiers ^= MOD_SNAP;
+                               t->redraw |= TREDRAW_HARD;
+                               break;
+                       case TFM_MODAL_AXIS_X:
+                               if ((t->flag & T_NO_CONSTRAINT)==0) {
+                                       if (cmode == 'X') {
+                                               stopConstraint(t);
+                                       }
+                                       else {
+                                               if (t->flag & T_2D_EDIT) {
+                                                       setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), "along X");
+                                               }
+                                               else {
+                                                       setUserConstraint(t, t->current_orientation, (CON_AXIS0), "along %s X");
+                                               }
+                                       }
+                                       t->redraw |= TREDRAW_HARD;
+                               }
+                               break;
+                       case TFM_MODAL_AXIS_Y:
+                               if ((t->flag & T_NO_CONSTRAINT)==0) {
+                                       if (cmode == 'Y') {
+                                               stopConstraint(t);
+                                       }
+                                       else {
+                                               if (t->flag & T_2D_EDIT) {
+                                                       setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), "along Y");
+                                               }
+                                               else {
+                                                       setUserConstraint(t, t->current_orientation, (CON_AXIS1), "along %s Y");
+                                               }
+                                       }
+                                       t->redraw |= TREDRAW_HARD;
+                               }
+                               break;
+                       case TFM_MODAL_AXIS_Z:
+                               if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))== 0) {
+                                       if (cmode == 'Z') {
+                                               stopConstraint(t);
+                                       }
+                                       else {
+                                               setUserConstraint(t, t->current_orientation, (CON_AXIS2), "along %s Z");
+                                       }
+                                       t->redraw |= TREDRAW_HARD;
+                               }
+                               break;
+                       case TFM_MODAL_PLANE_X:
+                               if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))== 0) {
+                                       if (cmode == 'X') {
+                                               stopConstraint(t);
+                                       }
+                                       else {
+                                               setUserConstraint(t, t->current_orientation, (CON_AXIS1|CON_AXIS2), "locking %s X");
+                                       }
+                                       t->redraw |= TREDRAW_HARD;
+                               }
+                               break;
+                       case TFM_MODAL_PLANE_Y:
+                               if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))== 0) {
+                                       if (cmode == 'Y') {
+                                               stopConstraint(t);
+                                       }
+                                       else {
+                                               setUserConstraint(t, t->current_orientation, (CON_AXIS0|CON_AXIS2), "locking %s Y");
+                                       }
+                                       t->redraw |= TREDRAW_HARD;
+                               }
+                               break;
+                       case TFM_MODAL_PLANE_Z:
+                               if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))== 0) {
+                                       if (cmode == 'Z') {
+                                               stopConstraint(t);
+                                       }
+                                       else {
+                                               setUserConstraint(t, t->current_orientation, (CON_AXIS0|CON_AXIS1), "locking %s Z");
+                                       }
+                                       t->redraw |= TREDRAW_HARD;
+                               }
+                               break;
+                       case TFM_MODAL_CONS_OFF:
+                               if ((t->flag & T_NO_CONSTRAINT)==0) {
+                                       stopConstraint(t);
+                                       t->redraw |= TREDRAW_HARD;
+                               }
+                               break;
+                       case TFM_MODAL_ADD_SNAP:
+                               addSnapPoint(t);
+                               t->redraw |= TREDRAW_HARD;
                                break;
-                       case TFM_MODAL_SNAP_GEARS_OFF:
-                               t->modifiers &= ~MOD_SNAP_GEARS;
-                               t->redraw = 1;
+                       case TFM_MODAL_REMOVE_SNAP:
+                               removeSnapPoint(t);
+                               t->redraw |= TREDRAW_HARD;
                                break;
-                       case TFM_MODAL_SNAP_GEARS_TOGGLE:
-                               t->modifiers ^= MOD_SNAP_GEARS;
-                               t->redraw = 1;
+                       default:
+                               handled = 0;
                                break;
                }
+
+               // Modal numinput events
+               t->redraw |= handleNumInput(&(t->num), event);
        }
        /* else do non-mapped events */
        else if (event->val==KM_PRESS) {
@@ -653,7 +733,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                case LEFTSHIFTKEY:
                case RIGHTSHIFTKEY:
                        t->modifiers |= MOD_CONSTRAINT_PLANE;
-                       t->redraw = 1;
+                       t->redraw |= TREDRAW_HARD;
                        break;
 
                case SPACEKEY:
@@ -701,7 +781,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                                postSelectConstraint(t);
                                        }
                                }
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case ESCKEY:
@@ -718,7 +798,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                restoreTransObjects(t);
                                initTranslation(t);
                                initSnapping(t, NULL); // need to reinit after mode change
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case SKEY:
@@ -728,7 +808,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                restoreTransObjects(t);
                                initResize(t);
                                initSnapping(t, NULL); // need to reinit after mode change
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case RKEY:
@@ -746,7 +826,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                        initRotation(t);
                                }
                                initSnapping(t, NULL); // need to reinit after mode change
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case CKEY:
@@ -758,103 +838,93 @@ void transformEvent(TransInfo *t, wmEvent *event)
                        }
                        else {
                                stopConstraint(t);
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case XKEY:
                        if ((t->flag & T_NO_CONSTRAINT)==0) {
-                               if (cmode == 'X') {
-                                       if (t->flag & T_2D_EDIT) {
+                               if (t->flag & T_2D_EDIT) {
+                                       if (cmode == 'X') {
                                                stopConstraint(t);
+                                       } else {
+                                               setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), "along X");
                                        }
-                                       else {
-                                               if (t->con.mode & CON_USER) {
+                               } else {
+                                       if (cmode == 'X') {
+                                               if (t->con.orientation != V3D_MANIP_GLOBAL) {
                                                        stopConstraint(t);
-                                               }
-                                               else {
+                                               } else {
                                                        short orientation = t->current_orientation != V3D_MANIP_GLOBAL ? t->current_orientation : V3D_MANIP_LOCAL;
                                                        if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                                setUserConstraint(t, orientation, (CON_AXIS0), "along %s X");
                                                        else if (t->modifiers & MOD_CONSTRAINT_PLANE)
                                                                setUserConstraint(t, orientation, (CON_AXIS1|CON_AXIS2), "locking %s X");
                                                }
-                                       }
-                               }
-                               else {
-                                       if (t->flag & T_2D_EDIT) {
-                                               setConstraint(t, mati, (CON_AXIS0), "along X axis");
-                                       }
-                                       else {
+                                       } else {
                                                if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
-                                                       setConstraint(t, mati, (CON_AXIS0), "along global X");
+                                                       setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), "along %s X");
                                                else if (t->modifiers & MOD_CONSTRAINT_PLANE)
-                                                       setConstraint(t, mati, (CON_AXIS1|CON_AXIS2), "locking global X");
+                                                       setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1|CON_AXIS2), "locking %s X");
                                        }
                                }
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case YKEY:
                        if ((t->flag & T_NO_CONSTRAINT)==0) {
-                               if (cmode == 'Y') {
-                                       if (t->flag & T_2D_EDIT) {
+                               if (t->flag & T_2D_EDIT) {
+                                       if (cmode == 'Y') {
                                                stopConstraint(t);
+                                       } else {
+                                               setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), "along Y");
                                        }
-                                       else {
-                                               if (t->con.mode & CON_USER) {
+                               } else {
+                                       if (cmode == 'Y') {
+                                               if (t->con.orientation != V3D_MANIP_GLOBAL) {
                                                        stopConstraint(t);
-                                               }
-                                               else {
+                                               } else {
                                                        short orientation = t->current_orientation != V3D_MANIP_GLOBAL ? t->current_orientation : V3D_MANIP_LOCAL;
                                                        if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                                setUserConstraint(t, orientation, (CON_AXIS1), "along %s Y");
                                                        else if (t->modifiers & MOD_CONSTRAINT_PLANE)
                                                                setUserConstraint(t, orientation, (CON_AXIS0|CON_AXIS2), "locking %s Y");
                                                }
-                                       }
-                               }
-                               else {
-                                       if (t->flag & T_2D_EDIT) {
-                                               setConstraint(t, mati, (CON_AXIS1), "along Y axis");
-                                       }
-                                       else {
+                                       } else {
                                                if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
-                                                       setConstraint(t, mati, (CON_AXIS1), "along global Y");
+                                                       setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), "along %s Y");
                                                else if (t->modifiers & MOD_CONSTRAINT_PLANE)
-                                                       setConstraint(t, mati, (CON_AXIS0|CON_AXIS2), "locking global Y");
+                                                       setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0|CON_AXIS2), "locking %s Y");
                                        }
                                }
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case ZKEY:
-                       if ((t->flag & T_NO_CONSTRAINT)==0) {
+                       if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))==0) {
                                if (cmode == 'Z') {
-                                       if (t->con.mode & CON_USER) {
+                                       if (t->con.orientation != V3D_MANIP_GLOBAL) {
                                                stopConstraint(t);
-                                       }
-                                       else {
+                                       } else {
                                                short orientation = t->current_orientation != V3D_MANIP_GLOBAL ? t->current_orientation : V3D_MANIP_LOCAL;
                                                if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
                                                        setUserConstraint(t, orientation, (CON_AXIS2), "along %s Z");
-                                               else if ((t->modifiers & MOD_CONSTRAINT_PLANE) && ((t->flag & T_2D_EDIT)==0))
+                                               else if (t->modifiers & MOD_CONSTRAINT_PLANE)
                                                        setUserConstraint(t, orientation, (CON_AXIS0|CON_AXIS1), "locking %s Z");
                                        }
-                               }
-                               else if ((t->flag & T_2D_EDIT)==0) {
+                               } else {
                                        if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
-                                               setConstraint(t, mati, (CON_AXIS2), "along global Z");
+                                               setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS2), "along %s Z");
                                        else if (t->modifiers & MOD_CONSTRAINT_PLANE)
-                                               setConstraint(t, mati, (CON_AXIS0|CON_AXIS1), "locking global Z");
+                                               setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0|CON_AXIS1), "locking %s Z");
                                }
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case OKEY:
                        if (t->flag & T_PROP_EDIT && event->shift) {
                                t->prop_mode = (t->prop_mode + 1) % 6;
                                calculatePropRatio(t);
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case PADPLUSKEY:
@@ -898,6 +968,9 @@ void transformEvent(TransInfo *t, wmEvent *event)
 //             case NDOFMOTION:
 //            viewmoveNDOF(1);
   //         break;
+               default:
+                       handled = 0;
+                       break;
                }
 
                // Numerical input events
@@ -922,7 +995,7 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                else
                                {
                                        /* Otherwise, just redraw, NDof input was cancelled */
-                                       t->redraw = 1;
+                                       t->redraw |= TREDRAW_HARD;
                                }
                                break;
                        case NDOF_NOMOVE:
@@ -933,9 +1006,11 @@ void transformEvent(TransInfo *t, wmEvent *event)
                                }
                                break;
                        case NDOF_REFRESH:
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
+                               break;
+                       default:
+                               handled = 0;
                                break;
-
                }
 
                // Snapping events
@@ -948,14 +1023,14 @@ void transformEvent(TransInfo *t, wmEvent *event)
                case LEFTSHIFTKEY:
                case RIGHTSHIFTKEY:
                        t->modifiers &= ~MOD_CONSTRAINT_PLANE;
-                       t->redraw = 1;
+                       t->redraw |= TREDRAW_HARD;
                        break;
 
                case MIDDLEMOUSE:
                        if ((t->flag & T_NO_CONSTRAINT)==0) {
                                t->modifiers &= ~MOD_CONSTRAINT_SELECT;
                                postSelectConstraint(t);
-                               t->redraw = 1;
+                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
 //             case LEFTMOUSE:
@@ -964,6 +1039,9 @@ void transformEvent(TransInfo *t, wmEvent *event)
 ////                   if (t->options & CTX_TWEAK)
 //                             t->state = TRANS_CONFIRM;
 //                     break;
+               default:
+                       handled = 0;
+                       break;
                }
 
                /* confirm transform if launch key is released after mouse move */
@@ -977,9 +1055,14 @@ void transformEvent(TransInfo *t, wmEvent *event)
        // Per transform event, if present
        if (t->handleEvent)
                t->redraw |= t->handleEvent(t, event);
+
+       if (handled || t->redraw)
+               return 0;
+       else
+               return OPERATOR_PASS_THROUGH;
 }
 
-int calculateTransformCenter(bContext *C, wmEvent *event, int centerMode, float *vec)
+int calculateTransformCenter(bContext *C, int centerMode, float *vec)
 {
        TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
        int success = 1;
@@ -990,9 +1073,9 @@ int calculateTransformCenter(bContext *C, wmEvent *event, int centerMode, float
 
        t->mode = TFM_DUMMY;
 
-       initTransInfo(C, t, NULL, event);                                       // internal data, mouse, vectors
+       initTransInfo(C, t, NULL, NULL);        // internal data, mouse, vectors
 
-       createTransData(C, t);                  // make TransData structs from selection
+       createTransData(C, t);                          // make TransData structs from selection
 
        t->around = centerMode;                         // override userdefined mode
 
@@ -1010,9 +1093,9 @@ int calculateTransformCenter(bContext *C, wmEvent *event, int centerMode, float
 
 
        /* aftertrans does insert ipos and action channels, and clears base flags, doesnt read transdata */
-       special_aftertrans_update(t);
+       special_aftertrans_update(C, t);
 
-       postTrans(t);
+       postTrans(C, t);
 
        MEM_freeN(t);
 
@@ -1103,11 +1186,14 @@ static void drawArc(float size, float angle_start, float angle_end, int segments
        glEnd();
 }
 
-void drawHelpline(const struct bContext *C, TransInfo *t)
+static void drawHelpline(bContext *C, int x, int y, void *customdata)
 {
+       TransInfo *t = (TransInfo*)customdata;
+
        if (t->helpline != HLP_NONE && !(t->flag & T_USES_MANIPULATOR))
        {
                float vecrot[3], cent[2];
+               int mval[2] = {x, y};
 
                VECCOPY(vecrot, t->center);
                if(t->flag & T_EDIT) {
@@ -1134,7 +1220,7 @@ void drawHelpline(const struct bContext *C, TransInfo *t)
                                glVertex2fv(cent);
                                glEnd();
 
-                               glTranslatef(t->mval[0], t->mval[1], 0);
+                               glTranslatef(mval[0], mval[1], 0);
                                glRotatef(-180 / M_PI * atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1]), 0, 0, 1);
 
                                setlinestyle(0);
@@ -1146,7 +1232,7 @@ void drawHelpline(const struct bContext *C, TransInfo *t)
                        case HLP_HARROW:
                                UI_ThemeColor(TH_WIRE);
 
-                               glTranslatef(t->mval[0], t->mval[1], 0);
+                               glTranslatef(mval[0], mval[1], 0);
 
                                glLineWidth(3.0);
                                drawArrow(RIGHT, 5, 10, 5);
@@ -1156,7 +1242,7 @@ void drawHelpline(const struct bContext *C, TransInfo *t)
                        case HLP_VARROW:
                                UI_ThemeColor(TH_WIRE);
 
-                               glTranslatef(t->mval[0], t->mval[1], 0);
+                               glTranslatef(mval[0], mval[1], 0);
 
                                glLineWidth(3.0);
                                glBegin(GL_LINES);
@@ -1179,7 +1265,7 @@ void drawHelpline(const struct bContext *C, TransInfo *t)
                                        glVertex2fv(cent);
                                        glEnd();
 
-                                       glTranslatef(cent[0], cent[1], 0);
+                                       glTranslatef(cent[0] - t->mval[0] + mval[0], cent[1] - t->mval[1] + mval[1], 0);
 
                                        setlinestyle(0);
                                        glLineWidth(3.0);
@@ -1208,7 +1294,7 @@ void drawHelpline(const struct bContext *C, TransInfo *t)
                                        char col[3], col2[3];
                                        UI_GetThemeColor3ubv(TH_GRID, col);
 
-                                       glTranslatef(t->mval[0], t->mval[1], 0);
+                                       glTranslatef(mval[0], mval[1], 0);
 
                                        glLineWidth(3.0);
 
@@ -1243,9 +1329,9 @@ void drawTransformView(const struct bContext *C, struct ARegion *ar, void *arg)
 
 void drawTransformPixel(const struct bContext *C, struct ARegion *ar, void *arg)
 {
-       TransInfo *t = arg;
-
-       drawHelpline(C, t);
+//     TransInfo *t = arg;
+//
+//     drawHelpline(C, t->mval[0], t->mval[1], t);
 }
 
 void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
@@ -1280,28 +1366,30 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
        }
 
        // If modal, save settings back in scene if not set as operator argument
-       if (t->flag & T_MODAL)
-       {
+       if (t->flag & T_MODAL) {
+
                /* save settings if not set in operator */
-               if (RNA_struct_find_property(op->ptr, "proportional") && !RNA_property_is_set(op->ptr, "proportional"))
-               {
+               if (RNA_struct_find_property(op->ptr, "proportional") && !RNA_property_is_set(op->ptr, "proportional")) {
                        ts->proportional = proportional;
                }
 
-               if (RNA_struct_find_property(op->ptr, "proportional_size") && !RNA_property_is_set(op->ptr, "proportional_size"))
-               {
+               if (RNA_struct_find_property(op->ptr, "proportional_size") && !RNA_property_is_set(op->ptr, "proportional_size")) {
                        ts->proportional_size = t->prop_size;
                }
                        
-               if (RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && !RNA_property_is_set(op->ptr, "proportional_editing_falloff"))
-               {
+               if (RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && !RNA_property_is_set(op->ptr, "proportional_editing_falloff")) {
                        ts->prop_mode = t->prop_mode;
                }
                
-               if(t->spacetype == SPACE_VIEW3D)
-               {
-                       if (RNA_struct_find_property(op->ptr, "constraint_orientation") && !RNA_property_is_set(op->ptr, "constraint_orientation"))
-                       {
+               /* do we check for parameter? */
+               if (t->modifiers & MOD_SNAP) {
+                       ts->snap_flag |= SCE_SNAP;
+               } else {
+                       ts->snap_flag &= ~SCE_SNAP;
+               }
+
+               if(t->spacetype == SPACE_VIEW3D) {
+                       if (RNA_struct_find_property(op->ptr, "constraint_orientation") && !RNA_property_is_set(op->ptr, "constraint_orientation")) {
                                View3D *v3d = t->view;
        
                                v3d->twmode = t->current_orientation;
@@ -1316,6 +1404,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
                RNA_float_set(op->ptr, "proportional_size", t->prop_size);
        }
 
+       if (RNA_struct_find_property(op->ptr, "axis"))
+       {
+               RNA_float_set_array(op->ptr, "axis", t->axis);
+       }
+
        if (RNA_struct_find_property(op->ptr, "mirror"))
        {
                RNA_boolean_set(op->ptr, "mirror", t->flag & T_MIRROR);
@@ -1323,7 +1416,14 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
 
        if (RNA_struct_find_property(op->ptr, "constraint_axis"))
        {
-               RNA_enum_set(op->ptr, "constraint_orientation", t->current_orientation);
+               /* constraint orientation can be global, event if user selects something else
+                * so use the orientation in the constraint if set
+                * */
+               if (t->con.mode & CON_APPLY) {
+                       RNA_enum_set(op->ptr, "constraint_orientation", t->con.orientation);
+               } else {
+                       RNA_enum_set(op->ptr, "constraint_orientation", t->current_orientation);
+               }
 
                if (t->con.mode & CON_APPLY)
                {
@@ -1366,13 +1466,15 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
                //calc_manipulator_stats(curarea);
                initTransformOrientation(C, t);
 
+               t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
                t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
-               t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
+               //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
+               t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), NULL, drawHelpline, t);
        }
        else if(t->spacetype == SPACE_IMAGE) {
                unit_m3(t->spacemtx);
                t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
-               t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
+               //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
        }
        else
                unit_m3(t->spacemtx);
@@ -1380,7 +1482,7 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
        createTransData(C, t);                  // make TransData structs from selection
 
        if (t->total == 0) {
-               postTrans(t);
+               postTrans(C, t);
                return 0;
        }
 
@@ -1486,6 +1588,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
        case TFM_ALIGN:
                initAlign(t);
                break;
+       case TFM_SEQ_SLIDE:
+               initSeqSlide(t);
+               break;
        }
 
        /* overwrite initial values if operator supplied a non-null vector */
@@ -1498,6 +1603,13 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
                t->flag |= T_AUTOVALUES;
        }
 
+       /* Transformation axis from operator */
+       if (RNA_struct_find_property(op->ptr, "axis") && RNA_property_is_set(op->ptr, "axis"))
+       {
+               RNA_float_get_array(op->ptr, "axis", t->axis);
+               normalize_v3(t->axis);
+       }
+
        /* Constraint init from operator */
        if (RNA_struct_find_property(op->ptr, "constraint_axis") && RNA_property_is_set(op->ptr, "constraint_axis"))
        {
@@ -1526,19 +1638,18 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
        return 1;
 }
 
-void transformApply(bContext *C, TransInfo *t)
+void transformApply(const bContext *C, TransInfo *t)
 {
-       if (t->redraw)
+       if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT)))
        {
-               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;
+               t->redraw = TREDRAW_NOTHING;
+       } else if (t->redraw & TREDRAW_SOFT) {
+               viewRedrawForce(C, t);
        }
 
        /* If auto confirm is on, break after one pass */
@@ -1551,7 +1662,17 @@ void transformApply(bContext *C, TransInfo *t)
        {
                // TRANSFORM_FIX_ME
                //do_screenhandlers(G.curscreen);
-               t->redraw = 1;
+               t->redraw |= TREDRAW_HARD;
+       }
+}
+
+void drawTransformApply(const struct bContext *C, struct ARegion *ar, void *arg)
+{
+       TransInfo *t = arg;
+
+       if (t->redraw & TREDRAW_SOFT) {
+               t->redraw |= TREDRAW_HARD;
+               transformApply(C, t);
        }
 }
 
@@ -1573,10 +1694,10 @@ int transformEnd(bContext *C, TransInfo *t)
                }
 
                /* aftertrans does insert keyframes, and clears base flags, doesnt read transdata */
-               special_aftertrans_update(t);
+               special_aftertrans_update(C, t);
 
                /* free data */
-               postTrans(t);
+               postTrans(C, t);
 
                /* send events out for redraws */
                viewRedrawPost(t);
@@ -1960,6 +2081,8 @@ void initWarp(TransInfo *t)
        t->snap[1] = 5.0f;
        t->snap[2] = 1.0f;
        
+       t->num.increment = 1.0f;
+
        t->flag |= T_NO_CONSTRAINT;
        
        /* we need min/max in view space */
@@ -2116,6 +2239,8 @@ void initShear(TransInfo *t)
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
        
+       t->num.increment = 0.1f;
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -2242,6 +2367,8 @@ void initResize(TransInfo *t)
        t->snap[0] = 0.0f;
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
+
+       t->num.increment = t->snap[1];
 }
 
 static void headerResize(TransInfo *t, float vec[3], char *str) {
@@ -2493,6 +2620,8 @@ void initToSphere(TransInfo *t)
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
        
+       t->num.increment = t->snap[1];
+
        t->num.flag |= NUM_NULL_ONE | NUM_NO_NEGATIVE;
        t->flag |= T_NO_CONSTRAINT;
        
@@ -2584,8 +2713,13 @@ void initRotation(TransInfo *t)
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
        
+       t->num.increment = 1.0f;
+
        if (t->flag & T_2D_EDIT)
                t->flag |= T_NO_CONSTRAINT;
+
+       negate_v3_v3(t->axis, t->viewinv[2]);
+       normalize_v3(t->axis);
 }
 
 static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short around) {
@@ -2830,21 +2964,20 @@ int Rotation(TransInfo *t, short mval[2])
        
        float final;
        
-       float axis[3];
        float mat[3][3];
        
-       VECCOPY(axis, t->viewinv[2]);
-       mul_v3_fl(axis, -1.0f);
-       normalize_v3(axis);
-       
        final = t->values[0];
        
        applyNDofInput(&t->ndof, &final);
        
        snapGrid(t, &final);
        
-       if (t->con.applyRot) {
-               t->con.applyRot(t, NULL, axis, &final);
+       if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+               t->con.applyRot(t, NULL, t->axis, &final);
+       } else {
+               /* reset axis if constraint is not set */
+               negate_v3_v3(t->axis, t->viewinv[2]);
+               normalize_v3(t->axis);
        }
        
        applySnapping(t, &final);
@@ -2871,13 +3004,16 @@ int Rotation(TransInfo *t, short mval[2])
                sprintf(str, "Rot: %.2f%s %s", 180.0*final/M_PI, t->con.text, t->proptext);
        }
        
-       vec_rot_to_mat3( mat,axis, final);
+       // fixes [#21433] but breaks, typical local axis rotation - campbell
+       // t->values[0] = final;
+
+       vec_rot_to_mat3( mat, t->axis, final);
        
        // TRANSFORM_FIX_ME
 //     t->values[0] = final;           // used in manipulator
 //     copy_m3_m3(t->mat, mat);        // used in manipulator
        
-       applyRotation(t, final, axis);
+       applyRotation(t, final, t->axis);
        
        recalcData(t);
        
@@ -2907,6 +3043,8 @@ void initTrackball(TransInfo *t)
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
 
+       t->num.increment = 1.0f;
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -3007,11 +3145,13 @@ void initTranslation(TransInfo *t)
        t->ndof.axis = (t->flag & T_2D_EDIT)? 1|2: 1|2|4;
 
        if(t->spacetype == SPACE_VIEW3D) {
-               View3D *v3d = t->view;
+               RegionView3D *rv3d = t->ar->regiondata;
 
-               t->snap[0] = 0.0f;
-               t->snap[1] = v3d->gridview * 1.0f;
-               t->snap[2] = t->snap[1] * 0.1f;
+               if (rv3d) {
+                       t->snap[0] = 0.0f;
+                       t->snap[1] = rv3d->gridview * 1.0f;
+                       t->snap[2] = t->snap[1] * 0.1f;
+               }
        }
        else if(t->spacetype == SPACE_IMAGE) {
                t->snap[0] = 0.0f;
@@ -3022,6 +3162,8 @@ void initTranslation(TransInfo *t)
                t->snap[0] = 0.0f;
                t->snap[1] = t->snap[2] = 1.0f;
        }
+
+       t->num.increment = t->snap[1];
 }
 
 static void headerTranslation(TransInfo *t, float vec[3], char *str) {
@@ -3156,11 +3298,11 @@ static void applyTranslation(TransInfo *t, float vec[3]) {
 /* uses t->vec to store actual translation in */
 int Translation(TransInfo *t, short mval[2])
 {
-       float tvec[3];
        char str[250];
 
        if (t->con.mode & CON_APPLY) {
                float pvec[3] = {0.0f, 0.0f, 0.0f};
+               float tvec[3];
                applySnapping(t, t->values);
                t->con.applyVec(t, NULL, t->values, tvec, pvec);
                VECCOPY(t->values, tvec);
@@ -3212,6 +3354,8 @@ void initShrinkFatten(TransInfo *t)
                t->snap[1] = 1.0f;
                t->snap[2] = t->snap[1] * 0.1f;
 
+               t->num.increment = t->snap[1];
+
                t->flag |= T_NO_CONSTRAINT;
        }
 }
@@ -3286,6 +3430,8 @@ void initTilt(TransInfo *t)
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
 
+       t->num.increment = t->snap[1];
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -3355,6 +3501,11 @@ void initCurveShrinkFatten(TransInfo *t)
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
 
+       t->num.increment = t->snap[1];
+
+       t->flag |= T_NO_ZERO;
+       t->num.flag |= NUM_NO_ZERO;
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -3392,7 +3543,7 @@ int CurveShrinkFatten(TransInfo *t, short mval[2])
                if(td->val) {
                        //*td->val= ratio;
                        *td->val= td->ival*ratio;
-                       if (*td->val <= 0.0f) *td->val = 0.0001f;
+                       if (*td->val <= 0.0f) *td->val = 0.001f;
                }
        }
 
@@ -3421,6 +3572,8 @@ void initPushPull(TransInfo *t)
        t->snap[0] = 0.0f;
        t->snap[1] = 1.0f;
        t->snap[2] = t->snap[1] * 0.1f;
+
+       t->num.increment = t->snap[1];
 }
 
 
@@ -3509,6 +3662,8 @@ void initBevel(TransInfo *t)
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
 
+       t->num.increment = t->snap[1];
+
        /* DON'T KNOW WHY THIS IS NEEDED */
        if (G.editBMesh->imval[0] == 0 && G.editBMesh->imval[1] == 0) {
                /* save the initial mouse co */
@@ -3618,6 +3773,8 @@ void initBevelWeight(TransInfo *t)
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
 
+       t->num.increment = t->snap[1];
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -3689,6 +3846,8 @@ void initCrease(TransInfo *t)
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
 
+       t->num.increment = t->snap[1];
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -3763,6 +3922,8 @@ void initBoneSize(TransInfo *t)
        t->snap[0] = 0.0f;
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
+
+       t->num.increment = t->snap[1];
 }
 
 static void headerBoneSize(TransInfo *t, float vec[3], char *str) {
@@ -3879,6 +4040,8 @@ void initBoneEnvelope(TransInfo *t)
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
        
+       t->num.increment = t->snap[1];
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -4456,6 +4619,8 @@ void initEdgeSlide(TransInfo *t)
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
 
+       t->num.increment = t->snap[1];
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -4624,6 +4789,8 @@ void initBoneRoll(TransInfo *t)
        t->snap[1] = (float)((5.0/180)*M_PI);
        t->snap[2] = t->snap[1] * 0.2f;
 
+       t->num.increment = 1.0f;
+
        t->flag |= T_NO_CONSTRAINT;
 }
 
@@ -4684,6 +4851,8 @@ void initBakeTime(TransInfo *t)
        t->snap[0] = 0.0f;
        t->snap[1] = 1.0f;
        t->snap[2] = t->snap[1] * 0.1f;
+
+       t->num.increment = t->snap[1];
 }
 
 int BakeTime(TransInfo *t, short mval[2])
@@ -4884,6 +5053,92 @@ int Align(TransInfo *t, short mval[2])
        return 1;
 }
 
+/* ************************** SEQ SLIDE *************************** */
+
+void initSeqSlide(TransInfo *t)
+{
+       t->transform = SeqSlide;
+
+       initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
+
+       t->idx_max = 1;
+       t->num.flag = 0;
+       t->num.idx_max = t->idx_max;
+
+       t->ndof.axis = 1|2;
+
+       t->snap[0] = 0.0f;
+       t->snap[1] = floor(t->scene->r.frs_sec / t->scene->r.frs_sec_base);
+       t->snap[2] = 10.0f;
+
+       t->num.increment = t->snap[1];
+}
+
+static void headerSeqSlide(TransInfo *t, float val[2], char *str)
+{
+       char tvec[60];
+
+       if (hasNumInput(&t->num)) {
+               outputNumInput(&(t->num), tvec);
+       }
+       else {
+               sprintf(&tvec[0], "%.0f, %.0f", val[0], val[1]);
+       }
+
+       sprintf(str, "Sequence Slide: %s%s", &tvec[0], t->con.text);
+}
+
+static void applySeqSlide(TransInfo *t, float val[2]) {
+       TransData *td = t->data;
+       int i;
+
+       for(i = 0 ; i < t->total; i++, td++) {
+               float tvec[2];
+
+               if (td->flag & TD_NOACTION)
+                       break;
+
+               if (td->flag & TD_SKIP)
+                       continue;
+
+               copy_v2_v2(tvec, val);
+
+               mul_v2_fl(tvec, td->factor);
+
+               td->loc[0] = td->iloc[0] + tvec[0];
+               td->loc[1] = td->iloc[1] + tvec[1];
+       }
+}
+
+int SeqSlide(TransInfo *t, short mval[2])
+{
+       char str[200];
+
+       if (t->con.mode & CON_APPLY) {
+               float pvec[3] = {0.0f, 0.0f, 0.0f};
+               float tvec[3];
+               t->con.applyVec(t, NULL, t->values, tvec, pvec);
+               VECCOPY(t->values, tvec);
+       }
+       else {
+               applyNDofInput(&t->ndof, t->values);
+               snapGrid(t, t->values);
+               applyNumInput(&t->num, t->values);
+       }
+
+       t->values[0] = floor(t->values[0] + 0.5);
+       t->values[1] = floor(t->values[1] + 0.5);
+
+       headerSeqSlide(t, t->values, str);
+       applySeqSlide(t, t->values);
+
+       recalcData(t);
+
+       ED_area_headerprint(t->sa, str);
+
+       return 1;
+}
+
 /* ************************** ANIM EDITORS - TRANSFORM TOOLS *************************** */
 
 /* ---------------- Special Helpers for Various Settings ------------- */
@@ -4896,37 +5151,37 @@ int Align(TransInfo *t, short mval[2])
 static short getAnimEdit_SnapMode(TransInfo *t)
 {
        short autosnap= SACTSNAP_OFF;
-
-       /* currently, some of these are only for the action editor */
+       
        if (t->spacetype == SPACE_ACTION) {
                SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
-
+               
                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)
                        autosnap= snla->autosnap;
        }
        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;
+       }
+       
+       /* toggle autosnap on/off 
+        *      - when toggling on, prefer nearest frame over 1.0 frame increments
+        */
+       if (t->modifiers & MOD_SNAP_INVERT) {
+               if (autosnap)
                        autosnap= SACTSNAP_OFF;
+               else
+                       autosnap= SACTSNAP_FRAME;
        }
 
        return autosnap;
@@ -4940,17 +5195,21 @@ static short getAnimEdit_DrawTime(TransInfo *t)
 {
        short drawtime;
 
-       /* currently, some of these are only for the action editor */
        if (t->spacetype == SPACE_ACTION) {
                SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
-
+               
                drawtime = (saction->flag & SACTION_DRAWTIME)? 1 : 0;
        }
        else if (t->spacetype == SPACE_NLA) {
                SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first;
-
+               
                drawtime = (snla->flag & SNLA_DRAWTIME)? 1 : 0;
        }
+       else if (t->spacetype == SPACE_IPO) {
+               SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+               
+               drawtime = (sipo->flag & SIPO_DRAWTIME)? 1 : 0;
+       }       
        else {
                drawtime = 0;
        }
@@ -5028,6 +5287,8 @@ void initTimeTranslate(TransInfo *t)
        /* initialise snap like for everything else */
        t->snap[0] = 0.0f;
        t->snap[1] = t->snap[2] = 1.0f;
+
+       t->num.increment = t->snap[1];
 }
 
 static void headerTimeTranslate(TransInfo *t, char *str)
@@ -5044,7 +5305,7 @@ static void headerTimeTranslate(TransInfo *t, char *str)
                const short doTime = getAnimEdit_DrawTime(t);
                const double secf= FPS;
                float val = t->values[0];
-
+               
                /* apply snapping + frame->seconds conversions */
                if (autosnap == SACTSNAP_STEP) {
                        if (doTime)
@@ -5056,8 +5317,11 @@ static void headerTimeTranslate(TransInfo *t, char *str)
                        if (doTime)
                                val= val / secf;
                }
-
-               sprintf(&tvec[0], "%.4f", val);
+               
+               if (autosnap == SACTSNAP_FRAME)
+                       sprintf(&tvec[0], "%d.00 (%.4f)", (int)val, val);
+               else
+                       sprintf(&tvec[0], "%.4f", val);
        }
 
        sprintf(str, "DeltaX: %s", &tvec[0]);
@@ -5085,7 +5349,7 @@ static void applyTimeTranslate(TransInfo *t, float sval)
                AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL;
 
                /* check if any need to apply nla-mapping */
-               if (adt) {
+               if (adt && t->spacetype != SPACE_SEQ) {
                        deltax = t->values[0];
 
                        if (autosnap == SACTSNAP_STEP) {
@@ -5171,6 +5435,8 @@ void initTimeSlide(TransInfo *t)
        /* initialise snap like for everything else */
        t->snap[0] = 0.0f;
        t->snap[1] = t->snap[2] = 1.0f;
+
+       t->num.increment = t->snap[1];
 }
 
 static void headerTimeSlide(TransInfo *t, float sval, char *str)
@@ -5276,11 +5542,21 @@ int TimeSlide(TransInfo *t, short mval[2])
 
 void initTimeScale(TransInfo *t)
 {
+       int center[2];
+
        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 */
+       /* recalculate center2d to use CFRA and mouse Y, since that's
+        * what is used in time scale */
+       t->center[0] = t->scene->r.cfra;
+       projectIntView(t, t->center, center);
+       center[1] = t->imval[1];
+
+       /* force a reinit with the center2d used here */
+       initMouseInput(t, &t->mouse, center, t->imval);
+
+       initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
 
        t->flag |= T_NULL_ONE;
        t->num.flag |= NUM_NULL_ONE;
@@ -5293,6 +5569,8 @@ void initTimeScale(TransInfo *t)
        /* initialise snap like for everything else */
        t->snap[0] = 0.0f;
        t->snap[1] = t->snap[2] = 1.0f;
+
+       t->num.increment = t->snap[1];
 }
 
 static void headerTimeScale(TransInfo *t, char *str) {
@@ -5348,19 +5626,8 @@ static void applyTimeScale(TransInfo *t) {
 
 int TimeScale(TransInfo *t, short mval[2])
 {
-       float cval, sval;
-       float deltax, startx;
-       float width= 0.0f;
        char str[200];
-
-       sval= t->imval[0];
-       cval= mval[0];
-
-       /* calculate scaling factor */
-       startx= sval-(width/2+(t->ar->winx)/2);
-       deltax= cval-(width/2+(t->ar->winx)/2);
-       t->values[0] = deltax / startx;
-
+       
        /* handle numeric-input stuff */
        t->vec[0] = t->values[0];
        applyNumInput(&t->num, &t->vec[0]);