Sculpt:
[blender.git] / source / blender / blenkernel / intern / constraint.c
index 912bc7a..aff3bf0 100644 (file)
 #include <float.h>
 
 #include "MEM_guardedalloc.h"
-//XXX #include "nla.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_arithb.h"
+#include "BLI_math.h"
+#include "BLI_editVert.h"
 
 #include "DNA_armature_types.h"
 #include "DNA_constraint_types.h"
+#include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_action_types.h"
 #include "DNA_curve_types.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_idprop.h"
+#include "BKE_shrinkwrap.h"
+#include "BKE_mesh.h"
 
 #ifndef DISABLE_PYTHON
 #include "BPY_extern.h"
 #endif
 
+#include "ED_mesh.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -92,7 +96,7 @@
 /* Find the first available, non-duplicate name for a given constraint */
 void unique_constraint_name (bConstraint *con, ListBase *list)
 {
-       BLI_uniquename(list, con, "Const", offsetof(bConstraint, name), 32);
+       BLI_uniquename(list, con, "Const", '.', offsetof(bConstraint, name), 32);
 }
 
 /* ----------------- Evaluation Loop Preparation --------------- */
@@ -117,12 +121,13 @@ bConstraintOb *constraints_make_evalob (Scene *scene, Object *ob, void *subdata,
                        if (ob) {
                                cob->ob = ob;
                                cob->type = datatype;
-                               Mat4CpyMat4(cob->matrix, ob->obmat);
+                               cob->rotOrder = EULER_ORDER_DEFAULT; // TODO: when objects have rotation order too, use that
+                               copy_m4_m4(cob->matrix, ob->obmat);
                        }
                        else
-                               Mat4One(cob->matrix);
+                               unit_m4(cob->matrix);
                        
-                       Mat4CpyMat4(cob->startmat, cob->matrix);
+                       copy_m4_m4(cob->startmat, cob->matrix);
                }
                        break;
                case CONSTRAINT_OBTYPE_BONE:
@@ -133,19 +138,28 @@ bConstraintOb *constraints_make_evalob (Scene *scene, Object *ob, void *subdata,
                                cob->pchan = (bPoseChannel *)subdata;
                                cob->type = datatype;
                                
+                               if (cob->pchan->rotmode > 0) {
+                                       /* should be some type of Euler order */
+                                       cob->rotOrder= cob->pchan->rotmode; 
+                               }
+                               else {
+                                       /* Quats, so eulers should just use default order */
+                                       cob->rotOrder= EULER_ORDER_DEFAULT;
+                               }
+                               
                                /* matrix in world-space */
-                               Mat4MulMat4(cob->matrix, cob->pchan->pose_mat, ob->obmat);
+                               mul_m4_m4m4(cob->matrix, cob->pchan->pose_mat, ob->obmat);
                        }
                        else
-                               Mat4One(cob->matrix);
+                               unit_m4(cob->matrix);
                                
-                       Mat4CpyMat4(cob->startmat, cob->matrix);
+                       copy_m4_m4(cob->startmat, cob->matrix);
                }
                        break;
                        
                default: /* other types not yet handled */
-                       Mat4One(cob->matrix);
-                       Mat4One(cob->startmat);
+                       unit_m4(cob->matrix);
+                       unit_m4(cob->startmat);
                        break;
        }
        
@@ -162,8 +176,8 @@ void constraints_clear_evalob (bConstraintOb *cob)
                return;
        
        /* calculate delta of constraints evaluation */
-       Mat4Invert(imat, cob->startmat);
-       Mat4MulMat4(delta, imat, cob->matrix);
+       invert_m4_m4(imat, cob->startmat);
+       mul_m4_m4m4(delta, imat, cob->matrix);
        
        /* copy matrices back to source */
        switch (cob->type) {
@@ -172,10 +186,10 @@ void constraints_clear_evalob (bConstraintOb *cob)
                        /* cob->ob might not exist! */
                        if (cob->ob) {
                                /* copy new ob-matrix back to owner */
-                               Mat4CpyMat4(cob->ob->obmat, cob->matrix);
+                               copy_m4_m4(cob->ob->obmat, cob->matrix);
                                
                                /* copy inverse of delta back to owner */
-                               Mat4Invert(cob->ob->constinv, delta);
+                               invert_m4_m4(cob->ob->constinv, delta);
                        }
                }
                        break;
@@ -184,10 +198,10 @@ void constraints_clear_evalob (bConstraintOb *cob)
                        /* cob->ob or cob->pchan might not exist */
                        if (cob->ob && cob->pchan) {
                                /* copy new pose-matrix back to owner */
-                               Mat4MulMat4(cob->pchan->pose_mat, cob->matrix, cob->ob->imat);
+                               mul_m4_m4m4(cob->pchan->pose_mat, cob->matrix, cob->ob->imat);
                                
                                /* copy inverse of delta back to owner */
-                               Mat4Invert(cob->pchan->constinv, delta);
+                               invert_m4_m4(cob->pchan->constinv, delta);
                        }
                }
                        break;
@@ -221,9 +235,9 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                        case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */
                        {
                                /* world to pose */
-                               Mat4Invert(imat, ob->obmat);
-                               Mat4CpyMat4(tempmat, mat);
-                               Mat4MulMat4(mat, tempmat, imat);
+                               invert_m4_m4(imat, ob->obmat);
+                               copy_m4_m4(tempmat, mat);
+                               mul_m4_m4m4(mat, tempmat, imat);
                                
                                /* use pose-space as stepping stone for other spaces... */
                                if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) {
@@ -236,8 +250,8 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                        {
                                /* pose to world */
                                if (to == CONSTRAINT_SPACE_WORLD) {
-                                       Mat4CpyMat4(tempmat, mat);
-                                       Mat4MulMat4(mat, tempmat, ob->obmat);
+                                       copy_m4_m4(tempmat, mat);
+                                       mul_m4_m4m4(mat, tempmat, ob->obmat);
                                }
                                /* pose to local */
                                else if (to == CONSTRAINT_SPACE_LOCAL) {
@@ -246,7 +260,7 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                                                        float offs_bone[4][4];
                                                                
                                                        /* construct offs_bone the same way it is done in armature.c */
-                                                       Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
+                                                       copy_m4_m3(offs_bone, pchan->bone->bone_mat);
                                                        VECCOPY(offs_bone[3], pchan->bone->head);
                                                        offs_bone[3][1]+= pchan->bone->parent->length;
                                                        
@@ -255,37 +269,37 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                                                                float tmat[4][4];
                                                                
                                                                /* the rotation of the parent restposition */
-                                                               Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat);
+                                                               copy_m4_m4(tmat, pchan->bone->parent->arm_mat);
                                                                
                                                                /* the location of actual parent transform */
                                                                VECCOPY(tmat[3], offs_bone[3]);
                                                                offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
-                                                               Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]);
+                                                               mul_m4_v3(pchan->parent->pose_mat, tmat[3]);
                                                                
-                                                               Mat4MulMat4(diff_mat, offs_bone, tmat);
-                                                               Mat4Invert(imat, diff_mat);
+                                                               mul_m4_m4m4(diff_mat, offs_bone, tmat);
+                                                               invert_m4_m4(imat, diff_mat);
                                                        }
                                                        else {
                                                                /* pose_mat = par_pose_mat * bone_mat * chan_mat */
-                                                               Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat);
-                                                               Mat4Invert(imat, diff_mat);
+                                                               mul_m4_m4m4(diff_mat, offs_bone, pchan->parent->pose_mat);
+                                                               invert_m4_m4(imat, diff_mat);
                                                        }
                                                }
                                                else {
                                                        /* pose_mat = chan_mat * arm_mat */
-                                                       Mat4Invert(imat, pchan->bone->arm_mat);
+                                                       invert_m4_m4(imat, pchan->bone->arm_mat);
                                                }
                                                
-                                               Mat4CpyMat4(tempmat, mat);
-                                               Mat4MulMat4(mat, tempmat, imat);
+                                               copy_m4_m4(tempmat, mat);
+                                               mul_m4_m4m4(mat, tempmat, imat);
                                        }
                                }
                                /* pose to local with parent */
                                else if (to == CONSTRAINT_SPACE_PARLOCAL) {
                                        if (pchan->bone) {
-                                               Mat4Invert(imat, pchan->bone->arm_mat);
-                                               Mat4CpyMat4(tempmat, mat);
-                                               Mat4MulMat4(mat, tempmat, imat);
+                                               invert_m4_m4(imat, pchan->bone->arm_mat);
+                                               copy_m4_m4(tempmat, mat);
+                                               mul_m4_m4m4(mat, tempmat, imat);
                                        }
                                }
                        }
@@ -299,7 +313,7 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                                                float offs_bone[4][4];
                                                
                                                /* construct offs_bone the same way it is done in armature.c */
-                                               Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
+                                               copy_m4_m3(offs_bone, pchan->bone->bone_mat);
                                                VECCOPY(offs_bone[3], pchan->bone->head);
                                                offs_bone[3][1]+= pchan->bone->parent->length;
                                                
@@ -308,29 +322,29 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                                                        float tmat[4][4];
                                                        
                                                        /* the rotation of the parent restposition */
-                                                       Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat);
+                                                       copy_m4_m4(tmat, pchan->bone->parent->arm_mat);
                                                        
                                                        /* the location of actual parent transform */
                                                        VECCOPY(tmat[3], offs_bone[3]);
                                                        offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
-                                                       Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]);
+                                                       mul_m4_v3(pchan->parent->pose_mat, tmat[3]);
                                                        
-                                                       Mat4MulMat4(diff_mat, offs_bone, tmat);
-                                                       Mat4CpyMat4(tempmat, mat);
-                                                       Mat4MulMat4(mat, tempmat, diff_mat);
+                                                       mul_m4_m4m4(diff_mat, offs_bone, tmat);
+                                                       copy_m4_m4(tempmat, mat);
+                                                       mul_m4_m4m4(mat, tempmat, diff_mat);
                                                }
                                                else {
                                                        /* pose_mat = par_pose_mat * bone_mat * chan_mat */
-                                                       Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat);
-                                                       Mat4CpyMat4(tempmat, mat);
-                                                       Mat4MulMat4(mat, tempmat, diff_mat);
+                                                       mul_m4_m4m4(diff_mat, offs_bone, pchan->parent->pose_mat);
+                                                       copy_m4_m4(tempmat, mat);
+                                                       mul_m4_m4m4(mat, tempmat, diff_mat);
                                                }
                                        }
                                        else {
-                                               Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
+                                               copy_m4_m4(diff_mat, pchan->bone->arm_mat);
                                                
-                                               Mat4CpyMat4(tempmat, mat);
-                                               Mat4MulMat4(mat, tempmat, diff_mat);
+                                               copy_m4_m4(tempmat, mat);
+                                               mul_m4_m4m4(mat, tempmat, diff_mat);
                                        }
                                }
                                
