=bmesh= merge from trunk at r36529
[blender.git] / source / blender / editors / transform / transform.c
index 86fdb81e0d9c6d981aefea4d837cba34624955fe..fd2bb59294bb81840a010272d33f391c0b756d3b 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/transform/transform.c
+ *  \ingroup edtransform
+ */
+
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 #include "RNA_access.h"
 
-//#include "BIF_editview.h"            /* arrows_move_cursor   */
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
-//#include "BIF_mywindow.h"
-//#include "BIF_resources.h"
-//#include "BIF_screen.h"
-//#include "BIF_space.h"                       /* undo                                 */
-//#include "BIF_toets.h"                       /* persptoetsen                 */
-//#include "BIF_mywindow.h"            /* warp_pointer                 */
-//#include "BIF_toolbox.h"                     /* notice                               */
-//#include "BIF_editmesh.h"
-//#include "BIF_editsima.h"
-//#include "BIF_editparticle.h"
-
-#include "BKE_action.h"
+
 #include "BKE_nla.h"
-//#include "BKE_bad_level_calls.h"/* popmenu and error */
 #include "BKE_bmesh.h"
 #include "BKE_context.h"
 #include "BKE_constraint.h"
 #include "BKE_global.h"
 #include "BKE_particle.h"
 #include "BKE_pointcache.h"
-#include "BKE_utildefines.h"
-#include "BKE_context.h"
 #include "BKE_unit.h"
 
-//#include "BSE_view.h"
-
 #include "ED_image.h"
 #include "ED_keyframing.h"
 #include "ED_screen.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
 #include "BLI_editVert.h"
 #include "BLI_ghash.h"
 #include "BLI_linklist.h"
-
+#include "BLI_smallhash.h"
+#include "BLI_array.h"
 
 #include "UI_resources.h"
 
 
 #include "transform.h"
 
+#include <stdio.h>
+
 void drawTransformApply(const struct bContext *C, struct ARegion *ar, void *arg);
+int doEdgeSlide(TransInfo *t, float perc);
 
 /* ************************** SPACE DEPENDANT CODE **************************** */
 
@@ -203,15 +196,18 @@ 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(t->spacetype == SPACE_ACTION) {
-               SpaceAction *sact = t->sa->spacedata.first;
                int out[2] = {0, 0};
+#if 0
+               SpaceAction *sact = t->sa->spacedata.first;
 
                if (sact->flag & SACTION_DRAWTIME) {
                        //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base));
-
+                       /* same as below */
                        UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], out, out+1);
                } 
-               else {
+               else
+#endif
+               {
                        UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], out, out+1);
                }
 
@@ -301,7 +297,10 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
        if (t->spacetype == SPACE_VIEW3D)
        {
                /* Do we need more refined tags? */
-               WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+               if(t->flag & T_POSE)
+                       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
+               else
+                       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?
@@ -337,7 +336,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
        }
 }
 
-static void viewRedrawPost(TransInfo *t)
+static void viewRedrawPost(bContext *C, TransInfo *t)
 {
        ED_area_headerprint(t->sa, NULL);
        
@@ -345,6 +344,10 @@ static void viewRedrawPost(TransInfo *t)
                /* if autokeying is enabled, send notifiers that keyframes were added */
                if (IS_AUTOKEY_ON(t->scene))
                        WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+               
+               /* XXX temp, first hack to get auto-render in compositor work (ton) */
+               WM_event_add_notifier(C, NC_SCENE|ND_TRANSFORM_DONE, CTX_data_scene(C));
+
        }
        
 #if 0 // TRANSFORM_FIX_ME
@@ -371,7 +374,7 @@ static void viewRedrawPost(TransInfo *t)
 
 /* ************************** TRANSFORMATIONS **************************** */
 
-void BIF_selectOrientation() {
+void BIF_selectOrientation(void) {
 #if 0 // TRANSFORM_FIX_ME
        short val;
        char *str_menu = BIF_menustringTransformOrientation("Orientation");
@@ -384,7 +387,7 @@ void BIF_selectOrientation() {
 #endif
 }
 
-static void view_editmove(unsigned short event)
+static void view_editmove(unsigned short UNUSED(event))
 {
 #if 0 // TRANSFORM_FIX_ME
        int refresh = 0;
@@ -481,6 +484,8 @@ static void view_editmove(unsigned short event)
  * */
 #define TFM_MODAL_PROPSIZE_UP  20
 #define TFM_MODAL_PROPSIZE_DOWN        21
+#define TFM_MODAL_AUTOIK_LEN_INC 22
+#define TFM_MODAL_AUTOIK_LEN_DEC 23
 
 /* called in transform_ops.c, on each regeneration of keymaps */
 wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf)
@@ -507,6 +512,8 @@ wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf)
        {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""},
        {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""},
        {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Poportional Influence", ""},
+       {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""},
+       {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""},
        {0, NULL, 0, NULL, NULL}};
        
        wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "Transform Modal Map");
@@ -530,25 +537,30 @@ wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf)
 
        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, RIGHTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_SNAP_INV_ON);
+       WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, 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);
-       
        WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP);
        WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN);
        WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP);
        WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN);
-
+       
+       WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_INC);
+       WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC);
+       WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_INC);
+       WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC);
+       
        return keymap;
 }
 
 
 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}};
+       float mati[3][3]= MAT3_UNITY;
        char cmode = constraintModeToChar(t);
        int handled = 1;
 
@@ -562,7 +574,9 @@ int transformEvent(TransInfo *t, wmEvent *event)
                t->mval[0] = event->x - t->ar->winrct.xmin;
                t->mval[1] = event->y - t->ar->winrct.ymin;
 
-               t->redraw |= TREDRAW_SOFT;
+               // t->redraw |= TREDRAW_SOFT; /* Use this for soft redraw. Might cause flicker in object mode */
+               t->redraw |= TREDRAW_HARD;
+
 
                if (t->state == TRANS_STARTING) {
                        t->state = TRANS_RUNNING;
@@ -592,20 +606,22 @@ int transformEvent(TransInfo *t, wmEvent *event)
                                break;
                        case TFM_MODAL_ROTATE:
                                /* only switch when... */
-                               if( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) {
-                                       
-                                       resetTransRestrictions(t);
-                                       
-                                       if (t->mode == TFM_ROTATION) {
-                                               restoreTransObjects(t);
-                                               initTrackball(t);
-                                       }
-                                       else {
-                                               restoreTransObjects(t);
-                                               initRotation(t);
+                               if(!(t->options & CTX_TEXTURE)) {
+                                       if( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) {
+                                               
+                                               resetTransRestrictions(t);
+                                               
+                                               if (t->mode == TFM_ROTATION) {
+                                                       restoreTransObjects(t);
+                                                       initTrackball(t);
+                                               }
+                                               else {
+                                                       restoreTransObjects(t);
+                                                       initRotation(t);
+                                               }
+                                               initSnapping(t, NULL); // need to reinit after mode change
+                                               t->redraw |= TREDRAW_HARD;
                                        }
-                                       initSnapping(t, NULL); // need to reinit after mode change
-                                       t->redraw |= TREDRAW_HARD;
                                }
                                break;
                        case TFM_MODAL_RESIZE:
@@ -724,6 +740,8 @@ int transformEvent(TransInfo *t, wmEvent *event)
                        case TFM_MODAL_PROPSIZE_UP:
                                if(t->flag & T_PROP_EDIT) {
                                        t->prop_size*= 1.1f;
+                                       if(t->spacetype==SPACE_VIEW3D && t->persp != RV3D_ORTHO)
+                                               t->prop_size= MIN2(t->prop_size, ((View3D *)t->view)->far);
                                        calculatePropRatio(t);
                                }
                                t->redraw |= TREDRAW_HARD;
@@ -735,6 +753,16 @@ int transformEvent(TransInfo *t, wmEvent *event)
                                }
                                t->redraw |= TREDRAW_HARD;
                                break;
+                       case TFM_MODAL_AUTOIK_LEN_INC:
+                               if (t->flag & T_AUTOIK)
+                                       transform_autoik_update(t, 1);
+                               t->redraw |= TREDRAW_HARD;
+                               break;
+                       case TFM_MODAL_AUTOIK_LEN_DEC:
+                               if (t->flag & T_AUTOIK) 
+                                       transform_autoik_update(t, -1);
+                               t->redraw |= TREDRAW_HARD;
+                               break;
                        default:
                                handled = 0;
                                break;
@@ -833,20 +861,22 @@ int transformEvent(TransInfo *t, wmEvent *event)
                        break;
                case RKEY:
                        /* only switch when... */
-                       if( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) {
+                       if(!(t->options & CTX_TEXTURE)) {
+                               if( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) {
 
-                               resetTransRestrictions(t);
+                                       resetTransRestrictions(t);
 
-                               if (t->mode == TFM_ROTATION) {
-                                       restoreTransObjects(t);
-                                       initTrackball(t);
-                               }
-                               else {
-                                       restoreTransObjects(t);
-                                       initRotation(t);
+                                       if (t->mode == TFM_ROTATION) {
+                                               restoreTransObjects(t);
+                                               initTrackball(t);
+                                       }
+                                       else {
+                                               restoreTransObjects(t);
+                                               initRotation(t);
+                                       }
+                                       initSnapping(t, NULL); // need to reinit after mode change
+                                       t->redraw |= TREDRAW_HARD;
                                }
-                               initSnapping(t, NULL); // need to reinit after mode change
-                               t->redraw |= TREDRAW_HARD;
                        }
                        break;
                case CKEY:
@@ -950,6 +980,8 @@ int transformEvent(TransInfo *t, wmEvent *event)
                case PADPLUSKEY:
                        if(event->alt && t->flag & T_PROP_EDIT) {
                                t->prop_size *= 1.1f;
+                               if(t->spacetype==SPACE_VIEW3D && t->persp != RV3D_ORTHO)
+                                       t->prop_size= MIN2(t->prop_size, ((View3D *)t->view)->far);
                                calculatePropRatio(t);
                        }
                        t->redraw= 1;
@@ -1028,7 +1060,6 @@ int transformEvent(TransInfo *t, wmEvent *event)
                // Snapping events
                t->redraw |= handleSnapping(t, event);
 
-               //arrows_move_cursor(event->type);
        }
        else if (event->val==KM_RELEASE) {
                switch (event->type){
@@ -1201,14 +1232,26 @@ static void drawArc(float size, float angle_start, float angle_end, int segments
        glEnd();
 }
 
-static void drawHelpline(bContext *C, int x, int y, void *customdata)
+static int helpline_poll(bContext *C)
+{
+       ARegion *ar= CTX_wm_region(C);
+       
+       if(ar && ar->regiontype==RGN_TYPE_WINDOW)
+               return 1;
+       return 0;
+}
+
+static void drawHelpline(bContext *UNUSED(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};
+               int mval[2];
+
+               mval[0]= x;
+               mval[1]= y;
 
                VECCOPY(vecrot, t->center);
                if(t->flag & T_EDIT) {
@@ -1236,7 +1279,7 @@ static void drawHelpline(bContext *C, int x, int y, void *customdata)
                                glEnd();
 
                                glTranslatef(mval[0], mval[1], 0);
-                               glRotatef(-180 / M_PI * atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1]), 0, 0, 1);
+                               glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 0, 0, 1);
 
                                setlinestyle(0);
                                glLineWidth(3.0);
@@ -1270,8 +1313,8 @@ static void drawHelpline(bContext *C, int x, int y, void *customdata)
                                        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);
+                                       float delta_angle = MIN2(15.0f / dist, (float)M_PI/4.0f);
+                                       float spacing_angle = MIN2(5.0f / dist, (float)M_PI/12.0f);
                                        UI_ThemeColor(TH_WIRE);
 
                                        setlinestyle(3);
@@ -1290,14 +1333,14 @@ static void drawHelpline(bContext *C, int x, int y, void *customdata)
                                        glPushMatrix();
 
                                        glTranslatef(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
-                                       glRotatef(180 / M_PI * (angle - delta_angle), 0, 0, 1);
+                                       glRotatef(RAD2DEGF(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);
+                                       glRotatef(RAD2DEGF(angle + delta_angle), 0, 0, 1);
 
                                        drawArrowHead(UP, 5);
 
@@ -1306,20 +1349,20 @@ static void drawHelpline(bContext *C, int x, int y, void *customdata)
                                }
                                case HLP_TRACKBALL:
                                {
-                                       char col[3], col2[3];
+                                       unsigned char col[3], col2[3];
                                        UI_GetThemeColor3ubv(TH_GRID, col);
 
                                        glTranslatef(mval[0], mval[1], 0);
 
                                        glLineWidth(3.0);
 
-                                       UI_make_axis_color(col, col2, 'x');
+                                       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');
+                                       UI_make_axis_color(col, col2, 'Y');
                                        glColor3ubv((GLubyte *)col2);
 
                                        drawArrow(UP, 5, 10, 5);
@@ -1333,21 +1376,23 @@ static void drawHelpline(bContext *C, int x, int y, void *customdata)
        }
 }
 
-void drawTransformView(const struct bContext *C, struct ARegion *ar, void *arg)
+static void drawTransformView(const struct bContext *C, struct ARegion *UNUSED(ar), void *arg)
 {
        TransInfo *t = arg;
 
-       drawConstraint(C, t);
+       drawConstraint(t);
        drawPropCircle(C, t);
        drawSnapping(C, t);
 }
 
-void drawTransformPixel(const struct bContext *C, struct ARegion *ar, void *arg)
+#if 0
+static void drawTransformPixel(const struct bContext *UNUSED(C), struct ARegion *UNUSED(ar), void *UNUSED(arg))
 {
 //     TransInfo *t = arg;
 //
 //     drawHelpline(C, t->mval[0], t->mval[1], t);
 }
+#endif
 
 void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
 {
@@ -1367,17 +1412,17 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
                }
        }
 
-       /* XXX convert stupid flag to enum */
+       /* convert flag to enum */
        switch(t->flag & (T_PROP_EDIT|T_PROP_CONNECTED))
        {
        case (T_PROP_EDIT|T_PROP_CONNECTED):
-               proportional = 2;
+               proportional = PROP_EDIT_CONNECTED;
                break;
        case T_PROP_EDIT:
-               proportional = 1;
+               proportional = PROP_EDIT_ON;
                break;
        default:
-               proportional = 0;
+               proportional = PROP_EDIT_OFF;
        }
 
        // If modal, save settings back in scene if not set as operator argument
@@ -1385,14 +1430,17 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
 
                /* save settings if not set in operator */
                if (RNA_struct_find_property(op->ptr, "proportional") && !RNA_property_is_set(op->ptr, "proportional")) {
-                       ts->proportional = proportional;
+                       if (t->obedit)
+                               ts->proportional = proportional;
+                       else
+                               ts->proportional_objects = (proportional != PROP_EDIT_OFF);
                }
 
                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_edit_falloff") && !RNA_property_is_set(op->ptr, "proportional_edit_falloff")) {
                        ts->prop_mode = t->prop_mode;
                }
                
@@ -1415,7 +1463,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
        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_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
                RNA_float_set(op->ptr, "proportional_size", t->prop_size);
        }
 
