Fix #27849: 3D manipulator widget lost on mesh in edge mode.
[blender.git] / source / blender / editors / transform / transform_manipulator.c
index bdf0a91bf89b259cfde03abf28b9e17035edd888..d62227a122d7081ebc5efc36bd031206b32ef3a5 100644 (file)
@@ -1,5 +1,5 @@
-/**
-* $Id:
+/*
+* $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2005 Blender Foundation
  * All rights reserved.
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/transform/transform_manipulator.c
+ *  \ingroup edtransform
+ */
+
+
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
+#include <float.h>
 
 #ifndef WIN32
 #include <unistd.h>
 #include "MEM_guardedalloc.h"
 
 #include "DNA_armature_types.h"
-#include "DNA_action_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_lattice_types.h"
-#include "DNA_mesh_types.h"
 #include "DNA_meta_types.h"
-#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_scene_types.h"
-#include "DNA_space_types.h"
-#include "DNA_userdef_types.h"
 #include "DNA_view3d_types.h"
 
 #include "RNA_access.h"
 
-#include "BKE_armature.h"
+#include "BKE_action.h"
 #include "BKE_context.h"
 #include "BKE_global.h"
-#include "BKE_lattice.h"
 #include "BKE_mesh.h"
-#include "BKE_object.h"
 #include "BKE_particle.h"
 #include "BKE_pointcache.h"
-#include "BKE_utildefines.h"
 
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_editVert.h"
+#include "BLI_utildefines.h"
 
 #include "BIF_gl.h"
 
@@ -76,9 +74,8 @@
 #include "ED_armature.h"
 #include "ED_mesh.h"
 #include "ED_particle.h"
-#include "ED_space_api.h"
-#include "ED_transform.h"
 #include "ED_view3d.h"
+#include "ED_curve.h" /* for ED_curve_editnurbs */
 
 #include "UI_resources.h"
 
 #define MAN_GHOST      1
 #define MAN_MOVECOL    2
 
-
-static int is_mat4_flipped(float mat[][4])
-{
-       float vec[3];
-
-       Crossf(vec, mat[0], mat[1]);
-       if( Inpf(vec, mat[2]) < 0.0 ) return 1;
-       return 0;
-}
-
 /* transform widget center calc helper for below */
 static void calc_tw_center(Scene *scene, float *co)
 {
@@ -128,7 +115,7 @@ static void calc_tw_center(Scene *scene, float *co)
        float *max= scene->twmax;
 
        DO_MINMAX(co, min, max);
-       VecAddf(twcent, twcent, co);
+       add_v3_v3(twcent, co);
 }
 
 static void protectflag_to_drawflags(short protectflag, short *drawflags)
@@ -156,25 +143,133 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags)
 }
 
 /* for pose mode */
-static void stats_pose(Scene *scene, View3D *v3d, bPoseChannel *pchan)
+static void stats_pose(Scene *scene, RegionView3D *rv3d, bPoseChannel *pchan)
 {
        Bone *bone= pchan->bone;
 
        if(bone) {
                if (bone->flag & BONE_TRANSFORM) {
                        calc_tw_center(scene, pchan->pose_head);
-                       protectflag_to_drawflags(pchan->protectflag, &v3d->twdrawflag);
+                       protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
                }
        }
 }
 
 /* for editmode*/
-static void stats_editbone(View3D *v3d, EditBone *ebo)
+static void stats_editbone(RegionView3D *rv3d, EditBone *ebo)
 {
        if (ebo->flag & BONE_EDITMODE_LOCKED)
-               protectflag_to_drawflags(OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE, &v3d->twdrawflag);
+               protectflag_to_drawflags(OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE, &rv3d->twdrawflag);
+}
+
+/* could move into BLI_math however this is only useful for display/editing purposes */
+static void axis_angle_to_gimbal_axis(float gmat[3][3], float axis[3], float angle)
+{
+       /* X/Y are arbitrary axies, most importantly Z is the axis of rotation */
+
+       float cross_vec[3];
+       float quat[4];
+
+       /* this is an un-scientific method to get a vector to cross with
+        * XYZ intentionally YZX */
+       cross_vec[0]= axis[1];
+       cross_vec[1]= axis[2];
+       cross_vec[2]= axis[0];
+
+       /* X-axis */
+       cross_v3_v3v3(gmat[0], cross_vec, axis);
+       normalize_v3(gmat[0]);
+       axis_angle_to_quat(quat, axis, angle);
+       mul_qt_v3(quat, gmat[0]);
+
+       /* Y-axis */
+       axis_angle_to_quat(quat, axis, M_PI/2.0);
+       copy_v3_v3(gmat[1], gmat[0]);
+       mul_qt_v3(quat, gmat[1]);
+
+       /* Z-axis */
+       copy_v3_v3(gmat[2], axis);
+
+       normalize_m3(gmat);
+}
+
+
+static int test_rotmode_euler(short rotmode)
+{
+       return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0:1;
 }
 