@@ -345,9 +359,9 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                        {
                                /* local + parent to pose */
                                if (pchan->bone) {                                      
-                                       Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
-                                       Mat4CpyMat4(tempmat, mat);
-                                       Mat4MulMat4(mat, diff_mat, tempmat);
+                                       copy_m4_m4(diff_mat, pchan->bone->arm_mat);
+                                       copy_m4_m4(tempmat, mat);
+                                       mul_m4_m4m4(mat, diff_mat, tempmat);
                                }
                                
                                /* use pose-space as stepping stone for other spaces */
@@ -365,19 +379,19 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                        /* check if object has a parent - otherwise this won't work */
                        if (ob->parent) {
                                /* 'subtract' parent's effects from owner */
-                               Mat4MulMat4(diff_mat, ob->parentinv, ob->parent->obmat);
-                               Mat4Invert(imat, diff_mat);
-                               Mat4CpyMat4(tempmat, mat);
-                               Mat4MulMat4(mat, tempmat, imat);
+                               mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat);
+                               invert_m4_m4(imat, diff_mat);
+                               copy_m4_m4(tempmat, mat);
+                               mul_m4_m4m4(mat, tempmat, imat);
                        }
                }
                else if (from==CONSTRAINT_SPACE_LOCAL && to==CONSTRAINT_SPACE_WORLD) {
                        /* check that object has a parent - otherwise this won't work */
                        if (ob->parent) {
                                /* 'add' parent's effect back to owner */
-                               Mat4CpyMat4(tempmat, mat);
-                               Mat4MulMat4(diff_mat, ob->parentinv, ob->parent->obmat);
-                               Mat4MulMat4(mat, tempmat, diff_mat);
+                               copy_m4_m4(tempmat, mat);
+                               mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat);
+                               mul_m4_m4m4(mat, tempmat, diff_mat);
                        }
                }
        }
@@ -386,51 +400,61 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
 /* ------------ General Target Matrix Tools ---------- */
 
 /* function that sets the given matrix based on given vertex group in mesh */
-static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
+static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, float mat[][4])
 {
        DerivedMesh *dm;
        Mesh *me= ob->data;
+       EditMesh *em = BKE_mesh_get_editmesh(me);
        float vec[3] = {0.0f, 0.0f, 0.0f}, tvec[3];
        float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3];
        float imat[3][3], tmat[3][3];
        int dgroup;
+       short freeDM = 0;
        
        /* initialize target matrix using target matrix */
-       Mat4CpyMat4(mat, ob->obmat);
+       copy_m4_m4(mat, ob->obmat);
        
        /* get index of vertex group */
        dgroup = get_named_vertexgroup_num(ob, substring);
        if (dgroup < 0) return;
        
        /* get DerivedMesh */
-       if (me->edit_mesh) {
+       if (em) {
                /* target is in editmode, so get a special derived mesh */
-               dm = CDDM_from_editmesh(me->edit_mesh, ob->data);
+               dm = CDDM_from_editmesh(em, ob->data);
+               freeDM= 1;
        }
        else {
-               /* when not in EditMode, this should exist */
-               dm = (DerivedMesh *)ob->derivedFinal;
+               /* when not in EditMode, use the 'final' derived mesh 
+                *      - check if the custom data masks for derivedFinal mean that we can just use that
+                *        (this is more effficient + sufficient for most cases)
+                */
+               if (ob->lastDataMask != CD_MASK_DERIVEDMESH) {
+                       dm = mesh_get_derived_final(scene, ob, CD_MASK_DERIVEDMESH);
+                       freeDM= 1;
+               }
+               else 
+                       dm = (DerivedMesh *)ob->derivedFinal;
        }
        
        /* only continue if there's a valid DerivedMesh */
        if (dm) {
                MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-               int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
                int numVerts = dm->getNumVerts(dm);
                int i, j, count = 0;
                float co[3], nor[3];
                
-               /* check that dvert and index are valid pointers (just in case) */
-               if (dvert && index) {
+               /* check that dvert is a valid pointers (just in case) */
+               if (dvert) {
                        /* get the average of all verts with that are in the vertex-group */
-                       for (i = 0; i < numVerts; i++, index++) {       
+                       for (i = 0; i < numVerts; i++) {        
                                for (j = 0; j < dvert[i].totweight; j++) {
                                        /* does this vertex belong to nominated vertex group? */
                                        if (dvert[i].dw[j].def_nr == dgroup) {
                                                dm->getVertCo(dm, i, co);
                                                dm->getVertNo(dm, i, nor);
-                                               VecAddf(vec, vec, co);
-                                               VecAddf(normal, normal, nor);
+                                               add_v3_v3v3(vec, vec, co);
+                                               add_v3_v3v3(normal, normal, nor);
                                                count++;
                                                break;
                                        }
@@ -441,8 +465,8 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
                        
                        /* calculate averages of normal and coordinates */
                        if (count > 0) {
-                               VecMulf(vec, 1.0f / count);
-                               VecMulf(normal, 1.0f / count);
+                               mul_v3_fl(vec, 1.0f / count);
+                               mul_v3_fl(normal, 1.0f / count);
                        }
                        
                        
@@ -451,33 +475,34 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
                         *                      calc_manipulator_stats, V3D_MANIP_NORMAL case
                         */
                        /*      we need the transpose of the inverse for a normal... */
-                       Mat3CpyMat4(imat, ob->obmat);
+                       copy_m3_m4(imat, ob->obmat);
                        
-                       Mat3Inv(tmat, imat);
-                       Mat3Transp(tmat);
-                       Mat3MulVecfl(tmat, normal);
+                       invert_m3_m3(tmat, imat);
+                       transpose_m3(tmat);
+                       mul_m3_v3(tmat, normal);
                        
-                       Normalize(normal);
+                       normalize_v3(normal);
                        VECCOPY(plane, tmat[1]);
                        
                        VECCOPY(tmat[2], normal);
-                       Crossf(tmat[0], normal, plane);
-                       Crossf(tmat[1], tmat[2], tmat[0]);
+                       cross_v3_v3v3(tmat[0], normal, plane);
+                       cross_v3_v3v3(tmat[1], tmat[2], tmat[0]);
                        
-                       Mat4CpyMat3(mat, tmat);
-                       Mat4Ortho(mat);
+                       copy_m4_m3(mat, tmat);
+                       normalize_m4(mat);
                        
                        
                        /* apply the average coordinate as the new location */
-                       VecMat4MulVecfl(tvec, ob->obmat, vec);
+                       mul_v3_m4v3(tvec, ob->obmat, vec);
                        VECCOPY(mat[3], tvec);
                }
        }
        
        /* free temporary DerivedMesh created (in EditMode case) */
-       if (me->edit_mesh) {
-               if (dm) dm->release(dm);
-       }
+       if (dm && freeDM)
+               dm->release(dm);
+       if (em)
+               BKE_mesh_end_editmesh(me, em);
 }
 
 /* function that sets the given matrix based on given vertex group in lattice */
@@ -496,7 +521,7 @@ static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][
        int i, n;
        
        /* initialize target matrix using target matrix */
-       Mat4CpyMat4(mat, ob->obmat);
+       copy_m4_m4(mat, ob->obmat);
        
        /* get index of vertex group */
        dgroup = get_named_vertexgroup_num(ob, substring);
@@ -516,7 +541,7 @@ static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][
                                else
                                        memcpy(tvec, bp->vec, 3*sizeof(float));
                                        
-                               VecAddf(vec, vec, tvec);
+                               add_v3_v3v3(vec, vec, tvec);
                                grouped++;
                                
                                break;
@@ -530,8 +555,8 @@ static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][
        
        /* find average location, then multiply by ob->obmat to find world-space location */
        if (grouped)
-               VecMulf(vec, 1.0f / grouped);
-       VecMat4MulVecfl(tvec, ob->obmat, vec);
+               mul_v3_fl(vec, 1.0f / grouped);
+       mul_v3_m4v3(tvec, ob->obmat, vec);
        
        /* copy new location to matrix */
        VECCOPY(mat[3], tvec);
@@ -539,11 +564,11 @@ static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][
 
 /* generic function to get the appropriate matrix for most target cases */
 /* The cases where the target can be object data have not been implemented */
-static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][4], short from, short to, float headtail)
+static void constraint_target_to_mat4 (Scene *scene, Object *ob, char *substring, float mat[][4], short from, short to, float headtail)
 {
        /*      Case OBJECT */
        if (!strlen(substring)) {
-               Mat4CpyMat4(mat, ob->obmat);
+               copy_m4_m4(mat, ob->obmat);
                constraint_mat_convertspace(ob, NULL, mat, from, to);
        }
        /*      Case VERTEXGROUP */
@@ -556,7 +581,7 @@ static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][
         *              way as constraints can only really affect things on object/bone level.
         */
        else if (ob->type == OB_MESH) {
-               contarget_get_mesh_mat(ob, substring, mat);
+               contarget_get_mesh_mat(scene, ob, substring, mat);
                constraint_mat_convertspace(ob, NULL, mat, from, to);
        }
        else if (ob->type == OB_LATTICE) {
@@ -575,23 +600,23 @@ static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][
                         */
                        if (headtail < 0.000001) {
                                /* skip length interpolation if set to head */
-                               Mat4MulMat4(mat, pchan->pose_mat, ob->obmat);
+                               mul_m4_m4m4(mat, pchan->pose_mat, ob->obmat);
                        }
                        else {
                                float tempmat[4][4], loc[3];
                                
                                /* interpolate along length of bone */
-                               VecLerpf(loc, pchan->pose_head, pchan->pose_tail, headtail);    
+                               interp_v3_v3v3(loc, pchan->pose_head, pchan->pose_tail, headtail);      
                                
                                /* use interpolated distance for subtarget */
-                               Mat4CpyMat4(tempmat, pchan->pose_mat);  
-                               VecCopyf(tempmat[3], loc);
+                               copy_m4_m4(tempmat, pchan->pose_mat);   
+                               copy_v3_v3(tempmat[3], loc);
                                
-                               Mat4MulMat4(mat, tempmat, ob->obmat);
+                               mul_m4_m4m4(mat, tempmat, ob->obmat);
                        }
                } 
                else
-                       Mat4CpyMat4(mat, ob->obmat);
+                       copy_m4_m4(mat, ob->obmat);
                        
                /* convert matrix space as required */
                constraint_mat_convertspace(ob, pchan, mat, from, to);
@@ -638,9 +663,9 @@ static bConstraintTypeInfo CTI_CONSTRNAME = {
 static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
 {
        if (VALID_CONS_TARGET(ct))
-               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
+               constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
        else if (ct)
-               Mat4One(ct->matrix);
+               unit_m4(ct->matrix);
 }
 
 /* This following macro should be used for all standard single-target *_get_tars functions 
@@ -648,6 +673,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
  * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
  *  really just to help this code easier to read)
  */
+// TODO: cope with getting rotation order...
 #define SINGLETARGET_GET_TARS(con, datatar, datasubtarget, ct, list) \
        { \
                ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
@@ -658,9 +684,19 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
                ct->flag= CONSTRAINT_TAR_TEMP; \
                 \
                if (ct->tar) { \
-                       if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_BONE; \
-                       else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_VERT; \
-                       else ct->type = CONSTRAINT_OBTYPE_OBJECT; \
+                       if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) { \
+                               bPoseChannel *pchan= get_pose_channel(ct->tar->pose, ct->subtarget); \
+                               ct->type = CONSTRAINT_OBTYPE_BONE; \
+                               ct->rotOrder= (pchan) ? (pchan->rotmode) : EULER_ORDER_DEFAULT; \
+                       }\
+                       else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { \
+                               ct->type = CONSTRAINT_OBTYPE_VERT; \
+                               ct->rotOrder = EULER_ORDER_DEFAULT; \
+                       } \
+                       else {\
+                               ct->type = CONSTRAINT_OBTYPE_OBJECT; \
+                               ct->rotOrder= ct->tar->rotmode; \
+                       } \
                } \
                 \
                BLI_addtail(list, ct); \
@@ -671,6 +707,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
  * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
  *  really just to help this code easier to read)
  */
+// TODO: cope with getting rotation order...
 #define SINGLETARGETNS_GET_TARS(con, datatar, ct, list) \
        { \
                ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
@@ -734,7 +771,7 @@ static void childof_new_data (void *cdata)
        data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ |
                                        CHILDOF_ROTX |CHILDOF_ROTY | CHILDOF_ROTZ |
                                        CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ);
-       Mat4One(data->invmat);
+       unit_m4(data->invmat);
 }
 
 static int childof_get_tars (bConstraint *con, ListBase *list)
@@ -775,16 +812,16 @@ static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                float loco[3], eulo[3], sizo[3];
                
                /* get offset (parent-inverse) matrix */
-               Mat4CpyMat4(invmat, data->invmat);
+               copy_m4_m4(invmat, data->invmat);
                
                /* extract components of both matrices */
                VECCOPY(loc, ct->matrix[3]);
-               Mat4ToEul(ct->matrix, eul);
-               Mat4ToSize(ct->matrix, size);
+               mat4_to_eulO( eul, ct->rotOrder,ct->matrix);
+               mat4_to_size( size,ct->matrix);
                
                VECCOPY(loco, invmat[3]);
-               Mat4ToEul(invmat, eulo);
-               Mat4ToSize(invmat, sizo);
+               mat4_to_eulO( eulo, cob->rotOrder,invmat);
+               mat4_to_size( sizo,invmat);
                
                /* disable channels not enabled */
                if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f;
@@ -798,19 +835,19 @@ static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f;
                
                /* make new target mat and offset mat */
-               LocEulSizeToMat4(ct->matrix, loc, eul, size);
-               LocEulSizeToMat4(invmat, loco, eulo, sizo);
+               loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder);
+               loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder);
                
                /* multiply target (parent matrix) by offset (parent inverse) to get 
                 * the effect of the parent that will be exherted on the owner
                 */