@@ -1457,19 +1505,28 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
        }
 }
 
+/* note: caller needs to free 't' on a 0 return */
 int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int mode)
 {
        int options = 0;
 
+       t->context = C;
+
        /* added initialize, for external calls to set stuff in TransInfo, like undo string */
 
        t->state = TRANS_STARTING;
 
+       if(RNA_struct_find_property(op->ptr, "texture_space"))
+               if(RNA_boolean_get(op->ptr, "texture_space"))
+                       options |= CTX_TEXTURE;
+       
        t->options = options;
 
        t->mode = mode;
 
        t->launch_event = event ? event->type : -1;
+       if (RNA_property_is_set(op->ptr, "launch_event"))
+               t->launch_event = RNA_int_get(op->ptr, "launch_event");
 
        if (t->launch_event == EVT_TWEAK_R)
        {
@@ -1500,7 +1557,7 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
                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_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), NULL, drawHelpline, t);
+               t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
        }
        else if(t->spacetype == SPACE_IMAGE) {
                unit_m3(t->spacemtx);
@@ -1530,7 +1587,7 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
                                if ((ELEM(kmi->type, LEFTCTRLKEY, RIGHTCTRLKEY) && event->ctrl) ||
                                        (ELEM(kmi->type, LEFTSHIFTKEY, RIGHTSHIFTKEY) && event->shift) ||
                                        (ELEM(kmi->type, LEFTALTKEY, RIGHTALTKEY) && event->alt) ||
-                                       (kmi->type == COMMANDKEY && event->oskey)) {
+                                       (kmi->type == OSKEY && event->oskey)) {
                                        t->modifiers |= MOD_SNAP_INVERT;
                                }
                                break;
@@ -1615,6 +1672,16 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
        case TFM_TIME_SCALE:
                initTimeScale(t);
                break;
+       case TFM_TIME_DUPLICATE:
+               /* same as TFM_TIME_EXTEND, but we need the mode info for later 
+                * so that duplicate-culling will work properly
+                */
+               if ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)
+                       initTranslation(t);
+               else
+                       initTimeTranslate(t);
+               t->mode = mode;
+               break;
        case TFM_TIME_EXTEND:
                /* 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
@@ -1646,10 +1713,17 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
                break;
        }
 
+       if(t->state == TRANS_CANCEL)
+       {
+               postTrans(C, t);
+               return 0;
+       }
+
+
        /* overwrite initial values if operator supplied a non-null vector */
        if (RNA_property_is_set(op->ptr, "value"))
        {
-               float values[4];
+               float values[4]= {0}; /* incase value isn't length 4, avoid uninitialized memory  */
                RNA_float_get_array(op->ptr, "value", values);
                QUATCOPY(t->values, values);
                QUATCOPY(t->auto_values, values);
@@ -1661,6 +1735,7 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
        {
                RNA_float_get_array(op->ptr, "axis", t->axis);
                normalize_v3(t->axis);
+               copy_v3_v3(t->axis_orig, t->axis);
        }
 
        /* Constraint init from operator */
@@ -1688,11 +1763,15 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
                }
        }
 
+       t->context = NULL;
+
        return 1;
 }
 
-void transformApply(const bContext *C, TransInfo *t)
+void transformApply(bContext *C, TransInfo *t)
 {
+       t->context = C;
+
        if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT)))
        {
                selectConstraint(t);
@@ -1717,15 +1796,17 @@ void transformApply(const bContext *C, TransInfo *t)
                //do_screenhandlers(G.curscreen);
                t->redraw |= TREDRAW_HARD;
        }
+
+       t->context = NULL;
 }
 
-void drawTransformApply(const struct bContext *C, struct ARegion *ar, void *arg)
+void drawTransformApply(const bContext *C, struct ARegion *UNUSED(ar), void *arg)
 {
        TransInfo *t = arg;
 
        if (t->redraw & TREDRAW_SOFT) {
                t->redraw |= TREDRAW_HARD;
-               transformApply(C, t);
+               transformApply((bContext *)C, t);
        }
 }
 
@@ -1733,11 +1814,17 @@ int transformEnd(bContext *C, TransInfo *t)
 {
        int exit_code = OPERATOR_RUNNING_MODAL;
 
+       t->context = C;
+
        if (t->state != TRANS_STARTING && t->state != TRANS_RUNNING)
        {
                /* handle restoring objects */
                if(t->state == TRANS_CANCEL)
                {
+                       /* exception, edge slide transformed UVs too */
+                       if(t->mode==TFM_EDGE_SLIDE)
+                               doEdgeSlide(t, 0.0f);
+                       
                        exit_code = OPERATOR_CANCELLED;
                        restoreTransObjects(t); // calls recalcData()
                }
@@ -1753,7 +1840,7 @@ int transformEnd(bContext *C, TransInfo *t)
                postTrans(C, t);
 
                /* send events out for redraws */
-               viewRedrawPost(t);
+               viewRedrawPost(C, t);
 
                /*  Undo as last, certainly after special_trans_update! */
 
@@ -1769,6 +1856,8 @@ int transformEnd(bContext *C, TransInfo *t)
                viewRedrawForce(C, t);
        }
 
+       t->context = NULL;
+
        return exit_code;
 }
 