+int gimbal_axis(Object *ob, float gmat[][3])
+{
+       if (ob) {
+               if(ob->mode & OB_MODE_POSE)
+               {
+                       bPoseChannel *pchan= get_active_posechannel(ob);
+
+                       if(pchan) {
+                               float mat[3][3], tmat[3][3], obmat[3][3];
+                               if(test_rotmode_euler(pchan->rotmode)) {
+                                       eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
+                               }
+                               else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                                       axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
+                               }
+                               else { /* quat */
+                                       return 0;
+                               }
+
+
+                               /* apply bone transformation */
+                               mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
+
+                               if (pchan->parent)
+                               {
+                                       float parent_mat[3][3];
+
+                                       copy_m3_m4(parent_mat, pchan->parent->pose_mat);
+                                       mul_m3_m3m3(mat, parent_mat, tmat);
+
+                                       /* needed if object transformation isn't identity */
+                                       copy_m3_m4(obmat, ob->obmat);
+                                       mul_m3_m3m3(gmat, obmat, mat);
+                               }
+                               else
+                               {
+                                       /* needed if object transformation isn't identity */
+                                       copy_m3_m4(obmat, ob->obmat);
+                                       mul_m3_m3m3(gmat, obmat, tmat);
+                               }
+
+                               normalize_m3(gmat);
+                               return 1;
+                       }
+               }
+               else {
+                       if(test_rotmode_euler(ob->rotmode)) {
+                               eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
+                       }
+                       else if(ob->rotmode == ROT_MODE_AXISANGLE) {
+                               axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
+                       }
+                       else { /* quat */
+                               return 0;
+                       }
+
+                       if (ob->parent)
+                       {
+                               float parent_mat[3][3];
+                               copy_m3_m4(parent_mat, ob->parent->obmat);
+                               normalize_m3(parent_mat);
+                               mul_m3_m3m3(gmat, parent_mat, gmat);
+                       }
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+
 /* centroid, boundbox, of selection */
 /* returns total items selected */
 int calc_manipulator_stats(const bContext *C)
@@ -183,18 +278,17 @@ int calc_manipulator_stats(const bContext *C)
        ARegion *ar= CTX_wm_region(C);
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
+       ToolSettings *ts = CTX_data_tool_settings(C);
        View3D *v3d= sa->spacedata.first;
        RegionView3D *rv3d= ar->regiondata;
        Base *base;
        Object *ob= OBACT;
-       float normal[3]={0.0, 0.0, 0.0};
-       float plane[3]={0.0, 0.0, 0.0};
        int a, totsel= 0;
 
        /* transform widget matrix */
-       Mat4One(rv3d->twmat);
+       unit_m4(rv3d->twmat);
 
-       v3d->twdrawflag= 0xFFFF;
+       rv3d->twdrawflag= 0xFFFF;
 
        /* transform widget centroid/center */
        scene->twcent[0]= scene->twcent[1]= scene->twcent[2]= 0.0f;
@@ -216,11 +310,63 @@ int calc_manipulator_stats(const bContext *C)
                                calc_tw_center(scene, vec);
                                totsel= 1;
                        } else {
-                               /* do vertices for center, and if still no normal found, use vertex normals */
-                               for(eve= em->verts.first; eve; eve= eve->next) {
-                                       if(eve->f & SELECT) {
-                                               totsel++;
-                                               calc_tw_center(scene, eve->co);
+                               /* do vertices/edges/faces for center depending on selection
+                                  mode. note we can't use just vertex selection flag because
+                                  it is not flush down on changes */
+                               if(ts->selectmode & SCE_SELECT_VERTEX) {
+                                       for(eve= em->verts.first; eve; eve= eve->next) {
+                                               if(eve->f & SELECT) {
+                                                       totsel++;
+                                                       calc_tw_center(scene, eve->co);
+                                               }
+                                       }
+                               }
+                               else if(ts->selectmode & SCE_SELECT_EDGE) {
+                                       EditEdge *eed;
+
+                                       for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+                                       for(eed= em->edges.first; eed; eed= eed->next) {
+                                               if(eed->h==0 && (eed->f & SELECT)) {
+                                                       if(!eed->v1->f1) {
+                                                               eed->v1->f1= 1;
+                                                               totsel++;
+                                                               calc_tw_center(scene, eed->v1->co);
+                                                       }
+                                                       if(!eed->v2->f1) {
+                                                               eed->v2->f1= 1;
+                                                               totsel++;
+                                                               calc_tw_center(scene, eed->v2->co);
+                                                       }
+                                               }
+                                       }
+                               }
+                               else {
+                                       EditFace *efa;
+
+                                       for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+                                       for(efa= em->faces.first; efa; efa= efa->next) {
+                                               if(efa->h==0 && (efa->f & SELECT)) {
+                                                       if(!efa->v1->f1) {
+                                                               efa->v1->f1= 1;
+                                                               totsel++;
+                                                               calc_tw_center(scene, efa->v1->co);
+                                                       }
+                                                       if(!efa->v2->f1) {
+                                                               efa->v2->f1= 1;
+                                                               totsel++;
+                                                               calc_tw_center(scene, efa->v2->co);
+                                                       }
+                                                       if(!efa->v3->f1) {
+                                                               efa->v3->f1= 1;
+                                                               totsel++;
+                                                               calc_tw_center(scene, efa->v3->co);
+                                                       }
+                                                       if(efa->v4 && !efa->v4->f1) {
+                                                               efa->v4->f1= 1;
+                                                               totsel++;
+                                                               calc_tw_center(scene, efa->v4->co);
+                                                       }
+                                               }
                                        }
                                }
                        }
@@ -229,7 +375,7 @@ int calc_manipulator_stats(const bContext *C)
                        bArmature *arm= obedit->data;
                        EditBone *ebo;
                        for (ebo= arm->edbo->first; ebo; ebo=ebo->next){
-                               if(ebo->layer & arm->layer) {
+                               if(EBONE_VISIBLE(arm, ebo)) {
                                        if (ebo->flag & BONE_TIPSEL) {
                                                calc_tw_center(scene, ebo->tail);
                                                totsel++;
@@ -239,7 +385,7 @@ int calc_manipulator_stats(const bContext *C)
                                                totsel++;
                                        }
                                        if (ebo->flag & BONE_SELECTED) {
-                                               stats_editbone(v3d, ebo);
+                                               stats_editbone(rv3d, ebo);
                                        }
                                }
                        }
@@ -249,8 +395,9 @@ int calc_manipulator_stats(const bContext *C)
                        Nurb *nu;
                        BezTriple *bezt;
                        BPoint *bp;
+                       ListBase *nurbs= ED_curve_editnurbs(cu);
 
-                       nu= cu->editnurb->first;
+                       nu= nurbs->first;
                        while(nu) {
                                if(nu->type == CU_BEZIER) {
                                        bezt= nu->bezt;
@@ -258,7 +405,7 @@ int calc_manipulator_stats(const bContext *C)
                                        while(a--) {
                                                /* exceptions
                                                 * if handles are hidden then only check the center points.
-                                                * If 2 or more are selected then only use the center point too.
+                                                * If the center knot is selected then only use this as the center point.
                                                 */
                                                if (cu->drawflag & CU_HIDE_HANDLES) {
                                                        if (bezt->f2 & SELECT) {
@@ -266,7 +413,7 @@ int calc_manipulator_stats(const bContext *C)
                                                                totsel++;
                                                        }
                                                }
-                                               else if ( (bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT ) {
+                                               else if (bezt->f2 & SELECT) {
                                                        calc_tw_center(scene, bezt->vec[1]);
                                                        totsel++;
                                                }
@@ -275,10 +422,6 @@ int calc_manipulator_stats(const bContext *C)
                                                                calc_tw_center(scene, bezt->vec[0]);
                                                                totsel++;
                                                        }
-                                                       if(bezt->f2) {
-                                                               calc_tw_center(scene, bezt->vec[1]);
-                                                               totsel++;
-                                                       }
                                                        if(bezt->f3) {
                                                                calc_tw_center(scene, bezt->vec[2]);
                                                                totsel++;
@@ -319,9 +462,9 @@ int calc_manipulator_stats(const bContext *C)
                        BPoint *bp;
                        Lattice *lt= obedit->data;
 
-                       bp= lt->editlatt->def;
+                       bp= lt->editlatt->latt->def;
 
-                       a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+                       a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
                        while(a--) {
                                if(bp->f1 & SELECT) {
                                        calc_tw_center(scene, bp->vec);
@@ -333,10 +476,10 @@ int calc_manipulator_stats(const bContext *C)
 
                /* selection center */
                if(totsel) {
-                       VecMulf(scene->twcent, 1.0f/(float)totsel);     // centroid!
-                       Mat4MulVecfl(obedit->obmat, scene->twcent);
-                       Mat4MulVecfl(obedit->obmat, scene->twmin);
-                       Mat4MulVecfl(obedit->obmat, scene->twmax);
+                       mul_v3_fl(scene->twcent, 1.0f/(float)totsel);   // centroid!
+                       mul_m4_v3(obedit->obmat, scene->twcent);
+                       mul_m4_v3(obedit->obmat, scene->twmin);
+                       mul_m4_v3(obedit->obmat, scene->twmax);
                }
        }
        else if(ob && (ob->mode & OB_MODE_POSE)) {
@@ -350,16 +493,16 @@ int calc_manipulator_stats(const bContext *C)
                if(totsel) {
                        /* use channels to get stats */
                        for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-                               stats_pose(scene, v3d, pchan);
+                               stats_pose(scene, rv3d, pchan);
                        }
 
-                       VecMulf(scene->twcent, 1.0f/(float)totsel);     // centroid!
-                       Mat4MulVecfl(ob->obmat, scene->twcent);
-                       Mat4MulVecfl(ob->obmat, scene->twmin);
-                       Mat4MulVecfl(ob->obmat, scene->twmax);
+                       mul_v3_fl(scene->twcent, 1.0f/(float)totsel);   // centroid!
+                       mul_m4_v3(ob->obmat, scene->twcent);
+                       mul_m4_v3(ob->obmat, scene->twmin);
+                       mul_m4_v3(ob->obmat, scene->twmax);
                }
        }
-       else if(ob && (ob->mode & (OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))) {
+       else if(ob && (ob->mode & OB_MODE_ALL_PAINT)) {
                ;
        }
        else if(ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
@@ -383,7 +526,7 @@ int calc_manipulator_stats(const bContext *C)
 
                        /* selection center */
                        if(totsel)
-                               VecMulf(scene->twcent, 1.0f/(float)totsel);     // centroid!
+                               mul_v3_fl(scene->twcent, 1.0f/(float)totsel);   // centroid!
                }
        }
        else {
@@ -393,18 +536,18 @@ int calc_manipulator_stats(const bContext *C)
                if(ob && !(ob->flag & SELECT)) ob= NULL;
 
                for(base= scene->base.first; base; base= base->next) {
-                       if TESTBASELIB(scene, base) {
+                       if TESTBASELIB(v3d, base) {
                                if(ob==NULL)
                                        ob= base->object;
                                calc_tw_center(scene, base->object->obmat[3]);
-                               protectflag_to_drawflags(base->object->protectflag, &v3d->twdrawflag);
+                               protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
                                totsel++;
                        }
                }
 
                /* selection center */
                if(totsel) {
-                       VecMulf(scene->twcent, 1.0f/(float)totsel);     // centroid!
+                       mul_v3_fl(scene->twcent, 1.0f/(float)totsel);   // centroid!
                }
        }
 
@@ -416,70 +559,41 @@ int calc_manipulator_stats(const bContext *C)
                case V3D_MANIP_GLOBAL:
                        break; /* nothing to do */
 
+               case V3D_MANIP_GIMBAL:
+               {
+                       float mat[3][3];
+                       if (gimbal_axis(ob, mat)) {
+                               copy_m4_m3(rv3d->twmat, mat);
+                               break;
+                       }
+                       /* if not gimbal, fall through to normal */
+               }
                case V3D_MANIP_NORMAL:
                        if(obedit || ob->mode & OB_MODE_POSE) {
                                float mat[3][3];
-                               int type;
-
-                               type = getTransformOrientation(C, normal, plane, (v3d->around == V3D_ACTIVE));
-
-                               switch (type)
-                               {
-                                       case ORIENTATION_NORMAL:
-                                               if (createSpaceNormalTangent(mat, normal, plane) == 0)
-                                               {
-                                                       type = ORIENTATION_NONE;
-                                               }
-                                               break;
-                                       case ORIENTATION_VERT:
-                                               if (createSpaceNormal(mat, normal) == 0)
-                                               {
-                                                       type = ORIENTATION_NONE;
-                                               }
-                                               break;
-                                       case ORIENTATION_EDGE:
-                                               if (createSpaceNormalTangent(mat, normal, plane) == 0)
-                                               {
-                                                       type = ORIENTATION_NONE;
-                                               }
-                                               break;
-                                       case ORIENTATION_FACE:
-                                               if (createSpaceNormalTangent(mat, normal, plane) == 0)
-                                               {
-                                                       type = ORIENTATION_NONE;
-                                               }
-                                               break;
-                               }
-
-                               if (type == ORIENTATION_NONE)
-                               {
-                                       Mat4One(rv3d->twmat);
-                               }
-                               else
-                               {
-                                       Mat4CpyMat3(rv3d->twmat, mat);
-                               }
+                               ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE));
+                               copy_m4_m3(rv3d->twmat, mat);
                                break;
                        }
                        /* no break we define 'normal' as 'local' in Object mode */
                case V3D_MANIP_LOCAL:
-                       Mat4CpyMat4(rv3d->twmat, ob->obmat);
-                       Mat4Ortho(rv3d->twmat);
+                       copy_m4_m4(rv3d->twmat, ob->obmat);
+                       normalize_m4(rv3d->twmat);
                        break;
 
                case V3D_MANIP_VIEW:
                        {
                                float mat[3][3];
-                               Mat3CpyMat4(mat, rv3d->viewinv);
-                               Mat3Ortho(mat);
-                               Mat4CpyMat3(rv3d->twmat, mat);
+                               copy_m3_m4(mat, rv3d->viewinv);
+                               normalize_m3(mat);
+                               copy_m4_m3(rv3d->twmat, mat);
                        }
                        break;
                default: /* V3D_MANIP_CUSTOM */
                        {
                                float mat[3][3];
                                applyTransformOrientation(C, mat, NULL);
-                               Mat4CpyMat3(rv3d->twmat, mat);
+                               copy_m4_m3(rv3d->twmat, mat);
                                break;
                        }
                }
@@ -489,21 +603,54 @@ int calc_manipulator_stats(const bContext *C)
        return totsel;
 }
 
+/* don't draw axis perpendicular to the view */
+static void test_manipulator_axis(const bContext *C)
+{
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       float angle;
+       float vec[3];
+
+       ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], vec);
+
+       angle = fabs(angle_v3v3(rv3d->twmat[0], vec));
+       if (angle > (float)M_PI / 2.0f) {
+               angle = (float)M_PI - angle;
+       }
+       angle = rv3d->twangle[0] = RAD2DEGF(angle);
+       if (angle < 5.0f) {
+               rv3d->twdrawflag &= ~(MAN_TRANS_X|MAN_SCALE_X);
+       }
+
+       angle = fabs(angle_v3v3(rv3d->twmat[1], vec));
+       if (angle > (float)M_PI / 2.0f) {
+               angle = (float)M_PI - angle;
+       }
+       angle = rv3d->twangle[1] = RAD2DEGF(angle);
+       if (angle < 5.0f) {
+               rv3d->twdrawflag &= ~(MAN_TRANS_Y|MAN_SCALE_Y);
+       }
+
+       angle = fabs(angle_v3v3(rv3d->twmat[2], vec));
+       if (angle > (float)M_PI / 2.0f) {
+               angle = (float)M_PI - angle;
+       }
+       angle = rv3d->twangle[2] = RAD2DEGF(angle);
+       if (angle < 5.0f) {
+               rv3d->twdrawflag &= ~(MAN_TRANS_Z|MAN_SCALE_Z);
+       }
+}
+
+
 /* ******************** DRAWING STUFFIES *********** */
 
 static float screen_aligned(RegionView3D *rv3d, float mat[][4])
 {
-       float vec[3], size;
-
-       VECCOPY(vec, mat[0]);
-       size= Normalize(vec);
-
        glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
 
        /* sets view screen aligned */
        glRotatef( -360.0f*saacos(rv3d->viewquat[0])/(float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]);
 
-       return size;
+       return len_v3(mat[0]); /* draw scale */
 }
 
 
@@ -591,28 +738,36 @@ static void partial_donut(float radring, float radhole, int start, int end, int
        }
 }
 
+static char axisBlendAngle(float angle)
+{
+       if (angle > 20)
+               return 255;
+
+       if (angle < 5)
+               return 0;
+
+       return (char)(255.0f * (angle - 5) / 15.0f);
+}
+
 /* three colors can be set;
    grey for ghosting
    moving: in transform theme color
    else the red/green/blue
 */
-static void manipulator_setcolor(View3D *v3d, char axis, int colcode)
+static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned char alpha)
 {
-       float vec[4];
-       char col[4];
-
-       vec[3]= 0.7f; // alpha set on 0.5, can be glEnabled or not
+       unsigned char col[4]= {0};
+       col[3]= alpha;
 
        if(colcode==MAN_GHOST) {
-               glColor4ub(0, 0, 0, 70);
+               col[3]= 70;
        }
        else if(colcode==MAN_MOVECOL) {
                UI_GetThemeColor3ubv(TH_TRANSFORM, col);
-               glColor4ub(col[0], col[1], col[2], 128);
        }
        else {
                switch(axis) {
-               case 'c':
+               case 'C':
                        UI_GetThemeColor3ubv(TH_TRANSFORM, col);
                        if(v3d->twmode == V3D_MANIP_LOCAL) {
                                col[0]= col[0]>200?255:col[0]+55;
@@ -624,28 +779,33 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode)
                                col[1]= col[1]<55?0:col[1]-55;
                                col[2]= col[2]<55?0:col[2]-55;
                        }
-                       glColor4ub(col[0], col[1], col[2], 128);
                        break;
-               case 'x':
-                       glColor4ub(220, 0, 0, 128);
+               case 'X':
+                       col[0]= 220;
                        break;
-               case 'y':
-                       glColor4ub(0, 220, 0, 128);
+               case 'Y':
+                       col[1]= 220;
                        break;
-               case 'z':
-                       glColor4ub(30, 30, 220, 128);
+               case 'Z':
+                       col[0]= 30;
+                       col[1]= 30;
+                       col[2]= 220;
                        break;
+               default:
+                       BLI_assert(!"invalid axis arg");
                }
        }
+
+       glColor4ubv(col);
 }
 
 /* viewmatrix should have been set OK, also no shademode! */
-static void draw_manipulator_axes(View3D *v3d, int colcode, int flagx, int flagy, int flagz)
+static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode, int flagx, int flagy, int flagz)
 {
 
        /* axes */
        if(flagx) {
-               manipulator_setcolor(v3d, 'x', colcode);
+               manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
                if(flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X);
                else if(flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X);
                glBegin(GL_LINES);
@@ -656,7 +816,7 @@ static void draw_manipulator_axes(View3D *v3d, int colcode, int flagx, int flagy
        if(flagy) {
                if(flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y);
                else if(flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y);
-               manipulator_setcolor(v3d, 'y', colcode);
+               manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
                glBegin(GL_LINES);
                glVertex3f(0.0f, 0.2f, 0.0f);
                glVertex3f(0.0f, 1.0f, 0.0f);
@@ -665,7 +825,7 @@ static void draw_manipulator_axes(View3D *v3d, int colcode, int flagx, int flagy
        if(flagz) {
                if(flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z);
                else if(flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z);
-               manipulator_setcolor(v3d, 'z', colcode);
+               manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
                glBegin(GL_LINES);
                glVertex3f(0.0f, 0.0f, 0.2f);
                glVertex3f(0.0f, 0.0f, 1.0f);
@@ -673,153 +833,36 @@ static void draw_manipulator_axes(View3D *v3d, int colcode, int flagx, int flagy
        }
 }
 
-/* only called while G.moving */
-static void draw_manipulator_rotate_ghost(View3D *v3d, RegionView3D *rv3d, int drawflags)
+static void preOrthoFront(int ortho, float twmat[][4], int axis)
 {
-       GLUquadricObj *qobj;
-       float size, phi, startphi, vec[3], svec[3], matt[4][4], cross[3], tmat[3][3];
-       int arcs= (G.rt!=2);
-
-       glDisable(GL_DEPTH_TEST);
-
-       qobj= gluNewQuadric();
-       gluQuadricDrawStyle(qobj, GLU_FILL);
-
-       glColor4ub(0,0,0,64);
-       glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
-       glEnable(GL_BLEND);
-
-       /* we need both [4][4] transforms, t->mat seems to be premul, not post for mat[][4] */
-       Mat4CpyMat4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
-// XXX Mat4MulMat34(matt, t->mat, rv3d->twmat);
-
-       /* Screen aligned view rot circle */
-       if(drawflags & MAN_ROT_V) {
-
-               /* prepare for screen aligned draw */
+       if (ortho == 0) {
+               float omat[4][4];
+               copy_m4_m4(omat, twmat);
+               orthogonalize_m4(omat, axis);
                glPushMatrix();
-               size= screen_aligned(rv3d, rv3d->twmat);
-
-               vec[0]= 0; // XXX (float)(t->con.imval[0] - t->center2d[0]);
-               vec[1]= 0; // XXX (float)(t->con.imval[1] - t->center2d[1]);
-               vec[2]= 0.0f;
-               Normalize(vec);
-
-               startphi= saacos( vec[1] );
-               if(vec[0]<0.0) startphi= -startphi;
-
-               phi= 0; // XXX (float)fmod(180.0*t->val/M_PI, 360.0);
-               if(phi > 180.0) phi-= 360.0;
-               else if(phi<-180.0) phi+= 360.0;
-
-               gluPartialDisk(qobj, 0.0, size, 32, 1, 180.0*startphi/M_PI, phi);
-
-               glPopMatrix();
+               glMultMatrixf(omat);
+               glFrontFace(is_negative_m4(omat) ? GL_CW:GL_CCW);
        }
-       else if(arcs) {
-               float imat[3][3], ivmat[3][3];
-               /* try to get the start rotation */
-
-               svec[0]= 0; // XXX (float)(t->con.imval[0] - t->center2d[0]);
-               svec[1]= 0; // XXX (float)(t->con.imval[1] - t->center2d[1]);
-               svec[2]= 0.0f;
-
-               /* screen aligned vec transform back to manipulator space */
-               Mat3CpyMat4(ivmat, rv3d->viewinv);
-               Mat3CpyMat4(tmat, rv3d->twmat);
-               Mat3Inv(imat, tmat);
-               Mat3MulMat3(tmat, imat, ivmat);
-
-               Mat3MulVecfl(tmat, svec);       // tmat is used further on
-               Normalize(svec);
-       }
-
-       wmMultMatrix(rv3d->twmat);      // aligns with original widget
-
-       /* Z disk */
-       if(drawflags & MAN_ROT_Z) {
-               if(arcs) {
-                       /* correct for squeezed arc */
-                       svec[0]+= tmat[2][0];
-                       svec[1]+= tmat[2][1];
-                       Normalize(svec);
-
-                       startphi= (float)atan2(svec[0], svec[1]);
-               }
-               else startphi= 0.5f*(float)M_PI;
-
-               VECCOPY(vec, rv3d->twmat[0]);   // use x axis to detect rotation
-               Normalize(vec);
-               Normalize(matt[0]);
-               phi= saacos( Inpf(vec, matt[0]) );
-               if(phi!=0.0) {
-                       Crossf(cross, vec, matt[0]);    // results in z vector
-                       if(Inpf(cross, rv3d->twmat[2]) > 0.0) phi= -phi;
-                       gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*(phi)/M_PI);
-               }
-       }
-       /* X disk */
-       if(drawflags & MAN_ROT_X) {
-               if(arcs) {
-                       /* correct for squeezed arc */
-                       svec[1]+= tmat[2][1];
-                       svec[2]+= tmat[2][2];
-                       Normalize(svec);
-
-                       startphi= (float)(M_PI + atan2(svec[2], -svec[1]));
-               }
-               else startphi= 0.0f;
-
-               VECCOPY(vec, rv3d->twmat[1]);   // use y axis to detect rotation
-               Normalize(vec);
-               Normalize(matt[1]);
-               phi= saacos( Inpf(vec, matt[1]) );
-               if(phi!=0.0) {
-                       Crossf(cross, vec, matt[1]);    // results in x vector
-                       if(Inpf(cross, rv3d->twmat[0]) > 0.0) phi= -phi;
-                       glRotatef(90.0, 0.0, 1.0, 0.0);
-                       gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*phi/M_PI);
-                       glRotatef(-90.0, 0.0, 1.0, 0.0);
-               }
-       }
-       /* Y circle */
-       if(drawflags & MAN_ROT_Y) {
-               if(arcs) {
-                       /* correct for squeezed arc */
-                       svec[0]+= tmat[2][0];
-                       svec[2]+= tmat[2][2];
-                       Normalize(svec);
+}
 
-                       startphi= (float)(M_PI + atan2(-svec[0], svec[2]));
-               }
-               else startphi= (float)M_PI;
-
-               VECCOPY(vec, rv3d->twmat[2]);   // use z axis to detect rotation
-               Normalize(vec);
-               Normalize(matt[2]);
-               phi= saacos( Inpf(vec, matt[2]) );
-               if(phi!=0.0) {
-                       Crossf(cross, vec, matt[2]);    // results in y vector
-                       if(Inpf(cross, rv3d->twmat[1]) > 0.0) phi= -phi;
-                       glRotatef(-90.0, 1.0, 0.0, 0.0);
-                       gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*phi/M_PI);
-                       glRotatef(90.0, 1.0, 0.0, 0.0);
-               }
+static void postOrtho(int ortho)
+{
+       if (ortho == 0) {
+               glPopMatrix();
        }
-
-       glDisable(GL_BLEND);
-       wmLoadMatrix(rv3d->viewmat);
 }
 
 static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving, int drawflags, int combo)
 {
        GLUquadricObj *qobj;
        double plane[4];
-       float size, vec[3], unitmat[4][4];
+       float matt[4][4];
+       float size, unitmat[4][4];
        float cywid= 0.33f*0.01f*(float)U.tw_handlesize;
        float cusize= cywid*0.65f;
        int arcs= (G.rt!=2);
        int colcode;
+       int ortho;
 
        if(moving) colcode= MAN_MOVECOL;
        else colcode= MAN_RGB;
@@ -829,21 +872,20 @@ static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving,
 
        /* Init stuff */
        glDisable(GL_DEPTH_TEST);
-       Mat4One(unitmat);
+       unit_m4(unitmat);
 
        qobj= gluNewQuadric();
        gluQuadricDrawStyle(qobj, GLU_FILL);
 
        /* prepare for screen aligned draw */
-       VECCOPY(vec, rv3d->twmat[0]);
-       size= Normalize(vec);
+       size= len_v3(rv3d->twmat[0]);
        glPushMatrix();
        glTranslatef(rv3d->twmat[3][0], rv3d->twmat[3][1], rv3d->twmat[3][2]);
 
        if(arcs) {
                /* clipplane makes nice handles, calc here because of multmatrix but with translate! */
                VECCOPY(plane, rv3d->viewinv[2]);
-               plane[3]= -0.02*size; // clip just a bit more
+               plane[3]= -0.02f*size; // clip just a bit more
                glClipPlane(GL_CLIP_PLANE0, plane);
        }
        /* sets view screen aligned */
@@ -856,6 +898,15 @@ static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving,
                        drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat);
                }
        }
+
+       /* Screen aligned trackball rot circle */
+       if(drawflags & MAN_ROT_T) {
+               if(G.f & G_PICKSEL) glLoadName(MAN_ROT_T);
+
+               UI_ThemeColor(TH_TRANSFORM);
+               drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f*size, unitmat);
+       }
+
        /* Screen aligned view rot circle */
        if(drawflags & MAN_ROT_V) {
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
@@ -867,8 +918,8 @@ static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving,
                        vec[0]= 0; // XXX (float)(t->imval[0] - t->center2d[0]);
                        vec[1]= 0; // XXX (float)(t->imval[1] - t->center2d[1]);
                        vec[2]= 0.0f;
-                       Normalize(vec);
-                       VecMulf(vec, 1.2f*size);
+                       normalize_v3(vec);
+                       mul_v3_fl(vec, 1.2f*size);
                        glBegin(GL_LINES);
                        glVertex3f(0.0f, 0.0f, 0.0f);
                        glVertex3fv(vec);
@@ -877,17 +928,23 @@ static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving,
        }
        glPopMatrix();
 