-               Mat4MulMat4(parmat, invmat, ct->matrix);
+               mul_m4_m4m4(parmat, invmat, ct->matrix);
                
                /* now multiply the parent matrix by the owner matrix to get the 
                 * the effect of this constraint (i.e.  owner is 'parented' to parent)
                 */
-               Mat4CpyMat4(tempmat, cob->matrix);
-               Mat4MulMat4(cob->matrix, tempmat, parmat); 
+               copy_m4_m4(tempmat, cob->matrix);
+               mul_m4_m4m4(cob->matrix, tempmat, parmat); 
        }
 }
 
@@ -891,14 +928,14 @@ static void vectomat (float *vec, float *target_up, short axis, short upflag, sh
        float neg = -1;
        int right_index;
        
-       VecCopyf(n, vec);
-       if (Normalize(n) == 0.0) { 
+       copy_v3_v3(n, vec);
+       if (normalize_v3(n) == 0.0) { 
                n[0] = 0.0;
                n[1] = 0.0;
                n[2] = 1.0;
        }
        if (axis > 2) axis -= 3;
-       else VecNegf(n);
+       else negate_v3(n);
 
        /* n specifies the transformation of the track axis */
        if (flags & TARGET_Z_UP) { 
@@ -915,19 +952,19 @@ static void vectomat (float *vec, float *target_up, short axis, short upflag, sh
        }
 
        /* project the up vector onto the plane specified by n */
-       Projf(proj, u, n); /* first u onto n... */
-       VecSubf(proj, u, proj); /* then onto the plane */
+       project_v3_v3v3(proj, u, n); /* first u onto n... */
+       sub_v3_v3v3(proj, u, proj); /* then onto the plane */
        /* proj specifies the transformation of the up axis */
 
-       if (Normalize(proj) == 0.0) { /* degenerate projection */
+       if (normalize_v3(proj) == 0.0) { /* degenerate projection */
                proj[0] = 0.0;
                proj[1] = 1.0;
                proj[2] = 0.0;
        }
 
        /* Normalized cross product of n and proj specifies transformation of the right axis */
-       Crossf(right, proj, n);
-       Normalize(right);
+       cross_v3_v3v3(right, proj, n);
+       normalize_v3(right);
 
        if (axis != upflag) {
                right_index = 3 - axis - upflag;
@@ -967,7 +1004,7 @@ static void trackto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                float tmat[4][4];
                
                /* Get size property, since ob->size is only the object's own relative size, not its global one */
-               Mat4ToSize(cob->matrix, size);
+               mat4_to_size( size,cob->matrix);
                
                /* Clear the object's rotation */       
                cob->matrix[0][0]=size[0];
@@ -983,13 +1020,13 @@ static void trackto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                /* targetmat[2] instead of ownermat[2] is passed to vectomat
                 * for backwards compatability it seems... (Aligorith)
                 */
-               VecSubf(vec, cob->matrix[3], ct->matrix[3]);
+               sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);
                vectomat(vec, ct->matrix[2], 
                                (short)data->reserved1, (short)data->reserved2, 
                                data->flags, totmat);
                
-               Mat4CpyMat4(tmat, cob->matrix);
-               Mat4MulMat34(cob->matrix, totmat, tmat);
+               copy_m4_m4(tmat, cob->matrix);
+               mul_m4_m3m4(cob->matrix, totmat, tmat);
        }
 }
 
@@ -1017,6 +1054,7 @@ static void kinematic_new_data (void *cdata)
        data->weight= (float)1.0;
        data->orientweight= (float)1.0;
        data->iterations = 500;
+       data->dist= (float)1.0;
        data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS;
 }
 
@@ -1053,25 +1091,25 @@ static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstra
        bKinematicConstraint *data= con->data;
        
        if (VALID_CONS_TARGET(ct)) 
-               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
+               constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
        else if (ct) {
                if (data->flag & CONSTRAINT_IK_AUTO) {
                        Object *ob= cob->ob;
                        
                        if (ob == NULL) {
-                               Mat4One(ct->matrix);
+                               unit_m4(ct->matrix);
                        }
                        else {
                                float vec[3];
                                /* move grabtarget into world space */
                                VECCOPY(vec, data->grabtarget);
-                               Mat4MulVecfl(ob->obmat, vec);
-                               Mat4CpyMat4(ct->matrix, ob->obmat);
+                               mul_m4_v3(ob->obmat, vec);
+                               copy_m4_m4(ct->matrix, ob->obmat);
                                VECCOPY(ct->matrix[3], vec);
                        }
                }
                else
-                       Mat4One(ct->matrix);
+                       unit_m4(ct->matrix);
        }
 }
 
