NLA SoC: Start of 'Meta' Strips
[blender.git] / source / blender / blenkernel / intern / armature.c
index 78e8253625d66166248e9b875576b6fa08c1b40e..1b930a74449b7e0353507643de2a48e7b81c87d3 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -22,7 +22,7 @@
  *
  * Contributor(s): Full recode, Ton Roosendaal, Crete 2005
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include <ctype.h>
 #include <math.h>
 #include <string.h>
 #include <stdio.h>
+#include <float.h>
+
 #include "MEM_guardedalloc.h"
 
-#include "nla.h"
+//XXX #include "nla.h"
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 
 /*     **************** Generic Functions, data level *************** */
 
-bArmature *get_armature(Object *ob)
-{
-       if(ob==NULL) return NULL;
-       if(ob->type==OB_ARMATURE) return ob->data;
-       else return NULL;
-}
-
 bArmature *add_armature(char *name)
 {
        bArmature *arm;
@@ -92,6 +87,12 @@ bArmature *add_armature(char *name)
        return arm;
 }
 
+bArmature *get_armature(Object *ob)
+{
+       if(ob->type==OB_ARMATURE)
+               return (bArmature *)ob->data;
+       return NULL;
+}
 
 void free_boneChildren(Bone *bone)
 { 
@@ -131,6 +132,14 @@ void free_armature(bArmature *arm)
        if (arm) {
                /*              unlink_armature(arm);*/
                free_bones(arm);
+               
+               /* free editmode data */
+               if (arm->edbo) {
+                       BLI_freelistN(arm->edbo);
+                       
+                       MEM_freeN(arm->edbo);
+                       arm->edbo= NULL;
+               }
        }
 }
 
@@ -178,7 +187,7 @@ static void copy_bonechildren (Bone* newBone, Bone* oldBone)
        Bone    *curBone, *newChildBone;
        
        /*      Copy this bone's list*/
-       duplicatelist (&newBone->childbase, &oldBone->childbase);
+       BLI_duplicatelist(&newBone->childbase, &oldBone->childbase);
        
        /*      For each child in the list, update it's children*/
        newChildBone=newBone->childbase.first;
@@ -195,7 +204,7 @@ bArmature *copy_armature(bArmature *arm)
        Bone            *oldBone, *newBone;
        
        newArm= copy_libblock (arm);
-       duplicatelist(&newArm->bonebase, &arm->bonebase);
+       BLI_duplicatelist(&newArm->bonebase, &arm->bonebase);
        
        /*      Duplicate the childrens' lists*/
        newBone=newArm->bonebase.first;
@@ -354,6 +363,117 @@ void bone_flip_name (char *name, int strip_number)
        sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
 }
 