+
+       ortho = is_orthogonal_m4(rv3d->twmat);
+       
        /* apply the transform delta */
        if(moving) {
-               float matt[4][4];
-               Mat4CpyMat4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
-               // XXX Mat4MulMat34(matt, t->mat, rv3d->twmat);
-               wmMultMatrix(matt);
-               glFrontFace( is_mat4_flipped(matt)?GL_CW:GL_CCW);
+               copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
+               // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat);
+               if (ortho) {
+                       glMultMatrixf(matt);
+                       glFrontFace(is_negative_m4(matt) ? GL_CW:GL_CCW);
+               }
        }
        else {
-               glFrontFace( is_mat4_flipped(rv3d->twmat)?GL_CW:GL_CCW);
-               wmMultMatrix(rv3d->twmat);
+               if (ortho) {
+                       glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW:GL_CCW);
+                       glMultMatrixf(rv3d->twmat);
+               }
        }
 
        /* axes */
@@ -895,23 +952,33 @@ static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving,
                if(!(G.f & G_PICKSEL)) {
                        if( (combo & V3D_MANIP_SCALE)==0) {
                                /* axis */
-                               glBegin(GL_LINES);
                                if( (drawflags & MAN_ROT_X) || (moving && (drawflags & MAN_ROT_Z)) ) {
-                                       manipulator_setcolor(v3d, 'x', colcode);
+                                       preOrthoFront(ortho, rv3d->twmat, 2);
+                                       manipulator_setcolor(v3d, 'X', colcode, 255);
+                                       glBegin(GL_LINES);
                                        glVertex3f(0.2f, 0.0f, 0.0f);
                                        glVertex3f(1.0f, 0.0f, 0.0f);
+                                       glEnd();
+                                       postOrtho(ortho);
                                }
                                if( (drawflags & MAN_ROT_Y) || (moving && (drawflags & MAN_ROT_X)) ) {
-                                       manipulator_setcolor(v3d, 'y', colcode);
+                                       preOrthoFront(ortho, rv3d->twmat, 0);
+                                       manipulator_setcolor(v3d, 'Y', colcode, 255);
+                                       glBegin(GL_LINES);
                                        glVertex3f(0.0f, 0.2f, 0.0f);
                                        glVertex3f(0.0f, 1.0f, 0.0f);
+                                       glEnd();
+                                       postOrtho(ortho);
                                }
                                if( (drawflags & MAN_ROT_Z) || (moving && (drawflags & MAN_ROT_Y)) ) {
-                                       manipulator_setcolor(v3d, 'z', colcode);
+                                       preOrthoFront(ortho, rv3d->twmat, 1);
+                                       manipulator_setcolor(v3d, 'Z', colcode, 255);
+                                       glBegin(GL_LINES);
                                        glVertex3f(0.0f, 0.0f, 0.2f);
                                        glVertex3f(0.0f, 0.0f, 1.0f);
+                                       glEnd();
+                                       postOrtho(ortho);
                                }
-                               glEnd();
                        }
                }
        }