@@ -1134,53 +1172,73 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
        
        if (VALID_CONS_TARGET(ct)) {
                Curve *cu= ct->tar->data;
-               float q[4], vec[4], dir[3], quat[4], x1;
+               float q[4], vec[4], dir[3], quat[4], radius, x1;
                float totmat[4][4];
                float curvetime;
                
-               Mat4One(totmat);
-               Mat4One(ct->matrix);
+               unit_m4(totmat);
+               unit_m4(ct->matrix);
                
                /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
                 *              currently for paths to work it needs to go through the bevlist/displist system (ton) 
                 */
                
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (cu->path==NULL || cu->path->data==NULL) 
+               if (cu->path==NULL || cu->path->data==NULL)
                        makeDispListCurveTypes(cob->scene, ct->tar, 0);
                
                if (cu->path && cu->path->data) {
-                       curvetime= bsystem_time(cob->scene, ct->tar, (float)ctime, 0.0) - data->offset;
-                       
-#if 0 // XXX old animation system
-                       if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
-                               curvetime /= cu->pathlen;
+                       if ((data->followflag & FOLLOWPATH_STATIC) == 0) { 
+                               /* animated position along curve depending on time */
+                               if (cob->scene)
+                                       curvetime= bsystem_time(cob->scene, ct->tar, ctime, 0.0) - data->offset;
+                               else    
+                                       curvetime= ctime - data->offset;
+                               
+                               /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated,
+                                * but this will only work if it actually is animated... 
+                                *
+                                * we firstly calculate the modulus of cu->ctime/cu->pathlen to clamp ctime within the 0.0 to 1.0 times pathlen
+                                * range, then divide this (the modulus) by pathlen to get a value between 0.0 and 1.0
+                                */
+                               curvetime= fmod(cu->ctime, cu->pathlen) / cu->pathlen;
                                CLAMP(curvetime, 0.0, 1.0);
                        }
-#endif // XXX old animation system
+                       else {
+                               /* fixed position along curve */
+                               curvetime= data->offset; // XXX might need a more sensible value
+                       }
                        
-                       if ( where_on_path(ct->tar, curvetime, vec, dir) ) {
-                               if (data->followflag) {
-                                       vectoquat(dir, (short) data->trackflag, (short) data->upflag, quat);
+                       if ( where_on_path(ct->tar, curvetime, vec, dir, NULL, &radius) ) {
+                               if (data->followflag & FOLLOWPATH_FOLLOW) {
+                                       vec_to_quat( quat,dir, (short) data->trackflag, (short) data->upflag);
                                        
-                                       Normalize(dir);
+                                       normalize_v3(dir);
                                        q[0]= (float)cos(0.5*vec[3]);
                                        x1= (float)sin(0.5*vec[3]);
                                        q[1]= -x1*dir[0];
                                        q[2]= -x1*dir[1];
                                        q[3]= -x1*dir[2];
-                                       QuatMul(quat, q, quat);
+                                       mul_qt_qtqt(quat, q, quat);
                                        
-                                       QuatToMat4(quat, totmat);
+                                       quat_to_mat4( totmat,quat);
                                }
+                               
+                               if (data->followflag & FOLLOWPATH_RADIUS) {
+                                       float tmat[4][4], rmat[4][4];
+                                       scale_m4_fl(tmat, radius);
+                                       mul_m4_m4m4(rmat, totmat, tmat);
+                                       copy_m4_m4(totmat, rmat);
+                               }
+                               
                                VECCOPY(totmat[3], vec);
                                
-                               Mat4MulSerie(ct->matrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
+                               mul_serie_m4(ct->matrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
                        }
                }
        }
        else if (ct)
-               Mat4One(ct->matrix);
+               unit_m4(ct->matrix);
 }
 
 static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
@@ -1190,26 +1248,31 @@ static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
        /* only evaluate if there is a target */
        if (VALID_CONS_TARGET(ct)) {
                float obmat[4][4];
-               float size[3], obsize[3];
+               float size[3];
+               bFollowPathConstraint *data= con->data;
                
                /* get Object local transform (loc/rot/size) to determine transformation from path */
                //object_to_mat4(ob, obmat);
-               Mat4CpyMat4(obmat, cob->matrix); // FIXME!!!
+               copy_m4_m4(obmat, cob->matrix); // FIXME!!!
                
                /* get scaling of object before applying constraint */
-               Mat4ToSize(cob->matrix, size);
+               mat4_to_size( size,cob->matrix);
                
                /* apply targetmat - containing location on path, and rotation */
-               Mat4MulSerie(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
+               mul_serie_m4(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
                
                /* un-apply scaling caused by path */
-               Mat4ToSize(cob->matrix, obsize);
-               if (obsize[0])
-                       VecMulf(cob->matrix[0], size[0] / obsize[0]);
-               if (obsize[1])
-                       VecMulf(cob->matrix[1], size[1] / obsize[1]);
-               if (obsize[2])
-                       VecMulf(cob->matrix[2], size[2] / obsize[2]);
+               if ((data->followflag & FOLLOWPATH_RADIUS)==0) { /* XXX - assume that scale correction means that radius will have some scale error in it - Campbell */
+                       float obsize[3];
+                       
+                       mat4_to_size( obsize,cob->matrix);
+                       if (obsize[0])
+                               mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
+                       if (obsize[1])
+                               mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
+                       if (obsize[2])
+                               mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
+               }
        }
 }
 
@@ -1286,9 +1349,9 @@ static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t
        float size[3];
        
        VECCOPY(loc, cob->matrix[3]);
-       Mat4ToSize(cob->matrix, size);
+       mat4_to_size( size,cob->matrix);
        
-       Mat4ToEul(cob->matrix, eul);
+       mat4_to_eulO( eul, cob->rotOrder,cob->matrix);
        
        /* eulers: radians to degrees! */
        eul[0] = (float)(eul[0] / M_PI * 180);
@@ -1323,7 +1386,7 @@ static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t
        eul[1] = (float)(eul[1] / 180 * M_PI);
        eul[2] = (float)(eul[2] / 180 * M_PI);
        
-       LocEulSizeToMat4(cob->matrix, loc, eul, size);
+       loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
 }
 
 static bConstraintTypeInfo CTI_ROTLIMIT = {
@@ -1349,8 +1412,8 @@ static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
        bSizeLimitConstraint *data = con->data;
        float obsize[3], size[3];
        
-       Mat4ToSize(cob->matrix, size);
-       Mat4ToSize(cob->matrix, obsize);
+       mat4_to_size( size,cob->matrix);
+       mat4_to_size( obsize,cob->matrix);
        
        if (data->flag & LIMIT_XMIN) {
                if (size[0] < data->xmin) 
@@ -1378,11 +1441,11 @@ static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
        }
        
        if (obsize[0]) 
-               VecMulf(cob->matrix[0], size[0]/obsize[0]);
+               mul_v3_fl(cob->matrix[0], size[0]/obsize[0]);
        if (obsize[1]) 
-               VecMulf(cob->matrix[1], size[1]/obsize[1]);
+               mul_v3_fl(cob->matrix[1], size[1]/obsize[1]);
        if (obsize[2]) 
-               VecMulf(cob->matrix[2], size[2]/obsize[2]);
+               mul_v3_fl(cob->matrix[2], size[2]/obsize[2]);
 }
 
 static bConstraintTypeInfo CTI_SIZELIMIT = {
@@ -1528,16 +1591,17 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                float   size[3];
                
                VECCOPY(loc, cob->matrix[3]);
-               Mat4ToSize(cob->matrix, size);
+               mat4_to_size( size,cob->matrix);
                
-               Mat4ToEul(ct->matrix, eul);
-               Mat4ToEul(cob->matrix, obeul);
+               /* to allow compatible rotations, must get both rotations in the order of the owner... */
+               mat4_to_eulO( eul, cob->rotOrder,ct->matrix);
+               mat4_to_eulO( obeul, cob->rotOrder,cob->matrix);
                
                if ((data->flag & ROTLIKE_X)==0)
                        eul[0] = obeul[0];
                else {
                        if (data->flag & ROTLIKE_OFFSET)
-                               euler_rot(eul, obeul[0], 'x');
+                               rotate_eulO(eul, cob->rotOrder, 'x', obeul[0]);
                        
                        if (data->flag & ROTLIKE_X_INVERT)
                                eul[0] *= -1;
@@ -1547,7 +1611,7 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                        eul[1] = obeul[1];
                else {
                        if (data->flag & ROTLIKE_OFFSET)
-                               euler_rot(eul, obeul[1], 'y');
+                               rotate_eulO(eul, cob->rotOrder, 'y', obeul[1]);
                        
                        if (data->flag & ROTLIKE_Y_INVERT)
                                eul[1] *= -1;
@@ -1557,14 +1621,14 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                        eul[2] = obeul[2];
                else {
                        if (data->flag & ROTLIKE_OFFSET)
-                               euler_rot(eul, obeul[2], 'z');
+                               rotate_eulO(eul, cob->rotOrder, 'z', obeul[2]);
                        
                        if (data->flag & ROTLIKE_Z_INVERT)
                                eul[2] *= -1;
                }
                
                compatible_eul(eul, obeul);
-               LocEulSizeToMat4(cob->matrix, loc, eul, size);
+               loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
        }
 }
 
@@ -1626,32 +1690,32 @@ static void sizelike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t
        if (VALID_CONS_TARGET(ct)) {
                float obsize[3], size[3];
                
-               Mat4ToSize(ct->matrix, size);
-               Mat4ToSize(cob->matrix, obsize);
+               mat4_to_size( size,ct->matrix);
+               mat4_to_size( obsize,cob->matrix);
                
                if ((data->flag & SIZELIKE_X) && (obsize[0] != 0)) {
                        if (data->flag & SIZELIKE_OFFSET) {
                                size[0] += (obsize[0] - 1.0f);
-                               VecMulf(cob->matrix[0], size[0] / obsize[0]);
+                               mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
                        }
                        else
-                               VecMulf(cob->matrix[0], size[0] / obsize[0]);
+                               mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
                }
                if ((data->flag & SIZELIKE_Y) && (obsize[1] != 0)) {
                        if (data->flag & SIZELIKE_OFFSET) {
                                size[1] += (obsize[1] - 1.0f);
-                               VecMulf(cob->matrix[1], size[1] / obsize[1]);
+                               mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
                        }
                        else
-                               VecMulf(cob->matrix[1], size[1] / obsize[1]);
+                               mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
                }
                if ((data->flag & SIZELIKE_Z) && (obsize[2] != 0)) {
                        if (data->flag & SIZELIKE_OFFSET) {
                                size[2] += (obsize[2] - 1.0f);
-                               VecMulf(cob->matrix[2], size[2] / obsize[2]);
+                               mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
                        }
                        else
-                               VecMulf(cob->matrix[2], size[2] / obsize[2]);
+                               mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
                }
        }
 }
@@ -1743,7 +1807,7 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT
                /* firstly calculate the matrix the normal way, then let the py-function override
                 * this matrix if it needs to do so
                 */
-               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
+               constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
                
                /* only execute target calculation if allowed */
 #ifndef DISABLE_PYTHON
@@ -1752,7 +1816,7 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT
 #endif
        }
        else if (ct)
-               Mat4One(ct->matrix);
+               unit_m4(ct->matrix);
 }
 
 static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
@@ -1847,10 +1911,10 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint
                short axis;
                
                /* initialise return matrix */
-               Mat4One(ct->matrix);
+               unit_m4(ct->matrix);
                
                /* get the transform matrix of the target */
-               constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
+               constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
                
                /* determine where in transform range target is */
                /* data->type is mapped as follows for backwards compatability:
@@ -1860,7 +1924,7 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint
                 */
                if (data->type < 10) {
                        /* extract rotation (is in whatever space target should be in) */
-                       Mat4ToEul(tempmat, vec);
+                       mat4_to_eul(vec, tempmat);
                        vec[0] *= (float)(180.0/M_PI);
                        vec[1] *= (float)(180.0/M_PI);
                        vec[2] *= (float)(180.0/M_PI);
@@ -1868,7 +1932,7 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint
                }
                else if (data->type < 20) {
                        /* extract scaling (is in whatever space target should be in) */
-                       Mat4ToSize(tempmat, vec);
+                       mat4_to_size(vec, tempmat);
                        axis= data->type - 10;
                }
                else {
@@ -1880,31 +1944,44 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint
                /* Target defines the animation */
                s = (vec[axis]-data->min) / (data->max-data->min);
                CLAMP(s, 0, 1);
-               t = ( s * (data->end-data->start)) + data->start;
+               t = (s * (data->end-data->start)) + data->start;
+               
+               if (G.f & G_DEBUG)
+                       printf("do Action Constraint %s - Ob %s Pchan %s \n", con->name, cob->ob->id.name+2, (cob->pchan)?cob->pchan->name:NULL);
                
                /* Get the appropriate information from the action */
                if (cob->type == CONSTRAINT_OBTYPE_BONE) {
+                       Object workob;
                        bPose *pose;
                        bPoseChannel *pchan, *tchan;
                        
                        /* make a temporary pose and evaluate using that */
                        pose = MEM_callocN(sizeof(bPose), "pose");
                        
+                       /* make a copy of the bone of interest in the temp pose before evaluating action, so that it can get set 
+                        *      - we need to manually copy over a few settings, including rotation order, otherwise this fails
+                        */
                        pchan = cob->pchan;
+                       
                        tchan= verify_pose_channel(pose, pchan->name);
-                       extract_pose_from_action(pose, data->act, t);
+                       tchan->rotmode= pchan->rotmode;
                        
-                       chan_calc_mat(tchan);
+                       /* evaluate action using workob (it will only set the PoseChannel in question) */
+                       what_does_obaction(cob->scene, cob->ob, &workob, pose, data->act, pchan->name, t);
                        
-                       Mat4CpyMat4(ct->matrix, tchan->chan_mat);
+                       /* convert animation to matrices for use here */
+                       chan_calc_mat(tchan);
+                       copy_m4_m4(ct->matrix, tchan->chan_mat);
                        
                        /* Clean up */
                        free_pose(pose);
                }
                else if (cob->type == CONSTRAINT_OBTYPE_OBJECT) {
                        Object workob;
+                       
                        /* evaluate using workob */
-                       //what_does_obaction(cob->scene, cob->ob, &workob, data->act, t); // FIXME: missing func...
+                       // FIXME: we don't have any consistent standards on limiting effects on object...
+                       what_does_obaction(cob->scene, cob->ob, &workob, NULL, data->act, NULL, t);
                        object_to_mat4(&workob, ct->matrix);
                }
                else {
@@ -1924,8 +2001,8 @@ static void actcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *tar
                /* Nice and simple... we just need to multiply the matrices, as the get_target_matrix
                 * function has already taken care of everything else.
                 */
-               Mat4CpyMat4(temp, cob->matrix);
-               Mat4MulMat4(cob->matrix, ct->matrix, temp);
+               copy_m4_m4(temp, cob->matrix);
+               mul_m4_m4m4(cob->matrix, ct->matrix, temp);
        }
 }
 
@@ -1994,7 +2071,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                float mdet;
                
                /* Vector object -> target */
-               VecSubf(vec, ct->matrix[3], cob->matrix[3]);
+               sub_v3_v3v3(vec, ct->matrix[3], cob->matrix[3]);
                switch (data->lockflag){
                case LOCK_X: /* LOCK X */
                {
@@ -2002,71 +2079,71 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                                case TRACK_Y: /* LOCK X TRACK Y */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[0]);
-                                       VecSubf(totmat[1], vec, vec2);
-                                       Normalize(totmat[1]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[0]);
+                                       sub_v3_v3v3(totmat[1], vec, vec2);
+                                       normalize_v3(totmat[1]);
                                        
                                        /* the x axis is fixed */
                                        totmat[0][0] = cob->matrix[0][0];
                                        totmat[0][1] = cob->matrix[0][1];
                                        totmat[0][2] = cob->matrix[0][2];
-                                       Normalize(totmat[0]);
+                                       normalize_v3(totmat[0]);
                                        
                                        /* the z axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[2], totmat[0], totmat[1]);
+                                       cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
                                }
                                        break;
                                case TRACK_Z: /* LOCK X TRACK Z */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[0]);
-                                       VecSubf(totmat[2], vec, vec2);
-                                       Normalize(totmat[2]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[0]);
+                                       sub_v3_v3v3(totmat[2], vec, vec2);
+                                       normalize_v3(totmat[2]);
                                        
                                        /* the x axis is fixed */
                                        totmat[0][0] = cob->matrix[0][0];
                                        totmat[0][1] = cob->matrix[0][1];
                                        totmat[0][2] = cob->matrix[0][2];
-                                       Normalize(totmat[0]);
+                                       normalize_v3(totmat[0]);
                                        
                                        /* the z axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[1], totmat[2], totmat[0]);
+                                       cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
                                }
                                        break;
                                case TRACK_nY: /* LOCK X TRACK -Y */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[0]);