@@ -1841,7 +1930,7 @@ static void protectedAxisAngleBits(short protectflag, float axis[3], float *angl
                eulO_to_axis_angle( axis, angle,eul, EULER_ORDER_DEFAULT);
                
                /* when converting to axis-angle, we need a special exception for the case when there is no axis */
-               if (IS_EQ(axis[0], axis[1]) && IS_EQ(axis[1], axis[2])) {
+               if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) {
                        /* for now, rotate around y-axis then (so that it simply becomes the roll) */
                        axis[1]= 1.0f;
                }
@@ -1868,23 +1957,29 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu
        }
        else {
                /* quaternions get limited with euler... (compatability mode) */
-               float eul[3], oldeul[3], quat1[4];
-               
-               QUATCOPY(quat1, quat);
-               quat_to_eul( eul,quat);
-               quat_to_eul( oldeul,oldquat);
-               
+               float eul[3], oldeul[3], nquat[4], noldquat[4];
+               float qlen;
+
+               qlen= normalize_qt_qt(nquat, quat);
+               normalize_qt_qt(noldquat, oldquat);
+
+               quat_to_eul(eul, nquat);
+               quat_to_eul(oldeul, noldquat);
+
                if (protectflag & OB_LOCK_ROTX)
                        eul[0]= oldeul[0];
                if (protectflag & OB_LOCK_ROTY)
                        eul[1]= oldeul[1];
                if (protectflag & OB_LOCK_ROTZ)
                        eul[2]= oldeul[2];
-               
+
                eul_to_quat( quat,eul);
+
+               /* restore original quat size */
+               mul_qt_fl(quat, qlen);
                
                /* quaternions flip w sign to accumulate rotations correctly */
-               if ( (quat1[0]<0.0f && quat[0]>0.0f) || (quat1[0]>0.0f && quat[0]<0.0f) ) {
+               if ( (nquat[0]<0.0f && quat[0]>0.0f) || (nquat[0]>0.0f && quat[0]<0.0f) ) {
                        mul_qt_fl(quat, -1.0f);
                }
        }
@@ -1892,18 +1987,17 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu
 
 /* ******************* TRANSFORM LIMITS ********************** */
 
-static void constraintTransLim(TransInfo *t, TransData *td)
+static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
 {
        if (td->con) {
                bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
-               bConstraintOb cob;
+               bConstraintOb cob= {NULL};
                bConstraint *con;
                
                /* Make a temporary bConstraintOb for using these limit constraints
                 *      - they only care that cob->matrix is correctly set ;-)
                 *      - current space should be local
                 */
-               memset(&cob, 0, sizeof(bConstraintOb));
                unit_m4(cob.matrix);
                VECCOPY(cob.matrix[3], td->loc);
                
@@ -1957,37 +2051,29 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
         *      - current space should be local
         */
        memset(cob, 0, sizeof(bConstraintOb));
-       if (td->rotOrder == ROT_MODE_QUAT) {
-               /* quats */
-               if (td->ext) {
+       if (td->ext)
+       {
+               if (td->ext->rotOrder == ROT_MODE_QUAT) {
+                       /* quats */
                        /* objects and bones do normalization first too, otherwise
                           we don't necessarily end up with a rotation matrix, and
                           then conversion back to quat gives a different result */
                        float quat[4];
-                       copy_qt_qt(quat, td->ext->quat);
-                       normalize_qt(quat);
+                       normalize_qt_qt(quat, td->ext->quat);
                        quat_to_mat4(cob->matrix, quat);
                }
-               else
-                       return;
-       }
-       else if (td->rotOrder == ROT_MODE_AXISANGLE) {
-               /* axis angle */
-               if (td->ext)
+               else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+                       /* axis angle */
                        axis_angle_to_mat4(cob->matrix, &td->ext->quat[1], td->ext->quat[0]);
-               else
-                       return;
-       }
-       else {
-               /* eulers */
-               if (td->ext)
-                       eulO_to_mat4(cob->matrix, td->ext->rot, td->rotOrder);
-               else
-                       return;
+               }
+               else {
+                       /* eulers */
+                       eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrder);
+               }
        }
 }
 
-static void constraintRotLim(TransInfo *t, TransData *td)
+static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
 {
        if (td->con) {
                bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
@@ -2041,17 +2127,17 @@ static void constraintRotLim(TransInfo *t, TransData *td)
                
                if(dolimit) {
                        /* copy results from cob->matrix */
-                       if (td->rotOrder == ROT_MODE_QUAT) {
+                       if (td->ext->rotOrder == ROT_MODE_QUAT) {
                                /* quats */
                                mat4_to_quat( td->ext->quat,cob.matrix);
                        }
-                       else if (td->rotOrder == ROT_MODE_AXISANGLE) {
+                       else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
                                /* axis angle */
                                mat4_to_axis_angle( &td->ext->quat[1], &td->ext->quat[0],cob.matrix);
                        }
                        else {
                                /* eulers */
-                               mat4_to_eulO( td->ext->rot, td->rotOrder,cob.matrix);
+                               mat4_to_eulO( td->ext->rot, td->ext->rotOrder,cob.matrix);
                        }
                }
        }
@@ -2061,14 +2147,13 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
 {
        if (td->con && td->ext) {
                bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
-               bConstraintOb cob;
+               bConstraintOb cob= {NULL};
                bConstraint *con;
                
                /* Make a temporary bConstraintOb for using these limit constraints
                 *      - they only care that cob->matrix is correctly set ;-)
                 *      - current space should be local
                 */
-               memset(&cob, 0, sizeof(bConstraintOb));
                if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
                        /* scale val and reset size */
                        return; // TODO: fix this case
@@ -2136,7 +2221,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
 
 /* ************************** WARP *************************** */
 
-void postInputWarp(TransInfo *t, float values[3])
+static void postInputWarp(TransInfo *t, float values[3])
 {
        mul_v3_fl(values, (float)(M_PI * 2));
 
@@ -2161,8 +2246,8 @@ void initWarp(TransInfo *t)
        t->idx_max = 0;
        t->num.idx_max = 0;
        t->snap[0] = 0.0f;
-       t->snap[1] = 5.0f / 180 * M_PI;
-       t->snap[2] = 1.0f / 180 * M_PI;
+       t->snap[1] = 5.0f / 180.0f * (float)M_PI;
+       t->snap[2] = 1.0f / 180.0f * (float)M_PI;
        
        t->num.increment = 1.0f;
 
@@ -2171,23 +2256,21 @@ void initWarp(TransInfo *t)
        /* we need min/max in view space */
        for(i = 0; i < t->total; i++) {
                float center[3];
-               VECCOPY(center, t->data[i].center);
+               copy_v3_v3(center, t->data[i].center);
                mul_m3_v3(t->data[i].mtx, center);
                mul_m4_v3(t->viewmat, center);
                sub_v3_v3(center, t->viewmat[3]);
                if (i)
-                       minmax_v3_v3v3(min, max, center);
+                       minmax_v3v3_v3(min, max, center);
                else {
-                       VECCOPY(max, center);
-                       VECCOPY(min, center);
+                       copy_v3_v3(max, center);
+                       copy_v3_v3(min, center);
                }
        }
-       
-       t->center[0]= (min[0]+max[0])/2.0f;
-       t->center[1]= (min[1]+max[1])/2.0f;
-       t->center[2]= (min[2]+max[2])/2.0f;
 
-       if (max[0] == min[0]) max[0] += 0.1; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */
+       mid_v3_v3v3(t->center, min, max);
+
+       if (max[0] == min[0]) max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */
        t->val= (max[0]-min[0])/2.0f; /* t->val is X dimension projected boundbox */
 }
 
@@ -2198,10 +2281,10 @@ int handleEventWarp(TransInfo *t, wmEvent *event)
        if (event->type == MIDDLEMOUSE && event->val==KM_PRESS)
        {
                // Use customData pointer to signal warp direction
-               if      (t->customData == 0)
+               if      (t->customData == NULL)
                        t->customData = (void*)1;
                else
-                       t->customData = 0;
+                       t->customData = NULL;
                
                status = 1;
        }
@@ -2209,7 +2292,7 @@ int handleEventWarp(TransInfo *t, wmEvent *event)
        return status;
 }
 
-int Warp(TransInfo *t, short mval[2])
+int Warp(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        float vec[3], circumfac, dist, phi0, co, si, *curs, cursor[3], gcursor[3];
@@ -2251,11 +2334,11 @@ int Warp(TransInfo *t, short mval[2])
                
                sprintf(str, "Warp: %s", c);
 
-               circumfac = circumfac / 180 * M_PI;
+               circumfac = DEG2RADF(circumfac);
        }
        else {
                /* default header print */
-               sprintf(str, "Warp: %.3f", circumfac * 180 / M_PI);
+               sprintf(str, "Warp: %.3f", RAD2DEGF(circumfac));
        }
        
        t->values[0] = circumfac;
@@ -2307,7 +2390,7 @@ int Warp(TransInfo *t, short mval[2])
 
 /* ************************** SHEAR *************************** */
 
-void postInputShear(TransInfo *t, float values[3])
+static void postInputShear(TransInfo *UNUSED(t), float values[3])
 {
        mul_v3_fl(values, 0.05f);
 }
@@ -2339,7 +2422,7 @@ int handleEventShear(TransInfo *t, wmEvent *event)
        if (event->type == MIDDLEMOUSE && event->val==KM_PRESS)
        {
                // Use customData pointer to signal Shear direction
-               if      (t->customData == 0)
+               if      (t->customData == NULL)
                {
                        initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
                        t->customData = (void*)1;
@@ -2347,7 +2430,7 @@ int handleEventShear(TransInfo *t, wmEvent *event)
                else
                {
                        initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
-                       t->customData = 0;
+                       t->customData = NULL;
                }
                
                status = 1;
@@ -2357,7 +2440,7 @@ int handleEventShear(TransInfo *t, wmEvent *event)
 }
 
 
-int Shear(TransInfo *t, short mval[2])
+int Shear(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        float vec[3];
@@ -2391,7 +2474,7 @@ int Shear(TransInfo *t, short mval[2])
        unit_m3(smat);
        
        // Custom data signals shear direction
-       if (t->customData == 0)
+       if (t->customData == NULL)
                smat[1][0] = value;
        else
                smat[0][1] = value;
@@ -2461,6 +2544,7 @@ void initResize(TransInfo *t)
 
 static void headerResize(TransInfo *t, float vec[3], char *str) {
        char tvec[60];
+       char *spos= str;
        if (hasNumInput(&t->num)) {
                outputNumInput(&(t->num), tvec);
        }
@@ -2473,21 +2557,27 @@ static void headerResize(TransInfo *t, float vec[3], char *str) {
        if (t->con.mode & CON_APPLY) {
                switch(t->num.idx_max) {
                case 0:
-                       sprintf(str, "Scale: %s%s %s", &tvec[0], t->con.text, t->proptext);
+                       spos += sprintf(spos, "Scale: %s%s %s", &tvec[0], t->con.text, t->proptext);
                        break;
                case 1:
-                       sprintf(str, "Scale: %s : %s%s %s", &tvec[0], &tvec[20], t->con.text, t->proptext);
+                       spos += sprintf(spos, "Scale: %s : %s%s %s", &tvec[0], &tvec[20], t->con.text, t->proptext);
                        break;
                case 2:
-                       sprintf(str, "Scale: %s : %s : %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
+                       spos += sprintf(spos, "Scale: %s : %s : %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
                }
        }
        else {
                if (t->flag & T_2D_EDIT)
-                       sprintf(str, "Scale X: %s   Y: %s%s %s", &tvec[0], &tvec[20], t->con.text, t->proptext);
+                       spos += sprintf(spos, "Scale X: %s   Y: %s%s %s", &tvec[0], &tvec[20], t->con.text, t->proptext);
                else
-                       sprintf(str, "Scale X: %s   Y: %s  Z: %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
+                       spos += sprintf(spos, "Scale X: %s   Y: %s  Z: %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
+       }
+       
+       if (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) {
+               spos += sprintf(spos, " Proportional size: %.2f", t->prop_size);
        }
+
+       (void)spos;
 }
 
 #define SIGN(a)                (a<-FLT_EPSILON?1:a>FLT_EPSILON?2:3)
@@ -2616,7 +2706,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) {
        constraintTransLim(t, td);
 }
 
-int Resize(TransInfo *t, short mval[2])
+int Resize(TransInfo *t, const short mval[2])
 {
        TransData *td;
        float size[3], mat[3][3];
@@ -2721,7 +2811,7 @@ void initToSphere(TransInfo *t)
        t->val /= (float)t->total;
 }
 
-int ToSphere(TransInfo *t, short mval[2])
+int ToSphere(TransInfo *t, const short UNUSED(mval[2]))
 {
        float vec[3];
        float ratio, radius;
@@ -2786,7 +2876,7 @@ int ToSphere(TransInfo *t, short mval[2])
 /* ************************** ROTATION *************************** */
 
 
-void postInputRotation(TransInfo *t, float values[3])
+static void postInputRotation(TransInfo *t, float values[3])
 {
        if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
                t->con.applyRot(t, NULL, t->axis, values);
@@ -2818,6 +2908,8 @@ void initRotation(TransInfo *t)
 
        negate_v3_v3(t->axis, t->viewinv[2]);
        normalize_v3(t->axis);
+
+       copy_v3_v3(t->axis_orig, t->axis);
 }
 
 static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short around) {
@@ -2852,7 +2944,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                
                
                if(td->flag & TD_USEQUAT) {
-                       mul_serie_m3(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+                       mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
                        mat3_to_quat( quat,fmat);       // Actual transform
                        
                        if(td->ext->quat){
@@ -2895,9 +2987,19 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                        
                        sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location
                        
-                       mul_m3_v3(pmtx, vec);   // To Global space
-                       mul_m3_v3(td->smtx, vec);// To Pose space
-                       
+                       /* special exception, see TD_PBONE_LOCAL_MTX definition comments */
+                       if(td->flag & TD_PBONE_LOCAL_MTX_P) {
+                               /* do nothing */
+                       }
+                       else if (td->flag & TD_PBONE_LOCAL_MTX_C) {
+                               mul_m3_v3(pmtx, vec);   // To Global space
+                               mul_m3_v3(td->ext->l_smtx, vec);// To Pose space (Local Location)
+                       }
+                       else {
+                               mul_m3_v3(pmtx, vec);   // To Global space
+                               mul_m3_v3(td->smtx, vec);// To Pose space
+                       }
+
                        protectedTransBits(td->protectflag, vec);
                        
                        add_v3_v3v3(td->loc, td->iloc, vec);
@@ -2908,8 +3010,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
                        /* euler or quaternion/axis-angle? */
-                       if (td->rotOrder == ROT_MODE_QUAT) {
-                               mul_serie_m3(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+                       if (td->ext->rotOrder == ROT_MODE_QUAT) {
+                               mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
                                
                                mat3_to_quat( quat,fmat);       // Actual transform
                                
@@ -2918,13 +3020,13 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                                protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
                                
                        }
-                       else if (td->rotOrder == ROT_MODE_AXISANGLE) {
+                       else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
                                /* calculate effect based on quats */
                                float iquat[4], tquat[4];
                                
                                axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
                                
-                               mul_serie_m3(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+                               mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
                                mat3_to_quat( quat,fmat);       // Actual transform
                                mul_qt_qtqt(tquat, quat, iquat);
                                
@@ -2941,12 +3043,12 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                                
                                /* calculate the total rotatation in eulers */
                                VECCOPY(eul, td->ext->irot);
-                               eulO_to_mat3( eulmat,eul, td->rotOrder);
+                               eulO_to_mat3( eulmat,eul, td->ext->rotOrder);
                                
                                /* mat = transform, obmat = bone rotation */
                                mul_m3_m3m3(fmat, smat, eulmat);
                                
-                               mat3_to_compatible_eulO( eul, td->ext->rot, td->rotOrder,fmat);
+                               mat3_to_compatible_eulO( eul, td->ext->rot, td->ext->rotOrder,fmat);
                                
                                /* and apply (to end result only) */
                                protectedRotateBits(td->protectflag, eul, td->ext->irot);
@@ -2978,25 +3080,25 @@ 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
                        /* euler or quaternion? */
-                          if ((td->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
-                               mul_serie_m3(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+                          if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
+                               mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
                                mat3_to_quat( quat,fmat);       // Actual transform
                                
                                mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
                                /* this function works on end result */
                                protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
                        }
-                       else if (td->rotOrder == ROT_MODE_AXISANGLE) {
+                       else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
                                /* calculate effect based on quats */
                                float iquat[4], tquat[4];
                                
                                axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
                                
-                               mul_serie_m3(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+                               mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
                                mat3_to_quat( quat,fmat);       // Actual transform
                                mul_qt_qtqt(tquat, quat, iquat);
                                
-                               quat_to_axis_angle( td->ext->rotAxis, td->ext->rotAngle,quat); 
+                               quat_to_axis_angle( td->ext->rotAxis, td->ext->rotAngle,tquat); 
                                
                                /* this function works on end result */
                                protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle);
@@ -3009,11 +3111,11 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                                
                                /* calculate the total rotatation in eulers */
                                add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
-                               eulO_to_mat3( obmat,eul, td->rotOrder);
+                               eulO_to_mat3( obmat,eul, td->ext->rotOrder);
                                /* mat = transform, obmat = object rotation */
                                mul_m3_m3m3(fmat, smat, obmat);
                                
-                               mat3_to_compatible_eulO( eul, td->ext->rot, td->rotOrder,fmat);
+                               mat3_to_compatible_eulO( eul, td->ext->rot, td->ext->rotOrder,fmat);
                                
                                /* correct back for delta rot */
                                sub_v3_v3v3(eul, eul, td->ext->drot);
@@ -3056,14 +3158,12 @@ static void applyRotation(TransInfo *t, float angle, float axis[3])
        }
 }
 
-int Rotation(TransInfo *t, short mval[2])
+int Rotation(TransInfo *t, const short UNUSED(mval[2]))
 {
-       char str[64];
+       char str[128], *spos= str;
        
        float final;
-       
-       float mat[3][3];
-       
+
        final = t->values[0];
        
        applyNDofInput(&t->ndof, &final);
@@ -3074,8 +3174,7 @@ int Rotation(TransInfo *t, short mval[2])
                t->con.applyRot(t, NULL, t->axis, NULL);
        } else {
                /* reset axis if constraint is not set */
-               negate_v3_v3(t->axis, t->viewinv[2]);
-               normalize_v3(t->axis);
+               copy_v3_v3(t->axis, t->axis_orig);
        }
        
        applySnapping(t, &final);
@@ -3087,24 +3186,21 @@ int Rotation(TransInfo *t, short mval[2])
                
                outputNumInput(&(t->num), c);
                
-               sprintf(str, "Rot: %s %s %s", &c[0], t->con.text, t->proptext);
-               
+               spos+= sprintf(spos, "Rot: %s %s %s", &c[0], t->con.text, t->proptext);
+
                /* Clamp between -180 and 180 */
-               while (final >= 180.0)
-                       final -= 360.0;
-               
-               while (final <= -180.0)
-                       final += 360.0;
-               
-               final *= (float)(M_PI / 180.0);
+               final= angle_wrap_rad(DEG2RADF(final));
        }
        else {
-               sprintf(str, "Rot: %.2f%s %s", 180.0*final/M_PI, t->con.text, t->proptext);
+               spos += sprintf(spos, "Rot: %.2f%s %s", RAD2DEGF(final), t->con.text, t->proptext);
        }
        
-       t->values[0] = final;
+       if (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) {
+               spos += sprintf(spos, " Proportional size: %.2f", t->prop_size);
+       }
+       (void)spos;
 
-       vec_rot_to_mat3( mat, t->axis, final);
+       t->values[0] = final;
        
        applyRotation(t, final, t->axis);
        
@@ -3170,9 +3266,9 @@ static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a
        }
 }
 
-int Trackball(TransInfo *t, short mval[2])
+int Trackball(TransInfo *t, const short UNUSED(mval[2]))
 {
-       char str[128];
+       char str[128], *spos= str;
        float axis1[3], axis2[3];
        float mat[3][3], totmat[3][3], smat[3][3];
        float phi[2];
@@ -3196,15 +3292,20 @@ int Trackball(TransInfo *t, short mval[2])
 
                outputNumInput(&(t->num), c);
 
-               sprintf(str, "Trackball: %s %s %s", &c[0], &c[20], t->proptext);
+               spos += sprintf(spos, "Trackball: %s %s %s", &c[0], &c[20], t->proptext);
 
-               phi[0] *= (float)(M_PI / 180.0);
-               phi[1] *= (float)(M_PI / 180.0);
+               phi[0] = DEG2RADF(phi[0]);
+               phi[1] = DEG2RADF(phi[1]);
        }
        else {
-               sprintf(str, "Trackball: %.2f %.2f %s", 180.0*phi[0]/M_PI, 180.0*phi[1]/M_PI, t->proptext);
+               spos += sprintf(spos, "Trackball: %.2f %.2f %s", RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext);
        }
 
+       if (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) {
+               spos += sprintf(spos, " Proportional size: %.2f", t->prop_size);
+       }
+       (void)spos;
+
        vec_rot_to_mat3( smat,axis1, phi[0]);
        vec_rot_to_mat3( totmat,axis2, phi[1]);
 
@@ -3260,6 +3361,7 @@ void initTranslation(TransInfo *t)
 }
 
 static void headerTranslation(TransInfo *t, float vec[3], char *str) {
+       char *spos= str;
        char tvec[60];
        char distvec[20];
        char autoik[20];
@@ -3276,7 +3378,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) {
                applyAspectRatio(t, dvec);
 
                dist = len_v3(vec);
-               if(t->scene->unit.system) {
+               if(!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
                        int i, do_split= t->scene->unit.flag & USER_UNIT_OPT_SPLIT ? 1:0;
 
                        for(i=0; i<3; i++)
@@ -3289,9 +3391,9 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) {
                }
        }
 
-       if(t->scene->unit.system)
+       if(!(t->flag & T_2D_EDIT) && t->scene->unit.system)
                bUnit_AsString(distvec, sizeof(distvec), dist*t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0);
-       else if( dist > 1e10 || dist < -1e10 )  /* prevent string buffer overflow */
+       else if( dist > 1e10f || dist < -1e10f )        /* prevent string buffer overflow */
                sprintf(distvec, "%.4e", dist);
        else
                sprintf(distvec, "%.4f", dist);
@@ -3310,21 +3412,26 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) {
        if (t->con.mode & CON_APPLY) {
                switch(t->num.idx_max) {
                case 0:
-                       sprintf(str, "D: %s (%s)%s %s  %s", &tvec[0], distvec, t->con.text, t->proptext, &autoik[0]);
+                       spos += sprintf(spos, "D: %s (%s)%s %s  %s", &tvec[0], distvec, t->con.text, t->proptext, &autoik[0]);
                        break;
                case 1:
-                       sprintf(str, "D: %s   D: %s (%s)%s %s  %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext, &autoik[0]);
+                       spos += sprintf(spos, "D: %s   D: %s (%s)%s %s  %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext, &autoik[0]);
                        break;
                case 2:
-                       sprintf(str, "D: %s   D: %s  D: %s (%s)%s %s  %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]);
+                       spos += sprintf(spos, "D: %s   D: %s  D: %s (%s)%s %s  %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]);
                }
        }
        else {
                if(t->flag & T_2D_EDIT)
-                       sprintf(str, "Dx: %s   Dy: %s (%s)%s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext);
+                       spos += sprintf(spos, "Dx: %s   Dy: %s (%s)%s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext);
                else
-                       sprintf(str, "Dx: %s   Dy: %s  Dz: %s (%s)%s %s  %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]);
+                       spos += sprintf(spos, "Dx: %s   Dy: %s  Dz: %s (%s)%s %s  %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]);
+       }
+       
+       if (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) {
+               spos += sprintf(spos, " Proportional size: %.2f", t->prop_size);
        }
+       (void)spos;
 }
 
 static void applyTranslation(TransInfo *t, float vec[3]) {
@@ -3382,20 +3489,24 @@ static void applyTranslation(TransInfo *t, float vec[3]) {
                
                protectedTransBits(td->protectflag, tvec);
                
-               add_v3_v3v3(td->loc, td->iloc, tvec);
+               if (td->loc)
+                       add_v3_v3v3(td->loc, td->iloc, tvec);
                
                constraintTransLim(t, td);
        }
 }
 
 /* uses t->vec to store actual translation in */
-int Translation(TransInfo *t, short mval[2])
+int Translation(TransInfo *t, const short UNUSED(mval[2]))
 {
        char str[250];
 
        if (t->con.mode & CON_APPLY) {
                float pvec[3] = {0.0f, 0.0f, 0.0f};
                float tvec[3];
+               if (hasNumInput(&t->num)) {
+                       removeAspectRatio(t, t->values);
+               }
                applySnapping(t, t->values);
                t->con.applyVec(t, NULL, t->values, tvec, pvec);
                VECCOPY(t->values, tvec);
@@ -3405,11 +3516,9 @@ 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))
-               {
+               if (hasNumInput(&t->num)) {
                        removeAspectRatio(t, t->values);
                }
-
                applySnapping(t, t->values);
                headerTranslation(t, t->values, str);
        }
@@ -3455,7 +3564,7 @@ void initShrinkFatten(TransInfo *t)
 
 
 
-int ShrinkFatten(TransInfo *t, short mval[2])
+int ShrinkFatten(TransInfo *t, const short UNUSED(mval[2]))
 {
        float vec[3];
        float distance;
@@ -3525,12 +3634,12 @@ void initTilt(TransInfo *t)
 
        t->num.increment = t->snap[1];
 
-       t->flag |= T_NO_CONSTRAINT;
+       t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT;
 }
 
 
 
-int Tilt(TransInfo *t, short mval[2])
+int Tilt(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        int i;
@@ -3553,10 +3662,10 @@ int Tilt(TransInfo *t, short mval[2])
 
                sprintf(str, "Tilt: %s %s", &c[0], t->proptext);
 
-               final *= (float)(M_PI / 180.0);
+               final = DEG2RADF(final);
        }
        else {
-               sprintf(str, "Tilt: %.2f %s", 180.0*final/M_PI, t->proptext);
+               sprintf(str, "Tilt: %.2f %s", RAD2DEGF(final), t->proptext);
        }
 
        for(i = 0 ; i < t->total; i++, td++) {
@@ -3602,7 +3711,7 @@ void initCurveShrinkFatten(TransInfo *t)
        t->flag |= T_NO_CONSTRAINT;
 }
 
-int CurveShrinkFatten(TransInfo *t, short mval[2])
+int CurveShrinkFatten(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        float ratio;
@@ -3670,7 +3779,7 @@ void initPushPull(TransInfo *t)
 }
 
 
-int PushPull(TransInfo *t, short mval[2])
+int PushPull(TransInfo *t, const short UNUSED(mval[2]))
 {
        float vec[3], axis[3];
        float distance;
@@ -3803,12 +3912,12 @@ int handleEventBevel(TransInfo *t, wmEvent *event)
        return 0;
 }
 
-int Bevel(TransInfo *t, short mval[2])
+int Bevel(TransInfo *t, const short UNUSED(mval[2]))
 {
        float distance,d;
        int i;
        char str[128];
-       char *mode;
+       const char *mode;
        TransData *td = t->data;
 
        mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal";
@@ -3871,7 +3980,7 @@ void initBevelWeight(TransInfo *t)
        t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT;
 }
 
-int BevelWeight(TransInfo *t, short mval[2])
+int BevelWeight(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        float weight;
@@ -3944,7 +4053,7 @@ void initCrease(TransInfo *t)
        t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT;
 }
 
-int Crease(TransInfo *t, short mval[2])
+int Crease(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        float crease;
@@ -4012,6 +4121,7 @@ void initBoneSize(TransInfo *t)
        t->idx_max = 2;
        t->num.idx_max = 2;
        t->num.flag |= NUM_NULL_ONE;
+       t->num.flag |= NUM_AFFECT_ALL;
        t->snap[0] = 0.0f;
        t->snap[1] = 0.1f;
        t->snap[2] = t->snap[1] * 0.1f;
@@ -4062,7 +4172,7 @@ static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3])
        td->loc[1]= oldy;
 }
 
-int BoneSize(TransInfo *t, short mval[2])
+int BoneSize(TransInfo *t, const short mval[2])
 {
        TransData *td = t->data;
        float size[3], mat[3][3];
@@ -4135,10 +4245,10 @@ void initBoneEnvelope(TransInfo *t)
        
        t->num.increment = t->snap[1];
 
-       t->flag |= T_NO_CONSTRAINT;
+       t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT;
 }
 
-int BoneEnvelope(TransInfo *t, short mval[2])
+int BoneEnvelope(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        float ratio;
@@ -4186,505 +4296,501 @@ int BoneEnvelope(TransInfo *t, short mval[2])
 }
 
 /* ********************  Edge Slide   *************** */
+static BMEdge *get_other_edge(BMesh *bm, BMVert *v, BMEdge *e)
+{
+       BMIter iter;
+       BMEdge *e2;
+
+       BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, v) {
+               if (BM_TestHFlag(e2, BM_SELECT) && e2 != e)
+                       return e2;
+       }
+
+       return NULL;
+}
+
+static BMLoop *get_next_loop(BMesh *UNUSED(bm), BMVert *v, BMLoop *l, 
+                             BMEdge *olde, BMEdge *nexte, float vec[3])
+{
+       BMLoop *firstl;
+       float a[3] = {0.0f, 0.0f, 0.0f}, n[3] = {0.0f, 0.0f, 0.0f};
+       int i=0;
+
+       firstl = l;
+       do {
+               l = BM_OtherFaceLoop(l->e, l->f, v);
+               if (l->radial_next == l)
+                       return NULL;
+               
+               if (l->e == nexte) {
+                       if (i) {
+                               mul_v3_fl(a, 1.0f / (float)i);
+                       } else {
+                               float f1[3], f2[3], f3[3];
+
+                               sub_v3_v3v3(f1, BM_OtherEdgeVert(olde, v)->co, v->co);
+                               sub_v3_v3v3(f2, BM_OtherEdgeVert(nexte, v)->co, v->co);
+
+                               cross_v3_v3v3(f3, f1, l->f->no);
+                               cross_v3_v3v3(a, f2, l->f->no);
+                               mul_v3_fl(a, -1.0f);
+
+                               add_v3_v3(a, f3);
+                               mul_v3_fl(a, 0.5f);
+                       }
+                       
+                       VECCOPY(vec, a);
+                       return l;
+               } else {
+                       sub_v3_v3v3(n, BM_OtherEdgeVert(l->e, v)->co, v->co);
+                       add_v3_v3v3(a, a, n);
+                       i += 1;
+               }
+
+               if (BM_OtherFaceLoop(l->e, l->f, v)->e == nexte) {
+                       if (i)
+                               mul_v3_fl(a, 1.0f / (float)i);
+                       
+                       VECCOPY(vec, a);
+                       return BM_OtherFaceLoop(l->e, l->f, v);
+               }
+               
+               l = l->radial_next;
+       } while (l != firstl); 
+
+       if (i)
+               mul_v3_fl(a, 1.0f / (float)i);
+       
+       VECCOPY(vec, a);
+       
+       return NULL;
+}
 
 static int createSlideVerts(TransInfo *t)
 {
        Mesh *me = t->obedit->data;
-       EditMesh *em = me->edit_mesh;
-       EditFace *efa;
-       EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
-       EditVert *ev, *nearest = NULL;
-       LinkNode *edgelist = NULL, *vertlist=NULL, *look;
-       GHash *vertgh;
+       BMEditMesh *em = me->edit_btmesh;
+       BMesh *bm = em->bm;
+       BMIter iter, iter2;
+       BMEdge *e, *e1, *ee, *le;
+       BMVert *v, *v2, *first;
+       BMLoop *l, *l1, *l2;
        TransDataSlideVert *tempsv;
-       float vertdist; // XXX, projectMat[4][4];
-       int i, j, numsel, numadded=0, timesthrough = 0, vertsel=0;
-       /* UV correction vars */
-       GHash **uvarray= NULL;
+       BMBVHTree *btree = BMBVH_NewBVH(em);
+       SmallHash table;
        SlideData *sld = MEM_callocN(sizeof(*sld), "sld");
-       int  uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
-       int uvlay_idx;
-       TransDataSlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL;
-       RegionView3D *v3d = t->ar->regiondata;
+       View3D *v3d = t->sa ? t->sa->spacedata.first : NULL;
+       RegionView3D *rv3d = t->ar ? t->ar->regiondata : NULL; /* background mode support */
+       ARegion *ar = t->ar;
        float projectMat[4][4];
-       float start[3] = {0.0f, 0.0f, 0.0f}, end[3] = {0.0f, 0.0f, 0.0f};
-       float vec[3];
-       float totvec=0.0;
+       float start[3] = {0.0f, 0.0f, 0.0f}, dir[3], end[3] = {0.0f, 0.0f, 0.0f};
+       float vec[3], vec2[3], lastvec[3], size, dis=0.0, z;
+       int numsel, i, j;
 
        if (!v3d) {
                /*ok, let's try to survive this*/
                unit_m4(projectMat);
        } else {
-               view3d_get_object_project_mat(v3d, t->obedit, projectMat);
+               view3d_get_object_project_mat(rv3d, t->obedit, projectMat);
        }
        
-       numsel =0;
-
-       // Get number of selected edges and clear some flags
-       for(eed=em->edges.first;eed;eed=eed->next) {
-               eed->f1 = 0;
-               eed->f2 = 0;
-               if(eed->f & SELECT) numsel++;
-       }
-
-       for(ev=em->verts.first;ev;ev=ev->next) {
-               ev->f1 = 0;
-       }
+       BLI_smallhash_init(&sld->vhash);
+       BLI_smallhash_init(&sld->origfaces);
+       BLI_smallhash_init(&table);
+       
+       /*ensure valid selection*/
+       BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+               if (BM_TestHFlag(v, BM_SELECT)) {
+                       numsel = 0;
+                       BM_ITER(e, &iter2, em->bm, BM_EDGES_OF_VERT, v) {
+                               if (BM_TestHFlag(e, BM_SELECT)) {
+                                       /*BMESH_TODO: this is probably very evil,
+                                         set v->e to a selected edge*/
+                                       v->e = e;
 
-       //Make sure each edge only has 2 faces
-       // make sure loop doesn't cross face
-       for(efa=em->faces.first;efa;efa=efa->next) {
-               int ct = 0;
-               if(efa->e1->f & SELECT) {
-                       ct++;
-                       efa->e1->f1++;
-                       if(efa->e1->f1 > 2) {
-                               //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
-                               return 0;
-                       }
-               }
-               if(efa->e2->f & SELECT) {
-                       ct++;
-                       efa->e2->f1++;
-                       if(efa->e2->f1 > 2) {
-                               //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
-                               return 0;
-                       }
-               }
-               if(efa->e3->f & SELECT) {
-                       ct++;
-                       efa->e3->f1++;
-                       if(efa->e3->f1 > 2) {
-                               //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
-                               return 0;
+                                       numsel++;
+                               }
                        }
-               }
-               if(efa->e4 && efa->e4->f & SELECT) {
-                       ct++;
-                       efa->e4->f1++;
-                       if(efa->e4->f1 > 2) {
-                               //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
-                               return 0;
+
+                       if (numsel > 2) {
+                               return 0; //invalid edge selection
                        }
                }
-               // Make sure loop is not 2 edges of same face
-               if(ct > 1) {
-                  //BKE_report(op->reports, RPT_ERROR, "Loop crosses itself");
-                  return 0;
+       }
+
+       BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+               if (BM_TestHFlag(e, BM_SELECT)) {
+                       if (BM_Edge_FaceCount(e) > 2 || BM_Edge_FaceCount(e) == 0)
+                               return 0; //can't handle more then 2 faces around an edge
                }
        }
 
-       // Get # of selected verts
-       for(ev=em->verts.first;ev;ev=ev->next) {
-               if(ev->f & SELECT) vertsel++;
+       j = 0;
+       BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+               if (BM_TestHFlag(v, BM_SELECT)) {
+                       BMINDEX_SET(v, 1);
+                       BLI_smallhash_insert(&table, (uintptr_t)v, SET_INT_IN_POINTER(j));
+                       j += 1;
+               } else BMINDEX_SET(v, 0);
        }
 
-       // Test for multiple segments
-       if(vertsel > numsel+1) {
-               //BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop");
+       if (!j)
                return 0;
-       }
 
-       // Get the edgeloop in order - mark f1 with SELECT once added
-       for(eed=em->edges.first;eed;eed=eed->next) {
-               if((eed->f & SELECT) && !(eed->f1 & SELECT)) {
-                       // If this is the first edge added, just put it in
-                       if(!edgelist) {
-                               BLI_linklist_prepend(&edgelist,eed);
-                               numadded++;
-                               first = eed;
-                               last  = eed;
-                               eed->f1 = SELECT;
-                       } else {
-                               if(editedge_getSharedVert(eed, last)) {
-                                       BLI_linklist_append(&edgelist,eed);
-                                       eed->f1 = SELECT;
-                                       numadded++;
-                                       last = eed;
-                               }  else if(editedge_getSharedVert(eed, first)) {
-                                       BLI_linklist_prepend(&edgelist,eed);
-                                       eed->f1 = SELECT;
-                                       numadded++;
-                                       first = eed;
-                               }
-                       }
-               }
-               if(eed->next == NULL && numadded != numsel) {
-                       eed=em->edges.first;
-                       timesthrough++;
-               }
+       tempsv = MEM_callocN(sizeof(TransDataSlideVert)*j, "tempsv");
+
+       j = 0;
+       while (1) {
+               v = NULL;
+               BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+                       if (BMINDEX_GET(v))
+                               break;
 
-               // It looks like there was an unexpected case - Hopefully should not happen
-               if(timesthrough >= numsel*2) {
-                       BLI_linklist_free(edgelist,NULL);
-                       //BKE_report(op->reports, RPT_ERROR, "Could not order loop");
-                       return 0;
                }
-       }
 
-       // Put the verts in order in a linklist
-       look = edgelist;
-       while(look) {
-               eed = look->link;
-               if(!vertlist) {
-                       if(look->next) {
-                               temp = look->next->link;
+               if (!v)
+                       break;
 
-                               //This is the first entry takes care of extra vert
-                               if(eed->v1 != temp->v1 && eed->v1 != temp->v2) {
-                                       BLI_linklist_append(&vertlist,eed->v1);
-                                       eed->v1->f1 = 1;
-                               } else {
-                                       BLI_linklist_append(&vertlist,eed->v2);
-                                       eed->v2->f1 = 1;
-                               }
-                       } else {
-                               //This is the case that we only have 1 edge
-                               BLI_linklist_append(&vertlist,eed->v1);
-                               eed->v1->f1 = 1;
-                       }
-               }
-               // for all the entries
-               if(eed->v1->f1 != 1) {
-                       BLI_linklist_append(&vertlist,eed->v1);
-                       eed->v1->f1 = 1;
-               } else  if(eed->v2->f1 != 1) {
-                       BLI_linklist_append(&vertlist,eed->v2);
-                       eed->v2->f1 = 1;
-               }
-               look = look->next;
-       }
-
-       // populate the SlideVerts
-
-       vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createSlideVerts gh");
-       look = vertlist;
-       while(look) {
-               i=0;
-               j=0;
-               ev = look->link;
-               tempsv = (struct TransDataSlideVert*)MEM_mallocN(sizeof(struct TransDataSlideVert),"SlideVert");
-               tempsv->up = NULL;
-               tempsv->down = NULL;
-               tempsv->origvert.co[0] = ev->co[0];
-               tempsv->origvert.co[1] = ev->co[1];
-               tempsv->origvert.co[2] = ev->co[2];
-               tempsv->origvert.no[0] = ev->no[0];
-               tempsv->origvert.no[1] = ev->no[1];
-               tempsv->origvert.no[2] = ev->no[2];
-               // i is total edges that vert is on
-               // j is total selected edges that vert is on
-
-               for(eed=em->edges.first;eed;eed=eed->next) {
-                       if(eed->v1 == ev || eed->v2 == ev) {
-                               i++;
-                               if(eed->f & SELECT) {
-                                        j++;
-                               }
-                       }
-               }
-               // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
-               if(i == 4 && j == 2) {
-                       for(eed=em->edges.first;eed;eed=eed->next) {
-                               if(editedge_containsVert(eed, ev)) {
-                                       if(!(eed->f & SELECT)) {
-                                                if(!tempsv->up) {
-                                                        tempsv->up = eed;
-                                                } else if (!(tempsv->down)) {
-                                                        tempsv->down = eed;
-                                                }
-                                       }
-                               }
-                       }
-               }
-               // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
-               if(i >= 3 && j == 1) {
-                       for(eed=em->edges.first;eed;eed=eed->next) {
-                               if(editedge_containsVert(eed, ev) && eed->f & SELECT) {
-                                       for(efa = em->faces.first;efa;efa=efa->next) {
-                                               if(editface_containsEdge(efa, eed)) {
-                                                       if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) {
-                                                                if(!tempsv->up) {
-                                                                        tempsv->up = efa->e1;
-                                                                } else if (!(tempsv->down)) {
-                                                                        tempsv->down = efa->e1;
-                                                                }
-                                                       }
-                                                       if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) {
-                                                                if(!tempsv->up) {
-                                                                        tempsv->up = efa->e2;
-                                                                } else if (!(tempsv->down)) {
-                                                                        tempsv->down = efa->e2;
-                                                                }
-                                                       }
-                                                       if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) {
-                                                                if(!tempsv->up) {
-                                                                        tempsv->up = efa->e3;
-                                                                } else if (!(tempsv->down)) {
-                                                                        tempsv->down = efa->e3;
-                                                                }
-                                                       }
-                                                       if(efa->e4) {
-                                                               if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) {
-                                                                        if(!tempsv->up) {
-                                                                                tempsv->up = efa->e4;
-                                                                        } else if (!(tempsv->down)) {
-                                                                                tempsv->down = efa->e4;
-                                                                        }
-                                                               }
-                                                       }
+               if (!v->e)
+                       continue;
+               
+               first = v;
 
-                                               }
-                                       }
-                               }
+               /*walk along the edge loop*/
+               e = v->e;
+
+               /*first, rewind*/
+               numsel = 0;
+               do {
+                       e = get_other_edge(bm, v, e);
+                       if (!e) {
+                               e = v->e;
+                               break;
                        }
-               }
-               if(i > 4 && j == 2) {
-                       BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
-                       BLI_linklist_free(vertlist,NULL);
-                       BLI_linklist_free(edgelist,NULL);
-                       return 0;
-               }
-               BLI_ghash_insert(vertgh,ev,tempsv);
 
-               look = look->next;
-       }
+                       numsel += 1;
 
-       // make sure the UPs nad DOWNs are 'faceloops'
-       // Also find the nearest slidevert to the cursor
+                       if (!BMINDEX_GET(BM_OtherEdgeVert(e, v)))
+                               break;
 
-       look = vertlist;
-       nearest = NULL;
-       vertdist = -1;
-       while(look) {
-               tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+                       v = BM_OtherEdgeVert(e, v);
+               } while (e != first->e);
 
-               if(!tempsv->up || !tempsv->down) {
-                       //BKE_report(op->reports, RPT_ERROR, "Missing rails");
-                       BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
-                       BLI_linklist_free(vertlist,NULL);
-                       BLI_linklist_free(edgelist,NULL);
-                       return 0;
-               }
+               BMINDEX_SET(v, 0);
 
-               if(me->drawflag & ME_DRAW_EDGELEN) {
-                       if(!(tempsv->up->f & SELECT)) {
-                               tempsv->up->f |= SELECT;
-                               tempsv->up->f2 |= 16;
-                       } else {
-                               tempsv->up->f2 |= ~16;
-                       }
-                       if(!(tempsv->down->f & SELECT)) {
-                               tempsv->down->f |= SELECT;
-                               tempsv->down->f2 |= 16;
-                       } else {
-                               tempsv->down->f2 |= ~16;
-                       }
+               l1 = l2 = l = NULL;
+               l1 = e->l;
+               l2 = e->l->radial_next;
+
+               l = BM_OtherFaceLoop(l1->e, l1->f, v);
+               sub_v3_v3v3(vec, BM_OtherEdgeVert(l->e, v)->co, v->co);
+
+               if (l2 != l1) {
+                       l = BM_OtherFaceLoop(l2->e, l2->f, v);
+                       sub_v3_v3v3(vec2, BM_OtherEdgeVert(l->e, v)->co, v->co);
+               } else {
+                       l2 = NULL;
                }
 
-               if(look->next != NULL) {
-                       TransDataSlideVert *sv;
-                       
-                       ev = (EditVert*)look->next->link;
-                       sv = BLI_ghash_lookup(vertgh, ev);
+               /*iterate over the loop*/
+               first = v;
+               j = 0;
+               do {
+                       TransDataSlideVert *sv = tempsv + j;
 
-                       if(sv) {
-                               float co[3], co2[3], vec[3];
+                       sv->v = v;
+                       sv->origvert = *v;
+                       VECCOPY(sv->upvec, vec);
+                       if (l2)
+                               VECCOPY(sv->downvec, vec2);
 
-                               ev = (EditVert*)look->link;
+                       l = BM_OtherFaceLoop(l1->e, l1->f, v);
+                       sv->up = BM_OtherEdgeVert(l->e, v);
 
-                               if(!sharesFace(em, tempsv->up,sv->up)) {
-                                       EditEdge *swap;
-                                       swap = sv->up;
-                                       sv->up = sv->down;
-                                       sv->down = swap;
-                               }
-                               
-                               if (v3d) {
-                                       view3d_project_float(t->ar, tempsv->up->v1->co, co, projectMat);
-                                       view3d_project_float(t->ar, tempsv->up->v2->co, co2, projectMat);
-                               }
+                       if (l2) {
+                               l = BM_OtherFaceLoop(l2->e, l2->f, v);
+                               sv->down = BM_OtherEdgeVert(l->e, v);
+                       }
 
-                               if (ev == tempsv->up->v1) {
-                                       sub_v3_v3v3(vec, co, co2);
-                               } else {
-                                       sub_v3_v3v3(vec, co2, co);
-                               }
+                       v2=v, v = BM_OtherEdgeVert(e, v);
 
-                               add_v3_v3(start, vec);
+                       e1 = e;
+                       e = get_other_edge(bm, v, e);
+                       if (!e) {
+                               //v2=v, v = BM_OtherEdgeVert(l1->e, v);
 
-                               if (v3d) {
-                                       view3d_project_float(t->ar, tempsv->down->v1->co, co, projectMat);
-                                       view3d_project_float(t->ar, tempsv->down->v2->co, co2, projectMat);
+                               sv = tempsv + j + 1;
+                               sv->v = v;
+                               sv->origvert = *v;
+                               
+                               l = BM_OtherFaceLoop(l1->e, l1->f, v);
+                               sv->up = BM_OtherEdgeVert(l->e, v);
+                               sub_v3_v3v3(sv->upvec, BM_OtherEdgeVert(l->e, v)->co, v->co);
+
+                               if (l2) {
+                                       l = BM_OtherFaceLoop(l2->e, l2->f, v);
+                                       sv->down = BM_OtherEdgeVert(l->e, v);
+                                       sub_v3_v3v3(sv->downvec, BM_OtherEdgeVert(l->e, v)->co, v->co);
                                }
 
-                               if (ev == tempsv->down->v1) {
-                                       sub_v3_v3v3(vec, co2, co);
-                               } else {
-                                       sub_v3_v3v3(vec, co, co2);
-                               }
+                               BMINDEX_SET(v, 0);
+                               BMINDEX_SET(v2, 0);
+                               
+                               j += 2;
+                               break;
+                       }
+
+                       l1 = get_next_loop(bm, v, l1, e1, e, vec);
+                       l2 = l2 ? get_next_loop(bm, v, l2, e1, e, vec2) : NULL;
+
+                       j += 1;
+
+                       BMINDEX_SET(v, 0);
+                       BMINDEX_SET(v2, 0);
+               } while (e != first->e && l1);
+       }
+
+       //EDBM_clear_flag_all(em, BM_SELECT);
+
+       sld->sv = tempsv;
+       sld->totsv = j;
+       
+       /*find mouse vector*/
+       dis = z = -1.0f;
+       size = 50.0;
+       zero_v3(lastvec); zero_v3(dir);
+       ee = le = NULL;
+       BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+               if (BM_TestHFlag(e, BM_SELECT)) {
+                       BMIter iter2;
+                       BMEdge *e2;
+                       float vec1[3], dis2, mval[2] = {t->mval[0], t->mval[1]}, d;
+                                               
+                       /*search cross edges for visible edge to the mouse cursor,
+              then use the shared vertex to calculate screen vector*/
+                       dis2 = -1.0f;
+                       for (i=0; i<2; i++) {
+                               v = i?e->v1:e->v2;
+                               BM_ITER(e2, &iter2, em->bm, BM_EDGES_OF_VERT, v) {
+                                       if (BM_TestHFlag(e2, BM_SELECT))
+                                               continue;
+                                       
+                                       if (!BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit))
+                                               continue;
+                                       
+                                       j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
 
-                               add_v3_v3(end, vec);
+                                       if (tempsv[j].down) {
+                                               view3d_project_float_v3(ar, tempsv[j].down->co, vec1, projectMat);
+                                       } else {
+                                               add_v3_v3v3(vec1, v->co, tempsv[j].downvec);
+                                               view3d_project_float_v3(ar, vec1, vec1, projectMat);
+                                       }
+                                       
+                                       if (tempsv[j].up) {
+                                               view3d_project_float_v3(ar, tempsv[j].up->co, vec2, projectMat);
+                                       } else {
+                                               add_v3_v3v3(vec1, v->co, tempsv[j].upvec);
+                                               view3d_project_float_v3(ar, vec2, vec2, projectMat);
+                                       }
 
-                               totvec += 1.0f;
-                               nearest = (EditVert*)look->link;
+                                       d = dist_to_line_segment_v2(mval, vec1, vec2);
+                                       if (dis2 == -1.0f || d < dis2) {
+                                               dis2 = d;
+                                               ee = e2;
+                                               size = len_v3v3(vec1, vec2);
+                                               sub_v3_v3v3(dir, vec1, vec2);
+                                       }
+                               }
                        }
                }
+       }
+       
+       em->bm->ob = t->obedit;
+       bmesh_begin_edit(em->bm, BMOP_UNTAN_MULTIRES);
 
+       /*create copies of faces for customdata projection*/
+       tempsv = sld->sv;
+       for (i=0; i<sld->totsv; i++, tempsv++) {
+               BMIter fiter, liter;
+               BMFace *f;
+               BMLoop *l;
+               
+               BM_ITER(f, &fiter, em->bm, BM_FACES_OF_VERT, tempsv->v) {
+                       
+                       if (!BLI_smallhash_haskey(&sld->origfaces, (uintptr_t)f)) {
+                               BMFace *copyf = BM_Copy_Face(em->bm, f, 1, 1);
+                               
+                               BM_Select(em->bm, copyf, 0);
+                               BM_SetHFlag(copyf, BM_HIDDEN);
+                               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, copyf) {
+                                       BM_Select(em->bm, l->v, 0);
+                                       BM_SetHFlag(l->v, BM_HIDDEN);
+                                       BM_Select(em->bm, l->e, 0);
+                                       BM_SetHFlag(l->e, BM_HIDDEN);
+                               }
 
+                               BLI_smallhash_insert(&sld->origfaces, (uintptr_t)f, copyf);
+                       }
+               }
 
-               look = look->next;
+               BLI_smallhash_insert(&sld->vhash, (uintptr_t)tempsv->v, tempsv);
        }
-
-       add_v3_v3(start, end);
-       mul_v3_fl(start, 0.5*(1.0/totvec));
-       VECCOPY(vec, start);
-       start[0] = t->mval[0];
-       start[1] = t->mval[1];
-       add_v3_v3v3(end, start, vec);
        
-       sld->start[0] = (short) start[0];
-       sld->start[1] = (short) start[1];
-       sld->end[0] = (short) end[0];
-       sld->end[1] = (short) end[1];
+       sld->em = em;
        
-       if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
-               int maxnum = 0;
-
-               uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array");
-               sld->totuv = uvlay_tot;
-               suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(TransDataSlideUv), "SlideUVs"); /* uvLayers * verts */
-               suv = NULL;
+       /*zero out start*/
+       zero_v3(start);
+       
+       /*dir holds a vector along edge loop*/
+       copy_v3_v3(end, dir);
+       mul_v3_fl(end, 0.5);
+       
+       sld->start[0] = t->mval[0] + start[0];
+       sld->start[1] = t->mval[1] + start[1];
 
-               for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+       sld->end[0] = t->mval[0] + end[0];
+       sld->end[1] = t->mval[1] + end[1];
+       
+       sld->perc = 0.0f;
+       
+       t->customData = sld;
+       
+       BLI_smallhash_release(&table);
+       BMBVH_FreeBVH(btree);
+       
+       return 1;
+}
 
-                       uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createSlideVerts2 gh");
+void projectSVData(TransInfo *t, int final)
+{
+       SlideData *sld = t->customData;
+       TransDataSlideVert *tempsv;
+       BMEditMesh *em = sld->em;
+       SmallHash visit;
+       int i;
+       
+       if (!em)
+               return;
+       
+       BLI_smallhash_init(&visit);
+       
+               for (i=0, tempsv=sld->sv; i<sld->totsv; i++, tempsv++) {
+               BMIter fiter;
+               BMFace *f;
+               
+               BM_ITER(f, &fiter, em->bm, BM_FACES_OF_VERT, tempsv->v) {
+                       BMIter liter2;
+                       BMFace *copyf, *copyf2;
+                       BMLoop *l2;
+                       int sel, do_vdata;
+                       
+                       if (BLI_smallhash_haskey(&visit, (uintptr_t)f))
+                               continue;
+                       
+                       BLI_smallhash_insert(&visit, (uintptr_t)f, NULL);
+                       
+                       /*the face attributes of the copied face will get
+                         copied over, so its necessary to save the selection state*/
+                       sel = BM_TestHFlag(f, BM_SELECT);
+                       
+                       copyf2 = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)f);
+                       
+                       /*project onto copied projection face*/
+                       BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_FACE, f) {
+                               copyf = copyf2;
+                               do_vdata = l2->v==tempsv->v;
+                               
+                               if (BM_TestHFlag(l2->e, BM_SELECT) || BM_TestHFlag(l2->prev->e, BM_SELECT)) {
+                                       BMLoop *l3 = l2;
+                                       
+                                       do_vdata = 1;
+                                       
+                                       if (!BM_TestHFlag(l2->e, BM_SELECT))
+                                               l3 = l3->prev;
+                                       
+                                       if (sld->perc < 0.0 && BM_Vert_In_Face(l3->radial_next->f, tempsv->down)) {
+                                               copyf = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l3->radial_next->f);
+                                       } else if (sld->perc > 0.0 && BM_Vert_In_Face(l3->radial_next->f, tempsv->up)) {
+                                               copyf = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l3->radial_next->f);
+                                       }
+                               }
+                               
+                               BM_loop_interp_from_face(em->bm, l2, copyf, do_vdata, 0);
 
-                       for(ev=em->verts.first;ev;ev=ev->next) {
-                               ev->tmp.l = 0;
-                       }
-                       look = vertlist;
-                       while(look) {
-                               float *uv_new;
-                               tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
-
-                               ev = look->link;
-                               suv = NULL;
-                               for(efa = em->faces.first;efa;efa=efa->next) {
-                                       if (ev->tmp.l != -1) { /* test for self, in this case its invalid */
-                                               int k=-1; /* face corner */
-
-                                               /* Is this vert in the faces corner? */
-                                               if              (efa->v1==ev)                           k=0;
-                                               else if (efa->v2==ev)                           k=1;
-                                               else if (efa->v3==ev)                           k=2;
-                                               else if (efa->v4 && efa->v4==ev)        k=3;
-
-                                               if (k != -1) {
-                                                       MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx);
-                                                       EditVert *ev_up, *ev_down;
-
-                                                       uv_new = tf->uv[k];
-
-                                                       if (ev->tmp.l) {
-                                                               if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) {
-                                                                       ev->tmp.l = -1; /* Tag as invalid */
-                                                                       BLI_linklist_free(suv->fuv_list,NULL);
-                                                                       suv->fuv_list = NULL;
-                                                                       BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL);
-                                                                       suv = NULL;
-                                                                       break;
-                                                               }
-                                                       } else {
-                                                               ev->tmp.l = 1;
-                                                               suv = suv_last;
-
-                                                               suv->fuv_list = NULL;
-                                                               suv->uv_up = suv->uv_down = NULL;
-                                                               suv->origuv[0] = uv_new[0];
-                                                               suv->origuv[1] = uv_new[1];
-
-                                                               BLI_linklist_prepend(&suv->fuv_list, uv_new);
-                                                               BLI_ghash_insert(uvarray[uvlay_idx],ev,suv);
-
-                                                               suv_last++; /* advance to next slide UV */
-                                                               maxnum++;
-                                                       }
-
-                                                       /* Now get the uvs along the up or down edge if we can */
-                                                       if (suv) {
-                                                               if (!suv->uv_up) {
-                                                                       ev_up = editedge_getOtherVert(tempsv->up,ev);
-                                                                       if              (efa->v1==ev_up)                                suv->uv_up = tf->uv[0];
-                                                                       else if (efa->v2==ev_up)                                suv->uv_up = tf->uv[1];
-                                                                       else if (efa->v3==ev_up)                                suv->uv_up = tf->uv[2];
-                                                                       else if (efa->v4 && efa->v4==ev_up)             suv->uv_up = tf->uv[3];
-                                                               }
-                                                               if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */
-                                                                       ev_down = editedge_getOtherVert(tempsv->down,ev);
-                                                                       if              (efa->v1==ev_down)                              suv->uv_down = tf->uv[0];
-                                                                       else if (efa->v2==ev_down)                              suv->uv_down = tf->uv[1];
-                                                                       else if (efa->v3==ev_down)                              suv->uv_down = tf->uv[2];
-                                                                       else if (efa->v4 && efa->v4==ev_down)   suv->uv_down = tf->uv[3];
-                                                               }
-
-                                                               /* Copy the pointers to the face UV's */
-                                                               BLI_linklist_prepend(&suv->fuv_list, uv_new);
-                                                       }
-                                               }
+                               if (final) {
+                                       BM_loop_interp_multires(em->bm, l2, copyf);     
+                                       if (copyf2 != copyf) {
+                                               BM_loop_interp_multires(em->bm, l2, copyf2);
                                        }
                                }
-                               look = look->next;
                        }
-               } /* end uv layer loop */
-       } /* end uvlay_tot */
-
-       sld->uvhash = uvarray;
-       sld->slideuv = slideuvs;
-       sld->vhash = vertgh;
-       sld->nearest = nearest;
-       sld->vertlist = vertlist;
-       sld->edgelist = edgelist;
-       sld->suv_last = suv_last;
-       sld->uvlay_tot = uvlay_tot;
-
-       // we should have enough info now to slide
-
-       t->customData = sld;
-
-       return 1;
+                       
+                       /*make sure face-attributes are correct (e.g. MTexPoly)*/
+                       BM_Copy_Attributes(em->bm, em->bm, copyf2, f);
+                       
+                       /*restore selection, and undo hidden flag*/
+                       BM_ClearHFlag(f, BM_HIDDEN);
+                       if (sel)
+                               BM_Select(em->bm, f, sel);
+               }
+       }
+       
+       BLI_smallhash_release(&visit);
 }
 
 void freeSlideVerts(TransInfo *t)
 {
-       TransDataSlideUv *suv;
        SlideData *sld = t->customData;
-       int uvlay_idx;
-
-       //BLI_ghash_free(edgesgh, freeGHash, NULL);
-       BLI_ghash_free(sld->vhash, NULL, (GHashValFreeFP)MEM_freeN);
-       BLI_linklist_free(sld->vertlist, NULL);
-       BLI_linklist_free(sld->edgelist, NULL);
-
-       if (sld->uvlay_tot) {
-               for (uvlay_idx=0; uvlay_idx<sld->uvlay_tot; uvlay_idx++) {
-                       BLI_ghash_free(sld->uvhash[uvlay_idx], NULL, NULL);
-               }
-
-               suv = sld->suv_last-1;
-               while (suv >= sld->slideuv) {
-                       if (suv->fuv_list) {
-                               BLI_linklist_free(suv->fuv_list,NULL);
+       SmallHashIter hiter;
+       BMFace *copyf;
+       
+#if 0
+       if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
+               TransDataSlideVert *tempsv;
+               LinkNode *look = sld->vertlist;
+               GHash *vertgh = sld->vhash;
+               while(look) {
+                       tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+                       if(tempsv != NULL) {
+                               tempsv->up->f &= !SELECT;
+                               tempsv->down->f &= !SELECT;
                        }
-                       suv--;
+                       look = look->next;
                }
-
-               MEM_freeN(sld->slideuv);
-               MEM_freeN(sld->uvhash);
        }
+#endif
+       
+       if (!sld)
+               return;
+       
+       /*handle multires reprojection, done
+      on transform completion since it's
+      really slow -joeedh*/
+       if (t->state != TRANS_CANCEL) {
+               projectSVData(t, 1);
+       } else {
+               sld->perc = 0.0;
+               projectSVData(t, 0);
+       }
+       
+       copyf = BLI_smallhash_iternew(&sld->origfaces, &hiter, NULL);
+       for (; copyf; copyf=BLI_smallhash_iternext(&hiter, NULL)) {
+               BM_Kill_Face_Verts(sld->em->bm, copyf);
+       }
+       
+       sld->em->bm->ob = t->obedit;
+       bmesh_end_edit(sld->em->bm, BMOP_UNTAN_MULTIRES);
 
+       BLI_smallhash_release(&sld->vhash);
+       BLI_smallhash_release(&sld->origfaces);
+       
+       MEM_freeN(sld->sv);
        MEM_freeN(sld);
+       
        t->customData = NULL;
+       
+       recalcData(t);
 }
 
 void initEdgeSlide(TransInfo *t)
@@ -4694,7 +4800,11 @@ void initEdgeSlide(TransInfo *t)
        t->mode = TFM_EDGE_SLIDE;
        t->transform = EdgeSlide;
        
-       createSlideVerts(t);
+       if(!createSlideVerts(t)) {
+               t->state= TRANS_CANCEL;
+               return;
+       }
+       
        sld = t->customData;
 
        if (!sld)
@@ -4719,117 +4829,32 @@ void initEdgeSlide(TransInfo *t)
 
 int doEdgeSlide(TransInfo *t, float perc)
 {
-       Mesh *me= t->obedit->data;
-       EditMesh *em = me->edit_mesh;
        SlideData *sld = t->customData;
-       EditVert *ev, *nearest = sld->nearest;
-       EditVert *centerVert, *upVert, *downVert;
-       LinkNode *vertlist=sld->vertlist, *look;
-       GHash *vertgh = sld->vhash;
-       TransDataSlideVert *tempsv;
-       float len = 0.0f;
-       int prop=1, flip=0;
-       /* UV correction vars */
-       GHash **uvarray= sld->uvhash;
-       int  uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
-       int uvlay_idx;
-       TransDataSlideUv *suv=sld->slideuv;
-       float uv_tmp[2];
-       LinkNode *fuv_link;
-
-       len = 0.0f;
-
-       tempsv = BLI_ghash_lookup(vertgh,nearest);
-
-       centerVert = editedge_getSharedVert(tempsv->up, tempsv->down);
-       upVert = editedge_getOtherVert(tempsv->up, centerVert);
-       downVert = editedge_getOtherVert(tempsv->down, centerVert);
-
-       len = MIN2(perc, len_v3v3(upVert->co,downVert->co));
-       len = MAX2(len, 0);
-
-       //Adjust Edgeloop
-       if(prop) {
-               look = vertlist;
-               while(look) {
-                       EditVert *tempev;
-                       ev = look->link;
-                       tempsv = BLI_ghash_lookup(vertgh,ev);
-
-                       tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev);
-                       interp_v3_v3v3(ev->co, tempsv->origvert.co, tempev->co, fabs(perc));
-
-                       if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
-                               for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
-                                       suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
-                                       if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
-                                               interp_v2_v2v2(uv_tmp, suv->origuv,  (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc));
-                                               fuv_link = suv->fuv_list;
-                                               while (fuv_link) {
-                                                       VECCOPY2D(((float *)fuv_link->link), uv_tmp);
-                                                       fuv_link = fuv_link->next;
-                                               }
-                                       }
-                               }
-                       }
+       TransDataSlideVert *svlist = sld->sv, *sv;
+       float vec[3];
+       int i;
 
-                       look = look->next;
-               }
-       }
-       else {
-               //Non prop code
-               look = vertlist;
-               while(look) {
-                       float newlen, edgelen;
-                       ev = look->link;
-                       tempsv = BLI_ghash_lookup(vertgh,ev);
-                       edgelen = len_v3v3(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co);
-                       newlen = (edgelen != 0.0f)? (len / edgelen): 0.0f;
-                       if(newlen > 1.0) {newlen = 1.0;}
-                       if(newlen < 0.0) {newlen = 0.0;}
-                       if(flip == 0) {
-                               interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));
-                               if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
-                                       /* dont do anything if no UVs */
-                                       for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
-                                               suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
-                                               if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
-                                                       interp_v2_v2v2(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen));
-                                                       fuv_link = suv->fuv_list;
-                                                       while (fuv_link) {
-                                                               VECCOPY2D(((float *)fuv_link->link), uv_tmp);
-                                                               fuv_link = fuv_link->next;
-                                                       }
-                                               }
-                                       }
-                               }
-                       } else{
-                               interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));
-
-                               if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
-                                       /* dont do anything if no UVs */
-                                       for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
-                                               suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
-                                               if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
-                                                       interp_v2_v2v2(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen));
-                                                       fuv_link = suv->fuv_list;
-                                                       while (fuv_link) {
-                                                               VECCOPY2D(((float *)fuv_link->link), uv_tmp);
-                                                               fuv_link = fuv_link->next;
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-                       look = look->next;
-               }
+       sld->perc = perc;
 
+       sv = svlist;
+       for (i=0; i<sld->totsv; i++, sv++) {
+               if (perc > 0.0f) {
+                       VECCOPY(vec, sv->upvec);
+                       mul_v3_fl(vec, perc);
+                       add_v3_v3v3(sv->v->co, sv->origvert.co, vec);
+               } else {
+                       VECCOPY(vec, sv->downvec);
+                       mul_v3_fl(vec, -perc);
+                       add_v3_v3v3(sv->v->co, sv->origvert.co, vec);
+               }
        }
-
+       
+       projectSVData(t, 0);
+       
        return 1;
 }
 
-int EdgeSlide(TransInfo *t, short mval[2])
+int EdgeSlide(TransInfo *t, const short UNUSED(mval[2]))
 {
        char str[50];
        float final;
@@ -4885,10 +4910,10 @@ void initBoneRoll(TransInfo *t)
 
        t->num.increment = 1.0f;
 
-       t->flag |= T_NO_CONSTRAINT;
+       t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT;
 }
 
-int BoneRoll(TransInfo *t, short mval[2])
+int BoneRoll(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        int i;
@@ -4909,10 +4934,10 @@ int BoneRoll(TransInfo *t, short mval[2])
 
                sprintf(str, "Roll: %s", &c[0]);
 
-               final *= (float)(M_PI / 180.0);
+               final = DEG2RADF(final);
        }
        else {
-               sprintf(str, "Roll: %.2f", 180.0*final/M_PI);
+               sprintf(str, "Roll: %.2f", RAD2DEGF(final));
        }
 
        /* set roll values */
@@ -4949,7 +4974,7 @@ void initBakeTime(TransInfo *t)
        t->num.increment = t->snap[1];
 }
 
-int BakeTime(TransInfo *t, short mval[2])
+int BakeTime(TransInfo *t, const short mval[2])
 {
        TransData *td = t->data;
        float time;
@@ -5024,7 +5049,7 @@ void initMirror(TransInfo *t)
        }
 }
 
-int Mirror(TransInfo *t, short mval[2])
+int Mirror(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td;
        float size[3], mat[3][3];
@@ -5101,7 +5126,7 @@ void initAlign(TransInfo *t)
        initMouseInputMode(t, &t->mouse, INPUT_NONE);
 }
 
-int Align(TransInfo *t, short mval[2])
+int Align(TransInfo *t, const short UNUSED(mval[2]))
 {
        TransData *td = t->data;
        float center[3];
@@ -5204,7 +5229,7 @@ static void applySeqSlide(TransInfo *t, float val[2]) {
        }
 }
 
-int SeqSlide(TransInfo *t, short mval[2])
+int SeqSlide(TransInfo *t, const short UNUSED(mval[2]))
 {
        char str[200];
 
@@ -5220,8 +5245,8 @@ int SeqSlide(TransInfo *t, short mval[2])
                applyNumInput(&t->num, t->values);
        }
 
-       t->values[0] = floor(t->values[0] + 0.5);
-       t->values[1] = floor(t->values[1] + 0.5);
+       t->values[0] = floor(t->values[0] + 0.5f);
+       t->values[1] = floor(t->values[1] + 0.5f);
 
        headerSeqSlide(t, t->values, str);
        applySeqSlide(t, t->values);
@@ -5320,7 +5345,7 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d,
        /* snap key to nearest frame? */
        if (autosnap == SACTSNAP_FRAME) {
                const Scene *scene= t->scene;
-               const short doTime= 0; //XXX doesn't work - getAnimEdit_DrawTime(t);
+               const short doTime= 0; //getAnimEdit_DrawTime(t); // NOTE: this works, but may be confusing behaviour given the option's label, hence disabled
                const double secf= FPS;
                double val;
                
@@ -5379,6 +5404,11 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d,
 
 void initTimeTranslate(TransInfo *t)
 {
+       /* this tool is only really available in the Action Editor... */
+       if (t->spacetype != SPACE_ACTION) {
+               t->state = TRANS_CANCEL;
+       }
+
        t->mode = TFM_TIME_TRANSLATE;
        t->transform = TimeTranslate;
 
@@ -5432,7 +5462,7 @@ static void headerTimeTranslate(TransInfo *t, char *str)
        sprintf(str, "DeltaX: %s", &tvec[0]);
 }
 
-static void applyTimeTranslate(TransInfo *t, float sval)
+static void applyTimeTranslate(TransInfo *t, float UNUSED(sval))
 {
        TransData *td = t->data;
        TransData2D *td2d = t->data2d;
@@ -5489,7 +5519,7 @@ static void applyTimeTranslate(TransInfo *t, float sval)
        }
 }
 
-int TimeTranslate(TransInfo *t, short mval[2])
+int TimeTranslate(TransInfo *t, const short mval[2])
 {
        View2D *v2d = (View2D *)t->view;
        float cval[2], sval[2];
@@ -5527,8 +5557,11 @@ void initTimeSlide(TransInfo *t)
 
                /* set flag for drawing stuff */
                saction->flag |= SACTION_MOVING;
+       } else {
+               t->state = TRANS_CANCEL;
        }
 
+
        t->mode = TFM_TIME_SLIDE;
        t->transform = TimeSlide;
        t->flag |= T_FREE_CUSTOMDATA;
@@ -5616,7 +5649,7 @@ static void applyTimeSlide(TransInfo *t, float sval)
        }
 }
 
-int TimeSlide(TransInfo *t, short mval[2])
+int TimeSlide(TransInfo *t, const short mval[2])
 {
        View2D *v2d = (View2D *)t->view;
        float cval[2], sval[2];
@@ -5635,7 +5668,7 @@ int TimeSlide(TransInfo *t, short mval[2])
        /* handle numeric-input stuff */
        t->vec[0] = 2.0f*(cval[0]-sval[0]) / (maxx-minx);
        applyNumInput(&t->num, &t->vec[0]);
-       t->values[0] = (maxx-minx) * t->vec[0] / 2.0 + sval[0];
+       t->values[0] = (maxx-minx) * t->vec[0] / 2.0f + sval[0];
 
        headerTimeSlide(t, sval[0], str);
        applyTimeSlide(t, sval[0]);
@@ -5653,6 +5686,13 @@ void initTimeScale(TransInfo *t)
 {
        int center[2];
 
+       /* this tool is only really available in the Action Editor
+        * AND NLA Editor (for strip scaling)
+        */
+       if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA) == 0) {
+               t->state = TRANS_CANCEL;
+       }
+
        t->mode = TFM_TIME_SCALE;
        t->transform = TimeScale;
 
@@ -5734,7 +5774,7 @@ static void applyTimeScale(TransInfo *t) {
        }
 }
 
-int TimeScale(TransInfo *t, short mval[2])
+int TimeScale(TransInfo *t, const short UNUSED(mval[2]))
 {
        char str[200];
        
@@ -5755,16 +5795,16 @@ int TimeScale(TransInfo *t, short mval[2])
 
 /* ************************************ */
 
-void BIF_TransformSetUndo(char *str)
+void BIF_TransformSetUndo(char *UNUSED(str))
 {
        // TRANSFORM_FIX_ME
        //Trans.undostr= str;
 }
 
 
-void NDofTransform()
-{
 #if 0 // TRANSFORM_FIX_ME
+static void NDofTransform(void)
+{
        float fval[7];
        float maxval = 50.0f; // also serves as threshold
        int axis = -1;
@@ -5809,5 +5849,5 @@ void NDofTransform()
                initTransform(mode, CTX_NDOF);
                Transform();
        }
-#endif
 }
+#endif