@@ -920,25 +987,31 @@ static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving,
 
                /* Z circle */
                if(drawflags & MAN_ROT_Z) {
+                       preOrthoFront(ortho, matt, 2);
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
-                       manipulator_setcolor(v3d, 'z', colcode);
+                       manipulator_setcolor(v3d, 'Z', colcode, 255);
                        drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
+                       postOrtho(ortho);
                }
                /* X circle */
                if(drawflags & MAN_ROT_X) {
+                       preOrthoFront(ortho, matt, 0);
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
                        glRotatef(90.0, 0.0, 1.0, 0.0);
-                       manipulator_setcolor(v3d, 'x', colcode);
+                       manipulator_setcolor(v3d, 'X', colcode, 255);
                        drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
                        glRotatef(-90.0, 0.0, 1.0, 0.0);
+                       postOrtho(ortho);
                }
                /* Y circle */
                if(drawflags & MAN_ROT_Y) {
+                       preOrthoFront(ortho, matt, 1);
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
                        glRotatef(-90.0, 1.0, 0.0, 0.0);
-                       manipulator_setcolor(v3d, 'y', colcode);
+                       manipulator_setcolor(v3d, 'Y', colcode, 255);
                        drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
                        glRotatef(90.0, 1.0, 0.0, 0.0);
+                       postOrtho(ortho);
                }
 
                if(arcs) glDisable(GL_CLIP_PLANE0);