-                                       VecSubf(totmat[1], vec, vec2);
-                                       Normalize(totmat[1]);
-                                       VecNegf(totmat[1]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[0]);
+                                       sub_v3_v3v3(totmat[1], vec, vec2);
+                                       normalize_v3(totmat[1]);
+                                       negate_v3(totmat[1]);
                                        
                                        /* the x axis is fixed */
                                        totmat[0][0] = cob->matrix[0][0];
                                        totmat[0][1] = cob->matrix[0][1];
                                        totmat[0][2] = cob->matrix[0][2];
-                                       Normalize(totmat[0]);
+                                       normalize_v3(totmat[0]);
                                        
                                        /* the z axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[2], totmat[0], totmat[1]);
+                                       cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
                                }
                                        break;
                                case TRACK_nZ: /* LOCK X TRACK -Z */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[0]);
-                                       VecSubf(totmat[2], vec, vec2);
-                                       Normalize(totmat[2]);
-                                       VecNegf(totmat[2]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[0]);
+                                       sub_v3_v3v3(totmat[2], vec, vec2);
+                                       normalize_v3(totmat[2]);
+                                       negate_v3(totmat[2]);
                                                
                                        /* the x axis is fixed */
                                        totmat[0][0] = cob->matrix[0][0];
                                        totmat[0][1] = cob->matrix[0][1];
                                        totmat[0][2] = cob->matrix[0][2];
-                                       Normalize(totmat[0]);
+                                       normalize_v3(totmat[0]);
                                                
                                        /* the z axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[1], totmat[2], totmat[0]);
+                                       cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
                                }
                                        break;
                                default:
@@ -2085,71 +2162,71 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                                case TRACK_X: /* LOCK Y TRACK X */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[1]);
-                                       VecSubf(totmat[0], vec, vec2);
-                                       Normalize(totmat[0]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[1]);
+                                       sub_v3_v3v3(totmat[0], vec, vec2);
+                                       normalize_v3(totmat[0]);
                                        
                                        /* the y axis is fixed */
                                        totmat[1][0] = cob->matrix[1][0];
                                        totmat[1][1] = cob->matrix[1][1];
                                        totmat[1][2] = cob->matrix[1][2];
-                                       Normalize(totmat[1]);
+                                       normalize_v3(totmat[1]);
                                        
                                        /* the z axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[2], totmat[0], totmat[1]);
+                                       cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
                                }
                                        break;
                                case TRACK_Z: /* LOCK Y TRACK Z */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[1]);
-                                       VecSubf(totmat[2], vec, vec2);
-                                       Normalize(totmat[2]);
-
+                                       project_v3_v3v3(vec2, vec, cob->matrix[1]);
+                                       sub_v3_v3v3(totmat[2], vec, vec2);
+                                       normalize_v3(totmat[2]);
+                                       
                                        /* the y axis is fixed */
                                        totmat[1][0] = cob->matrix[1][0];
                                        totmat[1][1] = cob->matrix[1][1];
                                        totmat[1][2] = cob->matrix[1][2];
-                                       Normalize(totmat[1]);
+                                       normalize_v3(totmat[1]);
                                        
                                        /* the z axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[0], totmat[1], totmat[2]);
+                                       cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
                                }
                                        break;
                                case TRACK_nX: /* LOCK Y TRACK -X */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[1]);
-                                       VecSubf(totmat[0], vec, vec2);
-                                       Normalize(totmat[0]);
-                                       VecNegf(totmat[0]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[1]);
+                                       sub_v3_v3v3(totmat[0], vec, vec2);
+                                       normalize_v3(totmat[0]);
+                                       negate_v3(totmat[0]);
                                        
                                        /* the y axis is fixed */
                                        totmat[1][0] = cob->matrix[1][0];
                                        totmat[1][1] = cob->matrix[1][1];
                                        totmat[1][2] = cob->matrix[1][2];
-                                       Normalize(totmat[1]);
+                                       normalize_v3(totmat[1]);
                                        
                                        /* the z axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[2], totmat[0], totmat[1]);
+                                       cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
                                }
                                        break;
                                case TRACK_nZ: /* LOCK Y TRACK -Z */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[1]);
-                                       VecSubf(totmat[2], vec, vec2);
-                                       Normalize(totmat[2]);
-                                       VecNegf(totmat[2]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[1]);
+                                       sub_v3_v3v3(totmat[2], vec, vec2);
+                                       normalize_v3(totmat[2]);
+                                       negate_v3(totmat[2]);
                                        
                                        /* the y axis is fixed */
                                        totmat[1][0] = cob->matrix[1][0];
                                        totmat[1][1] = cob->matrix[1][1];
                                        totmat[1][2] = cob->matrix[1][2];
-                                       Normalize(totmat[1]);
+                                       normalize_v3(totmat[1]);
                                        
                                        /* the z axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[0], totmat[1], totmat[2]);
+                                       cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
                                }
                                        break;
                                default:
@@ -2168,107 +2245,107 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                                case TRACK_X: /* LOCK Z TRACK X */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[2]);
-                                       VecSubf(totmat[0], vec, vec2);
-                                       Normalize(totmat[0]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[2]);
+                                       sub_v3_v3v3(totmat[0], vec, vec2);
+                                       normalize_v3(totmat[0]);
                                        
                                        /* the z axis is fixed */
                                        totmat[2][0] = cob->matrix[2][0];
                                        totmat[2][1] = cob->matrix[2][1];
                                        totmat[2][2] = cob->matrix[2][2];
-                                       Normalize(totmat[2]);
+                                       normalize_v3(totmat[2]);
                                        
                                        /* the x axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[1], totmat[2], totmat[0]);
+                                       cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
                                }
                                        break;
                                case TRACK_Y: /* LOCK Z TRACK Y */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[2]);
-                                       VecSubf(totmat[1], vec, vec2);
-                                       Normalize(totmat[1]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[2]);
+                                       sub_v3_v3v3(totmat[1], vec, vec2);
+                                       normalize_v3(totmat[1]);
                                        
                                        /* the z axis is fixed */
                                        totmat[2][0] = cob->matrix[2][0];
                                        totmat[2][1] = cob->matrix[2][1];
                                        totmat[2][2] = cob->matrix[2][2];
-                                       Normalize(totmat[2]);
+                                       normalize_v3(totmat[2]);
                                                
                                        /* the x axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[0], totmat[1], totmat[2]);
+                                       cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
                                }
                                        break;
                                case TRACK_nX: /* LOCK Z TRACK -X */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[2]);
-                                       VecSubf(totmat[0], vec, vec2);
-                                       Normalize(totmat[0]);
-                                       VecNegf(totmat[0]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[2]);
+                                       sub_v3_v3v3(totmat[0], vec, vec2);
+                                       normalize_v3(totmat[0]);
+                                       negate_v3(totmat[0]);
                                        
                                        /* the z axis is fixed */
                                        totmat[2][0] = cob->matrix[2][0];
                                        totmat[2][1] = cob->matrix[2][1];
                                        totmat[2][2] = cob->matrix[2][2];
-                                       Normalize(totmat[2]);
+                                       normalize_v3(totmat[2]);
                                        
                                        /* the x axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[1], totmat[2], totmat[0]);
+                                       cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
                                }
                                        break;
                                case TRACK_nY: /* LOCK Z TRACK -Y */
                                {
                                        /* Projection of Vector on the plane */
-                                       Projf(vec2, vec, cob->matrix[2]);
-                                       VecSubf(totmat[1], vec, vec2);
-                                       Normalize(totmat[1]);
-                                       VecNegf(totmat[1]);
+                                       project_v3_v3v3(vec2, vec, cob->matrix[2]);
+                                       sub_v3_v3v3(totmat[1], vec, vec2);
+                                       normalize_v3(totmat[1]);
+                                       negate_v3(totmat[1]);
                                        
                                        /* the z axis is fixed */
                                        totmat[2][0] = cob->matrix[2][0];
                                        totmat[2][1] = cob->matrix[2][1];
                                        totmat[2][2] = cob->matrix[2][2];
-                                       Normalize(totmat[2]);
+                                       normalize_v3(totmat[2]);
                                                
                                        /* the x axis gets mapped onto a third orthogonal vector */
-                                       Crossf(totmat[0], totmat[1], totmat[2]);
+                                       cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
                                }
                                        break;
                                default:
                                {
-                                               totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
-                                               totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
-                                               totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
                                }
                                        break;
                        }
                }
                        break;
                default:
-                       {
-                               totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
-                               totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
-                               totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
-                       }
+               {
+                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+               }
                        break;
                }
                /* Block to keep matrix heading */
                tmpmat[0][0] = cob->matrix[0][0];tmpmat[0][1] = cob->matrix[0][1];tmpmat[0][2] = cob->matrix[0][2];
                tmpmat[1][0] = cob->matrix[1][0];tmpmat[1][1] = cob->matrix[1][1];tmpmat[1][2] = cob->matrix[1][2];
                tmpmat[2][0] = cob->matrix[2][0];tmpmat[2][1] = cob->matrix[2][1];tmpmat[2][2] = cob->matrix[2][2];
-               Normalize(tmpmat[0]);
-               Normalize(tmpmat[1]);
-               Normalize(tmpmat[2]);
-               Mat3Inv(invmat, tmpmat);
-               Mat3MulMat3(tmpmat, totmat, invmat);
+               normalize_v3(tmpmat[0]);
+               normalize_v3(tmpmat[1]);
+               normalize_v3(tmpmat[2]);
+               invert_m3_m3(invmat, tmpmat);
+               mul_m3_m3m3(tmpmat, totmat, invmat);
                totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
                totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
                totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
                
-               Mat4CpyMat4(tmat, cob->matrix);
+               copy_m4_m4(tmat, cob->matrix);
                
-               mdet = Det3x3(  totmat[0][0],totmat[0][1],totmat[0][2],
+               mdet = determinant_m3(  totmat[0][0],totmat[0][1],totmat[0][2],
                                                totmat[1][0],totmat[1][1],totmat[1][2],
                                                totmat[2][0],totmat[2][1],totmat[2][2]);
                if (mdet==0) {
@@ -2278,7 +2355,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                }
                
                /* apply out transformaton to the object */
-               Mat4MulMat34(cob->matrix, totmat, tmat);
+               mul_m4_m3m4(cob->matrix, totmat, tmat);
        }
 }
 
