replace VECCOPY and QUATCOPY with inline funcs.
[blender.git] / source / blender / blenkernel / intern / armature.c
index 0d1d08a..9fba18d 100644 (file)
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/armature.c
+ *  \ingroup bke
+ */
+
+
 #include <ctype.h>
 #include <stdlib.h>
 #include <math.h>
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_bpath.h"
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
 
 #include "DNA_anim_types.h"
 #include "DNA_armature_types.h"
@@ -63,7 +68,7 @@
 #include "BKE_lattice.h"
 #include "BKE_main.h"
 #include "BKE_object.h"
-#include "BKE_utildefines.h"
+
 #include "BIK_api.h"
 #include "BKE_sketch.h"
 
@@ -131,39 +136,42 @@ void free_armature(bArmature *arm)
 
 void make_local_armature(bArmature *arm)
 {
-       int local=0, lib=0;
+       Main *bmain= G.main;
+       int is_local= FALSE, is_lib= FALSE;
        Object *ob;
-       bArmature *newArm;
-       
-       if (arm->id.lib==0)
-               return;
+
+       if (arm->id.lib==NULL) return;
        if (arm->id.us==1) {
-               arm->id.lib= 0;
-               arm->id.flag= LIB_LOCAL;
-               new_id(0, (ID*)arm, 0);
+               id_clear_lib_data(bmain, &arm->id);
                return;
        }
-       
-       if(local && lib==0) {
-               arm->id.lib= 0;
-               arm->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)arm, 0);
+
+       for(ob= bmain->object.first; ob && ELEM(0, is_lib, is_local); ob= ob->id.next) {
+               if(ob->data == arm) {
+                       if(ob->id.lib) is_lib= TRUE;
+                       else is_local= TRUE;
+               }
        }
-       else if(local && lib) {
-               newArm= copy_armature(arm);
-               newArm->id.us= 0;
-               
-               ob= G.main->object.first;
-               while(ob) {
-                       if(ob->data==arm) {
-                               
-                               if(ob->id.lib==0) {
-                                       ob->data= newArm;
-                                       newArm->id.us++;
+
+       if(is_local && is_lib == FALSE) {
+               id_clear_lib_data(bmain, &arm->id);
+       }
+       else if(is_local && is_lib) {
+               char *bpath_user_data[2]= {bmain->name, arm->id.lib->filepath};
+               bArmature *armn= copy_armature(arm);
+               armn->id.us= 0;
+
+               /* Remap paths of new ID using old library as base. */
+               bpath_traverse_id(bmain, &armn->id, bpath_relocate_visitor, 0, bpath_user_data);
+
+               for(ob= bmain->object.first; ob; ob= ob->id.next) {
+                       if(ob->data == arm) {
+                               if(ob->id.lib==NULL) {
+                                       ob->data= armn;
+                                       armn->id.us++;
                                        arm->id.us--;
                                }
                        }
-                       ob= ob->id.next;
                }
        }
 }
@@ -208,6 +216,11 @@ bArmature *copy_armature(bArmature *arm)
        };
        
        newArm->act_bone= newActBone;
+
+       newArm->edbo= NULL;
+       newArm->act_edbone= NULL;
+       newArm->sketch= NULL;
+
        return newArm;
 }
 
@@ -247,16 +260,15 @@ Bone *get_named_bone (bArmature *arm, const char *name)
 }
 
 /* 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
  */
-int bone_autoside_name (char *name, int UNUSED(strip_number), short axis, float head, float tail)
+int bone_autoside_name (char name[MAXBONENAME], int UNUSED(strip_number), short axis, float head, float tail)
 {
        unsigned int len;
-       char    basename[32]={""};
-       char    extension[5]={""};
+       char    basename[MAXBONENAME]= "";
+       char    extension[5]= "";
 
        len= strlen(name);
        if (len == 0) return 0;
@@ -349,13 +361,13 @@ int bone_autoside_name (char *name, int UNUSED(strip_number), short axis, float
                                }
                        }
                }