@@ -949,25 +1022,31 @@ static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving,
 
                /* Z circle */
                if(drawflags & MAN_ROT_Z) {
+                       preOrthoFront(ortho, rv3d->twmat, 2);
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
-                       manipulator_setcolor(v3d, 'z', colcode);
+                       manipulator_setcolor(v3d, 'Z', colcode, 255);
                        partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
+                       postOrtho(ortho);
                }
                /* X circle */
                if(drawflags & MAN_ROT_X) {
+                       preOrthoFront(ortho, rv3d->twmat, 0);
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
                        glRotatef(90.0, 0.0, 1.0, 0.0);
-                       manipulator_setcolor(v3d, 'x', colcode);
+                       manipulator_setcolor(v3d, 'X', colcode, 255);
                        partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
                        glRotatef(-90.0, 0.0, 1.0, 0.0);
+                       postOrtho(ortho);
                }
                /* Y circle */
                if(drawflags & MAN_ROT_Y) {
+                       preOrthoFront(ortho, rv3d->twmat, 1);
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
                        glRotatef(-90.0, 1.0, 0.0, 0.0);
-                       manipulator_setcolor(v3d, 'y', colcode);
+                       manipulator_setcolor(v3d, 'Y', colcode, 255);
                        partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
                        glRotatef(90.0, 1.0, 0.0, 0.0);
+                       postOrtho(ortho);
                }
 
                glDisable(GL_CLIP_PLANE0);