+/* Finds the best possible extension to the name on a particular axis. (For renaming, check for unique names afterwards)
+ * This assumes that bone names are at most 32 chars long!
+ *     strip_number: removes number extensions  (TODO: not used)
+ *     axis: the axis to name on
+ *     head/tail: the head/tail co-ordinate of the bone on the specified axis
+ */
+void bone_autoside_name (char *name, int strip_number, short axis, float head, float tail)
+{
+       unsigned int len;
+       char    basename[32]={""};
+       char    extension[5]={""};
+
+       len= strlen(name);
+       if (len == 0) return;
+       strcpy(basename, name);
+       
+       /* Figure out extension to append: 
+        *      - The extension to append is based upon the axis that we are working on.
+        *      - If head happens to be on 0, then we must consider the tail position as well to decide
+        *        which side the bone is on
+        *              -> If tail is 0, then it's bone is considered to be on axis, so no extension should be added
+        *              -> Otherwise, extension is added from perspective of object based on which side tail goes to
+        *      - If head is non-zero, extension is added from perspective of object based on side head is on
+        */
+       if (axis == 2) {
+               /* z-axis - vertical (top/bottom) */
+               if (IS_EQ(head, 0)) {
+                       if (tail < 0)
+                               strcpy(extension, "Bot");
+                       else if (tail > 0)
+                               strcpy(extension, "Top");
+               }
+               else {
+                       if (head < 0)
+                               strcpy(extension, "Bot");
+                       else
+                               strcpy(extension, "Top");
+               }
+       }
+       else if (axis == 1) {
+               /* y-axis - depth (front/back) */
+               if (IS_EQ(head, 0)) {
+                       if (tail < 0)
+                               strcpy(extension, "Fr");
+                       else if (tail > 0)
+                               strcpy(extension, "Bk");
+               }
+               else {
+                       if (head < 0)
+                               strcpy(extension, "Fr");
+                       else
+                               strcpy(extension, "Bk");
+               }
+       }
+       else {
+               /* x-axis - horizontal (left/right) */
+               if (IS_EQ(head, 0)) {
+                       if (tail < 0)
+                               strcpy(extension, "R");
+                       else if (tail > 0)
+                               strcpy(extension, "L");
+               }
+               else {
+                       if (head < 0)
+                               strcpy(extension, "R");
+                       else if (head > 0)
+                               strcpy(extension, "L");
+               }
+       }
+
+       /* Simple name truncation 
+        *      - truncate if there is an extension and it wouldn't be able to fit
+        *      - otherwise, just append to end
+        */
+       if (extension[0]) {
+               int change = 1;
+               
+               while (change) { /* remove extensions */
+                       change = 0;
+                       if (len > 2 && basename[len-2]=='.') {
+                               if (basename[len-1]=='L' || basename[len-1] == 'R' ) { /* L R */
+                                       basename[len-2] = '\0';
+                                       len-=2;
+                                       change= 1;
+                               }
+                       } else if (len > 3 && basename[len-3]=='.') {
+                               if (    (basename[len-2]=='F' && basename[len-1] == 'r') ||     /* Fr */
+                                               (basename[len-2]=='B' && basename[len-1] == 'k')        /* Bk */
+                               ) {
+                                       basename[len-3] = '\0';
+                                       len-=3;
+                                       change= 1;
+                               }
+                       } else if (len > 4 && basename[len-4]=='.') {
+                               if (    (basename[len-3]=='T' && basename[len-2]=='o' && basename[len-1] == 'p') ||     /* Top */
+                                               (basename[len-3]=='B' && basename[len-2]=='o' && basename[len-1] == 't')        /* Bot */
+                               ) {
+                                       basename[len-4] = '\0';
+                                       len-=4;
+                                       change= 1;
+                               }
+                       }
+               }
+               
+               if ((32 - len) < strlen(extension) + 1) { /* add 1 for the '.' */
+                       strncpy(name, basename, len-strlen(extension));
+               }
+       }
+
+       sprintf(name, "%s.%s", basename, extension);
+}
 
 /* ************* B-Bone support ******************* */
 
@@ -494,7 +614,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
                        Mat3Inv(imat3, mat3);
                        Mat3MulMat3(mat3, result, imat3);                       // the matrix transforming vec_roll to desired roll
                        
-                       roll1= atan2(mat3[2][0], mat3[2][2]);
+                       roll1= (float)atan2(mat3[2][0], mat3[2][2]);
                }
        }
        else {
@@ -527,7 +647,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
                Mat3Inv(imat3, mat3);
                Mat3MulMat3(mat3, imat3, result);                       // the matrix transforming vec_roll to desired roll
                
-               roll2= atan2(mat3[2][0], mat3[2][2]);
+               roll2= (float)atan2(mat3[2][0], mat3[2][2]);
                
                /* and only now negate handle */
                VecMulf(h2, -hlength2);
@@ -672,7 +792,7 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl
                
                if(l!=0.0f) {
                        rad= a/l;
-                       rad= rad*rad2 + (1.0-rad)*rad1;
+                       rad= rad*rad2 + (1.0f-rad)*rad1;
                }
                else rad= rad1;
        }
@@ -686,8 +806,8 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl
                if(rdist==0.0f || dist >= l) 
                        return 0.0f;
                else {
-                       a= sqrt(dist)-rad;
-                       return 1.0-( a*a )/( rdist*rdist );
+                       a= (float)sqrt(dist)-rad;
+                       return 1.0f-( a*a )/( rdist*rdist );
                }
        }
 }