-               
-               if ((32 - len) < strlen(extension) + 1) { /* add 1 for the '.' */
+
+               if ((MAXBONENAME - len) < strlen(extension) + 1) { /* add 1 for the '.' */
                        strncpy(name, basename, len-strlen(extension));
                }
-               
-               sprintf(name, "%s.%s", basename, extension);
-               
+
+               BLI_snprintf(name, MAXBONENAME, "%s.%s", basename, extension);
+
                return 1;
        }
 
@@ -378,11 +390,11 @@ static void equalize_bezier(float *data, int desired)
        
        pdist[0]= 0.0f;
        for(a=0, fp= data; a<MAX_BBONE_SUBDIV; a++, fp+=4) {
-               QUATCOPY(temp[a], fp);
+               copy_qt_qt(temp[a], fp);
                pdist[a+1]= pdist[a]+len_v3v3(fp, fp+4);
        }
        /* do last point */
-       QUATCOPY(temp[a], fp);
+       copy_qt_qt(temp[a], fp);
        totdist= pdist[a];
        
        /* go over distances and calculate new points */
@@ -408,7 +420,7 @@ static void equalize_bezier(float *data, int desired)
                fp[3]= fac1*temp[nr-1][3]+ fac2*temp[nr][3];
        }
        /* set last point, needed for orientation calculus */
-       QUATCOPY(fp, temp[MAX_BBONE_SUBDIV]);
+       copy_qt_qt(fp, temp[MAX_BBONE_SUBDIV]);
 }
 
 /* returns pointer to static array, filled with desired amount of bone->segments elements */
@@ -433,7 +445,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
                scale[1]= len_v3(pchan->pose_mat[1]);
                scale[2]= len_v3(pchan->pose_mat[2]);
 