@@ -977,45 +1056,51 @@ static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving,
 
                /* Z handle on X axis */
                if(drawflags & MAN_ROT_Z) {
+                       preOrthoFront(ortho, rv3d->twmat, 2);
                        glPushMatrix();
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
-                       manipulator_setcolor(v3d, 'z', colcode);
+                       manipulator_setcolor(v3d, 'Z', colcode, 255);
 
                        partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
 
                        glPopMatrix();
+                       postOrtho(ortho);
                }
 
                /* Y handle on X axis */
                if(drawflags & MAN_ROT_Y) {
+                       preOrthoFront(ortho, rv3d->twmat, 1);
                        glPushMatrix();
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
-                       manipulator_setcolor(v3d, 'y', colcode);
+                       manipulator_setcolor(v3d, 'Y', colcode, 255);
 
                        glRotatef(90.0, 1.0, 0.0, 0.0);
                        glRotatef(90.0, 0.0, 0.0, 1.0);
                        partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
 
                        glPopMatrix();
+                       postOrtho(ortho);
                }
 
                /* X handle on Z axis */
                if(drawflags & MAN_ROT_X) {
+                       preOrthoFront(ortho, rv3d->twmat, 0);
                        glPushMatrix();
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
-                       manipulator_setcolor(v3d, 'x', colcode);
+                       manipulator_setcolor(v3d, 'X', colcode, 255);
 
                        glRotatef(-90.0, 0.0, 1.0, 0.0);
                        glRotatef(90.0, 0.0, 0.0, 1.0);
                        partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
 
                        glPopMatrix();
+                       postOrtho(ortho);
                }
 
        }
 
        /* restore */
-       wmLoadMatrix(rv3d->viewmat);
+       glLoadMatrixf(rv3d->viewmat);
        gluDeleteQuadric(qobj);
        if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
 
@@ -1101,10 +1186,10 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving,
                /* center circle, do not add to selection when shift is pressed (planar constraint)  */
                if( (G.f & G_PICKSEL) && shift==0) glLoadName(MAN_SCALE_C);
 
-               manipulator_setcolor(v3d, 'c', colcode);
+               manipulator_setcolor(v3d, 'C', colcode, 255);
                glPushMatrix();
                size= screen_aligned(rv3d, rv3d->twmat);
-               Mat4One(unitmat);
+               unit_m4(unitmat);
                drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f*size, unitmat);
                glPopMatrix();
 
@@ -1115,40 +1200,40 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving,
        if(moving) {
                float matt[4][4];
 
-               Mat4CpyMat4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
-               // XXX Mat4MulMat34(matt, t->mat, rv3d->twmat);
-               wmMultMatrix(matt);
-               glFrontFace( is_mat4_flipped(matt)?GL_CW:GL_CCW);
+               copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
+               // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat);
+               glMultMatrixf(matt);
+               glFrontFace(is_negative_m4(matt) ? GL_CW:GL_CCW);
        }
        else {
-               wmMultMatrix(rv3d->twmat);
-               glFrontFace( is_mat4_flipped(rv3d->twmat)?GL_CW:GL_CCW);
+               glMultMatrixf(rv3d->twmat);
+               glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW:GL_CCW);
        }
 
        /* axis */
 
        /* in combo mode, this is always drawn as first type */
-       draw_manipulator_axes(v3d, colcode, drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z);
+       draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z);
 
        /* Z cube */
        glTranslatef(0.0, 0.0, dz);
        if(drawflags & MAN_SCALE_Z) {
                if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z);
-               manipulator_setcolor(v3d, 'z', colcode);
+               manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
                drawsolidcube(cusize);
        }
        /* X cube */
        glTranslatef(dz, 0.0, -dz);
        if(drawflags & MAN_SCALE_X) {
                if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_X);
-               manipulator_setcolor(v3d, 'x', colcode);
+               manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
                drawsolidcube(cusize);
        }
        /* Y cube */
        glTranslatef(-dz, dz, 0.0);
        if(drawflags & MAN_SCALE_Y) {
                if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y);