@@ -793,6 +913,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
                                                   int numVerts, int deformflag, 
                                                   float (*prevCos)[3], const char *defgrp_name)
 {
+       bArmature *arm= armOb->data;
        bPoseChannel *pchan, **defnrToPC = NULL;
        MDeformVert *dverts = NULL;
        bDeformGroup *dg;
@@ -808,7 +929,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
        int armature_def_nr = -1;
        int totchan;
 
-       if(armOb == G.obedit) return;
+       if(arm->edbo) return;
        
        Mat4Invert(obinv, target->obmat);
        Mat4CpyMat4(premat, target->obmat);
@@ -1103,7 +1224,10 @@ void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outm
        if (pchan==NULL) return;
        
        /* get the inverse matrix of the pchan's transforms */
-       LocQuatSizeToMat4(pc_trans, pchan->loc, pchan->quat, pchan->size);
+       if (pchan->rotmode)
+               LocEulSizeToMat4(pc_trans, pchan->loc, pchan->eul, pchan->size);
+       else
+               LocQuatSizeToMat4(pc_trans, pchan->loc, pchan->quat, pchan->size);
        Mat4Invert(inv_trans, pc_trans);
        
        /* Remove the pchan's transforms from it's pose_mat.
@@ -1185,7 +1309,7 @@ void mat3_to_vec_roll(float mat[][3], float *vec, float *roll)
         Mat3Inv(vecmatinv, vecmat);
         Mat3MulMat3(rollmat, vecmatinv, mat);
 
-        *roll= atan2(rollmat[2][0], rollmat[2][2]);
+        *roll= (float)atan2(rollmat[2][0], rollmat[2][2]);
     }
 }
 
@@ -1217,7 +1341,7 @@ void vec_roll_to_mat3(float *vec, float roll, float mat[][3])
                float updown;
                
                /* point same direction, or opposite? */
-               updown = ( Inpf (target,nor) > 0 ) ? 1.0 : -1.0;
+               updown = ( Inpf (target,nor) > 0 ) ? 1.0f : -1.0f;
                
                /* I think this should work ... */
                bMatrix[0][0]=updown; bMatrix[0][1]=0.0;    bMatrix[0][2]=0.0;
@@ -1305,18 +1429,27 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
        bPoseChannel *pchan, *pchanp, pchanw;
        bConstraint *con;
        
-       if(frompose==NULL) return;
+       if (frompose==NULL) return;
        
        /* exception, armature local layer should be proxied too */
-       if(pose->proxy_layer)
+       if (pose->proxy_layer)
                ((bArmature *)ob->data)->layer= pose->proxy_layer;
        
        /* clear all transformation values from library */
        rest_pose(frompose);
        
-       pchan= pose->chanbase.first;
-       for(; pchan; pchan= pchan->next) {
-               if(pchan->bone->layer & layer_protected) {
+       /* copy over all of the proxy's bone groups */
+               /* TODO for later - implement 'local' bone groups as for constraints
+                *      Note: this isn't trivial, as bones reference groups by index not by pointer, 
+                *               so syncing things correctly needs careful attention
+                */
+       BLI_freelistN(&pose->agroups);
+       BLI_duplicatelist(&pose->agroups, &frompose->agroups);
+       pose->active_group= frompose->active_group;
+       
+       for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+               if (pchan->bone->layer & layer_protected) {
+                       ListBase proxylocal_constraints = {NULL, NULL};
                        pchanp= get_pose_channel(frompose, pchan->name);
                        
                        /* copy posechannel to temp, but restore important pointers */
@@ -1327,9 +1460,16 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
                        pchanw.child= pchan->child;
                        pchanw.path= NULL;
                        
-                       /* constraints, set target ob pointer to own object */
+                       /* constraints - proxy constraints are flushed... local ones are added after 
+                        *      1. extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints
+                        *      2. copy proxy-pchan's constraints on-to new
+                        *      3. add extracted local constraints back on top 
+                        */
+                       extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints);
                        copy_constraints(&pchanw.constraints, &pchanp->constraints);
+                       addlisttolist(&pchanw.constraints, &proxylocal_constraints);
                        
+                       /* constraints - set target ob pointer to own object */
                        for (con= pchanw.constraints.first; con; con= con->next) {
                                bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
                                ListBase targets = {NULL, NULL};
@@ -1439,26 +1579,21 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip)
        PoseTree *tree;
        PoseTarget *target;
        bConstraint *con;
-       bKinematicConstraint *data;
+       bKinematicConstraint *data= NULL;
        int a, segcount= 0, size, newsize, *oldparent, parent;
        
        /* find IK constraint, and validate it */
        for(con= pchan_tip->constraints.first; con; con= con->next) {
-               if(con->type==CONSTRAINT_TYPE_KINEMATIC) break;
+               if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
+                       data=(bKinematicConstraint*)con->data;
+                       if (data->flag & CONSTRAINT_IK_AUTO) break;
+                       if (data->tar==NULL) continue;
+                       if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) continue;
+                       if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) break;
+               }
        }
        if(con==NULL) return;
        