-               if(fabs(scale[0] - scale[1]) > 1e-6f || fabs(scale[1] - scale[2]) > 1e-6f) {
+               if(fabsf(scale[0] - scale[1]) > 1e-6f || fabsf(scale[1] - scale[2]) > 1e-6f) {
                        unit_m4(scalemat);
                        scalemat[0][0]= scale[0];
                        scalemat[1][1]= scale[1];
@@ -476,9 +488,9 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
 
                /* transform previous point inside this bone space */
                if(rest)
-                       VECCOPY(h1, prev->bone->arm_head)
+                       copy_v3_v3(h1, prev->bone->arm_head);
                else
-                       VECCOPY(h1, prev->pose_head)
+                       copy_v3_v3(h1, prev->pose_head);
                mul_m4_v3(imat, h1);
 
                if(prev->bone->segments>1) {
@@ -515,9 +527,9 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
                
                /* transform next point inside this bone space */
                if(rest)
-                       VECCOPY(h2, next->bone->arm_tail)
+                       copy_v3_v3(h2, next->bone->arm_tail);
                else
-                       VECCOPY(h2, next->pose_tail)
+                       copy_v3_v3(h2, next->pose_tail);
                mul_m4_v3(imat, h2);
                /* if next bone is B-bone too, use average handle direction */
                if(next->bone->segments>1);
@@ -563,7 +575,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
                vec_roll_to_mat3(h1, fp[3], mat3);              // fp[3] is roll
 
                copy_m4_m3(result_array[a].mat, mat3);
-               VECCOPY(result_array[a].mat[3], fp);
+               copy_v3_v3(result_array[a].mat[3], fp);
 
                if(doscale) {
                        /* correct for scaling when this matrix is used in scaled space */
@@ -725,15 +737,15 @@ static float dist_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, f
 
        if(bone==NULL) return 0.0f;
        
-       VECCOPY (cop, co);
+       copy_v3_v3(cop, co);
 
        fac= distfactor_to_bone(cop, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
        
-       if (fac>0.0) {
+       if (fac > 0.0f) {
                
                fac*=bone->weight;
                contrib= fac;
-               if(contrib>0.0) {
+               if(contrib > 0.0f) {
                        if(vec) {
                                if(bone->segments>1)
                                        // applies on cop and bbonemat
@@ -770,7 +782,7 @@ static void pchan_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, f
        if (!weight)
                return;
 
-       VECCOPY(cop, co);
+       copy_v3_v3(cop, co);
 
        if(vec) {
                if(pchan->bone->segments>1)
@@ -936,19 +948,15 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
                        dvert = NULL;
 
                if(armature_def_nr >= 0 && dvert) {
-                       armature_weight = 0.0f; /* a def group was given, so default to 0 */
-                       for(j = 0; j < dvert->totweight; j++) {
-                               if(dvert->dw[j].def_nr == armature_def_nr) {
-                                       armature_weight = dvert->dw[j].weight;
-                                       break;
-                               }
+                       armature_weight= defvert_find_weight(dvert, armature_def_nr);
+
+                       if(invert_vgroup) {
+                               armature_weight= 1.0f-armature_weight;
                        }
+
                        /* hackish: the blending factor can be used for blending with prevCos too */
                        if(prevCos) {
-                               if(invert_vgroup)
-                                       prevco_weight= 1.0f-armature_weight;
-                               else
-                                       prevco_weight= armature_weight;
+                               prevco_weight= armature_weight;
                                armature_weight= 1.0f;
                        }
                }
@@ -1011,7 +1019,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
                                normalize_dq(dq, contrib);
 
                                if(armature_weight != 1.0f) {
-                                       VECCOPY(dco, co);
+                                       copy_v3_v3(dco, co);
                                        mul_v3m3_dq( dco, (defMats)? summat: NULL,dq);
                                        sub_v3_v3(dco, co);
                                        mul_v3_fl(dco, armature_weight);
@@ -1107,11 +1115,11 @@ void armature_loc_world_to_pose(Object *ob, float *inloc, float *outloc)
        float nLocMat[4][4];
        
        /* build matrix for location */
-       VECCOPY(xLocMat[3], inloc);
+       copy_v3_v3(xLocMat[3], inloc);
 
        /* get bone-space cursor matrix and extract location */
        armature_mat_world_to_pose(ob, xLocMat, nLocMat);
-       VECCOPY(outloc, nLocMat[3]);
+       copy_v3_v3(outloc, nLocMat[3]);
 }
 
 /* Convert Pose-Space Matrix to Bone-Space Matrix 
@@ -1186,11 +1194,11 @@ void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc)
        float nLocMat[4][4];
        
        /* build matrix for location */
-       VECCOPY(xLocMat[3], inloc);
+       copy_v3_v3(xLocMat[3], inloc);
 
        /* get bone-space cursor matrix and extract location */
        armature_mat_pose_to_bone(pchan, xLocMat, nLocMat);
-       VECCOPY(outloc, nLocMat[3]);
+       copy_v3_v3(outloc, nLocMat[3]);
 }
 
 /* same as object_mat3_to_rot() */
@@ -1225,10 +1233,10 @@ void pchan_apply_mat4(bPoseChannel *pchan, float mat[][4], short use_compat)
  */
 void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4])
 {
-        float imat[4][4];
-        invert_m4_m4(imat, arm_mat);
-        mul_m4_m4m4(delta_mat, pose_mat, imat);
+       float imat[4][4];
+       
+       invert_m4_m4(imat, arm_mat);
+       mul_m4_m4m4(delta_mat, pose_mat, imat);
 }
 
 /* **************** Rotation Mode Conversions ****************************** */
@@ -1276,7 +1284,7 @@ void BKE_rotMode_change_values (float quat[4], float eul[3], float axis[3], floa
                }
                
                /* when converting to axis-angle, we need a special exception for the case when there is no axis */
-               if (IS_EQ(axis[0], axis[1]) && IS_EQ(axis[1], axis[2])) {
+               if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) {
                        /* for now, rotate around y-axis then (so that it simply becomes the roll) */
                        axis[1]= 1.0f;
                }
@@ -1334,8 +1342,12 @@ void vec_roll_to_mat3(float *vec, float roll, float mat[][3])
        cross_v3_v3v3(axis,target,nor);
 
        /* was 0.0000000000001, caused bug [#23954], smaller values give unstable
-        * roll when toggling editmode */
-       if (dot_v3v3(axis,axis) > 0.00001) {
+        * roll when toggling editmode.
+        *
+        * was 0.00001, causes bug [#27675], with 0.00000495,
+        * so a value inbetween these is needed.
+        */
+       if (dot_v3v3(axis,axis) > 0.000001f) {
                /* if nor is *not* a multiple of target ... */
                normalize_v3(axis);
                
@@ -1378,7 +1390,7 @@ void where_is_armature_bone(Bone *bone, Bone *prevbone)
        bone->length= len_v3v3(bone->head, bone->tail);
        
        /* this is called on old file reading too... */
-       if(bone->xwidth==0.0) {
+       if(bone->xwidth==0.0f) {
                bone->xwidth= 0.1f;
                bone->zwidth= 0.1f;
                bone->segments= 1;
@@ -1391,7 +1403,7 @@ void where_is_armature_bone(Bone *bone, Bone *prevbone)
                copy_m4_m3(offs_bone, bone->bone_mat);
                                
                /* The bone's root offset (is in the parent's coordinate system) */
-               VECCOPY(offs_bone[3], bone->head);
+               copy_v3_v3(offs_bone[3], bone->head);
 
                /* Get the length translation of parent (length along y axis) */
                offs_bone[3][1]+= prevbone->length;
@@ -1401,16 +1413,9 @@ void where_is_armature_bone(Bone *bone, Bone *prevbone)
        }
        else {
                copy_m4_m3(bone->arm_mat, bone->bone_mat);
-               VECCOPY(bone->arm_mat[3], bone->head);
+               copy_v3_v3(bone->arm_mat[3], bone->head);
        }
        
-       /* head */
-       VECCOPY(bone->arm_head, bone->arm_mat[3]);
-       /* tail is in current local coord system */
-       VECCOPY(vec, bone->arm_mat[1]);
-       mul_v3_fl(vec, bone->length);
-       add_v3_v3v3(bone->arm_tail, bone->arm_head, vec);
-       
        /* and the kiddies */
        prevbone= bone;
        for(bone= bone->childbase.first; bone; bone= bone->next) {
@@ -1479,7 +1484,6 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
                        pchanw.next= pchan->next;
                        pchanw.parent= pchan->parent;
                        pchanw.child= pchan->child;
-                       pchanw.path= NULL;
                        
                        /* this is freed so copy a copy, else undo crashes */
                        if(pchanw.prop) {
@@ -1500,7 +1504,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
                         */
                        extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints);
                        copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE);
-                       addlisttolist(&pchanw.constraints, &proxylocal_constraints);
+                       BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints);
                        
                        /* constraints - set target ob pointer to own object */
                        for (con= pchanw.constraints.first; con; con= con->next) {
@@ -1845,8 +1849,8 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
        /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
        where_is_pose_bone(scene, ob, pchan, ctime, 1);
        
-       VECCOPY(poseHead, pchan->pose_head);
-       VECCOPY(poseTail, pchan->pose_tail);
+       copy_v3_v3(poseHead, pchan->pose_head);
+       copy_v3_v3(poseTail, pchan->pose_tail);
        
        /* step 1: determine the positions for the endpoints of the bone */
        {
@@ -1890,7 +1894,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
                        
                        /* store the position, and convert it to pose space */
                        mul_m4_v3(ob->imat, vec);
-                       VECCOPY(poseHead, vec);
+                       copy_v3_v3(poseHead, vec);
                        
                        /* set the new radius (it should be the average value) */
                        radius = (radius+rad) / 2;
@@ -1914,9 +1918,9 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
                /* compute the raw rotation matrix from the bone's current matrix by extracting only the
                 * orientation-relevant axes, and normalising them
                 */
-               VECCOPY(rmat[0], pchan->pose_mat[0]);
-               VECCOPY(rmat[1], pchan->pose_mat[1]);
-               VECCOPY(rmat[2], pchan->pose_mat[2]);
+               copy_v3_v3(rmat[0], pchan->pose_mat[0]);
+               copy_v3_v3(rmat[1], pchan->pose_mat[1]);
+               copy_v3_v3(rmat[2], pchan->pose_mat[2]);
                normalize_m3(rmat);
                
                /* also, normalise the orientation imposed by the bone, now that we've extracted the scale factor */
@@ -1976,12 +1980,12 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
                                /* calculate volume preservation factor which is 
                                 * basically the inverse of the y-scaling factor 
                                 */
-                               if (fabs(scaleFac) != 0.0f) {
-                                       scale= 1.0 / fabs(scaleFac);
+                               if (fabsf(scaleFac) != 0.0f) {
+                                       scale= 1.0f / fabsf(scaleFac);
                                        
                                        /* we need to clamp this within sensible values */
                                        // NOTE: these should be fine for now, but should get sanitised in future
-                                       scale= MIN2(MAX2(scale, 0.0001) , 100000);
+                                       CLAMP(scale, 0.0001f, 100000.0f);
                                }
                                else
                                        scale= 1.0f;
@@ -2007,7 +2011,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
                /* when the 'no-root' option is affected, the chain can retain
                 * the shape but be moved elsewhere
                 */
-               VECCOPY(poseHead, pchan->pose_head);
+               copy_v3_v3(poseHead, pchan->pose_head);
        }
        else if (tree->con->enforce < 1.0f) {
                /* when the influence is too low
@@ -2015,18 +2019,18 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
                 *      - stick to the parent for any other
                 */
                if (pchan->parent) {
-                       VECCOPY(poseHead, pchan->pose_head);
+                       copy_v3_v3(poseHead, pchan->pose_head);
                }
                else {
                        // FIXME: this introduces popping artifacts when we reach 0.0
                        interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce);
                }
        }
-       VECCOPY(poseMat[3], poseHead);
+       copy_v3_v3(poseMat[3], poseHead);
        
        /* finally, store the new transform */
        copy_m4_m4(pchan->pose_mat, poseMat);
-       VECCOPY(pchan->pose_head, poseHead);
+       copy_v3_v3(pchan->pose_head, poseHead);
        
        /* recalculate tail, as it's now outdated after the head gets adjusted above! */
        where_is_pose_bone_tail(pchan);
@@ -2105,13 +2109,13 @@ void pchan_to_mat4(bPoseChannel *pchan, float chan_mat[4][4])
        /* prevent action channels breaking chains */
        /* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */
        if ((pchan->bone==NULL) || !(pchan->bone->flag & BONE_CONNECTED)) {
-               VECCOPY(chan_mat[3], pchan->loc);
+               copy_v3_v3(chan_mat[3], pchan->loc);
        }
 }
 
 /* loc/rot/size to mat4 */
 /* used in constraint.c too */
-void chan_calc_mat(bPoseChannel *pchan)
+void pchan_calc_mat(bPoseChannel *pchan)
 {
        /* this is just a wrapper around the copy of this function which calculates the matrix 
         * and stores the result in any given channel
@@ -2191,11 +2195,11 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha
                                                ofs = amod->turbul / 200.0f;
                                                
                                                /* make a copy of starting conditions */
-                                               VECCOPY(loc, pchan->pose_mat[3]);
+                                               copy_v3_v3(loc, pchan->pose_mat[3]);
                                                mat4_to_eul( eul,pchan->pose_mat);
                                                mat4_to_size( size,pchan->pose_mat);
-                                               VECCOPY(eulo, eul);
-                                               VECCOPY(sizeo, size);
+                                               copy_v3_v3(eulo, eul);
+                                               copy_v3_v3(sizeo, size);
                                                
                                                /* apply noise to each set of channels */
                                                if (amod->channels & 4) {
@@ -2246,7 +2250,7 @@ void where_is_pose_bone_tail(bPoseChannel *pchan)
 {
        float vec[3];
        
-       VECCOPY(vec, pchan->pose_mat[1]);
+       copy_v3_v3(vec, pchan->pose_mat[1]);
        mul_v3_fl(vec, pchan->bone->length);
        add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec);
 }
@@ -2267,7 +2271,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
        parchan= pchan->parent;
        
        /* this gives a chan_mat with actions (ipos) results */
-       if(do_extra)    chan_calc_mat(pchan);
+       if(do_extra)    pchan_calc_mat(pchan);
        else                    unit_m4(pchan->chan_mat);
 
        /* construct the posemat based on PoseChannels, that we do before applying constraints */
@@ -2280,7 +2284,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
                copy_m4_m3(offs_bone, bone->bone_mat);
                
                /* The bone's root offset (is in the parent's coordinate system) */
-               VECCOPY(offs_bone[3], bone->head);
+               copy_v3_v3(offs_bone[3], bone->head);
                
                /* Get the length translation of parent (length along y axis) */
                offs_bone[3][1]+= parbone->length;
@@ -2358,7 +2362,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
                        bConstraintOb *cob;
 
                        /* make a copy of location of PoseChannel for later */
-                       VECCOPY(vec, pchan->pose_mat[3]);
+                       copy_v3_v3(vec, pchan->pose_mat[3]);
 
                        /* prepare PoseChannel for Constraint solving
                         * - makes a copy of matrix, and creates temporary struct to use
@@ -2375,13 +2379,13 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
 
                        /* prevent constraints breaking a chain */
                        if(pchan->bone->flag & BONE_CONNECTED) {
-                               VECCOPY(pchan->pose_mat[3], vec);
+                               copy_v3_v3(pchan->pose_mat[3], vec);
                        }
                }
        }
        
        /* calculate head */
-       VECCOPY(pchan->pose_head, pchan->pose_mat[3]);
+       copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]);
        /* calculate tail */
        where_is_pose_bone_tail(pchan);
 }
@@ -2412,8 +2416,8 @@ void where_is_pose (Scene *scene, Object *ob)
                        bone= pchan->bone;
                        if(bone) {
                                copy_m4_m4(pchan->pose_mat, bone->arm_mat);
-                               VECCOPY(pchan->pose_head, bone->arm_head);
-                               VECCOPY(pchan->pose_tail, bone->arm_tail);
+                               copy_v3_v3(pchan->pose_head, bone->arm_head);
+                               copy_v3_v3(pchan->pose_tail, bone->arm_tail);
                        }
                }
        }
@@ -2461,3 +2465,33 @@ void where_is_pose (Scene *scene, Object *ob)
                }
        }
 }
+
+
+/* Returns total selected vgroups,
+ * wpi.defbase_sel is assumed malloc'd, all values are set */
+int get_selected_defgroups(Object *ob, char *dg_selection, int defbase_len)
+{
+       bDeformGroup *defgroup;
+       unsigned int i;
+       Object *armob= object_pose_armature_get(ob);
+       int dg_flags_sel_tot= 0;
+
+       if(armob) {
+               bPose *pose= armob->pose;
+               for (i= 0, defgroup= ob->defbase.first; i < defbase_len && defgroup; defgroup = defgroup->next, i++) {
+                       bPoseChannel *pchan= get_pose_channel(pose, defgroup->name);
+                       if(pchan && (pchan->bone->flag & BONE_SELECTED)) {
+                               dg_selection[i]= TRUE;
+                               dg_flags_sel_tot++;
+                       }
+                       else {
+                               dg_selection[i]= FALSE;
+                       }
+               }
+       }
+       else {
+               memset(dg_selection, FALSE, sizeof(char) * defbase_len);
+       }
+
+       return dg_flags_sel_tot;
+}