-               manipulator_setcolor(v3d, 'y', colcode);
+               manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
                drawsolidcube(cusize);
        }
 
@@ -1166,7 +1251,7 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving,
        }
 
        /* restore */
-       wmLoadMatrix(rv3d->viewmat);
+       glLoadMatrixf(rv3d->viewmat);
 
        if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
        glFrontFace(GL_CCW);
@@ -1199,7 +1284,7 @@ static void draw_cylinder(GLUquadricObj *qobj, float len, float width)
 }
 
 
-static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int moving, int drawflags, int combo, int colcode)
+static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int UNUSED(moving), int drawflags, int combo, int colcode)
 {
        GLUquadricObj *qobj;
        float cylen= 0.01f*(float)U.tw_handlesize;
@@ -1219,22 +1304,22 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int movi
        /* center circle, do not add to selection when shift is pressed (planar constraint) */
        if( (G.f & G_PICKSEL) && shift==0) glLoadName(MAN_TRANS_C);
 
-       manipulator_setcolor(v3d, 'c', colcode);
+       manipulator_setcolor(v3d, 'C', colcode, 255);
        glPushMatrix();
        size= screen_aligned(rv3d, rv3d->twmat);
-       Mat4One(unitmat);
+       unit_m4(unitmat);
        drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f*size, unitmat);
        glPopMatrix();
 
        /* and now apply matrix, we move to local matrix drawing */
-       wmMultMatrix(rv3d->twmat);
+       glMultMatrixf(rv3d->twmat);
 
        /* axis */
        glLoadName(-1);
 
        // translate drawn as last, only axis when no combo with scale, or for ghosting
        if((combo & V3D_MANIP_SCALE)==0 || colcode==MAN_GHOST)
-               draw_manipulator_axes(v3d, colcode, drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z);
+               draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z);
 
 
        /* offset in combo mode, for rotate a bit more */
@@ -1246,7 +1331,7 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int movi
        glTranslatef(0.0, 0.0, dz);
        if(drawflags & MAN_TRANS_Z) {
                if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_Z);
-               manipulator_setcolor(v3d, 'z', colcode);
+               manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
                draw_cone(qobj, cylen, cywid);
        }
        /* X Cone */
@@ -1254,7 +1339,7 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int movi
        if(drawflags & MAN_TRANS_X) {
                if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_X);
                glRotatef(90.0, 0.0, 1.0, 0.0);
-               manipulator_setcolor(v3d, 'x', colcode);
+               manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
                draw_cone(qobj, cylen, cywid);
                glRotatef(-90.0, 0.0, 1.0, 0.0);
        }
@@ -1263,12 +1348,12 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int movi
        if(drawflags & MAN_TRANS_Y) {
                if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_Y);
                glRotatef(-90.0, 1.0, 0.0, 0.0);
-               manipulator_setcolor(v3d, 'y', colcode);
+               manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
                draw_cone(qobj, cylen, cywid);
        }
 
        gluDeleteQuadric(qobj);
-       wmLoadMatrix(rv3d->viewmat);
+       glLoadMatrixf(rv3d->viewmat);
 
        if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
 
@@ -1294,8 +1379,7 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
 
        /* Screen aligned view rot circle */
        if(drawflags & MAN_ROT_V) {
-               float unitmat[4][4];
-               Mat4One(unitmat);
+               float unitmat[4][4]= MAT4_UNITY;
 
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
                UI_ThemeColor(TH_TRANSFORM);
@@ -1306,8 +1390,8 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
                        vec[0]= 0; // XXX (float)(t->imval[0] - t->center2d[0]);
                        vec[1]= 0; // XXX (float)(t->imval[1] - t->center2d[1]);
                        vec[2]= 0.0f;
-                       Normalize(vec);
-                       VecMulf(vec, 1.2f*size);
+                       normalize_v3(vec);
+                       mul_v3_fl(vec, 1.2f*size);
                        glBegin(GL_LINES);
                        glVertex3f(0.0, 0.0, 0.0);
                        glVertex3fv(vec);
@@ -1319,24 +1403,24 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
        /* apply the transform delta */
        if(moving) {
                float matt[4][4];
-               Mat4CpyMat4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
+               copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
                // XXX          if (t->flag & T_USES_MANIPULATOR) {
-               // XXX                  Mat4MulMat34(matt, t->mat, rv3d->twmat);
+               // XXX                  mul_m4_m3m4(matt, t->mat, rv3d->twmat);
                // XXX }
-               wmMultMatrix(matt);
+               glMultMatrixf(matt);
        }
        else {
-               wmMultMatrix(rv3d->twmat);
+               glMultMatrixf(rv3d->twmat);
        }
 
-       glFrontFace( is_mat4_flipped(rv3d->twmat)?GL_CW:GL_CCW);
+       glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW:GL_CCW);
 
        /* axis */
        if( (G.f & G_PICKSEL)==0 ) {
 
                // only draw axis when combo didn't draw scale axes
                if((combo & V3D_MANIP_SCALE)==0)
-                       draw_manipulator_axes(v3d, colcode, drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z);
+                       draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z);
 
                /* only has to be set when not in picking */
                gluQuadricDrawStyle(qobj, GLU_FILL);
@@ -1346,7 +1430,7 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
        glTranslatef(0.0, 0.0, 1.0);
        if(drawflags & MAN_ROT_Z) {
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
-               manipulator_setcolor(v3d, 'z', colcode);
+               manipulator_setcolor(v3d, 'Z', colcode, 255);
                draw_cylinder(qobj, cylen, cywid);
        }
        /* X cyl */
@@ -1354,7 +1438,7 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
        if(drawflags & MAN_ROT_X) {
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
                glRotatef(90.0, 0.0, 1.0, 0.0);
-               manipulator_setcolor(v3d, 'x', colcode);
+               manipulator_setcolor(v3d, 'X', colcode, 255);
                draw_cylinder(qobj, cylen, cywid);
                glRotatef(-90.0, 0.0, 1.0, 0.0);
        }
@@ -1363,14 +1447,14 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
        if(drawflags & MAN_ROT_Y) {
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
                glRotatef(-90.0, 1.0, 0.0, 0.0);
-               manipulator_setcolor(v3d, 'y', colcode);
+               manipulator_setcolor(v3d, 'Y', colcode, 255);
                draw_cylinder(qobj, cylen, cywid);
        }
 
        /* restore */
 
        gluDeleteQuadric(qobj);
-       wmLoadMatrix(rv3d->viewmat);
+       glLoadMatrixf(rv3d->viewmat);
 
        if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
 
@@ -1379,17 +1463,6 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
 
 /* ********************************************* */
 
-static float get_manipulator_drawsize(ARegion *ar)
-{
-       RegionView3D *rv3d= ar->regiondata;
-       float size = get_drawsize(ar, rv3d->twmat[3]);
-
-       size*= (float)U.tw_size;
-
-       return size;
-}
-
-
 /* main call, does calc centers & orientation too */
 /* uses global G.moving */
 static int drawflags= 0xFFFF;          // only for the calls below, belongs in scene...?
@@ -1404,14 +1477,14 @@ void BIF_draw_manipulator(const bContext *C)
        int totsel;
 
        if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return;
-       if(G.moving && (G.moving & G_TRANSFORM_MANIP)==0) return;
+//     if(G.moving && (G.moving & G_TRANSFORM_MANIP)==0) return;
 