-       data=(bKinematicConstraint*)con->data;
-       
-       /* two types of targets */
-       if(data->flag & CONSTRAINT_IK_AUTO);
-       else {
-               if(con->flag & CONSTRAINT_DISABLE) return;      /* checked in editconstraint.c */
-               if(con->enforce == 0.0f) return;
-               if(data->tar==NULL) return;
-               if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0) return;
-       }
-       
        /* exclude tip from chain? */
        if(!(data->flag & CONSTRAINT_IK_TIP))
                pchan_tip= pchan_tip->parent;
@@ -1561,7 +1696,7 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip)
 were executed & assigned. Now as last we do an IK pass */
 static void execute_posetree(Object *ob, PoseTree *tree)
 {
-       float R_parmat[3][3];
+       float R_parmat[3][3], identity[3][3];
        float iR_parmat[3][3];
        float R_bonemat[3][3];
        float goalrot[3][3], goalpos[3];
@@ -1570,7 +1705,8 @@ static void execute_posetree(Object *ob, PoseTree *tree)
        float irest_basis[3][3], full_basis[3][3];
        float end_pose[4][4], world_pose[4][4];
        float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL;
-       int a, flag, hasstretch=0;
+       float resultinf=0.0f;
+       int a, flag, hasstretch=0, resultblend=0;
        bPoseChannel *pchan;
        IK_Segment *seg, *parent, **iktree, *iktarget;
        IK_Solver *solver;
@@ -1580,13 +1716,13 @@ static void execute_posetree(Object *ob, PoseTree *tree)
 
        if (tree->totchannel == 0)
                return;
-
+       
        iktree= MEM_mallocN(sizeof(void*)*tree->totchannel, "ik tree");
 
        for(a=0; a<tree->totchannel; a++) {
                pchan= tree->pchan[a];
                bone= pchan->bone;
-
+               
                /* set DoF flag */
                flag= 0;
                if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP))
@@ -1595,32 +1731,32 @@ static void execute_posetree(Object *ob, PoseTree *tree)
                        flag |= IK_YDOF;
                if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP))
                        flag |= IK_ZDOF;
-
+               
                if(tree->stretch && (pchan->ikstretch > 0.0)) {
                        flag |= IK_TRANS_YDOF;
                        hasstretch = 1;
                }
-
+               
                seg= iktree[a]= IK_CreateSegment(flag);
-
+               
                /* find parent */
                if(a == 0)
                        parent= NULL;
                else
                        parent= iktree[tree->parent[a]];
-
+                       
                IK_SetParent(seg, parent);
-       
+                       
                /* get the matrix that transforms from prevbone into this bone */
                Mat3CpyMat4(R_bonemat, pchan->pose_mat);
-
+               
                /* gather transformations for this IK segment */
-
+               
                if (pchan->parent)
                        Mat3CpyMat4(R_parmat, pchan->parent->pose_mat);
                else
                        Mat3One(R_parmat);
-
+               
                /* bone offset */
                if (pchan->parent && (a > 0))
                        VecSubf(start, pchan->pose_head, pchan->parent->pose_tail);
@@ -1630,41 +1766,41 @@ static void execute_posetree(Object *ob, PoseTree *tree)
                
                /* change length based on bone size */
                length= bone->length*VecLength(R_bonemat[1]);
-
+               
                /* compute rest basis and its inverse */
                Mat3CpyMat3(rest_basis, bone->bone_mat);
                Mat3CpyMat3(irest_basis, bone->bone_mat);
                Mat3Transp(irest_basis);