@@ -2343,7 +2420,7 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                short clamp_surf= 0;
                
                /* calculate our current distance from the target */
-               dist= VecLenf(cob->matrix[3], ct->matrix[3]);
+               dist= len_v3v3(cob->matrix[3], ct->matrix[3]);
                
                /* set distance (flag is only set when user demands it) */
                if (data->dist == 0)
@@ -2390,7 +2467,7 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                /* clamp to 'surface' (i.e. move owner so that dist == data->dist) */
                if (clamp_surf) {
                        /* simply interpolate along line formed by target -> owner */
-                       VecLerpf(dvec, ct->matrix[3], cob->matrix[3], sfac);
+                       interp_v3_v3v3(dvec, ct->matrix[3], cob->matrix[3], sfac);
                        
                        /* copy new vector onto owner */
                        VECCOPY(cob->matrix[3], dvec);
@@ -2464,27 +2541,27 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                float dist;
                
                /* store scaling before destroying obmat */
-               Mat4ToSize(cob->matrix, size);
+               mat4_to_size( size,cob->matrix);
                
                /* store X orientation before destroying obmat */
                xx[0] = cob->matrix[0][0];
                xx[1] = cob->matrix[0][1];
                xx[2] = cob->matrix[0][2];
-               Normalize(xx);
+               normalize_v3(xx);
                
                /* store Z orientation before destroying obmat */
                zz[0] = cob->matrix[2][0];
                zz[1] = cob->matrix[2][1];
                zz[2] = cob->matrix[2][2];
-               Normalize(zz);
+               normalize_v3(zz);
                
-               VecSubf(vec, cob->matrix[3], ct->matrix[3]);
+               sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);
                vec[0] /= size[0];
                vec[1] /= size[1];
                vec[2] /= size[2];
                
-               dist = Normalize(vec);
-               //dist = VecLenf( ob->obmat[3], targetmat[3]);
+               dist = normalize_v3(vec);
+               //dist = len_v3v3( ob->obmat[3], targetmat[3]);
                
                /* data->orglength==0 occurs on first run, and after 'R' button is clicked */
                if (data->orglength == 0)  
@@ -2527,8 +2604,8 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                cob->matrix[2][1]=0;
                cob->matrix[2][2]=size[2]*scale[2];
                
-               VecSubf(vec, cob->matrix[3], ct->matrix[3]);
-               Normalize(vec);
+               sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);
+               normalize_v3(vec);
                
                /* new Y aligns  object target connection*/
                totmat[1][0] = -vec[0];
@@ -2538,8 +2615,8 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                case PLANE_X:
                        /* build new Z vector */
                        /* othogonal to "new Y" "old X! plane */
-                       Crossf(orth, vec, xx);
-                       Normalize(orth);
+                       cross_v3_v3v3(orth, vec, xx);
+                       normalize_v3(orth);
                        
                        /* new Z*/
                        totmat[2][0] = orth[0];
@@ -2547,8 +2624,8 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                        totmat[2][2] = orth[2];
                        
                        /* we decided to keep X plane*/
-                       Crossf(xx, orth, vec);
-                       Normalize(xx);
+                       cross_v3_v3v3(xx, orth, vec);
+                       normalize_v3(xx);
                        totmat[0][0] = xx[0];
                        totmat[0][1] = xx[1];
                        totmat[0][2] = xx[2];
@@ -2556,8 +2633,8 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                case PLANE_Z:
                        /* build new X vector */
                        /* othogonal to "new Y" "old Z! plane */
-                       Crossf(orth, vec, zz);
-                       Normalize(orth);
+                       cross_v3_v3v3(orth, vec, zz);
+                       normalize_v3(orth);
                        
                        /* new X */
                        totmat[0][0] = -orth[0];
@@ -2565,16 +2642,16 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                        totmat[0][2] = -orth[2];
                        
                        /* we decided to keep Z */
-                       Crossf(zz, orth, vec);
-                       Normalize(zz);
+                       cross_v3_v3v3(zz, orth, vec);
+                       normalize_v3(zz);
                        totmat[2][0] = zz[0];
                        totmat[2][1] = zz[1];
                        totmat[2][2] = zz[2];
                        break;
                } /* switch (data->plane) */
                
-               Mat4CpyMat4(tmat, cob->matrix);
-               Mat4MulMat34(cob->matrix, totmat, tmat);
+               copy_m4_m4(tmat, cob->matrix);
+               mul_m4_m3m4(cob->matrix, totmat, tmat);
        }
 }
 
@@ -2642,15 +2719,15 @@ static void minmax_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *tar
                float val1, val2;
                int index;
                
-               Mat4CpyMat4(obmat, cob->matrix);
-               Mat4CpyMat4(tarmat, ct->matrix);
+               copy_m4_m4(obmat, cob->matrix);
+               copy_m4_m4(tarmat, ct->matrix);
                
                if (data->flag & MINMAX_USEROT) {
                        /* take rotation of target into account by doing the transaction in target's localspace */
-                       Mat4Invert(imat, tarmat);
-                       Mat4MulMat4(tmat, obmat, imat);
-                       Mat4CpyMat4(obmat, tmat);
-                       Mat4One(tarmat);
+                       invert_m4_m4(imat, tarmat);
+                       mul_m4_m4m4(tmat, obmat, imat);
+                       copy_m4_m4(obmat, tmat);
+                       unit_m4(tarmat);
                }
                
                switch (data->minmaxflag) {
@@ -2701,8 +2778,8 @@ static void minmax_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *tar
                        }
                        if (data->flag & MINMAX_USEROT) {
                                /* get out of localspace */
-                               Mat4MulMat4(tmat, obmat, ct->matrix);
-                               Mat4CpyMat4(cob->matrix, tmat);
+                               mul_m4_m4m4(tmat, obmat, ct->matrix);
+                               copy_m4_m4(cob->matrix, tmat);
                        } 
                        else {                  
                                VECCOPY(cob->matrix[3], obmat[3]);
@@ -2818,7 +2895,7 @@ static void clampto_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
                 */
                
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (cu->path==NULL || cu->path->data==NULL) 
+               if (cu->path==NULL || cu->path->data==NULL)
                        makeDispListCurveTypes(cob->scene, ct->tar, 0);
        }
        
@@ -2826,7 +2903,7 @@ static void clampto_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
         * might end up calling this...
         */
        if (ct)
-               Mat4One(ct->matrix);
+               unit_m4(ct->matrix);
 }
 
 static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
@@ -2840,8 +2917,8 @@ static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                float obmat[4][4], targetMatrix[4][4], ownLoc[3];
                float curveMin[3], curveMax[3];
                
-               Mat4CpyMat4(obmat, cob->matrix);
-               Mat4One(targetMatrix);
+               copy_m4_m4(obmat, cob->matrix);
+               unit_m4(targetMatrix);
                VECCOPY(ownLoc, obmat[3]);
                
                INIT_MINMAX(curveMin, curveMax)
@@ -2857,7 +2934,7 @@ static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                        /* 1. determine which axis to sample on? */
                        if (data->flag == CLAMPTO_AUTO) {
                                float size[3];
-                               VecSubf(size, curveMax, curveMin);
+                               sub_v3_v3v3(size, curveMax, curveMin);
                                
                                /* find axis along which the bounding box has the greatest
                                 * extent. Otherwise, default to the x-axis, as that is quite
@@ -2929,11 +3006,11 @@ static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                        }
                        
                        /* 3. position on curve */
-                       if (where_on_path(ct->tar, curvetime, vec, dir) ) {
-                               Mat4One(totmat);
+                       if (where_on_path(ct->tar, curvetime, vec, dir, NULL, NULL) ) {
+                               unit_m4(totmat);
                                VECCOPY(totmat[3], vec);
                                
-                               Mat4MulSerie(targetMatrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
+                               mul_serie_m4(targetMatrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
                        }
                }
                
@@ -3003,27 +3080,27 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
        if (VALID_CONS_TARGET(ct)) {
                float loc[3], eul[3], size[3];
                float dvec[3], sval[3];
-               short i;
+               int i;
                
                /* obtain target effect */
                switch (data->from) {
                        case 2: /* scale */
-                               Mat4ToSize(ct->matrix, dvec);
+                               mat4_to_size( dvec,ct->matrix);
                                break;
                        case 1: /* rotation (convert to degrees first) */
-                               Mat4ToEul(ct->matrix, dvec);
+                               mat4_to_eulO( dvec, cob->rotOrder,ct->matrix);
                                for (i=0; i<3; i++)
                                        dvec[i] = (float)(dvec[i] / M_PI * 180);
                                break;
                        default: /* location */
-                               VecCopyf(dvec, ct->matrix[3]);
+                               copy_v3_v3(dvec, ct->matrix[3]);
                                break;
                }
                
                /* extract components of owner's matrix */
                VECCOPY(loc, cob->matrix[3]);
-               Mat4ToEul(cob->matrix, eul);
-               Mat4ToSize(cob->matrix, size);  
+               mat4_to_eulO( eul, cob->rotOrder,cob->matrix);
+               mat4_to_size( size,cob->matrix);        
                
                /* determine where in range current transforms lie */
                if (data->expo) {
@@ -3050,7 +3127,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                switch (data->to) {
                        case 2: /* scaling */
                                for (i=0; i<3; i++)
-                                       size[i]= data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])); 
+                                       size[i]= data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i])); 
                                break;
                        case 1: /* rotation */
                                for (i=0; i<3; i++) {
@@ -3060,7 +3137,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                                        tmax= data->to_max[i];
                                        
                                        /* all values here should be in degrees */
-                                       eul[i]= tmin + (sval[data->map[i]] * (tmax - tmin)); 
+                                       eul[i]= tmin + (sval[(int)data->map[i]] * (tmax - tmin)); 
                                        
                                        /* now convert final value back to radians */
                                        eul[i] = (float)(eul[i] / 180 * M_PI);
@@ -3069,15 +3146,15 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
                        default: /* location */
                                /* get new location */
                                for (i=0; i<3; i++)
-                                       loc[i]= (data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])));
+                                       loc[i]= (data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i])));
                                
                                /* add original location back on (so that it can still be moved) */
-                               VecAddf(loc, cob->matrix[3], loc);
+                               add_v3_v3v3(loc, cob->matrix[3], loc);
                                break;
                }
                
                /* apply to matrix */
-               LocEulSizeToMat4(cob->matrix, loc, eul, size);
+               loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
        }
 }
 
@@ -3096,13 +3173,371 @@ static bConstraintTypeInfo CTI_TRANSFORM = {
        transform_evaluate /* evaluate */
 };
 