-       if(G.moving==0) {
+//     if(G.moving==0) {
+       {
                v3d->twflag &= ~V3D_DRAW_MANIPULATOR;
 
                totsel= calc_manipulator_stats(C);
                if(totsel==0) return;
-               drawflags= v3d->twdrawflag;     /* set in calc_manipulator_stats */
 
                v3d->twflag |= V3D_DRAW_MANIPULATOR;
 
@@ -1437,49 +1510,37 @@ void BIF_draw_manipulator(const bContext *C)
                        break;
                }
 
-               Mat4MulFloat3((float *)rv3d->twmat, get_manipulator_drawsize(ar));
+               mul_mat3_m4_fl(rv3d->twmat, ED_view3d_pixel_size(rv3d, rv3d->twmat[3]) * U.tw_size * 5.0f);
        }
 
+       test_manipulator_axis(C);
+       drawflags= rv3d->twdrawflag;    /* set in calc_manipulator_stats */
+
        if(v3d->twflag & V3D_DRAW_MANIPULATOR) {
 
+               glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+               glEnable(GL_BLEND);
                if(v3d->twtype & V3D_MANIP_ROTATE) {
 
-                       /* rotate has special ghosting draw, for pie chart */
-                       if(G.moving) draw_manipulator_rotate_ghost(v3d, rv3d, drawflags);
-
-                       if(G.moving) glEnable(GL_BLEND);
-
                        if(G.rt==3) {
                                if(G.moving) draw_manipulator_rotate_cyl(v3d, rv3d, 1, drawflags, v3d->twtype, MAN_MOVECOL);
                                else draw_manipulator_rotate_cyl(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
                        }
                        else
-                               draw_manipulator_rotate(v3d, rv3d, G.moving, drawflags, v3d->twtype);
-
-                       glDisable(GL_BLEND);
+                               draw_manipulator_rotate(v3d, rv3d, 0 /* G.moving*/, drawflags, v3d->twtype);
                }
                if(v3d->twtype & V3D_MANIP_SCALE) {
-                       if(G.moving) {
-                               glEnable(GL_BLEND);
-                               draw_manipulator_scale(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_GHOST);
-                               draw_manipulator_scale(v3d, rv3d, 1, drawflags, v3d->twtype, MAN_MOVECOL);
-                               glDisable(GL_BLEND);
-                       }
-                       else draw_manipulator_scale(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
+                       draw_manipulator_scale(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
                }
                if(v3d->twtype & V3D_MANIP_TRANSLATE) {
-                       if(G.moving) {
-                               glEnable(GL_BLEND);
-                               draw_manipulator_translate(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_GHOST);
-                               draw_manipulator_translate(v3d, rv3d, 1, drawflags, v3d->twtype, MAN_MOVECOL);
-                               glDisable(GL_BLEND);
-                       }
-                       else draw_manipulator_translate(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
+                       draw_manipulator_translate(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
                }
+
+               glDisable(GL_BLEND);
        }
 }
 
-static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, short *mval, float hotspot)
+static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], float hotspot)
 {
        View3D *v3d= sa->spacedata.first;
        RegionView3D *rv3d= ar->regiondata;
@@ -1496,7 +1557,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, short *mval, float ho
        rect.ymax= mval[1]+hotspot;
 
        setwinmatrixview3d(ar, v3d, &rect);
-       Mat4MulMat4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
+       mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
 
        glSelectBuffer( 64, buffer);
        glRenderMode(GL_SELECT);
@@ -1505,20 +1566,20 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, short *mval, float ho
 
        /* do the drawing */
        if(v3d->twtype & V3D_MANIP_ROTATE) {
-               if(G.rt==3) draw_manipulator_rotate_cyl(v3d, rv3d, 0, MAN_ROT_C & v3d->twdrawflag, v3d->twtype, MAN_RGB);
-               else draw_manipulator_rotate(v3d, rv3d, 0, MAN_ROT_C & v3d->twdrawflag, v3d->twtype);
+               if(G.rt==3) draw_manipulator_rotate_cyl(v3d, rv3d, 0, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB);
+               else draw_manipulator_rotate(v3d, rv3d, 0, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype);
        }
        if(v3d->twtype & V3D_MANIP_SCALE)
-               draw_manipulator_scale(v3d, rv3d, 0, MAN_SCALE_C & v3d->twdrawflag, v3d->twtype, MAN_RGB);
+               draw_manipulator_scale(v3d, rv3d, 0, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB);
        if(v3d->twtype & V3D_MANIP_TRANSLATE)
-               draw_manipulator_translate(v3d, rv3d, 0, MAN_TRANS_C & v3d->twdrawflag, v3d->twtype, MAN_RGB);
+               draw_manipulator_translate(v3d, rv3d, 0, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB);
 
        glPopName();
        hits= glRenderMode(GL_RENDER);
 
        G.f &= ~G_PICKSEL;
        setwinmatrixview3d(ar, v3d, NULL);
-       Mat4MulMat4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
+       mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
 
        if(hits==1) return buffer[3];
        else if(hits>1) {
@@ -1558,6 +1619,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, short *mval, float ho
        return 0;
 }
 
+
 /* return 0; nothing happened */
 int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op)
 {
@@ -1571,6 +1633,9 @@ int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op)
        if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return 0;
        if(!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return 0;
 
+       /* Force orientation */
+       RNA_enum_set(op->ptr, "constraint_orientation", v3d->twmode);
+
        // find the hotspots first test narrow hotspot
        val= manipulator_selectbuf(sa, ar, event->mval, 0.5f*(float)U.tw_hotspot);
        if(val) {
@@ -1609,7 +1674,8 @@ int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op)
                                break;
                        }
                        RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
-                       WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_DEFAULT, op->ptr);
+                       WM_operator_name_call(C, "TRANSFORM_OT_translate", WM_OP_INVOKE_DEFAULT, op->ptr);
+                       //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_translate", 0), event, op->ptr, NULL, FALSE);
                }
                else if (drawflags & MAN_SCALE_C) {
                        switch(drawflags) {
@@ -1639,10 +1705,12 @@ int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op)
                                break;
                        }
                        RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
-                       WM_operator_name_call(C, "TFM_OT_resize", WM_OP_INVOKE_DEFAULT, op->ptr);
+                       WM_operator_name_call(C, "TRANSFORM_OT_resize", WM_OP_INVOKE_DEFAULT, op->ptr);
+                       //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_resize", 0), event, op->ptr, NULL, FALSE);
                }
                else if (drawflags == MAN_ROT_T) { /* trackball need special case, init is different */
-                       WM_operator_name_call(C, "TFM_OT_trackball", WM_OP_INVOKE_DEFAULT, op->ptr);
+                       WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, op->ptr);
+                       //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, op->ptr, NULL, FALSE);
                }
                else if (drawflags & MAN_ROT_C) {
                        switch(drawflags) {
@@ -1657,7 +1725,8 @@ int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op)
                                break;
                        }
                        RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
-                       WM_operator_name_call(C, "TFM_OT_rotate", WM_OP_INVOKE_DEFAULT, op->ptr);
+                       WM_operator_name_call(C, "TRANSFORM_OT_rotate", WM_OP_INVOKE_DEFAULT, op->ptr);
+                       //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_rotate", 0), event, op->ptr, NULL, FALSE);
                }
        }
        /* after transform, restore drawflags */