-
+               
                /* compute basis with rest_basis removed */
                Mat3Inv(iR_parmat, R_parmat);
                Mat3MulMat3(full_basis, iR_parmat, R_bonemat);
                Mat3MulMat3(basis, irest_basis, full_basis);
-
+               
                /* basis must be pure rotation */
                Mat3Ortho(basis);
-
+               
                /* transform offset into local bone space */
                Mat3Ortho(iR_parmat);
                Mat3MulVecfl(iR_parmat, start);
-
+               
                IK_SetTransform(seg, start, rest_basis, basis, length);
-
+               
                if (pchan->ikflag & BONE_IK_XLIMIT)
                        IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]);
                if (pchan->ikflag & BONE_IK_YLIMIT)
                        IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]);
                if (pchan->ikflag & BONE_IK_ZLIMIT)
                        IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]);
-
+               
                IK_SetStiffness(seg, IK_X, pchan->stiffness[0]);
                IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]);
                IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]);
-
-               if(tree->stretch && (pchan->ikstretch > 0.0)) {
+               
+               if(tree->stretch && (pchan->ikstretch > 0.0f)) {
                        float ikstretch = pchan->ikstretch*pchan->ikstretch;
-                       IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0-ikstretch, 0.999));
-                       IK_SetLimit(seg, IK_TRANS_Y, 0.001, 1e10);
+                       IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0f-ikstretch, 0.99f));
+                       IK_SetLimit(seg, IK_TRANS_Y, 0.001f, 1e10);
                }
        }
 