+/* ---------- Shrinkwrap Constraint ----------- */
+
+static int shrinkwrap_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bShrinkwrapConstraint *data = con->data;
+               bConstraintTarget *ct;
+               
+               SINGLETARGETNS_GET_TARS(con, data->target, ct, list)
+               
+               return 1;
+       }
+       
+       return 0;
+}
+
+
+static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bShrinkwrapConstraint *data = con->data;
+               bConstraintTarget *ct= list->first;
+               
+               SINGLETARGETNS_FLUSH_TARS(con, data->target, ct, list, nocopy)
+       }
+}
+
+
+static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
+       
+       if( VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) )
+       {
+               int fail = FALSE;
+               float co[3] = {0.0f, 0.0f, 0.0f};
+               float no[3] = {0.0f, 0.0f, 0.0f};
+               float dist;
+
+               SpaceTransform transform;
+               DerivedMesh *target = object_get_derived_final(cob->scene, ct->tar, CD_MASK_BAREMESH);
+               BVHTreeRayHit hit;
+               BVHTreeNearest nearest;
+
+               BVHTreeFromMesh treeData;
+               memset( &treeData, 0, sizeof(treeData) );
+
+               nearest.index = -1;
+               nearest.dist = FLT_MAX;
+
+               hit.index = -1;
+               hit.dist = 100000.0f;  //TODO should use FLT_MAX.. but normal projection doenst yet supports it
+
+               unit_m4(ct->matrix);
+
+               if(target != NULL)
+               {
+                       space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat);
+
+                       switch(scon->shrinkType)
+                       {
+                               case MOD_SHRINKWRAP_NEAREST_SURFACE:
+                               case MOD_SHRINKWRAP_NEAREST_VERTEX:
+
+                                       if(scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX)
+                                               bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6);
+                                       else
+                                               bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6);
+
+                                       if(treeData.tree == NULL)
+                                       {
+                                               fail = TRUE;
+                                               break;
+                                       }
+
+                                       space_transform_apply(&transform, co);
+
+                                       BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
+                                       
+                                       dist = len_v3v3(co, nearest.co);
+                                       interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist)/dist);   /* linear interpolation */
+                                       space_transform_invert(&transform, co);
+                               break;
+
+                               case MOD_SHRINKWRAP_PROJECT:
+                                       if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) no[0] = 1.0f;
+                                       if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) no[1] = 1.0f;
+                                       if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) no[2] = 1.0f;
+
+                                       if(INPR(no,no) < FLT_EPSILON)
+                                       {
+                                               fail = TRUE;
+                                               break;
+                                       }
+
+                                       normalize_v3(no);
+
+
+                                       bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6);
+                                       if(treeData.tree == NULL)
+                                       {
+                                               fail = TRUE;
+                                               break;
+                                       }
+
+                                       if(normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE)
+                                       {
+                                               fail = TRUE;
+                                               break;
+                                       }
+                                       VECCOPY(co, hit.co);
+                               break;
+                       }
+
+                       free_bvhtree_from_mesh(&treeData);
+
+                       target->release(target);
+
+                       if(fail == TRUE)
+                       {
+                               /* Don't move the point */
+                               co[0] = co[1] = co[2] = 0.0f;
+                       }
+
+                       /* co is in local object coordinates, change it to global and update target position */
+                       mul_v3_m4v3(co, cob->matrix, co);
+                       VECCOPY(ct->matrix[3], co);
+               }
+       }
+}
+
+static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target */
+       if (VALID_CONS_TARGET(ct))
+       {
+               VECCOPY(cob->matrix[3], ct->matrix[3]);
+       }
+}
+
+static bConstraintTypeInfo CTI_SHRINKWRAP = {
+       CONSTRAINT_TYPE_SHRINKWRAP, /* type */
+       sizeof(bShrinkwrapConstraint), /* size */
+       "Shrinkwrap", /* name */
+       "bShrinkwrapConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       NULL, /* new data */
+       shrinkwrap_get_tars, /* get constraint targets */
+       shrinkwrap_flush_tars, /* flush constraint targets */
+       shrinkwrap_get_tarmat, /* get a target matrix */
+       shrinkwrap_evaluate /* evaluate */
+};
+
+/* --------- Damped Track ---------- */
+
+static void damptrack_new_data (void *cdata)
+{
+       bDampTrackConstraint *data= (bDampTrackConstraint *)cdata;
+       
+       data->trackflag = TRACK_Y;
+}      
+
+static int damptrack_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bDampTrackConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
+               
+               return 1;
+       }
+       
+       return 0;
+}
+
+static void damptrack_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bDampTrackConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
+       }
+}
+
+/* array of direction vectors for the tracking flags */
+static const float track_dir_vecs[6][3] = {
+       {+1,0,0}, {0,+1,0}, {0,0,+1},           /* TRACK_X,  TRACK_Y,  TRACK_Z */
+       {-1,0,0}, {0,-1,0}, {0,0,-1}            /* TRACK_NX, TRACK_NY, TRACK_NZ */
+};
+
+static void damptrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bDampTrackConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               float obvec[3], tarvec[3], obloc[3];
+               float raxis[3], rangle;
+               float rmat[3][3], tmat[4][4];
+               
+               /* find the (unit) direction that the axis we're interested in currently points 
+                *      - mul_mat3_m4_v3() only takes the 3x3 (rotation+scaling) components of the 4x4 matrix 
+                *      - the normalisation step at the end should take care of any unwanted scaling
+                *        left over in the 3x3 matrix we used
+                */
+               VECCOPY(obvec, track_dir_vecs[data->trackflag]);
+               mul_mat3_m4_v3(cob->matrix, obvec);
+               
+               if (normalize_v3(obvec) == 0.0f) {
+                       /* exceptional case - just use the track vector as appropriate */
+                       VECCOPY(obvec, track_dir_vecs[data->trackflag]);
+               }
+               
+               /* find the (unit) direction vector going from the owner to the target */
+               VECCOPY(obloc, cob->matrix[3]);
+               sub_v3_v3v3(tarvec, ct->matrix[3], obloc);
+               
+               if (normalize_v3(tarvec) == 0.0f) {
+                       /* the target is sitting on the owner, so just make them use the same direction vectors */
+                       // FIXME: or would it be better to use the pure direction vector?
+                       VECCOPY(tarvec, obvec);
+                       //VECCOPY(tarvec, track_dir_vecs[data->trackflag]);
+               }
+               
+               /* determine the axis-angle rotation, which represents the smallest possible rotation
+                * between the two rotation vectors (i.e. the 'damping' referred to in the name)
+                *      - we take this to be the rotation around the normal axis/vector to the plane defined
+                *        by the current and destination vectors, which will 'map' the current axis to the 
+                *        destination vector
+                *      - the min/max wrappers around (obvec . tarvec) result (stored temporarily in rangle)
+                *        are used to ensure that the smallest angle is chosen
+                */
+               cross_v3_v3v3(raxis, obvec, tarvec);
+               
+               rangle= dot_v3v3(obvec, tarvec);
+               rangle= acos( MAX2(-1.0f, MIN2(1.0f, rangle)) );
+               
+               /* construct rotation matrix from the axis-angle rotation found above 
+                *      - this call takes care to make sure that the axis provided is a unit vector first
+                */
+               axis_angle_to_mat3( rmat,raxis, rangle);
+               
+               /* rotate the owner in the way defined by this rotation matrix, then reapply the location since
+                * we may have destroyed that in the process of multiplying the matrix
+                */
+               unit_m4(tmat);
+               mul_m4_m3m4(tmat, rmat, cob->matrix); // m1, m3, m2
+               
+               copy_m4_m4(cob->matrix, tmat);
+               VECCOPY(cob->matrix[3], obloc);
+       }
+}
+
+static bConstraintTypeInfo CTI_DAMPTRACK = {
+       CONSTRAINT_TYPE_DAMPTRACK, /* type */
+       sizeof(bDampTrackConstraint), /* size */
+       "Damped Track", /* name */
+       "bDampTrackConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       damptrack_new_data, /* new data */
+       damptrack_get_tars, /* get constraint targets */
+       damptrack_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get target matrix */
+       damptrack_evaluate /* evaluate */
+};
+
+/* ----------- Spline IK ------------ */
+
+static void splineik_free (bConstraint *con)
+{
+       bSplineIKConstraint *data= con->data;
+       
+       /* binding array */
+       if (data->points)
+               MEM_freeN(data->points);
+}      
+
+static void splineik_copy (bConstraint *con, bConstraint *srccon)
+{
+       bSplineIKConstraint *src= srccon->data;
+       bSplineIKConstraint *dst= con->data;
+       
+       /* copy the binding array */
+       dst->points= MEM_dupallocN(src->points);
+}
+
+static int splineik_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bSplineIKConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints without subtargets */
+               SINGLETARGETNS_GET_TARS(con, data->tar, ct, list)
+               
+               return 1;
+       }
+       
+       return 0;
+}
+
+static void splineik_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bSplineIKConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy)
+       }
+}
+
+static void splineik_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       if (VALID_CONS_TARGET(ct)) {
+               Curve *cu= ct->tar->data;
+               
+               /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
+                *              currently for paths to work it needs to go through the bevlist/displist system (ton) 
+                */
+               
+               /* only happens on reload file, but violates depsgraph still... fix! */
+               if (cu->path==NULL || cu->path->data==NULL)
+                       makeDispListCurveTypes(cob->scene, ct->tar, 0);
+       }
+       
+       /* technically, this isn't really needed for evaluation, but we don't know what else
+        * might end up calling this...
+        */
+       if (ct)
+               unit_m4(ct->matrix);
+}
+
+static bConstraintTypeInfo CTI_SPLINEIK = {
+       CONSTRAINT_TYPE_SPLINEIK, /* type */
+       sizeof(bSplineIKConstraint), /* size */
+       "Spline IK", /* name */
+       "bSplineIKConstraint", /* struct name */
+       splineik_free, /* free data */
+       NULL, /* relink data */
+       splineik_copy, /* copy data */
+       NULL, /* new data */
+       splineik_get_tars, /* get constraint targets */
+       splineik_flush_tars, /* flush constraint targets */
+       splineik_get_tarmat, /* get target matrix */
+       NULL /* evaluate - solved as separate loop */
+};
+
 /* ************************* Constraints Type-Info *************************** */
 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
- * and operations that involve constraint specifc code.
+ * and operations that involve constraint specific code.
  */
 
 /* These globals only ever get directly accessed in this file */
-static bConstraintTypeInfo *constraintsTypeInfo[NUM_CONSTRAINT_TYPES+1];
+static bConstraintTypeInfo *constraintsTypeInfo[NUM_CONSTRAINT_TYPES];
 static short CTI_INIT= 1; /* when non-zero, the list needs to be updated */
 
 /* This function only gets called when CTI_INIT is non-zero */
@@ -3127,6 +3562,9 @@ static void constraints_init_typeinfo () {
        constraintsTypeInfo[17]= &CTI_RIGIDBODYJOINT;   /* RigidBody Constraint */
        constraintsTypeInfo[18]= &CTI_CLAMPTO;                  /* ClampTo Constraint */        
        constraintsTypeInfo[19]= &CTI_TRANSFORM;                /* Transformation Constraint */
+       constraintsTypeInfo[20]= &CTI_SHRINKWRAP;               /* Shrinkwrap Constraint */
+       constraintsTypeInfo[21]= &CTI_DAMPTRACK;                /* Damped TrackTo Constraint */
+       constraintsTypeInfo[22]= &CTI_SPLINEIK;                 /* Spline IK Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only
@@ -3142,7 +3580,7 @@ bConstraintTypeInfo *get_constraint_typeinfo (int type)
        
        /* only return for valid types */
        if ( (type >= CONSTRAINT_TYPE_NULL) && 
-                (type <= NUM_CONSTRAINT_TYPES ) ) 
+                (type < NUM_CONSTRAINT_TYPES ) ) 
        {
                /* there shouldn't be any segfaults here... */
                return constraintsTypeInfo[type];
@@ -3189,19 +3627,133 @@ void free_constraint_data (bConstraint *con)
 }
 
 /* Free all constraints from a constraint-stack */