@@ -1689,7 +1825,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
        for (target=tree->targets.first; target; target=target->next) {
                float polepos[3];
                int poleconstrain= 0;
-
+               
                data= (bKinematicConstraint*)target->con->data;
                
                /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
@@ -1706,7 +1842,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
                /* same for pole vector target */
                if(data->poletar) {
                        get_constraint_target_matrix(target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
-
+                       
                        if(data->flag & CONSTRAINT_IK_SETANGLE) {
                                /* don't solve IK when we are setting the pole angle */
                                break;
@@ -1716,6 +1852,12 @@ static void execute_posetree(Object *ob, PoseTree *tree)
                                VECCOPY(polepos, goal[3]);
                                poleconstrain= 1;
 
+                               /* for pole targets, we blend the result of the ik solver
+                                * instead of the target position, otherwise we can't get
+                                * a smooth transition */
+                               resultblend= 1;
+                               resultinf= target->con->enforce;
+                               
                                if(data->flag & CONSTRAINT_IK_GETANGLE) {
                                        poleangledata= data;
                                        data->flag &= ~CONSTRAINT_IK_GETANGLE;
@@ -1724,10 +1866,10 @@ static void execute_posetree(Object *ob, PoseTree *tree)
                }
 
                /* do we need blending? */
-               if (target->con->enforce!=1.0) {
+               if (!resultblend && target->con->enforce!=1.0f) {
                        float q1[4], q2[4], q[4];
                        float fac= target->con->enforce;
-                       float mfac= 1.0-fac;
+                       float mfac= 1.0f-fac;
                        
                        pchan= tree->pchan[target->tip];
                        
@@ -1750,13 +1892,13 @@ static void execute_posetree(Object *ob, PoseTree *tree)
                
                iktarget= iktree[target->tip];
                
-               if(data->weight != 0.0) {
+               if(data->weight != 0.0f) {
                        if(poleconstrain)
                                IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos,
-                                       polepos, data->poleangle*M_PI/180, (poleangledata == data));
+                                       polepos, data->poleangle*(float)M_PI/180.0f, (poleangledata == data));
                        IK_SolverAddGoal(solver, iktarget, goalpos, data->weight);
                }
-               if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0))
+               if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f))
                        if((data->flag & CONSTRAINT_IK_AUTO)==0)
                                IK_SolverAddGoalOrientation(solver, iktarget, goalrot,
                                        data->orientweight);
@@ -1766,7 +1908,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
        IK_Solve(solver, 0.0f, tree->iterations);
 
        if(poleangledata)
-               poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180/M_PI;
+               poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180.0f/(float)M_PI;
 
        IK_FreeSolver(solver);
 
@@ -1774,36 +1916,41 @@ static void execute_posetree(Object *ob, PoseTree *tree)
        tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change");
        if(hasstretch)
                ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch");
-
+       
        for(a=0; a<tree->totchannel; a++) {
                IK_GetBasisChange(iktree[a], tree->basis_change[a]);
-
+               
                if(hasstretch) {
                        /* have to compensate for scaling received from parent */
                        float parentstretch, stretch;
-
+                       
                        pchan= tree->pchan[a];
-                       parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0;
-
-                       if(tree->stretch && (pchan->ikstretch > 0.0)) {
+                       parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0f;
+                       
+                       if(tree->stretch && (pchan->ikstretch > 0.0f)) {
                                float trans[3], length;
-
+                               
                                IK_GetTranslationChange(iktree[a], trans);
                                length= pchan->bone->length*VecLength(pchan->pose_mat[1]);
-
-                               ikstretch[a]= (length == 0.0)? 1.0: (trans[1]+length)/length;
+                               
+                               ikstretch[a]= (length == 0.0f)? 1.0f: (trans[1]+length)/length;
                        }
                        else
-                               ikstretch[a] = 1.0;
-
-                       stretch= (parentstretch == 0.0)? 1.0: ikstretch[a]/parentstretch;
-
+                               ikstretch[a] = 1.0f;
+                       
+                       stretch= (parentstretch == 0.0f)? 1.0f: ikstretch[a]/parentstretch;
+                       
                        VecMulf(tree->basis_change[a][0], stretch);
                        VecMulf(tree->basis_change[a][1], stretch);
                        VecMulf(tree->basis_change[a][2], stretch);
-
                }
 
+               if(resultblend && resultinf!=1.0f) {
+                       Mat3One(identity);
+                       Mat3BlendMat3(tree->basis_change[a], identity,
+                               tree->basis_change[a], resultinf);
+               }
+               
                IK_FreeSegment(iktree[a]);
        }
        
@@ -1831,22 +1978,29 @@ void chan_calc_mat(bPoseChannel *chan)
        float rmat[3][3];
        float tmat[3][3];
        
+       /* get scaling matrix */
        SizeToMat3(chan->size, smat);
        
-       NormalQuat(chan->quat);
-
-       QuatToMat3(chan->quat, rmat);
+       /* rotations may either be quats or eulers (no rotation modes for now...) */
+       if (chan->rotmode) {
+               /* euler rotations (will cause gimble lock... no rotation order to solve that yet) */
+               EulToMat3(chan->eul, rmat);
+       }
+       else {
+               /* quats are normalised before use to eliminate scaling issues */
+               NormalQuat(chan->quat);
+               QuatToMat3(chan->quat, rmat);
+       }
        
+       /* calculate matrix of bone (as 3x3 matrix, but then copy the 4x4) */
        Mat3MulMat3(tmat, rmat, smat);
-       
        Mat4CpyMat3(chan->chan_mat, tmat);
        
        /* prevent action channels breaking chains */
        /* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */
-       if (chan->bone==NULL || !(chan->bone->flag & BONE_CONNECTED)) {
+       if ((chan->bone==NULL) || !(chan->bone->flag & BONE_CONNECTED)) {
                VECCOPY(chan->chan_mat[3], chan->loc);
        }
-
 }
 
 /* transform from bone(b) to bone(b+1), store in chan_mat */
@@ -1885,11 +2039,11 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3])   // nr = t
 }
 
 /* NLA strip modifiers */
-static void do_strip_modifiers(Object *armob, Bone *bone, bPoseChannel *pchan)
+static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseChannel *pchan)
 {
        bActionModifier *amod;
        bActionStrip *strip, *strip2;
-       float scene_cfra= G.scene->r.cfra;
+       float scene_cfra= (float)scene->r.cfra;
        int do_modif;
 
        for (strip=armob->nlastrips.first; strip; strip=strip->next) {
@@ -1938,7 +2092,7 @@ static void do_strip_modifiers(Object *armob, Bone *bone, bPoseChannel *pchan)
                                                if( strcmp(pchan->name, amod->channel)==0 ) {
                                                        float mat4[4][4], mat3[3][3];
                                                        
-                                                       curve_deform_vector(amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis);
+                                                       curve_deform_vector(scene, amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis);
                                                        Mat4CpyMat4(mat4, pchan->pose_mat);
                                                        Mat4MulMat34(pchan->pose_mat, mat3, mat4);
                                                        
@@ -2009,7 +2163,7 @@ static void do_strip_modifiers(Object *armob, Bone *bone, bPoseChannel *pchan)
 
 /* The main armature solver, does all constraints excluding IK */
 /* pchan is validated, as having bone and parent pointer */
-static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
+static void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime)
 {
        Bone *bone, *parbone;
        bPoseChannel *parchan;
@@ -2072,27 +2226,26 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
        }
        else {
                Mat4MulMat4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat);
-               /* only rootbones get the cyclic offset */
-               VecAddf(pchan->pose_mat[3], pchan->pose_mat[3], ob->pose->cyclic_offset);
+               
+               /* only rootbones get the cyclic offset (unless user doesn't want that) */
+               if ((bone->flag & BONE_NO_CYCLICOFFSET) == 0)
+                       VecAddf(pchan->pose_mat[3], pchan->pose_mat[3], ob->pose->cyclic_offset);
        }
        
        /* do NLA strip modifiers - i.e. curve follow */
-       do_strip_modifiers(ob, bone, pchan);
+       do_strip_modifiers(scene, ob, bone, pchan);
        
        /* Do constraints */
        if (pchan->constraints.first) {
                bConstraintOb *cob;
                
-               /* local constraints */
-               do_constraint_channels(&pchan->constraints, NULL, ctime, 0);
-               
                /* make a copy of location of PoseChannel for later */
                VECCOPY(vec, pchan->pose_mat[3]);
                
                /* prepare PoseChannel for Constraint solving 
                 * - makes a copy of matrix, and creates temporary struct to use 
                 */
-               cob= constraints_make_evalob(ob, pchan, CONSTRAINT_OBTYPE_BONE);
+               cob= constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
                
                /* Solve PoseChannel's Constraints */
                solve_constraints(&pchan->constraints, cob, ctime);     // ctime doesnt alter objects
@@ -2118,22 +2271,25 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
 
 /* This only reads anim data from channels, and writes to channels */
 /* This is the only function adding poses */
-void where_is_pose (Object *ob)
+void where_is_pose (Scene *scene, Object *ob)
 {
        bArmature *arm;
        Bone *bone;
        bPoseChannel *pchan;
        float imat[4][4];
-       float ctime= bsystem_time(ob, (float)G.scene->r.cfra, 0.0);     /* not accurate... */
+       float ctime;
        
-       arm = get_armature(ob);
+       if(ob->type!=OB_ARMATURE) return;
+       arm = ob->data;
        
-       if(arm==NULL) return;
-       if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC)) 
+       if(ELEM(NULL, arm, scene)) return;
+       if((ob->pose==NULL) || (ob->pose->flag & POSE_RECALC)) 
           armature_rebuild_pose(ob, arm);
+          
+       ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0);      /* not accurate... */
        
-       /* In restposition we read the data from the bones */
-       if(ob==G.obedit || (arm->flag & ARM_RESTPOS)) {
+       /* In editmode or restposition we read the data from the bones */
+       if(arm->edbo || (arm->flag & ARM_RESTPOS)) {
                
                for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
                        bone= pchan->bone;
@@ -2166,7 +2322,7 @@ void where_is_pose (Object *ob)
                                        /* 4. walk over the tree for regular solving */
                                        for(a=0; a<tree->totchannel; a++) {
                                                if(!(tree->pchan[a]->flag & POSE_DONE)) // successive trees can set the flag
-                                                       where_is_pose_bone(ob, tree->pchan[a], ctime);
+                                                       where_is_pose_bone(scene, ob, tree->pchan[a], ctime);
                                        }
                                        /* 5. execute the IK solver */
                                        execute_posetree(ob, tree);
@@ -2186,7 +2342,7 @@ void where_is_pose (Object *ob)
                                }
                        }
                        else if(!(pchan->flag & POSE_DONE)) {
-                               where_is_pose_bone(ob, pchan, ctime);
+                               where_is_pose_bone(scene, ob, pchan, ctime);
                        }
                }
        }