-void free_constraints (ListBase *conlist)
+void free_constraints (ListBase *list)
 {
        bConstraint *con;
        
        /* Free constraint data and also any extra data */
-       for (con= conlist->first; con; con= con->next) {
+       for (con= list->first; con; con= con->next)
                free_constraint_data(con);
-       }
        
        /* Free the whole list */
-       BLI_freelistN(conlist);
+       BLI_freelistN(list);
+}
+
+
+/* Remove the specified constraint from the given constraint stack */
+int remove_constraint (ListBase *list, bConstraint *con)
+{
+       if (con) {
+               free_constraint_data(con);
+               BLI_freelinkN(list, con);
+               return 1;
+       }
+       else
+               return 0;
+}
+
+/* Remove the nth constraint from the given constraint stack */
+int remove_constraint_index (ListBase *list, int index)
+{
+       bConstraint *con= BLI_findlink(list, index);
+       
+       if (con)
+               return remove_constraint(list, con);
+       else 
+               return 0;
+}
+
+/* ......... */
+
+/* Creates a new constraint, initialises its data, and returns it */
+static bConstraint *add_new_constraint_internal (const char *name, short type)
+{
+       bConstraint *con= MEM_callocN(sizeof(bConstraint), "Constraint");
+       bConstraintTypeInfo *cti= get_constraint_typeinfo(type);
+       const char *newName;
+
+       /* Set up a generic constraint datablock */
+       con->type = type;
+       con->flag |= CONSTRAINT_EXPAND;
+       con->enforce = 1.0f;
+
+       /* Determine a basic name, and info */
+       if (cti) {
+               /* initialise constraint data */
+               con->data = MEM_callocN(cti->size, cti->structName);
+               
+               /* only constraints that change any settings need this */
+               if (cti->new_data)
+                       cti->new_data(con->data);
+               
+               /* if no name is provided, use the type of the constraint as the name */
+               newName= (name && name[0]) ? name : cti->name;
+       }
+       else {
+               /* if no name is provided, use the generic "Const" name */
+               // NOTE: any constraint type that gets here really shouldn't get added...
+               newName= (name && name[0]) ? name : "Const";
+       }
+       
+       /* copy the name */
+       BLI_strncpy(con->name, newName, sizeof(con->name));
+       
+       /* return the new constraint */
+       return con;
+}
+
+/* if pchan is not NULL then assume we're adding a pose constraint */
+static bConstraint *add_new_constraint (Object *ob, bPoseChannel *pchan, const char *name, short type)
+{
+       bConstraint *con;
+       ListBase *list;
+       
+       /* add the constraint */
+       con= add_new_constraint_internal(name, type);
+       
+       /* find the constraint stack - bone or object? */
+       list = (pchan) ? (&pchan->constraints) : (&ob->constraints);
+       
+       if (list) {
+               /* add new constraint to end of list of constraints before ensuring that it has a unique name
+                * (otherwise unique-naming code will fail, since it assumes element exists in list)
+                */
+               BLI_addtail(list, con);
+               unique_constraint_name(con, list);
+               
+               /* if the target list is a list on some PoseChannel belonging to a proxy-protected
+                * Armature layer, we must tag newly added constraints with a flag which allows them
+                * to persist after proxy syncing has been done
+                */
+               if (proxylocked_constraints_owner(ob, pchan))
+                       con->flag |= CONSTRAINT_PROXY_LOCAL;
+               
+               /* make this constraint the active one */
+               constraints_set_active(list, con);
+       }
+       
+       return con;
+}
+
+/* ......... */
+
+/* Add new constraint for the given bone */
+bConstraint *add_pose_constraint (Object *ob, bPoseChannel *pchan, const char *name, short type)
+{
+       if (pchan == NULL)
+               return NULL;
+       
+       return add_new_constraint(ob, pchan, name, type);
+}
+
+/* Add new constraint for the given object */
+bConstraint *add_ob_constraint(Object *ob, const char *name, short type)
+{
+       return add_new_constraint(ob, NULL, name, type);
 }
 
+/* ......... */
+
 /* Reassign links that constraints have to other data (called during file loading?) */
 void relink_constraints (ListBase *conlist)
 {
@@ -3232,8 +3784,10 @@ void relink_constraints (ListBase *conlist)
        }
 }
 
+/* ......... */
+
 /* duplicate all of the constraints in a constraint stack */
-void copy_constraints (ListBase *dst, ListBase *src)
+void copy_constraints (ListBase *dst, const ListBase *src)
 {
        bConstraint *con, *srccon;
        
@@ -3246,12 +3800,47 @@ void copy_constraints (ListBase *dst, ListBase *src)
                /* make a new copy of the constraint's data */
                con->data = MEM_dupallocN(con->data);
                
+               // NOTE: depreceated... old animation system
+               id_us_plus((ID *)con->ipo);
+               
                /* only do specific constraints if required */
                if (cti && cti->copy_data)
                        cti->copy_data(con, srccon);
        }
 }
 
+/* ......... */
+
+/* finds the 'active' constraint in a constraint stack */
+bConstraint *constraints_get_active (ListBase *list)
+{
+       bConstraint *con;
+       
+       /* search for the first constraint with the 'active' flag set */
+       if (list) {
+               for (con= list->first; con; con= con->next) {
+                       if (con->flag & CONSTRAINT_ACTIVE)
+                               return con;
+               }
+       }
+       
+       /* no active constraint found */
+       return NULL;
+}
+
+/* Set the given constraint as the active one (clearing all the others) */
+void constraints_set_active (ListBase *list, bConstraint *con)
+{
+       bConstraint *c;
+       
+       for (c= list->first; c; c= c->next) {
+               if (c == con) 
+                       c->flag |= CONSTRAINT_ACTIVE;
+               else 
+                       c->flag &= ~CONSTRAINT_ACTIVE;
+       }
+}
+
 /* -------- Constraints and Proxies ------- */
 
 /* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL (i.e. added to bone that's proxy-synced in this file) */
@@ -3301,7 +3890,7 @@ short proxylocked_constraints_owner (Object *ob, bPoseChannel *pchan)
  * None of the actual calculations of the matricies should be done here! Also, this function is 
  * not to be used by any new constraints, particularly any that have multiple targets.
  */
-void get_constraint_target_matrix (bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime)
+void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime)
 {
        bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
        ListBase targets = {NULL, NULL};
@@ -3312,18 +3901,19 @@ void get_constraint_target_matrix (bConstraint *con, int n, short ownertype, voi
                /* make 'constraint-ob' */
                cob= MEM_callocN(sizeof(bConstraintOb), "tempConstraintOb");
                cob->type= ownertype;
+               cob->scene = scene;
                switch (ownertype) {
                        case CONSTRAINT_OBTYPE_OBJECT: /* it is usually this case */
                        {
                                cob->ob= (Object *)ownerdata;
                                cob->pchan= NULL;
                                if (cob->ob) {
-                                       Mat4CpyMat4(cob->matrix, cob->ob->obmat);
-                                       Mat4CpyMat4(cob->startmat, cob->matrix);
+                                       copy_m4_m4(cob->matrix, cob->ob->obmat);
+                                       copy_m4_m4(cob->startmat, cob->matrix);
                                }
                                else {
-                                       Mat4One(cob->matrix);
-                                       Mat4One(cob->startmat);
+                                       unit_m4(cob->matrix);
+                                       unit_m4(cob->startmat);
                                }
                        }       
                                break;
@@ -3332,12 +3922,12 @@ void get_constraint_target_matrix (bConstraint *con, int n, short ownertype, voi
                                cob->ob= NULL; /* this might not work at all :/ */
                                cob->pchan= (bPoseChannel *)ownerdata;
                                if (cob->pchan) {
-                                       Mat4CpyMat4(cob->matrix, cob->pchan->pose_mat);
-                                       Mat4CpyMat4(cob->startmat, cob->matrix);
+                                       copy_m4_m4(cob->matrix, cob->pchan->pose_mat);
+                                       copy_m4_m4(cob->startmat, cob->matrix);
                                }
                                else {
-                                       Mat4One(cob->matrix);
-                                       Mat4One(cob->startmat);
+                                       unit_m4(cob->matrix);
+                                       unit_m4(cob->startmat);
                                }
                        }
                                break;
@@ -3354,7 +3944,7 @@ void get_constraint_target_matrix (bConstraint *con, int n, short ownertype, voi
                if (ct) {
                        if (cti->get_target_matrix)
                                cti->get_target_matrix(con, cob, ct, ctime);
-                       Mat4CpyMat4(mat, ct->matrix);
+                       copy_m4_m4(mat, ct->matrix);
                }
                
                /* free targets + 'constraint-ob' */
@@ -3364,7 +3954,7 @@ void get_constraint_target_matrix (bConstraint *con, int n, short ownertype, voi
        }
        else {
                /* invalid constraint - perhaps... */
-               Mat4One(mat);
+               unit_m4(mat);
        }
 }
  
@@ -3394,7 +3984,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
                
                /* these we can skip completely (invalid constraints...) */
                if (cti == NULL) continue;
-               if (con->flag & CONSTRAINT_DISABLE) continue;
+               if (con->flag & (CONSTRAINT_DISABLE|CONSTRAINT_OFF)) continue;
                /* these constraints can't be evaluated anyway */
                if (cti->evaluate_constraint == NULL) continue;
                /* influence == 0 should be ignored */
@@ -3407,7 +3997,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
                
                /* move owner matrix into right space */
                constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
-               Mat4CpyMat4(oldmat, cob->matrix);
+               copy_m4_m4(oldmat, cob->matrix);
                
                /* prepare targets for constraint solving */
                if (cti->get_constraint_targets) {
@@ -3428,7 +4018,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
                        }
                        else {
                                for (ct= targets.first; ct; ct= ct->next)
-                                       Mat4One(ct->matrix);
+                                       unit_m4(ct->matrix);
                        }
                }
                
@@ -3445,21 +4035,21 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
                
                /* Interpolate the enforcement, to blend result of constraint into final owner transform */
                /* 1. Remove effects of original matrix from constraint solution ==> delta */
-               Mat4Invert(imat, oldmat);
-               Mat4CpyMat4(solution, cob->matrix);
-               Mat4MulMat4(delta, solution, imat);
+               invert_m4_m4(imat, oldmat);
+               copy_m4_m4(solution, cob->matrix);
+               mul_m4_m4m4(delta, solution, imat);
                
                /* 2. If constraint influence is not full strength, then interpolate
                 *      identity_matrix --> delta_matrix to get the effect the constraint actually exerts
                 */
                if (enf < 1.0) {
                        float identity[4][4];
-                       Mat4One(identity);
-                       Mat4BlendMat4(delta, identity, delta, enf);
+                       unit_m4(identity);
+                       blend_m4_m4m4(delta, identity, delta, enf);
                }
                
                /* 3. Now multiply the delta by the matrix in use before the evaluation */
-               Mat4MulMat4(cob->matrix, delta, oldmat);
+               mul_m4_m4m4(cob->matrix, delta, oldmat);
                
                /* move owner back into worldspace for next constraint/other business */
                if ((con->flag & CONSTRAINT_SPACEONCE) == 0)