bugfix [#24907] bone roll z up broken and python script showing correct method to...
[blender.git] / source / blender / editors / armature / editarmature.c
index 402715dbb0270cca5c8109d6dd754d1ff9af5fe0..61d16f99f2fc0e8bd5116b699bf7e3524a9ef54e 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 
 #include <ctype.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 #include <math.h> 
 #include <float.h> 
+#include <assert.h> 
 
-#include "MEM_guardedalloc.h"
 
-#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_constraint_types.h"
-#include "DNA_ID.h"
-#include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
-#include "DNA_nla_types.h"
-#include "DNA_object_types.h"
 #include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_ipo_types.h"
-#include "DNA_curve_types.h"
+
+#include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_editVert.h"
 #include "BLI_ghash.h"
 
+#include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_armature.h"
 #include "BKE_constraint.h"
 #include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_global.h"
+#include "BKE_idprop.h"
 #include "BKE_main.h"
 #include "BKE_object.h"
 #include "BKE_report.h"
 #include "BKE_subsurf.h"
-#include "BKE_utildefines.h"
 #include "BKE_modifier.h"
-#include "PIL_time.h"
+#include "DNA_object_types.h"
 
 #include "BIF_gl.h"
-#include "BIF_generate.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
 #include "WM_types.h"
 
 #include "ED_armature.h"
+#include "ED_keyframing.h"
 #include "ED_mesh.h"
 #include "ED_object.h"
 #include "ED_screen.h"
-#include "ED_transform.h"
 #include "ED_util.h"
 #include "ED_view3d.h"
 
 #include "reeb.h"
 #endif
 
-/* ************* XXX *************** */
-static int okee() {return 0;}
-static void BIF_undo_push(const char *msg) {}
-/* ************* XXX *************** */
-
 /* **************** tools on Editmode Armature **************** */
 
 /* Sync selection to parent for connected children */
@@ -110,24 +97,68 @@ void ED_armature_sync_selection(ListBase *edbo)
        EditBone *ebo;
        
        for (ebo=edbo->first; ebo; ebo= ebo->next) {
-               if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
-                       if (ebo->parent->flag & BONE_TIPSEL)
-                               ebo->flag |= BONE_ROOTSEL;
+               /* if bone is not selectable, we shouldn't alter this setting... */
+               if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
+                       if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
+                               if (ebo->parent->flag & BONE_TIPSEL)
+                                       ebo->flag |= BONE_ROOTSEL;
+                               else
+                                       ebo->flag &= ~BONE_ROOTSEL;
+                       }
+                       
+                       if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
+                               ebo->flag |= BONE_SELECTED;
                        else
-                               ebo->flag &= ~BONE_ROOTSEL;
+                               ebo->flag &= ~BONE_SELECTED;
                }
-               
-               if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
-                       ebo->flag |= BONE_SELECTED;
-               else
-                       ebo->flag &= ~BONE_SELECTED;
        }                               
 }
 
+void ED_armature_validate_active(struct bArmature *arm)
+{
+       EditBone *ebone= arm->act_edbone;
+
+       if(ebone) { 
+               if(ebone->flag & BONE_HIDDEN_A || (ebone->flag & BONE_SELECTED)==0)
+                       arm->act_edbone= NULL;
+       }
+}
+
+static void bone_free(bArmature *arm, EditBone *bone)
+{
+       if(arm->act_edbone==bone)
+               arm->act_edbone= NULL;
+
+       if(bone->prop) {
+               IDP_FreeProperty(bone->prop);
+               MEM_freeN(bone->prop);
+       }
+
+       BLI_freelinkN(arm->edbo, bone);
+}
+
+void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
+{
+       EditBone *curBone;
+
+       /* Find any bones that refer to this bone */
+       for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
+               if (curBone->parent==exBone) {
+                       curBone->parent=exBone->parent;
+                       curBone->flag &= ~BONE_CONNECTED;
+               }
+       }
+
+       bone_free(arm, exBone);
+}
+
+
 /* converts Bones to EditBone list, used for tools as well */
-void make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent)
+EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone)
 {
        EditBone        *eBone;
+       EditBone        *eBoneAct= NULL;
+       EditBone        *eBoneTest= NULL;
        Bone            *curBone;
        float delta[3];
        float premat[3][3];
@@ -140,33 +171,52 @@ void make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent)
                
                /*      Copy relevant data from bone to eBone */
                eBone->parent= parent;
-               BLI_strncpy(eBone->name, curBone->name, 32);
+               BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
                eBone->flag = curBone->flag;
                
                /* fix selection flags */
+
                if (eBone->flag & BONE_SELECTED) {
+                       /* if the bone is selected the copy its root selection to the parents tip */
                        eBone->flag |= BONE_TIPSEL;
-                       if (eBone->parent && (eBone->flag & BONE_CONNECTED))
+                       if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
                                eBone->parent->flag |= BONE_TIPSEL;
-                       else 
+                               eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */
+                       }
+                       else {
                                eBone->flag |= BONE_ROOTSEL;
+                       }
                }
-               else 
-                       eBone->flag &= ~BONE_ROOTSEL;
-               
-               VECCOPY(eBone->head, curBone->arm_head);
-               VECCOPY(eBone->tail, curBone->arm_tail);                
+               else {
+                       /* if the bone is not selected, but connected to its parent
+                        *  copy the parents tip selection state */
+                       if(eBone->parent &&  (eBone->flag & BONE_CONNECTED)) {
+                               /* selecting with the mouse gives this behavior */
+                               if(eBone->parent->flag & BONE_TIPSEL) {
+                                       eBone->flag |= BONE_ROOTSEL;
+                               }
+                               else {
+                                       eBone->flag &= ~BONE_ROOTSEL;
+                               }
+
+                               /* probably not selected but just incase */
+                               eBone->flag &= ~BONE_TIPSEL;
+                       }
+               }
+
+               copy_v3_v3(eBone->head, curBone->arm_head);
+               copy_v3_v3(eBone->tail, curBone->arm_tail);             
                
                eBone->roll= 0.0f;
                
                /* roll fixing */
-               VecSubf(delta, eBone->tail, eBone->head);
+               sub_v3_v3v3(delta, eBone->tail, eBone->head);
                vec_roll_to_mat3(delta, 0.0f, postmat);
                
-               Mat3CpyMat4(premat, curBone->arm_mat);
+               copy_m3_m4(premat, curBone->arm_mat);
                
-               Mat3Inv(imat, postmat);
-               Mat3MulMat3(difmat, imat, premat);
+               invert_m3_m3(imat, postmat);
+               mul_m3_m3m3(difmat, imat, premat);
                
                eBone->roll = (float)atan2(difmat[2][0], difmat[2][2]);
                
@@ -182,13 +232,24 @@ void make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent)
                eBone->rad_tail= curBone->rad_tail;
                eBone->segments = curBone->segments;            
                eBone->layer = curBone->layer;
+
+               if(curBone->prop)
+                       eBone->prop= IDP_CopyProperty(curBone->prop);
                
                BLI_addtail(edbo, eBone);
                
                /*      Add children if necessary */
-               if (curBone->childbase.first) 
-                       make_boneList(edbo, &curBone->childbase, eBone);
+               if (curBone->childbase.first) {
+                       eBoneTest= make_boneList(edbo, &curBone->childbase, eBone, actBone);
+                       if(eBoneTest)
+                               eBoneAct= eBoneTest;
+               }
+
+               if(curBone==actBone)
+                       eBoneAct= eBone;
        }
+
+       return eBoneAct;
 }
 
 /* nasty stuff for converting roll in editbones into bones */
@@ -214,19 +275,19 @@ static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist)
                
                if (ebone) {
                        /* Get the ebone premat */
-                       VecSubf(delta, ebone->tail, ebone->head);
+                       sub_v3_v3v3(delta, ebone->tail, ebone->head);
                        vec_roll_to_mat3(delta, ebone->roll, premat);
                        
                        /* Get the bone postmat */
-                       Mat3CpyMat4(postmat, curBone->arm_mat);
+                       copy_m3_m4(postmat, curBone->arm_mat);
                        
-                       Mat3Inv(imat, premat);
-                       Mat3MulMat3(difmat, imat, postmat);
+                       invert_m3_m3(imat, premat);
+                       mul_m3_m3m3(difmat, imat, postmat);
 #if 0
                        printf ("Bone %s\n", curBone->name);
-                       printmatrix4("premat", premat);
-                       printmatrix4("postmat", postmat);
-                       printmatrix4("difmat", difmat);
+                       print_m4("premat", premat);
+                       print_m4("postmat", postmat);
+                       print_m4("difmat", difmat);
                        printf ("Roll = %f\n",  (-atan2(difmat[2][0], difmat[2][2]) * (180.0/M_PI)));
 #endif
                        curBone->roll = (float)-atan2(difmat[2][0], difmat[2][2]);
@@ -247,11 +308,11 @@ void ED_armature_from_edit(Object *obedit)
        Object *obt;
        
        /* armature bones */
-       free_bones(arm);
+       free_bonelist(&arm->bonebase);
        
        /* remove zero sized bones, this gives instable restposes */
        for (eBone=arm->edbo->first; eBone; eBone= neBone) {
-               float len= VecLenf(eBone->head, eBone->tail);
+               float len= len_v3v3(eBone->head, eBone->tail);
                neBone= eBone->next;
                if (len <= 0.000001f) {         /* FLT_EPSILON is too large? */
                        EditBone *fBone;
@@ -261,8 +322,9 @@ void ED_armature_from_edit(Object *obedit)
                                if (fBone->parent==eBone)
                                        fBone->parent= eBone->parent;
                        }
-                       printf("Warning: removed zero sized bone: %s\n", eBone->name);
-                       BLI_freelinkN(arm->edbo, eBone);
+                       if (G.f & G_DEBUG)
+                               printf("Warning: removed zero sized bone: %s\n", eBone->name);
+                       bone_free(arm, eBone);
                }
        }
        
@@ -271,12 +333,16 @@ void ED_armature_from_edit(Object *obedit)
                newBone= MEM_callocN(sizeof(Bone), "bone");
                eBone->temp= newBone;   /* Associate the real Bones with the EditBones */
                
-               BLI_strncpy(newBone->name, eBone->name, 32);
-               memcpy(newBone->head, eBone->head, sizeof(float)*3);
-               memcpy(newBone->tail, eBone->tail, sizeof(float)*3);
+               BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
+               memcpy(newBone->head, eBone->head, sizeof(newBone->head));
+               memcpy(newBone->tail, eBone->tail, sizeof(newBone->tail));
                newBone->flag= eBone->flag;
-               if (eBone->flag & BONE_ACTIVE) 
+               
+               if (eBone == arm->act_edbone) {
                        newBone->flag |= BONE_SELECTED; /* important, editbones can be active with only 1 point selected */
+                       arm->act_edbone= NULL;
+                       arm->act_bone= newBone;
+               }
                newBone->roll = 0.0f;
                
                newBone->weight = eBone->weight;
@@ -290,6 +356,9 @@ void ED_armature_from_edit(Object *obedit)
                newBone->rad_tail= eBone->rad_tail;
                newBone->segments= eBone->segments;
                newBone->layer = eBone->layer;
+               
+               if(eBone->prop)
+                       newBone->prop= IDP_CopyProperty(eBone->prop);
        }
        
        /*      Fix parenting in a separate pass to ensure ebone->bone connections
@@ -307,22 +376,22 @@ void ED_armature_from_edit(Object *obedit)
                                float   delta[3];
                                
                                /* Get the parent's  matrix (rotation only) */
-                               VecSubf(delta, eBone->parent->tail, eBone->parent->head);
+                               sub_v3_v3v3(delta, eBone->parent->tail, eBone->parent->head);
                                vec_roll_to_mat3(delta, eBone->parent->roll, M_parentRest);
                                
                                /* Get this bone's  matrix (rotation only) */
-                               VecSubf(delta, eBone->tail, eBone->head);
+                               sub_v3_v3v3(delta, eBone->tail, eBone->head);
                                vec_roll_to_mat3(delta, eBone->roll, M_boneRest);
                                
                                /* Invert the parent matrix */
-                               Mat3Inv(iM_parentRest, M_parentRest);
+                               invert_m3_m3(iM_parentRest, M_parentRest);
                                
                                /* Get the new head and tail */
-                               VecSubf(newBone->head, eBone->head, eBone->parent->tail);
-                               VecSubf(newBone->tail, eBone->tail, eBone->parent->tail);
+                               sub_v3_v3v3(newBone->head, eBone->head, eBone->parent->tail);
+                               sub_v3_v3v3(newBone->tail, eBone->tail, eBone->parent->tail);
                                
-                               Mat3MulVecfl(iM_parentRest, newBone->head);
-                               Mat3MulVecfl(iM_parentRest, newBone->tail);
+                               mul_m3_v3(iM_parentRest, newBone->head);
+                               mul_m3_v3(iM_parentRest, newBone->tail);
                        }
                }
                /*      ...otherwise add this bone to the armature's bonebase */
@@ -347,15 +416,15 @@ void ED_armature_apply_transform(Object *ob, float mat[4][4])
 {
        EditBone *ebone;
        bArmature *arm= ob->data;
-       float scale = Mat4ToScalef(mat);        /* store the scale of the matrix here to use on envelopes */
+       float scale = mat4_to_scale(mat);       /* store the scale of the matrix here to use on envelopes */
        
        /* Put the armature into editmode */
        ED_armature_to_edit(ob);
 
        /* Do the rotations */
        for (ebone = arm->edbo->first; ebone; ebone=ebone->next){
-               Mat4MulVecfl(mat, ebone->head);
-               Mat4MulVecfl(mat, ebone->tail);
+               mul_m4_v3(mat, ebone->head);
+               mul_m4_v3(mat, ebone->tail);
                
                ebone->rad_head *= scale;
                ebone->rad_tail *= scale;
@@ -369,101 +438,89 @@ void ED_armature_apply_transform(Object *ob, float mat[4][4])
 
 /* exported for use in editors/object/ */
 /* 0 == do center, 1 == center new, 2 == center cursor */
-void docenter_armature (Scene *scene, View3D *v3d, Object *ob, int centermode)
+void docenter_armature (Scene *scene, Object *ob, float cursor[3], int centermode, int around)
 {
        Object *obedit= scene->obedit; // XXX get from context
        EditBone *ebone;
        bArmature *arm= ob->data;
-       float cent[3] = {0.0f, 0.0f, 0.0f};
-       float min[3], max[3];
-       float omat[3][3];
+       float cent[3];
 
        /* Put the armature into editmode */
-       if(ob!=obedit)
+       if(ob != obedit) {
                ED_armature_to_edit(ob);
+               obedit= NULL; /* we cant use this so behave as if there is no obedit */
+       }
 
        /* Find the centerpoint */
        if (centermode == 2) {
-               float *fp= give_cursor(scene, v3d);
-               VECCOPY(cent, fp);
-               Mat4Invert(ob->imat, ob->obmat);
-               Mat4MulVecfl(ob->imat, cent);
+               copy_v3_v3(cent, cursor);
+               invert_m4_m4(ob->imat, ob->obmat);
+               mul_m4_v3(ob->imat, cent);
        }
        else {
-               INIT_MINMAX(min, max);
-               
-               for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
-                       DO_MINMAX(ebone->head, min, max);
-                       DO_MINMAX(ebone->tail, min, max);
+               if(around==V3D_CENTROID) {
+                       int total= 0;
+                       zero_v3(cent);
+                       for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
+                               total+=2;
+                               add_v3_v3(cent, ebone->head);
+                               add_v3_v3(cent, ebone->tail);
+                       }
+                       mul_v3_fl(cent, 1.0f/(float)total);
+               }
+               else {
+                       float min[3], max[3];
+                       INIT_MINMAX(min, max);
+                       for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
+                               DO_MINMAX(ebone->head, min, max);
+                               DO_MINMAX(ebone->tail, min, max);
+                       }
+                       mid_v3_v3v3(cent, min, max);
                }
-               
-               cent[0]= (min[0] + max[0]) / 2.0f;
-               cent[1]= (min[1] + max[1]) / 2.0f;
-               cent[2]= (min[2] + max[2]) / 2.0f;
        }
        
        /* Do the adjustments */
        for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
-               VecSubf(ebone->head, ebone->head, cent);
-               VecSubf(ebone->tail, ebone->tail, cent);
+               sub_v3_v3(ebone->head, cent);
+               sub_v3_v3(ebone->tail, cent);
        }
        
        /* Turn the list into an armature */
-       ED_armature_from_edit(ob);
-       
+       if(obedit==NULL) {
+               ED_armature_from_edit(ob);
+               ED_armature_edit_free(ob);
+       }
+
        /* Adjust object location for new centerpoint */
        if(centermode && obedit==NULL) {
-               Mat3CpyMat4(omat, ob->obmat);
-               
-               Mat3MulVecfl(omat, cent);
-               ob->loc[0] += cent[0];
-               ob->loc[1] += cent[1];
-               ob->loc[2] += cent[2];
+               mul_mat3_m4_v3(ob->obmat, cent); /* ommit translation part */
+               add_v3_v3(ob->loc, cent);
        }
-       else 
-               ED_armature_edit_free(ob);
 }
 
 /* ---------------------- */
 
-static EditBone *editbone_name_exists (ListBase *edbo, char *name)
+/* checks if an EditBone with a matching name already, returning the matching bone if it exists */
+static EditBone *editbone_name_exists (ListBase *edbo, const char *name)
 {
-       EditBone        *eBone;
-       
-       for (eBone=edbo->first; eBone; eBone=eBone->next) {
-               if (!strcmp(name, eBone->name))
-                       return eBone;
-       }
-       return NULL;
+       return BLI_findstring(edbo, name, offsetof(EditBone, name));
 }
 
 /* note: there's a unique_bone_name() too! */
+static int editbone_unique_check(void *arg, const char *name)
+{
+       struct {ListBase *lb;void *bone;} *data= arg;
+       EditBone *dupli= editbone_name_exists(data->lb, name);
+       return dupli && dupli != data->bone;
+}
+
 void unique_editbone_name (ListBase *edbo, char *name, EditBone *bone)
 {
-       EditBone *dupli;
-       char            tempname[64];
-       int                     number;
-       char            *dot;
+       struct {ListBase *lb; void *bone;} data;
+       data.lb= edbo;
+       data.bone= bone;
 
-       dupli = editbone_name_exists(edbo, name);
-       
-       if (dupli && bone != dupli) {
-               /*      Strip off the suffix, if it's a number */
-               number= strlen(name);
-               if (number && isdigit(name[number-1])) {
-                       dot= strrchr(name, '.');        // last occurrance
-                       if (dot)
-                               *dot=0;
-               }
-               
-               for (number = 1; number <= 999; number++) {
-                       sprintf(tempname, "%s.%03d", name, number);
-                       if (!editbone_name_exists(edbo, tempname)) {
-                               BLI_strncpy(name, tempname, 32);
-                               return;
-                       }
-               }
-       }
+       BLI_uniquename_cb(editbone_unique_check, &data, "Bone", '.', name, sizeof(bone->name));
 }
 
 /* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
@@ -478,10 +535,10 @@ static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
                        /* apply current transform from parent (not yet destroyed), 
                         * then calculate new parent inverse matrix
                         */
-                       ED_object_apply_obmat(ob);
+                       object_apply_mat4(ob, ob->obmat, FALSE, FALSE);
                        
                        what_does_parent(scene, ob, &workob);
-                       Mat4Invert(ob->parentinv, workob.obmat);
+                       invert_m4_m4(ob->parentinv, workob.obmat);
                }
        }
 }
@@ -490,7 +547,7 @@ static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
 static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C); // must be active object, not edit-object
+       Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); // must be active object, not edit-object
        bArmature *arm= get_armature(ob);
        bPose *pose;
        bPoseChannel *pchan;
@@ -517,8 +574,8 @@ static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
                curbone= editbone_name_exists(arm->edbo, pchan->name);
                
                /* simply copy the head/tail values from pchan over to curbone */
-               VECCOPY(curbone->head, pchan->pose_head);
-               VECCOPY(curbone->tail, pchan->pose_tail);
+               copy_v3_v3(curbone->head, pchan->pose_head);
+               copy_v3_v3(curbone->tail, pchan->pose_tail);
                
                /* fix roll:
                 *      1. find auto-calculated roll value for this bone now
@@ -529,16 +586,16 @@ static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
                        float delta[3], eul[3];
                        
                        /* obtain new auto y-rotation */
-                       VecSubf(delta, curbone->tail, curbone->head);
+                       sub_v3_v3v3(delta, curbone->tail, curbone->head);
                        vec_roll_to_mat3(delta, 0.0f, premat);
-                       Mat3Inv(imat, premat);
+                       invert_m3_m3(imat, premat);
                        
                        /* get pchan 'visual' matrix */
-                       Mat3CpyMat4(pmat, pchan->pose_mat);
+                       copy_m3_m4(pmat, pchan->pose_mat);
                        
                        /* remove auto from visual and get euler rotation */
-                       Mat3MulMat3(tmat, imat, pmat);
-                       Mat3ToEul(tmat, eul);
+                       mul_m3_m3m3(tmat, imat, pmat);
+                       mat3_to_eul( eul,tmat);
                        
                        /* just use this euler-y as new roll value */
                        curbone->roll= eul[1];
@@ -554,8 +611,9 @@ static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
                curbone->flag |= BONE_UNKEYED;
        }
        
-       /* convert editbones back to bones */
+       /* convert editbones back to bones, and then free the edit-data */
        ED_armature_from_edit(ob);
+       ED_armature_edit_free(ob);
        
        /* flush positions of posebones */
        where_is_pose(scene, ob);
@@ -564,17 +622,17 @@ static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
        applyarmature_fix_boneparents(scene, ob);
        
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
        
        return OPERATOR_FINISHED;
 }
 
-void POSE_OT_apply (wmOperatorType *ot)
+void POSE_OT_armature_apply (wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Apply Pose as Rest Pose";
-       ot->idname= "POSE_OT_apply";
-       ot->description= "Apply the current pose as the new rest pose.";
+       ot->idname= "POSE_OT_armature_apply";
+       ot->description= "Apply the current pose as the new rest pose";
        
        /* callbacks */
        ot->exec= apply_armature_pose2bones_exec;
@@ -584,6 +642,64 @@ void POSE_OT_apply (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+
+/* set the current pose as the restpose */
+static int pose_visual_transform_apply_exec (bContext *C, wmOperator *UNUSED(op))
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); // must be active object, not edit-object
+
+       /* don't check if editmode (should be done by caller) */
+       if (ob->type!=OB_ARMATURE)
+               return OPERATOR_CANCELLED;
+
+       /* loop over all selected pchans
+        *
+        * TODO, loop over children before parents if multiple bones
+        * at once are to be predictable*/
+       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
+       {
+               float delta_mat[4][4], imat[4][4], mat[4][4];
+
+               where_is_pose_bone(scene, ob, pchan, CFRA, 1);
+
+               copy_m4_m4(mat, pchan->pose_mat);
+
+               /* calculate pchan->pose_mat without loc/size/rot & constraints applied */
+               where_is_pose_bone(scene, ob, pchan, CFRA, 0);
+               invert_m4_m4(imat, pchan->pose_mat);
+               mul_m4_m4m4(delta_mat, mat, imat);
+
+               pchan_apply_mat4(pchan, delta_mat, TRUE);
+
+               where_is_pose_bone(scene, ob, pchan, CFRA, 1);
+       }
+       CTX_DATA_END;
+
+       // ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+
+       return OPERATOR_FINISHED;
+}
+
+void POSE_OT_visual_transform_apply (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Apply Visual Transform to Pose";
+       ot->idname= "POSE_OT_visual_transform_apply";
+       ot->description= "Apply final constrained position of pose bones to their transform.";
+       
+       /* callbacks */
+       ot->exec= pose_visual_transform_apply_exec;
+       ot->poll= ED_operator_posemode;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /* ---------------------- */
 
 /* Helper function for armature joining - link fixing */
@@ -636,7 +752,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
                                                        
                                                        for (achan= act->chanbase.first; achan; achan= achan->next) {
                                                                if (strcmp(achan->name, pchan->name)==0)
-                                                                       BLI_strncpy(achan->name, curbone->name, 32);
+                                                                       BLI_strncpy(achan->name, curbone->name, sizeof(achan->name));
                                                        }
                                                }
                                        }
@@ -680,7 +796,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
                        if (ob->partype==PARBONE) {
                                /* bone name in object */
                                if (!strcmp(ob->parsubstr, pchan->name))
-                                       BLI_strncpy(ob->parsubstr, curbone->name, 32);
+                                       BLI_strncpy(ob->parsubstr, curbone->name, sizeof(ob->parsubstr));
                        }
                        
                        /* make tar armature be new parent */
@@ -690,8 +806,9 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
 }
 
 /* join armature exec is exported for use in object->join objects operator... */
-int join_armature_exec(bContext *C, wmOperator *op)
+int join_armature_exec(bContext *C, wmOperator *UNUSED(op))
 {
+       Main *bmain= CTX_data_main(C);
        Scene *scene= CTX_data_scene(C);
        Object  *ob= CTX_data_active_object(C);
        bArmature *arm= (ob)? ob->data: NULL;
@@ -726,8 +843,8 @@ int join_armature_exec(bContext *C, wmOperator *op)
                        //BASACT->flag &= ~OB_MODE_POSE;
                        
                        /* Find the difference matrix */
-                       Mat4Invert(oimat, ob->obmat);
-                       Mat4MulMat4(mat, base->object->obmat, oimat);
+                       invert_m4_m4(oimat, ob->obmat);
+                       mul_m4_m4m4(mat, base->object->obmat, oimat);
                        
                        /* Copy bones and posechannels from the object to the edit armature */
                        for (pchan=opose->chanbase.first; pchan; pchan=pchann) {
@@ -747,23 +864,23 @@ int join_armature_exec(bContext *C, wmOperator *op)
                                        float delta[3];
                                        
                                        /* Get the premat */
-                                       VecSubf(delta, curbone->tail, curbone->head);
+                                       sub_v3_v3v3(delta, curbone->tail, curbone->head);
                                        vec_roll_to_mat3(delta, curbone->roll, temp);
                                        
-                                       Mat4One(premat); /* Mat4MulMat34 only sets 3x3 part */
-                                       Mat4MulMat34(premat, temp, mat);
+                                       unit_m4(premat); /* Mat4MulMat34 only sets 3x3 part */
+                                       mul_m4_m3m4(premat, temp, mat);
                                        
-                                       Mat4MulVecfl(mat, curbone->head);
-                                       Mat4MulVecfl(mat, curbone->tail);
+                                       mul_m4_v3(mat, curbone->head);
+                                       mul_m4_v3(mat, curbone->tail);
                                        
                                        /* Get the postmat */
-                                       VecSubf(delta, curbone->tail, curbone->head);
+                                       sub_v3_v3v3(delta, curbone->tail, curbone->head);
                                        vec_roll_to_mat3(delta, curbone->roll, temp);
-                                       Mat4CpyMat3(postmat, temp);
+                                       copy_m4_m3(postmat, temp);
                                        
                                        /* Find the roll */
-                                       Mat4Invert(imat, premat);
-                                       Mat4MulMat4(difmat, postmat, imat);
+                                       invert_m4_m4(imat, premat);
+                                       mul_m4_m4m4(difmat, postmat, imat);
                                        
                                        curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
                                }
@@ -780,14 +897,16 @@ int join_armature_exec(bContext *C, wmOperator *op)
                                
                                BLI_remlink(&opose->chanbase, pchan);
                                BLI_addtail(&pose->chanbase, pchan);
+                               free_pose_channels_hash(opose);
+                               free_pose_channels_hash(pose);
                        }
                        
-                       ED_base_object_free_and_unlink(scene, base);
+                       ED_base_object_free_and_unlink(bmain, scene, base);
                }
        }
        CTX_DATA_END;
        
-       DAG_scene_sort(scene);  // because we removed object(s)
+       DAG_scene_sort(bmain, scene);   // because we removed object(s)
 
        ED_armature_from_edit(ob);
        ED_armature_edit_free(ob);
@@ -945,7 +1064,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
  *     sel: remove selected bones from the armature, otherwise the unselected bones are removed
  *  (ob is not in editmode)
  */
-static void separate_armature_bones (Scene *scene, Object *ob, short sel) 
+static void separate_armature_bones(Object *ob, short sel) 
 {
        bArmature *arm= (bArmature *)ob->data;
        bPoseChannel *pchan, *pchann;
@@ -982,11 +1101,11 @@ static void separate_armature_bones (Scene *scene, Object *ob, short sel)
                        }
                        
                        /* free any of the extra-data this pchan might have */
-                       if (pchan->path) MEM_freeN(pchan->path);
-                       free_constraints(&pchan->constraints);
+                       free_pose_channel(pchan);
+                       free_pose_channels_hash(ob->pose);
                        
                        /* get rid of unneeded bone */
-                       BLI_freelinkN(arm->edbo, curbone);
+                       bone_free(arm, curbone);
                        BLI_freelinkN(&ob->pose->chanbase, pchan);
                }
        }
@@ -997,8 +1116,9 @@ static void separate_armature_bones (Scene *scene, Object *ob, short sel)
 }
 
 /* separate selected bones into their armature */
-static int separate_armature_exec (bContext *C, wmOperator *op)
+static int separate_armature_exec (bContext *C, wmOperator *UNUSED(op))
 {
+       Main *bmain= CTX_data_main(C);
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
        Object *oldob, *newob;
@@ -1039,14 +1159,14 @@ static int separate_armature_exec (bContext *C, wmOperator *op)
        ED_armature_edit_free(obedit);
        
        /* 2) duplicate base */
-       newbase= ED_object_add_duplicate(scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
+       newbase= ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
        newob= newbase->object;         
        newbase->flag &= ~SELECT;
        
        
        /* 3) remove bones that shouldn't still be around on both armatures */
-       separate_armature_bones(scene, oldob, 1);
-       separate_armature_bones(scene, newob, 0);
+       separate_armature_bones(oldob, 1);
+       separate_armature_bones(newob, 0);
        
        
        /* 4) fix links before depsgraph flushes */ // err... or after?
@@ -1062,7 +1182,7 @@ static int separate_armature_exec (bContext *C, wmOperator *op)
        ED_armature_to_edit(obedit);
        
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, obedit);
        
        /* recalc/redraw + cleanup */
        WM_cursor_wait(0);
@@ -1073,9 +1193,9 @@ static int separate_armature_exec (bContext *C, wmOperator *op)
 void ARMATURE_OT_separate (wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Separate Armature";
+       ot->name= "Separate Bones";
        ot->idname= "ARMATURE_OT_separate";
-       ot->description= "Isolate selected bones into a separate armature.";
+       ot->description= "Isolate selected bones into a separate armature";
        
        /* callbacks */
        ot->invoke= WM_operator_confirm;
@@ -1127,7 +1247,7 @@ static void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *
                                        /* no singular posemode, so check for correct object */
                                        if(base->selcol == (hitresult & 0xFFFF)) {
                                                bone = get_indexed_bone(base->object, hitresult);
-
+                                               
                                                if (findunsel)
                                                        sel = (bone->flag & BONE_SELECTED);
                                                else
@@ -1233,8 +1353,9 @@ static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_
        for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
                if (curbone->parent == pabone) {
                        if (use_visibility) {
-                               if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A))
+                               if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) {
                                        chbone = curbone;
+                               }
                        }
                        else
                                chbone = curbone;
@@ -1251,14 +1372,14 @@ static int pose_setflag_exec (bContext *C, wmOperator *op)
        int mode= RNA_enum_get(op->ptr, "mode");
        
        /* loop over all selected pchans */
-       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pchans) 
+       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones) 
        {
                bone_setflag(&pchan->bone->flag, flag, mode);
        }
        CTX_DATA_END;
        
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, CTX_data_active_object(C));
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ED_object_pose_armature(CTX_data_active_object(C)));
        
        return OPERATOR_FINISHED;
 }
@@ -1307,7 +1428,7 @@ void ARMATURE_OT_flags_set (wmOperatorType *ot)
        /* identifiers */
        ot->name= "Set Bone Flags";
        ot->idname= "ARMATURE_OT_flags_set";
-       ot->description= "Set flags for armature bones.";
+       ot->description= "Set flags for armature bones";
        
        /* callbacks */
        ot->invoke= WM_menu_invoke;
@@ -1318,7 +1439,7 @@ void ARMATURE_OT_flags_set (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* properties */
-       RNA_def_enum(ot->srna, "type", prop_bone_setting_types, 0, "Type", "");
+       ot->prop= RNA_def_enum(ot->srna, "type", prop_bone_setting_types, 0, "Type", "");
        RNA_def_enum(ot->srna, "mode", prop_bone_setting_modes, 0, "Mode", "");
 }
 
@@ -1327,7 +1448,7 @@ void POSE_OT_flags_set (wmOperatorType *ot)
        /* identifiers */
        ot->name= "Set Bone Flags";
        ot->idname= "POSE_OT_flags_set";
-       ot->description= "Set flags for armature bones.";
+       ot->description= "Set flags for armature bones";
        
        /* callbacks */
        ot->invoke= WM_menu_invoke;
@@ -1338,7 +1459,7 @@ void POSE_OT_flags_set (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* properties */
-       RNA_def_enum(ot->srna, "type", prop_bone_setting_types, 0, "Type", "");
+       ot->prop= RNA_def_enum(ot->srna, "type", prop_bone_setting_types, 0, "Type", "");
        RNA_def_enum(ot->srna, "mode", prop_bone_setting_modes, 0, "Mode", "");
 }
 
@@ -1347,45 +1468,42 @@ void POSE_OT_flags_set (wmOperatorType *ot)
 /* **************** Posemode stuff ********************** */
 
 
-static void selectconnected_posebonechildren (Object *ob, Bone *bone)
+static void selectconnected_posebonechildren (Object *ob, Bone *bone, int extend)
 {
        Bone *curBone;
-       int shift= 0; // XXX
        
-       if (!(bone->flag & BONE_CONNECTED))
+       /* stop when unconnected child is encontered, or when unselectable bone is encountered */
+       if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
                return;
        
                // XXX old cruft! use notifiers instead
        //select_actionchannel_by_name (ob->action, bone->name, !(shift));
        
-       if (shift)
+       if (extend)
                bone->flag &= ~BONE_SELECTED;
        else
                bone->flag |= BONE_SELECTED;
        
-       for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
-               selectconnected_posebonechildren (ob, curBone);
-       }
+       for (curBone=bone->childbase.first; curBone; curBone=curBone->next)
+               selectconnected_posebonechildren(ob, curBone, extend);
 }
 
 /* within active object context */
 /* previously known as "selectconnected_posearmature" */
 static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {  
+       ARegion *ar= CTX_wm_region(C);
+       Object *ob= CTX_data_edit_object(C);
        Bone *bone, *curBone, *next= NULL;
-       int shift= 0; // XXX in pose mode, Shift+L is bound to another command
-                                 // named "PoseLib Add Current Pose"
+       int extend= RNA_boolean_get(op->ptr, "extend");
        int x, y;
-       ARegion *ar;
-       Object *ob= CTX_data_edit_object(C);
-       ar= CTX_wm_region(C);
-
+       
        x= event->x - ar->winrct.xmin;
        y= event->y - ar->winrct.ymin;
 
        view3d_operator_needs_opengl(C);
        
-       if (shift)
+       if (extend)
                bone= get_nearest_bone(C, 0, x, y);
        else
                bone= get_nearest_bone(C, 1, x, y);
@@ -1395,31 +1513,39 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *ev
        
        /* Select parents */
        for (curBone=bone; curBone; curBone=next){
-                       // XXX old cruft! use notifiers instead
-               //select_actionchannel_by_name (ob->action, curBone->name, !(shift));
-               if (shift)
-                       curBone->flag &= ~BONE_SELECTED;
-               else
-                       curBone->flag |= BONE_SELECTED;
-               
-               if (curBone->flag & BONE_CONNECTED)
-                       next=curBone->parent;
+               /* ignore bone if cannot be selected */
+               if ((curBone->flag & BONE_UNSELECTABLE) == 0) { 
+                               // XXX old cruft! use notifiers instead
+                       //select_actionchannel_by_name (ob->action, curBone->name, !(shift));
+                       
+                       if (extend)
+                               curBone->flag &= ~BONE_SELECTED;
+                       else
+                               curBone->flag |= BONE_SELECTED;
+                       
+                       if (curBone->flag & BONE_CONNECTED)
+                               next=curBone->parent;
+                       else
+                               next=NULL;
+               }
                else
-                       next=NULL;
+                       next= NULL;
        }
        
        /* Select children */
-       for (curBone=bone->childbase.first; curBone; curBone=next){
-               selectconnected_posebonechildren (ob, curBone);
-       }
+       for (curBone=bone->childbase.first; curBone; curBone=next)
+               selectconnected_posebonechildren(ob, curBone, extend);
        
-       // XXX this only counted the number of pose channels selected
-       //countall(); // flushes selection!
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
 
        return OPERATOR_FINISHED;
 }
 
+static int pose_select_linked_poll(bContext *C)
+{
+       return ( ED_operator_view3d_active(C) && ED_operator_posemode(C) );
+}
+
 void POSE_OT_select_linked(wmOperatorType *ot)
 {
        /* identifiers */
@@ -1429,12 +1555,13 @@ void POSE_OT_select_linked(wmOperatorType *ot)
        /* api callbacks */
        ot->exec= NULL;
        ot->invoke= pose_select_connected_invoke;
-       ot->poll= ED_operator_posemode;
+       ot->poll= pose_select_linked_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* props */     
+       RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first.");
 }
 
 /* **************** END Posemode stuff ********************** */
@@ -1446,7 +1573,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e
 {
        bArmature *arm;
        EditBone *bone, *curBone, *next;
-       int shift= 0; // XXX
+       int extend= RNA_boolean_get(op->ptr, "extend");
        int x, y;
        ARegion *ar;
        Object *obedit= CTX_data_edit_object(C);
@@ -1458,7 +1585,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e
 
        view3d_operator_needs_opengl(C);
 
-       if (shift)
+       if (extend)
                bone= get_nearest_bone(C, 0, x, y);
        else
                bone= get_nearest_bone(C, 1, x, y);
@@ -1467,14 +1594,16 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e
                return OPERATOR_CANCELLED;
 
        /* Select parents */
-       for (curBone=bone; curBone; curBone=next){
-               if (shift){
-                       curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
-               }
-               else{
-                       curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+       for (curBone=bone; curBone; curBone=next) {
+               if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
+                       if (extend) {
+                               curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                       }
+                       else{
+                               curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                       }
                }
-
+               
                if (curBone->flag & BONE_CONNECTED)
                        next=curBone->parent;
                else
@@ -1482,19 +1611,19 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e
        }
 
        /* Select children */
-       while (bone){
-               for (curBone=arm->edbo->first; curBone; curBone=next){
+       while (bone) {
+               for (curBone=arm->edbo->first; curBone; curBone=next) {
                        next = curBone->next;
-                       if (curBone->parent == bone){
-                               if (curBone->flag & BONE_CONNECTED){
-                                       if (shift)
+                       if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE)==0) {
+                               if (curBone->flag & BONE_CONNECTED) {
+                                       if (extend)
                                                curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                                        else
                                                curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                                        bone=curBone;
                                        break;
                                }
-                               else{ 
+                               else 
                                        bone=NULL;
                                        break;
                                }
@@ -1502,18 +1631,20 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e
                }
                if (!curBone)
                        bone=NULL;
-
        }
-
+       
        ED_armature_sync_selection(arm->edbo);
-
-       /* BIF_undo_push("Select connected"); */
-
+       
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
-
+       
        return OPERATOR_FINISHED;
 }
 
+static int armature_select_linked_poll(bContext *C)
+{
+       return ( ED_operator_view3d_active(C) && ED_operator_editarmature(C) );
+}
+
 void ARMATURE_OT_select_linked(wmOperatorType *ot)
 {
        /* identifiers */
@@ -1523,10 +1654,13 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot)
        /* api callbacks */
        ot->exec= NULL;
        ot->invoke= armature_select_linked_invoke;
-       ot->poll= ED_operator_editarmature;
+       ot->poll= armature_select_linked_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* properties s*/
+       RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first.");
 }
 
 /* does bones and points */
@@ -1619,21 +1753,6 @@ static EditBone *get_nearest_editbonepoint (ViewContext *vc, short mval[2], List
        return NULL;
 }
 
-static void delete_bone(ListBase *edbo, EditBone* exBone)
-{
-       EditBone *curBone;
-       
-       /* Find any bones that refer to this bone */
-       for (curBone=edbo->first;curBone;curBone=curBone->next) {
-               if (curBone->parent==exBone) {
-                       curBone->parent=exBone->parent;
-                       curBone->flag &= ~BONE_CONNECTED;
-               }
-       }
-       
-       BLI_freelinkN(edbo, exBone);
-}
-
 /* context: editmode armature */
 EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
 {
@@ -1642,9 +1761,8 @@ EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
        
        if (ebo == NULL)
                return NULL;
-       
-       BLI_strncpy(name, ebo->name, sizeof(name));
-       bone_flip_name(name, 0);                // 0 = don't strip off number extensions
+
+       flip_side_name(name, ebo->name, FALSE);
        
        for (eboflip= edbo->first; eboflip; eboflip=eboflip->next) {
                if (ebo != eboflip) {
@@ -1659,7 +1777,7 @@ EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
 
 /* previously delete_armature */
 /* only editmode! */
-static int armature_delete_selected_exec(bContext *C, wmOperator *op)
+static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
 {
        bArmature *arm;
        EditBone        *curBone, *next;
@@ -1686,17 +1804,18 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
        
        /*  First erase any associated pose channel */
        if (obedit->pose) {
-               bPoseChannel *chan, *next;
-               for (chan=obedit->pose->chanbase.first; chan; chan=next) {
-                       next= chan->next;
-                       curBone = editbone_name_exists(arm->edbo, chan->name);
+               bPoseChannel *pchan, *next;
+               for (pchan=obedit->pose->chanbase.first; pchan; pchan=next) {
+                       next= pchan->next;
+                       curBone = editbone_name_exists(arm->edbo, pchan->name);
                        
                        if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
-                               free_constraints(&chan->constraints);
-                               BLI_freelinkN (&obedit->pose->chanbase, chan);
+                               free_pose_channel(pchan);
+                               free_pose_channels_hash(obedit->pose);
+                               BLI_freelinkN (&obedit->pose->chanbase, pchan);
                        }
                        else {
-                               for (con= chan->constraints.first; con; con= con->next) {
+                               for (con= pchan->constraints.first; con; con= con->next) {
                                        bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
                                        ListBase targets = {NULL, NULL};
                                        bConstraintTarget *ct;
@@ -1728,15 +1847,17 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
        for (curBone=arm->edbo->first;curBone;curBone=next) {
                next=curBone->next;
                if (arm->layer & curBone->layer) {
-                       if (curBone->flag & BONE_SELECTED)
-                               delete_bone(arm->edbo, curBone);
+                       if (curBone->flag & BONE_SELECTED) {
+                               if(curBone==arm->act_edbone) arm->act_edbone= NULL;
+                               ED_armature_edit_bone_remove(arm, curBone);
+                       }
                }
        }
        
        
        ED_armature_sync_selection(arm->edbo);
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
 
        return OPERATOR_FINISHED;
 }
@@ -1761,7 +1882,7 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
  * toggle==2: only active tag
  * toggle==3: swap (no test)
  */
-void ED_armature_deselectall(Object *obedit, int toggle, int doundo)
+void ED_armature_deselect_all(Object *obedit, int toggle)
 {
        bArmature *arm= obedit->data;
        EditBone        *eBone;
@@ -1781,48 +1902,61 @@ void ED_armature_deselectall(Object *obedit, int toggle, int doundo)
        }
        else sel= toggle;
        
-       /*      Set the flags */
-       for (eBone=arm->edbo->first;eBone;eBone=eBone->next) {
-               if (sel==3) {
-                       /* invert selection of bone */
-                       if ((arm->layer & eBone->layer) && (eBone->flag & BONE_HIDDEN_A)==0) {
-                               eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
-                               eBone->flag &= ~BONE_ACTIVE;
+       if(sel==2) {
+               arm->act_edbone= NULL;
+       } else {
+               /*      Set the flags */
+               for (eBone=arm->edbo->first;eBone;eBone=eBone->next) {
+                       if (sel==3) {
+                               /* invert selection of bone */
+                               if(EBONE_VISIBLE(arm, eBone)) {
+                                       eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+                                       if(arm->act_edbone==eBone)
+                                               arm->act_edbone= NULL;
+                               }
                        }
-               }
-               else if (sel==1) {
-                       /* select bone */
-                       if(arm->layer & eBone->layer && (eBone->flag & BONE_HIDDEN_A)==0) {
-                               eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
-                               if(eBone->parent)
-                                       eBone->parent->flag |= (BONE_TIPSEL);
+                       else if (sel==1) {
+                               /* select bone */
+                               if(EBONE_VISIBLE(arm, eBone)) {
+                                       eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+                                       if(eBone->parent)
+                                               eBone->parent->flag |= (BONE_TIPSEL);
+                               }
+                       }
+                       else {
+                               /* deselect bone */
+                               eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+                               if(arm->act_edbone==eBone)
+                                       arm->act_edbone= NULL;
                        }
-               }
-               else if (sel==2) {
-                       /* clear active flag */
-                       eBone->flag &= ~(BONE_ACTIVE);
-               }
-               else {
-                       /* deselect bone */
-                       eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
                }
        }
        
        ED_armature_sync_selection(arm->edbo);
-       if (doundo) {
-               if (sel==1) BIF_undo_push("Select All");
-               else BIF_undo_push("Deselect All");
-       }
 }
 
+void ED_armature_deselect_all_visible(Object *obedit)
+{
+       bArmature *arm= obedit->data;
+       EditBone        *ebone;
+
+       for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
+               /* first and foremost, bone must be visible and selected */
+               if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE)==0) {
+                       ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+               }
+       }
+
+       ED_armature_sync_selection(arm->edbo);
+}
 
 /* context: editmode armature in view3d */
-void mouse_armature(bContext *C, short mval[2], int extend)
+int mouse_armature(bContext *C, short mval[2], int extend)
 {
        Object *obedit= CTX_data_edit_object(C);
        bArmature *arm= obedit->data;
        ViewContext vc;
-       EditBone *nearBone = NULL, *ebone;
+       EditBone *nearBone = NULL;
        int     selmask;
 
        view3d_set_viewcontext(C, &vc);
@@ -1833,10 +1967,10 @@ void mouse_armature(bContext *C, short mval[2], int extend)
        if (nearBone) {
 
                if (!extend)
-                       ED_armature_deselectall(obedit, 0, 0);
+                       ED_armature_deselect_all(obedit, 0);
                
                /* by definition the non-root connected bones have no root point drawn,
-              so a root selection needs to be delivered to the parent tip */
+                  so a root selection needs to be delivered to the parent tip */
                
                if(selmask & BONE_SELECTED) {
                        if(nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
@@ -1884,36 +2018,38 @@ void mouse_armature(bContext *C, short mval[2], int extend)
                
                if(nearBone) {
                        /* then now check for active status */
-                       for (ebone=arm->edbo->first;ebone;ebone=ebone->next) ebone->flag &= ~BONE_ACTIVE;
-                       if(nearBone->flag & BONE_SELECTED) nearBone->flag |= BONE_ACTIVE;
+                       if(nearBone->flag & BONE_SELECTED) arm->act_edbone= nearBone;
                }
                
                WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, vc.obedit);
+               return 1;
        }
+
+       return 0;
 }
 
 void ED_armature_edit_free(struct Object *ob)
 {
        bArmature *arm= ob->data;
+       EditBone *eBone;
        
        /*      Clear the editbones list */
        if (arm->edbo) {
-               if (arm->edbo->first)
+               if (arm->edbo->first) {
+                       for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
+                               if (eBone->prop) {
+                                       IDP_FreeProperty(eBone->prop);
+                                       MEM_freeN(eBone->prop);
+                               }
+                       }
+
                        BLI_freelistN(arm->edbo);
+               }
                MEM_freeN(arm->edbo);
                arm->edbo= NULL;
        }
 }
 
-void ED_armature_edit_remake(Object *obedit)
-{
-       if(okee("Reload original data")==0) return;
-       
-       ED_armature_to_edit(obedit);
-       
-//     BIF_undo_push("Delete bone");
-}
-
 /* Put armature in EditMode */
 void ED_armature_to_edit(Object *ob)
 {
@@ -1921,7 +2057,8 @@ void ED_armature_to_edit(Object *ob)
        
        ED_armature_edit_free(ob);
        arm->edbo= MEM_callocN(sizeof(ListBase), "edbo armature");
-       make_boneList(arm->edbo, &arm->bonebase,NULL);
+       arm->act_edbone= make_boneList(arm->edbo, &arm->bonebase, NULL, arm->act_bone);
+       arm->act_bone= NULL;
 
 //     BIF_freeTemplates(); /* force template update when entering editmode */
 }
@@ -1930,131 +2067,113 @@ void ED_armature_to_edit(Object *ob)
 /* adjust bone roll to align Z axis with vector
  * vec is in local space and is normalized
  */
-float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3])
-{
-       float mat[3][3], nor[3], up_axis[3], vec[3];
-       float roll;
 
-       VecSubf(nor, bone->tail, bone->head);
-       
-       vec_roll_to_mat3(nor, 0, mat);
-       VECCOPY(up_axis, mat[2]);
-       
-       roll = NormalizedVecAngle2(new_up_axis, up_axis);
-       
-       Crossf(vec, up_axis, new_up_axis);
-       
-       if (Inpf(vec, nor) < 0)
-       {
-               roll = -roll;
-       }
-       
-       return roll;
-}
+float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const short axis_only)
+{
+       float mat[3][3], nor[3];
 
+       sub_v3_v3v3(nor, bone->tail, bone->head);
+       vec_roll_to_mat3(nor, 0.0f, mat);
 
-/* Set roll value for given bone -> Z-Axis Point up (original method) */
-void auto_align_ebone_zaxisup(Scene *scene, View3D *v3d, EditBone *ebone)
-{
-       float   delta[3], curmat[3][3];
-       float   xaxis[3]={1.0f, 0.0f, 0.0f}, yaxis[3], zaxis[3]={0.0f, 0.0f, 1.0f};
-       float   targetmat[3][3], imat[3][3], diffmat[3][3];
-       
-       /* Find the current bone matrix */
-       VecSubf(delta, ebone->tail, ebone->head);
-       vec_roll_to_mat3(delta, 0.0f, curmat);
-       
-       /* Make new matrix based on y axis & z-up */
-       VECCOPY(yaxis, curmat[1]);
-       
-       Mat3One(targetmat);
-       VECCOPY(targetmat[0], xaxis);
-       VECCOPY(targetmat[1], yaxis);
-       VECCOPY(targetmat[2], zaxis);
-       Mat3Ortho(targetmat);
-       
-       /* Find the difference between the two matrices */
-       Mat3Inv(imat, targetmat);
-       Mat3MulMat3(diffmat, imat, curmat);
-       
-       // old-method... let's see if using mat3_to_vec_roll is more accurate
-       //ebone->roll = atan2(diffmat[2][0], diffmat[2][2]);  
-       mat3_to_vec_roll(diffmat, delta, &ebone->roll);
-}
+       /* check the bone isnt aligned with the axis */
+       if(!is_zero_v3(align_axis) && angle_v3v3(align_axis, mat[2]) > FLT_EPSILON) {
+               float vec[3], align_axis_proj[3], roll;
 
-/* Set roll value for given bone -> Z-Axis point towards cursor */
-void auto_align_ebone_tocursor(Scene *scene, View3D *v3d, EditBone *ebone)
-{
-       Object *obedit= scene->obedit; // XXX get from context
-       float   *cursor= give_cursor(scene, v3d);
-       float   delta[3], curmat[3][3];
-       float   mat[4][4], tmat[4][4], imat[4][4];
-       float   rmat[4][4], rot[3];
-       float   vec[3];
-       
-       /* find the current bone matrix as a 4x4 matrix (in Armature Space) */
-       VecSubf(delta, ebone->tail, ebone->head);
-       vec_roll_to_mat3(delta, ebone->roll, curmat);
-       Mat4CpyMat3(mat, curmat);
-       VECCOPY(mat[3], ebone->head);
-       
-       /* multiply bone-matrix by object matrix (so that bone-matrix is in WorldSpace) */
-       Mat4MulMat4(tmat, mat, obedit->obmat);
-       Mat4Invert(imat, tmat);
-       
-       /* find position of cursor relative to bone */
-       VecMat4MulVecfl(vec, imat, cursor);
-       
-       /* check that cursor is in usable position */
-       if ((IS_EQ(vec[0], 0)==0) && (IS_EQ(vec[2], 0)==0)) {
-               /* Compute a rotation matrix around y */
-               rot[1] = (float)atan2(vec[0], vec[2]);
-               rot[0] = rot[2] = 0.0f;
-               EulToMat4(rot, rmat);
+               /* project the new_up_axis along the normal */
+               project_v3_v3v3(vec, align_axis, nor);
+               sub_v3_v3v3(align_axis_proj, align_axis, vec);
+               
+               if(axis_only) {
+                       if(angle_v3v3(align_axis_proj, mat[2]) > M_PI/2) {
+                               negate_v3(align_axis_proj);
+                       }
+               }
+               
+               roll = angle_v3v3(align_axis_proj, mat[2]);
                
-               /* Multiply the bone matrix by rotation matrix. This should be new bone-matrix */
-               Mat4MulMat4(tmat, rmat, mat);
-               Mat3CpyMat4(curmat, tmat);
+               cross_v3_v3v3(vec, mat[2], align_axis_proj);
                
-               /* Now convert from new bone-matrix, back to a roll value (in radians) */
-               mat3_to_vec_roll(curmat, delta, &ebone->roll);
+               if (dot_v3v3(vec, nor) < 0) {
+                       roll = -roll;
+               }
+
+               return roll;
        }
+
+       return 0.0f;
 }
 
 
 static EnumPropertyItem prop_calc_roll_types[] = {
-       {0, "GLOBALUP", 0, "Z-Axis Up", ""},
-       {1, "CURSOR", 0, "Z-Axis to Cursor", ""},
+       {0, "X", 0, "X Axis", ""},
+       {1, "Y", 0, "Y Axis", ""},
+       {2, "Z", 0, "Z Axis", ""},
+       {6, "VIEW", 0, "View Axis", ""},
+       {7, "CURSOR", 0, "Cursor", ""},
        {0, NULL, 0, NULL, NULL}
 };
 
+
 static int armature_calc_roll_exec(bContext *C, wmOperator *op) 
 {
-       Scene *scene= CTX_data_scene(C);
-       View3D *v3d= CTX_wm_view3d(C);
        Object *ob= CTX_data_edit_object(C);
-       void (*roll_func)(Scene *, View3D *, EditBone *) = NULL;
+       const short type= RNA_enum_get(op->ptr, "type");
+       const short axis_only= RNA_boolean_get(op->ptr, "axis_only");
+       const short axis_flip= RNA_boolean_get(op->ptr, "axis_flip");
+
+       float imat[3][3];
+
+       copy_m3_m4(imat, ob->obmat);
+       invert_m3(imat);
+
+       if(type==7) { /* Cursor */
+               Scene *scene= CTX_data_scene(C);
+               View3D *v3d= CTX_wm_view3d(C); /* can be NULL */
+               float cursor_local[3];
+               float   *cursor= give_cursor(scene, v3d);
        
-       /* specific method used to calculate roll depends on mode */
-       switch (RNA_enum_get(op->ptr, "type")) {
-               case 1:  /* Z-Axis point towards cursor */
-                       roll_func= auto_align_ebone_tocursor;
-                       break;
-               default: /* Z-Axis Point Up */
-                       roll_func= auto_align_ebone_zaxisup;
-                       break;
+
+               copy_v3_v3(cursor_local, cursor);
+               mul_m3_v3(imat, cursor_local);
+
+               /* cursor */
+               CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+                       float cursor_rel[3];
+                       sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
+                       if(axis_flip) negate_v3(cursor_rel);
+                       ebone->roll= ED_rollBoneToVector(ebone, cursor_rel, axis_only);
+               }
+               CTX_DATA_END;
        }
-       
-       /* recalculate roll on selected bones */
-       CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
-               /* roll func is a callback which assumes that all is well */
-               roll_func(scene, v3d, ebone);
+       else {
+               float vec[3]= {0.0f, 0.0f, 0.0f};
+               if(type==6) { /* View */
+                       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+                       if(rv3d==NULL) {
+                               BKE_report(op->reports, RPT_ERROR, "No region view3d available");
+                               return OPERATOR_CANCELLED;
+                       }
+
+                       copy_v3_v3(vec, rv3d->viewinv[2]);
+               }
+               else { /* Axis */
+                       assert(type >= 0 && type <= 5);
+                       if(type<3)      vec[type]= 1.0f; 
+                       else            vec[type-2]= -1.0f; 
+               }
+
+               mul_m3_v3(imat, vec);
+               if(axis_flip) negate_v3(vec);
+
+               CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+                       /* roll func is a callback which assumes that all is well */
+                       ebone->roll= ED_rollBoneToVector(ebone, vec, axis_only);
+               }
+               CTX_DATA_END;
        }
-       CTX_DATA_END;
-       
 
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -2072,81 +2191,101 @@ void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
+
        /* properties */
-       RNA_def_enum(ot->srna, "type", prop_calc_roll_types, 0, "Type", "");
+       ot->prop= RNA_def_enum(ot->srna, "type", prop_calc_roll_types, 0, "Type", "");
+       RNA_def_boolean(ot->srna, "axis_flip", 0, "Flip Axis", "Negate the alignment axis.");
+       RNA_def_boolean(ot->srna, "axis_only", 0, "Shortest Rotation", "Ignore the axis direction, use the shortest rotation to align.");
 }
 
 /* **************** undo for armatures ************** */
 
-static void undoBones_to_editBones(void *lbuv, void *lbev)
+typedef struct UndoArmature {
+       EditBone *act_edbone;
+       ListBase lb;
+} UndoArmature;
+
+static void undoBones_to_editBones(void *uarmv, void *armv)
 {
-       ListBase *lbu= lbuv;
-       ListBase *edbo= lbev;
+       UndoArmature *uarm= uarmv;
+       bArmature *arm= armv;
        EditBone *ebo, *newebo;
        
-       BLI_freelistN(edbo);
+       BLI_freelistN(arm->edbo);
        
        /* copy  */
-       for(ebo= lbu->first; ebo; ebo= ebo->next) {
+       for(ebo= uarm->lb.first; ebo; ebo= ebo->next) {
                newebo= MEM_dupallocN(ebo);
                ebo->temp= newebo;
-               BLI_addtail(edbo, newebo);
+               BLI_addtail(arm->edbo, newebo);
        }
        
+       /* active bone */
+       if(uarm->act_edbone) {
+               ebo= uarm->act_edbone;
+               arm->act_edbone= ebo->temp;
+       }
+       else
+               arm->act_edbone= NULL;
+
        /* set pointers */
-       for(newebo= edbo->first; newebo; newebo= newebo->next) {
+       for(newebo= arm->edbo->first; newebo; newebo= newebo->next) {
                if(newebo->parent) newebo->parent= newebo->parent->temp;
        }
        /* be sure they dont hang ever */
-       for(newebo= edbo->first; newebo; newebo= newebo->next) {
+       for(newebo= arm->edbo->first; newebo; newebo= newebo->next) {
                newebo->temp= NULL;
        }
 }
 
-static void *editBones_to_undoBones(void *lbev)
+static void *editBones_to_undoBones(void *armv)
 {
-       ListBase *edbo= lbev;
-       ListBase *lb;
+       bArmature *arm= armv;
+       UndoArmature *uarm;
        EditBone *ebo, *newebo;
        
-       lb= MEM_callocN(sizeof(ListBase), "listbase undo");
+       uarm= MEM_callocN(sizeof(UndoArmature), "listbase undo");
        
        /* copy */
-       for(ebo= edbo->first; ebo; ebo= ebo->next) {
+       for(ebo= arm->edbo->first; ebo; ebo= ebo->next) {
                newebo= MEM_dupallocN(ebo);
                ebo->temp= newebo;
-               BLI_addtail(lb, newebo);
+               BLI_addtail(&uarm->lb, newebo);
        }
        
+       /* active bone */
+       if(arm->act_edbone) {
+               ebo= arm->act_edbone;
+               uarm->act_edbone= ebo->temp;
+       }
+
        /* set pointers */
-       for(newebo= lb->first; newebo; newebo= newebo->next) {
+       for(newebo= uarm->lb.first; newebo; newebo= newebo->next) {
                if(newebo->parent) newebo->parent= newebo->parent->temp;
        }
        
-       return lb;
+       return uarm;
 }
 
-static void free_undoBones(void *lbv)
+static void free_undoBones(void *uarmv)
 {
-       ListBase *lb= lbv;
+       UndoArmature *uarm= uarmv;
        
-       BLI_freelistN(lb);
-       MEM_freeN(lb);
+       BLI_freelistN(&uarm->lb);
+       MEM_freeN(uarm);
 }
 
 static void *get_armature_edit(bContext *C)
 {
        Object *obedit= CTX_data_edit_object(C);
        if(obedit && obedit->type==OB_ARMATURE) {
-               bArmature *arm= obedit->data;
-               return arm->edbo;
+               return obedit->data;
        }
        return NULL;
 }
 
 /* and this is all the undo system needs to know */
-void undo_push_armature(bContext *C, char *name)
+void undo_push_armature(bContext *C, const char *name)
 {
        // XXX solve getdata()
        undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
@@ -2158,11 +2297,11 @@ void undo_push_armature(bContext *C, char *name)
 /* *************** Adding stuff in editmode *************** */
 
 /* default bone add, returns it selected, but without tail set */
-EditBone *addEditBone(bArmature *arm, char *name)
+EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
 {
        EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
        
-       BLI_strncpy(bone->name, name, 32);
+       BLI_strncpy(bone->name, name, sizeof(bone->name));
        unique_editbone_name(arm->edbo, bone->name, NULL);
        
        BLI_addtail(arm->edbo, bone);
@@ -2182,53 +2321,43 @@ EditBone *addEditBone(bArmature *arm, char *name)
        return bone;
 }
 
-/* default bone add, returns it selected, but without tail set */
-static EditBone *add_editbone(Object *obedit, char *name)
-{
-       bArmature *arm= obedit->data;
-
-       return addEditBone(arm, name);
-}
-
 /* v3d and rv3d are allowed to be NULL */
 void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
 {
        Object *obedit= scene->obedit; // XXX get from context
        float           obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
        EditBone        *bone;
-       
-       VECCOPY(curs, give_cursor(scene, v3d)); 
 
        /* Get inverse point for head and orientation for tail */
-       Mat4Invert(obedit->imat, obedit->obmat);
-       Mat4MulVecfl(obedit->imat, curs);
+       invert_m4_m4(obedit->imat, obedit->obmat);
+       mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
 
        if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
-               Mat3CpyMat4(obmat, rv3d->viewmat);
-       else Mat3One(obmat);
+               copy_m3_m4(obmat, rv3d->viewmat);
+       else unit_m3(obmat);
        
-       Mat3CpyMat4(viewmat, obedit->obmat);
-       Mat3MulMat3(totmat, obmat, viewmat);
-       Mat3Inv(imat, totmat);
+       copy_m3_m4(viewmat, obedit->obmat);
+       mul_m3_m3m3(totmat, obmat, viewmat);
+       invert_m3_m3(imat, totmat);
        
-       ED_armature_deselectall(obedit, 0, 0);
+       ED_armature_deselect_all(obedit, 0);
        
        /*      Create a bone   */
-       bone= add_editbone(obedit, "Bone");
+       bone= ED_armature_edit_bone_add(obedit->data, "Bone");
 
-       VECCOPY(bone->head, curs);
+       copy_v3_v3(bone->head, curs);
        
-       if ( (U.flag & USER_ADD_VIEWALIGNED) )
-               VecAddf(bone->tail, bone->head, imat[1]);       // bone with unit length 1
+       if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+               add_v3_v3v3(bone->tail, bone->head, imat[1]);   // bone with unit length 1
        else
-               VecAddf(bone->tail, bone->head, imat[2]);       // bone with unit length 1, pointing up Z
+               add_v3_v3v3(bone->tail, bone->head, imat[2]);   // bone with unit length 1, pointing up Z
        
 }
 
 
 /* previously addvert_armature */
 /* the ctrl-click method */
-static int armature_click_extrude_exec(bContext *C, wmOperator *op)
+static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
 {
        View3D *v3d;
        bArmature *arm;
@@ -2246,7 +2375,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op)
        /* find the active or selected bone */
        for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
                if (EBONE_VISIBLE(arm, ebone)) {
-                       if (ebone->flag & (BONE_ACTIVE|BONE_TIPSEL)) 
+                       if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
                                break;
                }
        }
@@ -2254,7 +2383,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op)
        if (ebone==NULL) {
                for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
                        if (EBONE_VISIBLE(arm, ebone)) {
-                               if (ebone->flag & (BONE_ACTIVE|BONE_ROOTSEL)) 
+                               if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
                                        break;
                        }
                }
@@ -2264,7 +2393,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op)
                to_root= 1;
        }
        
-       ED_armature_deselectall(obedit, 0, 0);
+       ED_armature_deselect_all(obedit, 0);
        
        /* we re-use code for mirror editing... */
        flipbone= NULL;
@@ -2280,33 +2409,33 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op)
                        }
                }
                
-               newbone= add_editbone(obedit, ebone->name);
-               newbone->flag |= BONE_ACTIVE;
+               newbone= ED_armature_edit_bone_add(arm, ebone->name);
+               arm->act_edbone= newbone;
                
                if (to_root) {
-                       VECCOPY(newbone->head, ebone->head);
+                       copy_v3_v3(newbone->head, ebone->head);
                        newbone->rad_head= ebone->rad_tail;
                        newbone->parent= ebone->parent;
                }
                else {
-                       VECCOPY(newbone->head, ebone->tail);
+                       copy_v3_v3(newbone->head, ebone->tail);
                        newbone->rad_head= ebone->rad_tail;
                        newbone->parent= ebone;
                        newbone->flag |= BONE_CONNECTED;
                }
                
                curs= give_cursor(scene, v3d);
-               VECCOPY(newbone->tail, curs);
-               VecSubf(newbone->tail, newbone->tail, obedit->obmat[3]);
+               copy_v3_v3(newbone->tail, curs);
+               sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
                
                if (a==1) 
                        newbone->tail[0]= -newbone->tail[0];
                
-               Mat3CpyMat4(mat, obedit->obmat);
-               Mat3Inv(imat, mat);
-               Mat3MulVecfl(imat, newbone->tail);
+               copy_m3_m4(mat, obedit->obmat);
+               invert_m3_m3(imat, mat);
+               mul_m3_v3(imat, newbone->tail);
                
-               newbone->length= VecLenf(newbone->head, newbone->tail);
+               newbone->length= len_v3v3(newbone->head, newbone->tail);
                newbone->rad_tail= newbone->length*0.05f;
                newbone->dist= newbone->length*0.25f;
                
@@ -2340,7 +2469,7 @@ static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *e
        
        fp= give_cursor(scene, v3d);
        
-       VECCOPY(oldcurs, fp);
+       copy_v3_v3(oldcurs, fp);
        
        mx= event->x - ar->winrct.xmin;
        my= event->y - ar->winrct.ymin;
@@ -2351,7 +2480,7 @@ static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *e
        if(mval[0]!=IS_CLIPPED) {
                
                window_to_3d_delta(ar, dvec, mval[0]-mx, mval[1]-my);
-               VecSubf(fp, fp, dvec);
+               sub_v3_v3v3(fp, fp, dvec);
        }
        else {
                
@@ -2370,7 +2499,7 @@ static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *e
        retv= armature_click_extrude_exec(C, op);
 
        /* restore previous 3d cursor position */
-       VECCOPY(fp, oldcurs);
+       copy_v3_v3(fp, oldcurs);
 
        return retv;
 }
@@ -2397,10 +2526,10 @@ static EditBone *add_points_bone (Object *obedit, float head[], float tail[])
 {
        EditBone *ebo;
        
-       ebo= add_editbone(obedit, "Bone");
+       ebo= ED_armature_edit_bone_add(obedit->data, "Bone");
        
-       VECCOPY(ebo->head, head);
-       VECCOPY(ebo->tail, tail);
+       copy_v3_v3(ebo->head, head);
+       copy_v3_v3(ebo->tail, tail);
        
        return ebo;
 }
@@ -2444,12 +2573,12 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
         * they point to has also been duplicated
         */
        EditBone     *oldtarget, *newtarget;
-       bPoseChannel *chan;
+       bPoseChannel *pchan;
        bConstraint  *curcon;
        ListBase     *conlist;
        
-       if ( (chan = verify_pose_channel(dst_ob->pose, dupBone->name)) ) {
-               if ( (conlist = &chan->constraints) ) {
+       if ( (pchan = verify_pose_channel(dst_ob->pose, dupBone->name)) ) {
+               if ( (conlist = &pchan->constraints) ) {
                        for (curcon = conlist->first; curcon; curcon=curcon->next) {
                                /* does this constraint have a subtarget in
                                 * this armature?
@@ -2494,7 +2623,7 @@ void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob
 
 EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
 {
-       EditBone *eBone = MEM_callocN(sizeof(EditBone), "addup_editbone");
+       EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
        
        /*      Copy data from old bone to new bone */
        memcpy(eBone, curBone, sizeof(EditBone));
@@ -2504,51 +2633,31 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *edit
        
        if (name != NULL)
        {
-               BLI_strncpy(eBone->name, name, 32);
+               BLI_strncpy(eBone->name, name, sizeof(eBone->name));
        }
 
        unique_editbone_name(editbones, eBone->name, NULL);
        BLI_addtail(editbones, eBone);
        
+       /* copy the ID property */
+       if(curBone->prop)
+               eBone->prop= IDP_CopyProperty(curBone->prop);
+
        /* Lets duplicate the list of constraints that the
         * current bone has.
         */
        if (src_ob->pose) {
                bPoseChannel *chanold, *channew;
-               ListBase     *listold, *listnew;
                
                chanold = verify_pose_channel(src_ob->pose, curBone->name);
                if (chanold) {
-                       listold = &chanold->constraints;
-                       if (listold) {
-                               /* WARNING: this creates a new posechannel, but there will not be an attached bone 
-                                *              yet as the new bones created here are still 'EditBones' not 'Bones'. 
-                                */
-                               channew = 
-                                       verify_pose_channel(dst_ob->pose, eBone->name);
-                               if (channew) {
-                                       /* copy transform locks */
-                                       channew->protectflag = chanold->protectflag;
-                                       
-                                       /* copy bone group */
-                                       channew->agrp_index= chanold->agrp_index;
-                                       
-                                       /* ik (dof) settings */
-                                       channew->ikflag = chanold->ikflag;
-                                       VECCOPY(channew->limitmin, chanold->limitmin);
-                                       VECCOPY(channew->limitmax, chanold->limitmax);
-                                       VECCOPY(channew->stiffness, chanold->stiffness);
-                                       channew->ikstretch= chanold->ikstretch;
-                                       channew->ikrotweight= chanold->ikrotweight;
-                                       channew->iklinweight= chanold->iklinweight;
-                                       
-                                       /* constraints */
-                                       listnew = &channew->constraints;
-                                       copy_constraints(listnew, listold);
-                                       
-                                       /* custom shape */
-                                       channew->custom= chanold->custom;
-                               }
+                       /* WARNING: this creates a new posechannel, but there will not be an attached bone
+                        *              yet as the new bones created here are still 'EditBones' not 'Bones'.
+                        */
+                       channew= verify_pose_channel(dst_ob->pose, eBone->name);
+
+                       if(channew) {
+                               duplicate_pose_channel_data(channew, chanold);
                        }
                }
        }
@@ -2562,7 +2671,7 @@ EditBone *duplicateEditBone(EditBone *curBone, char *name, ListBase *editbones,
 }
 
 /* previously adduplicate_armature */
-static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
+static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
 {
        bArmature *arm;
        EditBone        *eBone = NULL;
@@ -2598,65 +2707,12 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
        for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
                if (EBONE_VISIBLE(arm, curBone)) {
                        if (curBone->flag & BONE_SELECTED) {
-                               eBone=MEM_callocN(sizeof(EditBone), "addup_editbone");
-                               eBone->flag |= BONE_SELECTED;
                                
-                               /* Copy data from old bone to new bone */
-                               memcpy(eBone, curBone, sizeof(EditBone));
+                               eBone= duplicateEditBone(curBone, curBone->name, arm->edbo, obedit);
                                
-                               curBone->temp = eBone;
-                               eBone->temp = curBone;
-                               
-                               unique_editbone_name(arm->edbo, eBone->name, NULL);
-                               BLI_addtail(arm->edbo, eBone);
                                if (!firstDup)
                                        firstDup=eBone;
-                               
-                               /* Lets duplicate the list of constraints that the
-                                * current bone has.
-                                */
-                               if (obedit->pose) {
-                                       bPoseChannel *chanold, *channew;
-                                       ListBase     *listold, *listnew;
-                                       
-                                       chanold = verify_pose_channel(obedit->pose, curBone->name);
-                                       if (chanold) {
-                                               listold = &chanold->constraints;
-                                               if (listold) {
-                                                       /* WARNING: this creates a new posechannel, but there will not be an attached bone 
-                                                        *              yet as the new bones created here are still 'EditBones' not 'Bones'. 
-                                                        */
-                                                       channew = 
-                                                               verify_pose_channel(obedit->pose, eBone->name);
-                                                       if (channew) {
-                                                               /* copy transform locks */
-                                                               channew->protectflag = chanold->protectflag;
-                                                               
-                                                               /* copy rotation mode */
-                                                               channew->rotmode = chanold->rotmode;
-                                                               
-                                                               /* copy bone group */
-                                                               channew->agrp_index= chanold->agrp_index;
-                                                               
-                                                               /* ik (dof) settings */
-                                                               channew->ikflag = chanold->ikflag;
-                                                               VECCOPY(channew->limitmin, chanold->limitmin);
-                                                               VECCOPY(channew->limitmax, chanold->limitmax);
-                                                               VECCOPY(channew->stiffness, chanold->stiffness);
-                                                               channew->ikstretch= chanold->ikstretch;
-                                                               channew->ikrotweight= chanold->ikrotweight;
-                                                               channew->iklinweight= chanold->iklinweight;
-                                                               
-                                                               /* constraints */
-                                                               listnew = &channew->constraints;
-                                                               copy_constraints(listnew, listold);
-                                                               
-                                                               /* custom shape */
-                                                               channew->custom= chanold->custom;
-                                                       }
-                                               }
-                                       }
-                               }
+
                        }
                }
        }
@@ -2695,28 +2751,26 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
                }
        } 
        
+       /* correct the active bone */
+       if(arm->act_edbone) {
+               eBone= arm->act_edbone;
+               if(eBone->temp)
+                       arm->act_edbone= eBone->temp;
+       }
+
        /*      Deselect the old bones and select the new ones */
        for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
                if (EBONE_VISIBLE(arm, curBone))
-                       curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
+                       curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
        }
 
+       ED_armature_validate_active(arm);
+
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
        
        return OPERATOR_FINISHED;
 }
 
-static int armature_duplicate_selected_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       int retv= armature_duplicate_selected_exec(C, op);
-
-       if (retv == OPERATOR_FINISHED) {
-               RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
-               WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
-       }
-
-       return retv;
-}
 
 void ARMATURE_OT_duplicate(wmOperatorType *ot)
 {
@@ -2725,15 +2779,11 @@ void ARMATURE_OT_duplicate(wmOperatorType *ot)
        ot->idname= "ARMATURE_OT_duplicate";
        
        /* api callbacks */
-       ot->invoke = armature_duplicate_selected_invoke;
        ot->exec = armature_duplicate_selected_exec;
        ot->poll = ED_operator_editarmature;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
-       /* to give to transform */
-       RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
 }
 
 
@@ -2806,14 +2856,14 @@ static void fill_add_joint (EditBone *ebo, short eb_tail, ListBase *points)
        short found= 0;
        
        if (eb_tail) {
-               VECCOPY(vec, ebo->tail);
+               copy_v3_v3(vec, ebo->tail);
        }
        else {
-               VECCOPY(vec, ebo->head);
+               copy_v3_v3(vec, ebo->head);
        }
        
        for (ebp= points->first; ebp; ebp= ebp->next) {
-               if (VecEqual(ebp->vec, vec)) {                  
+               if (equals_v3v3(ebp->vec, vec)) {                       
                        if (eb_tail) {
                                if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
                                        /* so this bone's tail owner is this bone */
@@ -2838,11 +2888,11 @@ static void fill_add_joint (EditBone *ebo, short eb_tail, ListBase *points)
                ebp= MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
                
                if (eb_tail) {
-                       VECCOPY(ebp->vec, ebo->tail);
+                       copy_v3_v3(ebp->vec, ebo->tail);
                        ebp->tail_owner= ebo;
                }
                else {
-                       VECCOPY(ebp->vec, ebo->head);
+                       copy_v3_v3(ebp->vec, ebo->head);
                        ebp->head_owner= ebo;
                }
                
@@ -2888,17 +2938,14 @@ static int armature_fill_bones_exec (bContext *C, wmOperator *op)
        }
        else if (count == 1) {
                EditBonePoint *ebp;
-               float *fp, curs[3];
+               float curs[3];
                
                /* Get Points - selected joint */
                ebp= (EditBonePoint *)points.first;
                
                /* Get points - cursor (tail) */
-               fp= give_cursor(scene, v3d);
-               VECCOPY (curs, fp);     
-               
-               Mat4Invert(obedit->imat, obedit->obmat);
-               Mat4MulVecfl(obedit->imat, curs);
+               invert_m4_m4(obedit->imat, obedit->obmat);
+               mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
                
                /* Create a bone */
                newbone= add_points_bone(obedit, ebp->vec, curs);
@@ -2926,21 +2973,19 @@ static int armature_fill_bones_exec (bContext *C, wmOperator *op)
                /* find which one should be the 'head' */
                if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) {
                        /* rule: whichever one is closer to 3d-cursor */
-                       float curs[3], *fp= give_cursor(scene, v3d);
+                       float curs[3];
                        float vecA[3], vecB[3];
                        float distA, distB;
                        
                        /* get cursor location */
-                       VECCOPY(curs, fp);      
-                       
-                       Mat4Invert(obedit->imat, obedit->obmat);
-                       Mat4MulVecfl(obedit->imat, curs);
+                       invert_m4_m4(obedit->imat, obedit->obmat);
+                       mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
                        
                        /* get distances */
-                       VecSubf(vecA, ebp->vec, curs);
-                       VecSubf(vecB, ebp2->vec, curs);
-                       distA= VecLength(vecA);
-                       distB= VecLength(vecB);
+                       sub_v3_v3v3(vecA, ebp->vec, curs);
+                       sub_v3_v3v3(vecB, ebp2->vec, curs);
+                       distA= len_v3(vecA);
+                       distB= len_v3(vecB);
                        
                        /* compare distances - closer one therefore acts as direction for bone to go */
                        headtail= (distA < distB) ? 2 : 1;
@@ -2954,12 +2999,12 @@ static int armature_fill_bones_exec (bContext *C, wmOperator *op)
                
                /* assign head/tail combinations */
                if (headtail == 2) {
-                       VECCOPY(head, ebp->vec);
-                       VECCOPY(tail, ebp2->vec);
+                       copy_v3_v3(head, ebp->vec);
+                       copy_v3_v3(tail, ebp2->vec);
                }
                else if (headtail == 1) {
-                       VECCOPY(head, ebp2->vec);
-                       VECCOPY(tail, ebp->vec);
+                       copy_v3_v3(head, ebp2->vec);
+                       copy_v3_v3(tail, ebp->vec);
                }
                
                /* add new bone and parent it to the appropriate end */
@@ -2987,12 +3032,14 @@ static int armature_fill_bones_exec (bContext *C, wmOperator *op)
        }
        else {
                // FIXME.. figure out a method for multiple bones
-               BKE_report(op->reports, RPT_ERROR, "Too many points selected"); 
-               printf("Points selected: %d \n", count);
+               BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d \n", count); 
                BLI_freelistN(&points);
                return OPERATOR_CANCELLED;
        }
        
+       /* updates */
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, obedit);
+       
        /* free points */
        BLI_freelistN(&points);
        
@@ -3004,7 +3051,7 @@ void ARMATURE_OT_fill (wmOperatorType *ot)
        /* identifiers */
        ot->name= "Fill Between Joints";
        ot->idname= "ARMATURE_OT_fill";
-       ot->description= "Add bone between selected joint(s) and/or 3D-Cursor.";
+       ot->description= "Add bone between selected joint(s) and/or 3D-Cursor";
        
        /* callbacks */
        ot->exec= armature_fill_bones_exec;
@@ -3028,8 +3075,10 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
        
        /* check if same bone */
        if (start == end) {
-               printf("Error: same bone! \n");
-               printf("\tstart = %s, end = %s \n", start->name, end->name);
+               if (G.f & G_DEBUG) {
+                       printf("Error: same bone! \n");
+                       printf("\tstart = %s, end = %s \n", start->name, end->name);
+               }
        }
        
        /* step 1: add a new bone
@@ -3037,17 +3086,17 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
         *      - tail = head/tail of end (default tail)
         *      - parent = parent of start
         */
-       if ((start->flag & BONE_TIPSEL) && !(start->flag & (BONE_SELECTED|BONE_ACTIVE))) {
-               VECCOPY(head, start->tail);
+       if ((start->flag & BONE_TIPSEL) && ((start->flag & BONE_SELECTED) || start==arm->act_edbone)==0) {
+               copy_v3_v3(head, start->tail);
        }
        else {
-               VECCOPY(head, start->head);
+               copy_v3_v3(head, start->head);
        }
-       if ((end->flag & BONE_ROOTSEL) && !(end->flag & (BONE_SELECTED|BONE_ACTIVE))) {
-               VECCOPY(tail, end->head);
+       if ((end->flag & BONE_ROOTSEL) && ((end->flag & BONE_SELECTED) || end==arm->act_edbone)==0) {
+               copy_v3_v3(tail, end->head);
        }
        else {
-               VECCOPY(tail, end->tail);
+               copy_v3_v3(tail, end->tail);
        }
        newbone= add_points_bone(obedit, head, tail);
        newbone->parent = start->parent;
@@ -3055,8 +3104,8 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
        /* step 2a: parent children of in-between bones to newbone */
        for (chain= chains->first; chain; chain= chain->next) {
                /* ick: we need to check if parent of each bone in chain is one of the bones in the */
+               short found= 0;
                for (ebo= chain->data; ebo; ebo= ebo->parent) {
-                       short found= 0;
                        
                        /* try to find which bone from the list to be removed, is the parent */
                        for (ebone= end; ebone; ebone= ebone->parent) {
@@ -3072,6 +3121,9 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
                                break;
                        }
                }
+               if (found) {
+                       break;
+               }
        }
        
        /* step 2b: parent child of end to newbone (child from this chain) */
@@ -3081,8 +3133,11 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
        /* step 3: delete all bones between and including start and end */
        for (ebo= end; ebo; ebo= ebone) {
                ebone= (ebo == start) ? (NULL) : (ebo->parent);
-               BLI_freelinkN(arm->edbo, ebo);
+               bone_free(arm, ebo);
        }
+       
+       newbone->flag |= (BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
+       ED_armature_sync_selection(arm->edbo);
 }
 
 
@@ -3121,7 +3176,7 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
                                /* check if visible + selected */
                                if ( EBONE_VISIBLE(arm, ebo) &&
                                         ((ebo->flag & BONE_CONNECTED) || (ebo->parent==NULL)) &&
-                                        (ebo->flag & (BONE_SELECTED|BONE_ACTIVE)) )
+                                        ((ebo->flag & BONE_SELECTED) || (ebo==arm->act_edbone)) )
                                {
                                        /* set either end or start (end gets priority, unless it is already set) */
                                        if (bend == NULL)  {
@@ -3152,41 +3207,116 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
                
                BLI_freelistN(&chains);
        }
-       
-       /* updates */
+       
+       /* updates */
+       ED_armature_sync_selection(arm->edbo);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, obedit);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_merge (wmOperatorType *ot)
+{
+       static EnumPropertyItem merge_types[] = {
+               {1, "WITHIN_CHAIN", 0, "Within Chains", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       /* identifiers */
+       ot->name= "Merge Bones";
+       ot->idname= "ARMATURE_OT_merge";
+       ot->description= "Merge continuous chains of selected bones";
+       
+       /* callbacks */
+       ot->invoke= WM_menu_invoke;
+       ot->exec= armature_merge_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* properties */
+       ot->prop= RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", "");
+}
+
+/* ************** END Add/Remove stuff in editmode ************ */
+/* *************** Tools in editmode *********** */
+
+static int armature_hide_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       Object *obedit= CTX_data_edit_object(C);
+       bArmature *arm= obedit->data;
+       EditBone *ebone;
+
+       /* cancel if nothing selected */
+       if (CTX_DATA_COUNT(C, selected_bones) == 0)
+               return OPERATOR_CANCELLED;
+
+       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+               if (EBONE_VISIBLE(arm, ebone)) {
+                       if (ebone->flag & BONE_SELECTED) {
+                               ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
+                               ebone->flag |= BONE_HIDDEN_A;
+                       }
+               }
+       }
+       ED_armature_validate_active(arm);
        ED_armature_sync_selection(arm->edbo);
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
-       
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
+
        return OPERATOR_FINISHED;
 }
 
-void ARMATURE_OT_merge (wmOperatorType *ot)
+void ARMATURE_OT_hide(wmOperatorType *ot)
 {
-       static EnumPropertyItem merge_types[] = {
-               {1, "WITHIN_CHAIN", 0, "Within Chains", ""},
-               {0, NULL, 0, NULL, NULL}
-       };
-
        /* identifiers */
-       ot->name= "Merge Bones";
-       ot->idname= "ARMATURE_OT_merge";
-       ot->description= "Merge continuous chains of selected bones.";
+       ot->name= "Hide Selected Bones";
+       ot->idname= "ARMATURE_OT_hide";
        
-       /* callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= armature_merge_exec;
+       /* api callbacks */
+       ot->exec= armature_hide_exec;
        ot->poll= ED_operator_editarmature;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       /* properties */
-       RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", "");
 }
 
-/* ************** END Add/Remove stuff in editmode ************ */
-/* *************** Tools in editmode *********** */
+static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       Object *obedit= CTX_data_edit_object(C);
+       bArmature *arm= obedit->data;
+       EditBone *ebone;
+       
+       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+               if(arm->layer & ebone->layer) {
+                       if (ebone->flag & BONE_HIDDEN_A) {
+                               ebone->flag |= (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
+                               ebone->flag &= ~BONE_HIDDEN_A;
+                       }
+               }
+       }
+       ED_armature_validate_active(arm);
+       ED_armature_sync_selection(arm->edbo);
 
+       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
+
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_reveal(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Reveal Bones";
+       ot->idname= "ARMATURE_OT_reveal";
+       
+       /* api callbacks */
+       ot->exec= armature_reveal_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
 void hide_selected_armature_bones(Scene *scene)
 {
@@ -3196,17 +3326,19 @@ void hide_selected_armature_bones(Scene *scene)
        
        for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
                if (EBONE_VISIBLE(arm, ebone)) {
-                       if (ebone->flag & (BONE_SELECTED)) {
-                               ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+                       if (ebone->flag & BONE_SELECTED) {
+                               ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
                                ebone->flag |= BONE_HIDDEN_A;
                        }
                }
        }
+       ED_armature_validate_active(arm);
        ED_armature_sync_selection(arm->edbo);
-       BIF_undo_push("Hide Bones");
 }
 
-void hide_unselected_armature_bones(Scene *scene)
+
+#if 0 // remove this?
+static void hide_unselected_armature_bones(Scene *scene)
 {
        Object *obedit= scene->obedit; // XXX get from context
        bArmature *arm= obedit->data;
@@ -3217,15 +3349,17 @@ void hide_unselected_armature_bones(Scene *scene)
                if (EBONE_VISIBLE(arm, ebone)) {
                        if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL));
                        else {
-                               ebone->flag &= ~BONE_ACTIVE;
                                ebone->flag |= BONE_HIDDEN_A;
                        }
                }
        }
+
+       ED_armature_validate_active(arm);
        ED_armature_sync_selection(arm->edbo);
-       BIF_undo_push("Hide Unselected Bones");
 }
+#endif
 
+#if 0 // remove this?
 void show_all_armature_bones(Scene *scene)
 {
        Object *obedit= scene->obedit; // XXX get from context
@@ -3240,9 +3374,10 @@ void show_all_armature_bones(Scene *scene)
                        }
                }
        }
+       ED_armature_validate_active(arm);
        ED_armature_sync_selection(arm->edbo);
-       BIF_undo_push("Reveal Bones");
 }
+#endif
 
 /* previously extrude_armature */
 /* context; editmode armature */
@@ -3292,7 +3427,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
                                                forked= 0;      // we extrude 2 different bones
                                                if (flipbone->flag & (BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED))
                                                        /* don't want this bone to be selected... */
-                                                       flipbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+                                                       flipbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
                                        }
                                        if ((flipbone==NULL) && (forked))
                                                flipbone= ebone;
@@ -3311,8 +3446,8 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
                                        newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
                                        
                                        if (do_extrude==1) {
-                                               VECCOPY (newbone->head, ebone->tail);
-                                               VECCOPY (newbone->tail, newbone->head);
+                                               copy_v3_v3(newbone->head, ebone->tail);
+                                               copy_v3_v3(newbone->tail, newbone->head);
                                                newbone->parent = ebone;
                                                
                                                newbone->flag = ebone->flag & BONE_TIPSEL;      // copies it, in case mirrored bone
@@ -3320,8 +3455,8 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
                                                if (newbone->parent) newbone->flag |= BONE_CONNECTED;
                                        }
                                        else {
-                                               VECCOPY(newbone->head, ebone->head);
-                                               VECCOPY(newbone->tail, ebone->head);
+                                               copy_v3_v3(newbone->head, ebone->head);
+                                               copy_v3_v3(newbone->tail, ebone->head);
                                                newbone->parent= ebone->parent;
                                                
                                                newbone->flag= BONE_TIPSEL;
@@ -3342,7 +3477,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
                                        newbone->segments= 1;
                                        newbone->layer= ebone->layer;
                                        
-                                       BLI_strncpy (newbone->name, ebone->name, 32);
+                                       BLI_strncpy (newbone->name, ebone->name, sizeof(newbone->name));
                                        
                                        if (flipbone && forked) {       // only set if mirror edit
                                                if (strlen(newbone->name)<30) {
@@ -3364,31 +3499,23 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
                        }
                        
                        /* Deselect the old bone */
-                       ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+                       ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
                }               
        }
        /* if only one bone, make this one active */
-       if (totbone==1 && first) first->flag |= BONE_ACTIVE;
+       if (totbone==1 && first) arm->act_edbone= first;
 
        if (totbone==0) return OPERATOR_CANCELLED;
        
+       if(arm->act_edbone && (((EditBone *)arm->act_edbone)->flag & BONE_SELECTED)==0)
+               arm->act_edbone= NULL;
+
        /* Transform the endpoints */
        ED_armature_sync_selection(arm->edbo);
 
        return OPERATOR_FINISHED;
 }
 
-static int armature_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       if (OPERATOR_CANCELLED == armature_extrude_exec(C, op))
-               return OPERATOR_CANCELLED;
-
-       RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
-       WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
-
-       return OPERATOR_FINISHED;
-}
-
 void ARMATURE_OT_extrude(wmOperatorType *ot)
 {
        /* identifiers */
@@ -3396,7 +3523,6 @@ void ARMATURE_OT_extrude(wmOperatorType *ot)
        ot->idname= "ARMATURE_OT_extrude";
        
        /* api callbacks */
-       ot->invoke= armature_extrude_invoke;
        ot->exec= armature_extrude_exec;
        ot->poll= ED_operator_editarmature;
        
@@ -3405,8 +3531,6 @@ void ARMATURE_OT_extrude(wmOperatorType *ot)
        
        /* props */
        RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
-       /* to give to transform */
-       RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
 }
 /* ********************** Bone Add ********************/
 
@@ -3422,34 +3546,34 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
        
        RNA_string_get(op->ptr, "name", name);
        
-       VECCOPY(curs, give_cursor(CTX_data_scene(C),CTX_wm_view3d(C))); 
+       copy_v3_v3(curs, give_cursor(CTX_data_scene(C),CTX_wm_view3d(C)));      
 
        /* Get inverse point for head and orientation for tail */
-       Mat4Invert(obedit->imat, obedit->obmat);
-       Mat4MulVecfl(obedit->imat, curs);
+       invert_m4_m4(obedit->imat, obedit->obmat);
+       mul_m4_v3(obedit->imat, curs);
 
-       if (U.flag & USER_ADD_VIEWALIGNED)
-               Mat3CpyMat4(obmat, rv3d->viewmat);
-       else Mat3One(obmat);
+       if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+               copy_m3_m4(obmat, rv3d->viewmat);
+       else unit_m3(obmat);
        
-       Mat3CpyMat4(viewmat, obedit->obmat);
-       Mat3MulMat3(totmat, obmat, viewmat);
-       Mat3Inv(imat, totmat);
+       copy_m3_m4(viewmat, obedit->obmat);
+       mul_m3_m3m3(totmat, obmat, viewmat);
+       invert_m3_m3(imat, totmat);
        
-       ED_armature_deselectall(obedit, 0, 0);
+       ED_armature_deselect_all(obedit, 0);
        
        /*      Create a bone   */
-       bone= add_editbone(obedit, name);
+       bone= ED_armature_edit_bone_add(obedit->data, name);
 
-       VECCOPY(bone->head, curs);
+       copy_v3_v3(bone->head, curs);
        
-       if(U.flag & USER_ADD_VIEWALIGNED)
-               VecAddf(bone->tail, bone->head, imat[1]);       // bone with unit length 1
+       if(rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+               add_v3_v3v3(bone->tail, bone->head, imat[1]);   // bone with unit length 1
        else
-               VecAddf(bone->tail, bone->head, imat[2]);       // bone with unit length 1, pointing up Z
+               add_v3_v3v3(bone->tail, bone->head, imat[2]);   // bone with unit length 1, pointing up Z
 
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
+       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
        
        return OPERATOR_FINISHED;
 }
@@ -3488,10 +3612,7 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
        int numcuts, i;
        
        /* there may not be a number_cuts property defined (for 'simple' subdivide) */
-       if (RNA_property_is_set(op->ptr, "number_cuts"))
-               numcuts= RNA_int_get(op->ptr, "number_cuts");
-       else
-               numcuts= 1;
+       numcuts= RNA_int_get(op->ptr, "number_cuts");
        
        /* loop over all editable bones */
        // XXX the old code did this in reverse order though!
@@ -3511,17 +3632,17 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
                        BLI_addtail(arm->edbo, newbone);
                        
                        /* calculate location of newbone->head */
-                       VECCOPY(val1, ebone->head);
-                       VECCOPY(val2, ebone->tail);
-                       VECCOPY(val3, newbone->head);
+                       copy_v3_v3(val1, ebone->head);
+                       copy_v3_v3(val2, ebone->tail);
+                       copy_v3_v3(val3, newbone->head);
                        
                        val3[0]= val1[0]*cutratio + val2[0]*cutratioI;
                        val3[1]= val1[1]*cutratio + val2[1]*cutratioI;
                        val3[2]= val1[2]*cutratio + val2[2]*cutratioI;
                        
-                       VECCOPY(newbone->head, val3);
-                       VECCOPY(newbone->tail, ebone->tail);
-                       VECCOPY(ebone->tail, newbone->head);
+                       copy_v3_v3(newbone->head, val3);
+                       copy_v3_v3(newbone->tail, ebone->tail);
+                       copy_v3_v3(ebone->tail, newbone->head);
                        
                        newbone->rad_head= 0.5f * (ebone->rad_head + ebone->rad_tail);
                        ebone->rad_tail= newbone->rad_head;
@@ -3541,31 +3662,16 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
        CTX_DATA_END;
        
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
        
        return OPERATOR_FINISHED;
 }
 
-
-void ARMATURE_OT_subdivide_simple(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Subdivide Simple";
-       ot->idname= "ARMATURE_OT_subdivide_simple";
-       
-       /* api callbacks */
-       ot->exec = armature_subdivide_exec;
-       ot->poll = ED_operator_editarmature;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-void ARMATURE_OT_subdivide_multi(wmOperatorType *ot)
+void ARMATURE_OT_subdivide(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Subdivide Multi";
-       ot->idname= "ARMATURE_OT_subdivide_multi";
+       ot->idname= "ARMATURE_OT_subdivide";
        
        /* api callbacks */
        ot->exec = armature_subdivide_exec;
@@ -3575,65 +3681,7 @@ void ARMATURE_OT_subdivide_multi(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* Properties */
-       RNA_def_int(ot->srna, "number_cuts", 2, 1, 10, "Number of Cuts", "", 1, INT_MAX);
-}
-
-
-
-static int armature_subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       uiPopupMenu *pup;
-       uiLayout *layout;
-
-       pup= uiPupMenuBegin(C, "Subdivision Type", 0);
-       layout= uiPupMenuLayout(pup);
-       uiItemsEnumO(layout, "ARMATURE_OT_subdivs", "type");
-       uiPupMenuEnd(C, pup);
-       
-       return OPERATOR_CANCELLED;
-}
-
-static int armature_subdivs_exec(bContext *C, wmOperator *op)
-{      
-       switch (RNA_int_get(op->ptr, "type"))
-       {
-               case 0: /* simple */
-                       RNA_int_set(op->ptr, "number_cuts", 1);
-                       armature_subdivide_exec(C, op);
-                       break;
-               case 1: /* multi */
-                       armature_subdivide_exec(C, op);
-                       break;
-       }
-       
-       return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_subdivs(wmOperatorType *ot)
-{
-       static EnumPropertyItem type_items[]= {
-               {0, "SIMPLE", 0, "Simple", ""},
-               {1, "MULTI", 0, "Multi", ""},
-               {0, NULL, 0, NULL, NULL}};
-
-       /* identifiers */
-       ot->name= "subdivs";
-       ot->idname= "ARMATURE_OT_subdivs";
-       
-       /* api callbacks */
-       ot->invoke= armature_subdivs_invoke;
-       ot->exec= armature_subdivs_exec;
-       
-       ot->poll= ED_operator_editarmature;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       /* props */
-       RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
-       
-       /* this is temp, the ops are different, but they are called from subdivs, so all the possible props should be here as well*/
-       RNA_def_int(ot->srna, "number_cuts", 2, 1, 10, "Number of Cuts", "", 1, INT_MAX); 
+       RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
 }
 
 /* ----------- */
@@ -3644,7 +3692,7 @@ void ARMATURE_OT_subdivs(wmOperatorType *ot)
  * this to be done easily.
  */
 
-static int armature_switch_direction_exec(bContext *C, wmOperator *op
+static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)
 {
        Object *ob= CTX_data_edit_object(C);
        bArmature *arm= (bArmature *)ob->data;
@@ -3679,7 +3727,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *op)
                                 *      - connected flag is only set if points are coincidental
                                 */
                                ebo->parent= child;
-                               if ((child) && VecEqual(ebo->head, child->tail))
+                               if ((child) && equals_v3v3(ebo->head, child->tail))
                                        ebo->flag |= BONE_CONNECTED;
                                else    
                                        ebo->flag &= ~BONE_CONNECTED;
@@ -3711,7 +3759,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *op)
        BLI_freelistN(&chains); 
 
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -3739,7 +3787,7 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot)
 static void bone_connect_to_existing_parent(EditBone *bone)
 {
        bone->flag |= BONE_CONNECTED;
-       VECCOPY(bone->head, bone->parent->tail);
+       copy_v3_v3(bone->head, bone->parent->tail);
        bone->rad_head = bone->parent->rad_tail;
 }
 
@@ -3765,12 +3813,12 @@ static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBo
        if (mode == ARM_PAR_CONNECT) {  
                /* Connected: Child bones will be moved to the parent tip */
                selbone->flag |= BONE_CONNECTED;
-               VecSubf(offset, actbone->tail, selbone->head);
+               sub_v3_v3v3(offset, actbone->tail, selbone->head);
                
-               VECCOPY(selbone->head, actbone->tail);
+               copy_v3_v3(selbone->head, actbone->tail);
                selbone->rad_head= actbone->rad_tail;
                
-               VecAddf(selbone->tail, selbone->tail, offset);
+               add_v3_v3(selbone->tail, offset);
                
                /* offset for all its children */
                for (ebone = edbo->first; ebone; ebone=ebone->next) {
@@ -3778,8 +3826,8 @@ static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBo
                        
                        for (par= ebone->parent; par; par= par->parent) {
                                if (par==selbone) {
-                                       VecAddf(ebone->head, ebone->head, offset);
-                                       VecAddf(ebone->tail, ebone->tail, offset);
+                                       add_v3_v3(ebone->head, offset);
+                                       add_v3_v3(ebone->tail, offset);
                                        break;
                                }
                        }
@@ -3860,12 +3908,12 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
        
 
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
        
        return OPERATOR_FINISHED;
 }
 
-static int armature_parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
 {
        EditBone *actbone = CTX_data_active_bone(C);
        uiPopupMenu *pup= uiPupMenuBegin(C, "Make Parent ", 0);
@@ -3879,11 +3927,11 @@ static int armature_parent_set_invoke(bContext *C, wmOperator *op, wmEvent *even
        }
        CTX_DATA_END;
 
-       uiItemEnumO(layout, NULL, 0, "ARMATURE_OT_parent_set", "type", ARM_PAR_CONNECT);
+       uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
        
        /* ob becomes parent, make the associated menus */
        if (allchildbones)
-               uiItemEnumO(layout, NULL, 0, "ARMATURE_OT_parent_set", "type", ARM_PAR_OFFSET); 
+               uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET); 
                
        uiPupMenuEnd(C, pup);
        
@@ -3938,7 +3986,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op)
        ED_armature_sync_selection(arm->edbo);
 
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -3957,18 +4005,20 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
-       RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
+       ot->prop= RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
 }
 
 /* ****************  Selections  ******************/
 
-static int armature_select_inverse_exec(bContext *C, wmOperator *op)
+static int armature_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
 {
        /*      Set the flags */
        CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
-               /* select bone */
-               ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
-               ebone->flag &= ~BONE_ACTIVE;
+               /* ignore bone if selection can't change */
+               if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+                       /* select bone */
+                       ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+               }
        }
        CTX_DATA_END;   
 
@@ -3979,7 +4029,6 @@ static int armature_select_inverse_exec(bContext *C, wmOperator *op)
 
 void ARMATURE_OT_select_inverse(wmOperatorType *ot)
 {
-       
        /* identifiers */
        ot->name= "Select Inverse";
        ot->idname= "ARMATURE_OT_select_inverse";
@@ -3994,23 +4043,39 @@ void ARMATURE_OT_select_inverse(wmOperatorType *ot)
 }
 static int armature_de_select_all_exec(bContext *C, wmOperator *op)
 {
-       int     sel=1;
+       int action = RNA_enum_get(op->ptr, "action");
 
-       /*      Determine if there are any selected bones
-       And therefore whether we are selecting or deselecting */
-       if (CTX_DATA_COUNT(C, selected_bones) > 0)      sel=0;
+       if (action == SEL_TOGGLE) {
+               action = SEL_SELECT;
+               /*      Determine if there are any selected bones
+               And therefore whether we are selecting or deselecting */
+               if (CTX_DATA_COUNT(C, selected_bones) > 0)
+                       action = SEL_DESELECT;
+       }
        
        /*      Set the flags */
        CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
-               if (sel==1) {
-                       /* select bone */
-                       ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
-                       if(ebone->parent)
-                               ebone->parent->flag |= (BONE_TIPSEL);
-               }
-               else {
-                       /* deselect bone */
-                       ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
+               /* ignore bone if selection can't change */
+               if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+                       switch (action) {
+                       case SEL_SELECT:
+                               ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+                               if(ebone->parent)
+                                       ebone->parent->flag |= (BONE_TIPSEL);
+                               break;
+                       case SEL_DESELECT:
+                               ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+                               break;
+                       case SEL_INVERT:
+                               if (ebone->flag & BONE_SELECTED) {
+                                       ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+                               } else {
+                                       ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+                                       if(ebone->parent)
+                                               ebone->parent->flag |= (BONE_TIPSEL);
+                               }
+                               break;
+                       }
                }
        }
        CTX_DATA_END;   
@@ -4020,12 +4085,12 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ARMATURE_OT_select_all_toggle(wmOperatorType *ot)
+void ARMATURE_OT_select_all(wmOperatorType *ot)
 {
        
        /* identifiers */
-       ot->name= "deselect all editbone";
-       ot->idname= "ARMATURE_OT_select_all_toggle";
+       ot->name= "Select or Deselect All";
+       ot->idname= "ARMATURE_OT_select_all";
        
        /* api callbacks */
        ot->exec= armature_de_select_all_exec;
@@ -4034,6 +4099,7 @@ void ARMATURE_OT_select_all_toggle(wmOperatorType *ot)
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
+       WM_operator_properties_select_all(ot);
 }
 
 /* ********************* select hierarchy operator ************** */
@@ -4051,18 +4117,19 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
        arm= (bArmature *)ob->data;
        
        for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
-               if (EBONE_VISIBLE(arm, curbone)) {
-                       if (curbone->flag & (BONE_ACTIVE)) {
+               /* only work on bone if it is visible and its selection can change */
+               if (EBONE_VISIBLE(arm, curbone) && (curbone->flag & BONE_UNSELECTABLE)==0) {
+                       if (curbone == arm->act_edbone) {
                                if (direction == BONE_SELECT_PARENT) {
                                        if (curbone->parent == NULL) continue;
                                        else pabone = curbone->parent;
                                        
                                        if (EBONE_VISIBLE(arm, pabone)) {
-                                               pabone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                               pabone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                               arm->act_edbone= pabone;
                                                if (pabone->parent)     pabone->parent->flag |= BONE_TIPSEL;
                                                
                                                if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
-                                               curbone->flag &= ~BONE_ACTIVE;
                                                break;
                                        }
                                        
@@ -4071,14 +4138,14 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
                                        chbone = editbone_get_child(arm, curbone, 1);
                                        if (chbone == NULL) continue;
                                        
-                                       if (EBONE_VISIBLE(arm, chbone)) {
-                                               chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                       if (EBONE_VISIBLE(arm, chbone) && (chbone->flag & BONE_UNSELECTABLE)==0) {
+                                               chbone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                               arm->act_edbone= chbone;
                                                
                                                if (!add_to_sel) {
                                                        curbone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL);
                                                        if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL;
                                                }
-                                               curbone->flag &= ~BONE_ACTIVE;
                                                break;
                                        }
                                }
@@ -4114,7 +4181,7 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
 
        /* props */
        RNA_def_enum(ot->srna, "direction", direction_items,
-                    BONE_SELECT_PARENT, "Direction", "");
+                        BONE_SELECT_PARENT, "Direction", "");
        RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
 }
 
@@ -4125,13 +4192,13 @@ static void fix_connected_bone(EditBone *ebone)
 {
        float diff[3];
        
-       if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || VecEqual(ebone->parent->tail, ebone->head))
+       if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || equals_v3v3(ebone->parent->tail, ebone->head))
                return;
        
        /* if the parent has moved we translate child's head and tail accordingly*/
-       VecSubf(diff, ebone->parent->tail, ebone->head);
-       VecAddf(ebone->head, ebone->head, diff);
-       VecAddf(ebone->tail, ebone->tail, diff);
+       sub_v3_v3v3(diff, ebone->parent->tail, ebone->head);
+       add_v3_v3(ebone->head, diff);
+       add_v3_v3(ebone->tail, diff);
        return;
 }
 
@@ -4153,14 +4220,14 @@ static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actb
 {
        float selboneaxis[3], actboneaxis[3], length;
 
-       VecSubf(actboneaxis, actbone->tail, actbone->head);
-       Normalize(actboneaxis);
+       sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head);
+       normalize_v3(actboneaxis);
 
-       VecSubf(selboneaxis, selbone->tail, selbone->head);
-       length =  VecLength(selboneaxis);
+       sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head);
+       length =  len_v3(selboneaxis);
 
-       VecMulf(actboneaxis, length);
-       VecAddf(selbone->tail, selbone->head, actboneaxis);
+       mul_v3_fl(actboneaxis, length);
+       add_v3_v3v3(selbone->tail, selbone->head, actboneaxis);
        selbone->roll = actbone->roll;
        
        /* if the bone being aligned has connected descendants they must be moved
@@ -4242,7 +4309,7 @@ void ARMATURE_OT_align(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Align Bones";
        ot->idname= "ARMATURE_OT_align";
-       ot->description= "Align selected bones to the active bone (or to their parent).";
+       ot->description= "Align selected bones to the active bone (or to their parent)";
        
        /* api callbacks */
        ot->invoke = WM_operator_confirm;
@@ -4255,40 +4322,32 @@ void ARMATURE_OT_align(wmOperatorType *ot)
 
 /* ***************** Pose tools ********************* */
 
-/* helper for function below */
-static int clear_active_flag(Object *ob, Bone *bone, void *data) 
-{
-       bone->flag &= ~BONE_ACTIVE;
-       return 0;
-}
-
-
 // XXX bone_looper is only to be used when we want to access settings (i.e. editability/visibility/selected) that context doesn't offer 
 static int bone_looper(Object *ob, Bone *bone, void *data,
                                int (*bone_func)(Object *, Bone *, void *)) 
 {
-    /* We want to apply the function bone_func to every bone 
+       /* We want to apply the function bone_func to every bone 
        * in an armature -- feed bone_looper the first bone and 
        * a pointer to the bone_func and watch it go!. The int count 
        * can be useful for counting bones with a certain property
        * (e.g. skinnable)
        */
-    int count = 0;
+       int count = 0;
        
-    if (bone) {
+       if (bone) {
                /* only do bone_func if the bone is non null */
-        count += bone_func(ob, bone, data);
+               count += bone_func(ob, bone, data);
                
                /* try to execute bone_func for the first child */
-        count += bone_looper(ob, bone->childbase.first, data, bone_func);
+               count += bone_looper(ob, bone->childbase.first, data, bone_func);
                
                /* try to execute bone_func for the next bone at this
                        * depth of the recursion.
                        */
-        count += bone_looper(ob, bone->next, data, bone_func);
-    }
+               count += bone_looper(ob, bone->next, data, bone_func);
+       }
        
-    return count;
+       return count;
 }
 
 /* called from editview.c, for mode-less pose selection */
@@ -4301,14 +4360,16 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
        if (!ob || !ob->pose) return 0;
 
        nearBone= get_bone_from_selectbuffer(scene, base, buffer, hits, 1);
-
-       if (nearBone) {
+       
+       /* if the bone cannot be affected, don't do anything */
+       if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
                bArmature *arm= ob->data;
                
                /* since we do unified select, we don't shift+select a bone if the armature object was not active yet */
                if (!(extend) || (base != scene->basact)) {
-                       ED_pose_deselectall(ob, 0, 0);
-                       nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+                       ED_pose_deselectall(ob, 0);
+                       nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                       arm->act_bone= nearBone;
                        
                                // XXX old cruft! use notifiers instead
                        //select_actionchannel_by_name(ob->action, nearBone->name, 1);
@@ -4316,21 +4377,19 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
                else {
                        if (nearBone->flag & BONE_SELECTED) {
                                /* if not active, we make it active */
-                               if((nearBone->flag & BONE_ACTIVE)==0) {
-                                       bone_looper(ob, arm->bonebase.first, NULL, clear_active_flag);
-                                       nearBone->flag |= BONE_ACTIVE;
+                               if(nearBone != arm->act_bone) {
+                                       arm->act_bone= nearBone;
                                }
                                else {
-                                       nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+                                       nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                                        
                                                // XXX old cruft! use notifiers instead
                                        //select_actionchannel_by_name(ob->action, nearBone->name, 0);
                                }
                        }
                        else {
-                               bone_looper(ob, arm->bonebase.first, NULL, clear_active_flag);
-                               
-                               nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+                               nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                               arm->act_bone= nearBone;
                                
                                        // XXX old cruft! use notifiers instead
                                //select_actionchannel_by_name(ob->action, nearBone->name, 1);
@@ -4339,7 +4398,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
                
                /* in weightpaint we select the associated vertex group too */
                if (OBACT && OBACT->mode & OB_MODE_WEIGHT_PAINT) {
-                       if (nearBone->flag & BONE_ACTIVE) {
+                       if (nearBone == arm->act_bone) {
                                ED_vgroup_select_by_name(OBACT, nearBone->name);
                                DAG_id_flush_update(&OBACT->id, OB_RECALC_DATA);
                        }
@@ -4355,7 +4414,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
    test==2: only clear active tag
    test==3: swap select (no test / inverse selection status of all independently)
 */
-void ED_pose_deselectall (Object *ob, int test, int doundo)
+void ED_pose_deselectall (Object *ob, int test)
 {
        bArmature *arm= ob->data;
        bPoseChannel *pchan;
@@ -4367,7 +4426,7 @@ void ED_pose_deselectall (Object *ob, int test, int doundo)
        /*      Determine if we're selecting or deselecting     */
        if (test==1) {
                for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-                       if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
+                       if (PBONE_VISIBLE(arm, pchan->bone)) {
                                if (pchan->bone->flag & BONE_SELECTED)
                                        break;
                        }
@@ -4381,51 +4440,46 @@ void ED_pose_deselectall (Object *ob, int test, int doundo)
        
        /*      Set the flags accordingly       */
        for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-               if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
+               /* ignore the pchan if it isn't visible or if its selection cannot be changed */
+               if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & (BONE_HIDDEN_P|BONE_UNSELECTABLE))) {
                        if (test==3) {
                                pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
-                               pchan->bone->flag &= ~BONE_ACTIVE;
                        }
                        else {
-                               if (selectmode==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+                               if (selectmode==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                                else if (selectmode==1) pchan->bone->flag |= BONE_SELECTED;
-                               else pchan->bone->flag &= ~BONE_ACTIVE;
                        }
                }
        }
        
-       //countall(); // XXX need an equivalent to this...
-       
-       if (doundo) {
-               if (selectmode==1) BIF_undo_push("Select All");
-               else BIF_undo_push("Deselect All");
-       }
+       if(arm->act_bone && (arm->act_bone->flag & BONE_SELECTED)==0)
+               arm->act_bone= NULL;
 }
 
-static int bone_skinnable(Object *ob, Bone *bone, void *datap)
+static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap)
 {
-    /* Bones that are deforming
-     * are regarded to be "skinnable" and are eligible for
-     * auto-skinning.
-     *
-     * This function performs 2 functions:
-     *
-     *   a) It returns 1 if the bone is skinnable.
-     *      If we loop over all bones with this 
-     *      function, we can count the number of
-     *      skinnable bones.
-     *   b) If the pointer data is non null,
-     *      it is treated like a handle to a
-     *      bone pointer -- the bone pointer
-     *      is set to point at this bone, and
-     *      the pointer the handle points to
-     *      is incremented to point to the
-     *      next member of an array of pointers
-     *      to bones. This way we can loop using
-     *      this function to construct an array of
-     *      pointers to bones that point to all
-     *      skinnable bones.
-     */
+       /* Bones that are deforming
+        * are regarded to be "skinnable" and are eligible for
+        * auto-skinning.
+        *
+        * This function performs 2 functions:
+        *
+        *   a) It returns 1 if the bone is skinnable.
+        *      If we loop over all bones with this 
+        *      function, we can count the number of
+        *      skinnable bones.
+        *   b) If the pointer data is non null,
+        *      it is treated like a handle to a
+        *      bone pointer -- the bone pointer
+        *      is set to point at this bone, and
+        *      the pointer the handle points to
+        *      is incremented to point to the
+        *      next member of an array of pointers
+        *      to bones. This way we can loop using
+        *      this function to construct an array of
+        *      pointers to bones that point to all
+        *      skinnable bones.
+        */
        Bone ***hbone;
        int a, segments;
        struct { Object *armob; void *list; int heat; } *data = datap;
@@ -4448,62 +4502,65 @@ static int bone_skinnable(Object *ob, Bone *bone, void *datap)
                        return segments;
                }
        }
-    return 0;
+       return 0;
 }
 
-static int ED_vgroup_add_unique_bone(Object *ob, Bone *bone, void *data
+static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)
 {
-    /* This group creates a vertex group to ob that has the
-      * same name as bone (provided the bone is skinnable). 
+       /* This group creates a vertex group to ob that has the
+         * same name as bone (provided the bone is skinnable). 
         * If such a vertex group aleady exist the routine exits.
-      */
+         */
        if (!(bone->flag & BONE_NO_DEFORM)) {
-               if (!get_named_vertexgroup(ob,bone->name)) {
+               if (!defgroup_find_name(ob,bone->name)) {
                        ED_vgroup_add_name(ob, bone->name);
                        return 1;
                }
-    }
-    return 0;
-}
-
-static int dgroup_skinnable(Object *ob, Bone *bone, void *datap) 
-{
-    /* Bones that are deforming
-     * are regarded to be "skinnable" and are eligible for
-     * auto-skinning.
-     *
-     * This function performs 2 functions:
-     *
-     *   a) If the bone is skinnable, it creates 
-     *      a vertex group for ob that has
-     *      the name of the skinnable bone
-     *      (if one doesn't exist already).
-     *   b) If the pointer data is non null,
-     *      it is treated like a handle to a
-     *      bDeformGroup pointer -- the 
-     *      bDeformGroup pointer is set to point
-     *      to the deform group with the bone's
-     *      name, and the pointer the handle 
-     *      points to is incremented to point to the
-     *      next member of an array of pointers
-     *      to bDeformGroups. This way we can loop using
-     *      this function to construct an array of
-     *      pointers to bDeformGroups, all with names
-     *      of skinnable bones.
-     */
-    bDeformGroup ***hgroup, *defgroup;
+       }
+       return 0;
+}
+
+static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap) 
+{
+       /* Bones that are deforming
+        * are regarded to be "skinnable" and are eligible for
+        * auto-skinning.
+        *
+        * This function performs 2 functions:
+        *
+        *   a) If the bone is skinnable, it creates 
+        *      a vertex group for ob that has
+        *      the name of the skinnable bone
+        *      (if one doesn't exist already).
+        *   b) If the pointer data is non null,
+        *      it is treated like a handle to a
+        *      bDeformGroup pointer -- the 
+        *      bDeformGroup pointer is set to point
+        *      to the deform group with the bone's
+        *      name, and the pointer the handle 
+        *      points to is incremented to point to the
+        *      next member of an array of pointers
+        *      to bDeformGroups. This way we can loop using
+        *      this function to construct an array of
+        *      pointers to bDeformGroups, all with names
+        *      of skinnable bones.
+        */
+       bDeformGroup ***hgroup, *defgroup= NULL;
        int a, segments;
        struct { Object *armob; void *list; int heat; } *data= datap;
+       int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
+       bArmature *arm= data->armob->data;
 
-       if (!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) {
+       if (!wpmode || !(bone->flag & BONE_HIDDEN_P)) {
           if (!(bone->flag & BONE_NO_DEFORM)) {
                        if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
                                segments = bone->segments;
                        else
                                segments = 1;
-                       
-                       if (!(defgroup = get_named_vertexgroup(ob, bone->name)))
-                               defgroup = ED_vgroup_add_name(ob, bone->name);
+
+                       if(!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED)))
+                               if (!(defgroup = defgroup_find_name(ob, bone->name)))
+                                       defgroup = ED_vgroup_add_name(ob, bone->name);
                        
                        if (data->list != NULL) {
                                hgroup = (bDeformGroup ***) &data->list;
@@ -4516,15 +4573,15 @@ static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
                        return segments;
                }
        }
-    return 0;
+       return 0;
 }
 
-static void add_vgroups__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+static void add_vgroups__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
 {
        /* DerivedMesh mapFunc for getting final coords in weight paint mode */
 
        float (*verts)[3] = userData;
-       VECCOPY(verts[index], co);
+       copy_v3_v3(verts[index], co);
 }
 
 static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, float scale)
@@ -4570,7 +4627,7 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
        }
 }
 
-void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int mirror)
+void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par, int heat, int mirror)
 {
        /* This functions implements the automatic computation of vertex group
         * weights, either through envelopes or using a heat equilibrium.
@@ -4587,7 +4644,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
        bArmature *arm= par->data;
        Bone **bonelist, *bone;
        bDeformGroup **dgrouplist, **dgroupflip;
-       bDeformGroup *dgroup, *curdg;
+       bDeformGroup *dgroup;
        bPoseChannel *pchan;
        Mesh *mesh;
        Mat4 *bbone = NULL;
@@ -4602,7 +4659,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
        looper_data.list= NULL;
 
        /* count the number of skinnable bones */
-       numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable);
+       numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
        
        if (numbones == 0)
                return;
@@ -4611,7 +4668,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
         * and fill it with all of the skinnable bones */
        bonelist = MEM_callocN(numbones*sizeof(Bone *), "bonelist");
        looper_data.list= bonelist;
-       bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable);
+       bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
 
        /* create an array of pointers to the deform groups that
         * coorespond to the skinnable bones (creating them
@@ -4620,7 +4677,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
        dgroupflip = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgroupflip");
 
        looper_data.list= dgrouplist;
-       bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable);
+       bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
 
        /* create an array of root and tip positions transformed into
         * global coords */
@@ -4629,7 +4686,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
        selected = MEM_callocN(numbones*sizeof(int), "selected");
 
        for (j=0; j < numbones; ++j) {
-               bone = bonelist[j];
+               bone = bonelist[j];
                dgroup = dgrouplist[j];
                
                /* handle bbone */
@@ -4651,22 +4708,21 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
                
                /* compute root and tip */
                if (bbone) {
-                       VECCOPY(root[j], bbone[segments].mat[3]);
-                       Mat4MulVecfl(bone->arm_mat, root[j]);
+                       mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
                        if ((segments+1) < bone->segments) {
-                               VECCOPY(tip[j], bbone[segments+1].mat[3])
-                               Mat4MulVecfl(bone->arm_mat, tip[j]);
+                               mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments+1].mat[3]);
+                       }
+                       else {
+                               copy_v3_v3(tip[j], bone->arm_tail);
                        }
-                       else
-                               VECCOPY(tip[j], bone->arm_tail)
                }
                else {
-                       VECCOPY(root[j], bone->arm_head);
-                       VECCOPY(tip[j], bone->arm_tail);
+                       copy_v3_v3(root[j], bone->arm_head);
+                       copy_v3_v3(tip[j], bone->arm_tail);
                }
                
-               Mat4MulVecfl(par->obmat, root[j]);
-               Mat4MulVecfl(par->obmat, tip[j]);
+               mul_m4_v3(par->obmat, root[j]);
+               mul_m4_v3(par->obmat, tip[j]);
                
                /* set selected */
                if (wpmode) {
@@ -4677,24 +4733,17 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
                        selected[j] = 1;
                
                /* find flipped group */
-               if (mirror) {
+               if (dgroup && mirror) {
                        char name[32];
-                       
-                       BLI_strncpy(name, dgroup->name, 32);
+
                        // 0 = don't strip off number extensions
-                       bone_flip_name(name, 0);
-                       
-                       for (curdg = ob->defbase.first; curdg; curdg=curdg->next) {
-                               if (!strcmp(curdg->name, name))
-                                       break;
-                       }
-                       
-                       dgroupflip[j] = curdg;
+                       flip_side_name(name, dgroup->name, FALSE);
+                       dgroupflip[j] = defgroup_find_name(ob, name);
                }
        }
 
        /* create verts */
-    mesh = (Mesh*)ob->data;
+       mesh = (Mesh*)ob->data;
        verts = MEM_callocN(mesh->totvert*sizeof(*verts), "closestboneverts");
 
        if (wpmode) {
@@ -4710,7 +4759,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
        }
        else if (modifiers_findByType(ob, eModifierType_Subsurf)) {
                /* is subsurf on? Lets use the verts on the limit surface then.
-                * = same amount of vertices as mesh, but vertices  moved to the
+                 * = same amount of vertices as mesh, but vertices  moved to the
                 * subsurfed position, like for 'optimal'. */
                subsurf_calculate_limit_positions(mesh, verts);
                vertsfilled = 1;
@@ -4719,23 +4768,31 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
        /* transform verts to global space */
        for (i=0; i < mesh->totvert; i++) {
                if (!vertsfilled)
-                       VECCOPY(verts[i], mesh->mvert[i].co)
-               Mat4MulVecfl(ob->obmat, verts[i]);
+                       copy_v3_v3(verts[i], mesh->mvert[i].co);
+               mul_m4_v3(ob->obmat, verts[i]);
        }
 
        /* compute the weights based on gathered vertices and bones */
        if (heat) {
+               const char *error= NULL;
                heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
-                       root, tip, selected);
+                       root, tip, selected, &error);
+               
+               if(error) {
+                       BKE_report(reports, RPT_WARNING, error);
+               }
        }
        else {
                envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist,
-                       dgroupflip, root, tip, selected, Mat4ToScalef(par->obmat));
+                       dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
        }
-       
-    /* free the memory allocated */
-    MEM_freeN(bonelist);
-    MEM_freeN(dgrouplist);
+
+       /* only generated in some cases but can call anyway */
+       mesh_octree_table(ob, NULL, NULL, 'e');
+
+       /* free the memory allocated */
+       MEM_freeN(bonelist);
+       MEM_freeN(dgrouplist);
        MEM_freeN(dgroupflip);
        MEM_freeN(root);
        MEM_freeN(tip);
@@ -4743,7 +4800,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
        MEM_freeN(verts);
 }
 
-void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par, int mode)
+void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par, int mode, int mirror)
 {
        /* Lets try to create some vertex groups 
         * based on the bones of the parent armature.
@@ -4754,7 +4811,7 @@ void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par, int mod
                /* Traverse the bone list, trying to create empty vertex 
                 * groups cooresponding to the bone.
                 */
-               bone_looper(ob, arm->bonebase.first, NULL, ED_vgroup_add_unique_bone);
+               bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
 
                if (ob->type == OB_MESH)
                        ED_vgroup_data_create(ob->data);
@@ -4764,17 +4821,19 @@ void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par, int mod
                 * that are populated with the vertices for which the
                 * bone is closest.
                 */
-               add_verts_to_dgroups(scene, ob, par, (mode == ARM_GROUPS_AUTO), 0);
+               add_verts_to_dgroups(reports, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
        }
 } 
 /* ************* Clear Pose *****************************/
 
-static int pose_clear_scale_exec(bContext *C, wmOperator *op
+static int pose_clear_scale_exec(bContext *C, wmOperator *UNUSED(op)
 {
-       Object *ob= CTX_data_active_object(C);
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
+       short autokey = 0;
        
        /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
+       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
                if ((pchan->protectflag & OB_LOCK_SCALEX)==0)
                        pchan->size[0]= 1.0f;
                if ((pchan->protectflag & OB_LOCK_SCALEY)==0)
@@ -4782,11 +4841,36 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *op)
                if ((pchan->protectflag & OB_LOCK_SCALEZ)==0)
                        pchan->size[2]= 1.0f;
                        
-               /* the current values from IPO's may not be zero, so tag as unkeyed */
-               //pchan->bone->flag |= BONE_UNKEYED;
+               /* do auto-keyframing as appropriate */
+               if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+                       /* clear any unkeyed tags */
+                       if (pchan->bone)
+                               pchan->bone->flag &= ~BONE_UNKEYED;
+                               
+                       /* tag for autokeying later */
+                       autokey = 1;
+               }
+               else {
+                       /* add unkeyed tags */
+                       if (pchan->bone)
+                               pchan->bone->flag |= BONE_UNKEYED;
+               }
        }
        CTX_DATA_END;
        
+       /* perform autokeying on the bones if needed */
+       if (autokey) {
+               /* get KeyingSet to use */
+               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Scaling");
+               
+               /* insert keyframes */
+               ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+               
+               /* now recalculate paths */
+               if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
+                       ED_pose_recalculate_paths(scene, ob);
+       }
+       
        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
@@ -4810,12 +4894,15 @@ void POSE_OT_scale_clear(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-static int pose_clear_loc_exec(bContext *C, wmOperator *op
+static int pose_clear_loc_exec(bContext *C, wmOperator *UNUSED(op)
 {
-       Object *ob= CTX_data_active_object(C);
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
+       short autokey = 0;
        
        /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
+       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
+               /* clear location */
                if ((pchan->protectflag & OB_LOCK_LOCX)==0)
                        pchan->loc[0]= 0.0f;
                if ((pchan->protectflag & OB_LOCK_LOCY)==0)
@@ -4823,11 +4910,36 @@ static int pose_clear_loc_exec(bContext *C, wmOperator *op)
                if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
                        pchan->loc[2]= 0.0f;
                        
-               /* the current values from IPO's may not be zero, so tag as unkeyed */
-               //pchan->bone->flag |= BONE_UNKEYED;
+               /* do auto-keyframing as appropriate */
+               if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+                       /* clear any unkeyed tags */
+                       if (pchan->bone)
+                               pchan->bone->flag &= ~BONE_UNKEYED;
+                               
+                       /* tag for autokeying later */
+                       autokey = 1;
+               }
+               else {
+                       /* add unkeyed tags */
+                       if (pchan->bone)
+                               pchan->bone->flag |= BONE_UNKEYED;
+               }
        }
        CTX_DATA_END;
        
+       /* perform autokeying on the bones if needed */
+       if (autokey) {
+               /* get KeyingSet to use */
+               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Location");
+               
+               /* insert keyframes */
+               ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+               
+               /* now recalculate paths */
+               if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
+                       ED_pose_recalculate_paths(scene, ob);
+       }
+       
        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
@@ -4851,38 +4963,65 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-static int pose_clear_rot_exec(bContext *C, wmOperator *op
+static int pose_clear_rot_exec(bContext *C, wmOperator *UNUSED(op)
 {
-       Object *ob= CTX_data_active_object(C);
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
+       short autokey = 0;
        
        /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
+       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
                if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
                        /* check if convert to eulers for locking... */
                        if (pchan->protectflag & OB_LOCK_ROT4D) {
                                /* perform clamping on a component by component basis */
-                               if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
-                                       pchan->quat[0]= (pchan->rotmode == ROT_MODE_AXISANGLE) ? 0.0f : 1.0f;
-                               if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
-                                       pchan->quat[1]= 0.0f;
-                               if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
-                                       pchan->quat[2]= 0.0f;
-                               if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
-                                       pchan->quat[3]= 0.0f;
+                               if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                                       if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+                                               pchan->rotAngle= 0.0f;
+                                       if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+                                               pchan->rotAxis[0]= 0.0f;
+                                       if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+                                               pchan->rotAxis[1]= 0.0f;
+                                       if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+                                               pchan->rotAxis[2]= 0.0f;
+                                               
+                                       /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
+                                       if (IS_EQ(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQ(pchan->rotAxis[1], pchan->rotAxis[2]))
+                                               pchan->rotAxis[1] = 1.0f;
+                               }
+                               else if (pchan->rotmode == ROT_MODE_QUAT) {
+                                       if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+                                               pchan->quat[0]= 1.0f;
+                                       if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+                                               pchan->quat[1]= 0.0f;
+                                       if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+                                               pchan->quat[2]= 0.0f;
+                                       if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+                                               pchan->quat[3]= 0.0f;
+                               }
+                               else {
+                                       /* the flag may have been set for the other modes, so just ignore the extra flag... */
+                                       if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+                                               pchan->eul[0]= 0.0f;
+                                       if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+                                               pchan->eul[1]= 0.0f;
+                                       if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+                                               pchan->eul[2]= 0.0f;
+                               }
                        }
                        else {
                                /* perform clamping using euler form (3-components) */
-                               float eul[3], oldeul[3], quat1[4];
+                               float eul[3], oldeul[3], quat1[4] = {0};
                                
                                if (pchan->rotmode == ROT_MODE_QUAT) {
-                                       QUATCOPY(quat1, pchan->quat);
-                                       QuatToEul(pchan->quat, oldeul);
+                                       copy_qt_qt(quat1, pchan->quat);
+                                       quat_to_eul( oldeul,pchan->quat);
                                }
                                else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                                       AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
+                                       axis_angle_to_eulO( oldeul, EULER_ORDER_DEFAULT,pchan->rotAxis, pchan->rotAngle);
                                }
                                else {
-                                       VECCOPY(oldeul, pchan->eul);
+                                       copy_v3_v3(oldeul, pchan->eul);
                                }
                                
                                eul[0]= eul[1]= eul[2]= 0.0f;
@@ -4895,20 +5034,20 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
                                        eul[2]= oldeul[2];
                                
                                if (pchan->rotmode == ROT_MODE_QUAT) {
-                                       EulToQuat(eul, pchan->quat);
+                                       eul_to_quat( pchan->quat,eul);
                                        /* quaternions flip w sign to accumulate rotations correctly */
                                        if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
-                                               QuatMulf(pchan->quat, -1.0f);
+                                               mul_qt_fl(pchan->quat, -1.0f);
                                        }
                                }
                                else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                                       AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
+                                       eulO_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,eul, EULER_ORDER_DEFAULT);
                                }
                                else {
-                                       VECCOPY(pchan->eul, eul);
+                                       copy_v3_v3(pchan->eul, eul);
                                }
                        }
-               }                                               
+               }                                               // Duplicated in source/blender/editors/object/object_transform.c
                else { 
                        if (pchan->rotmode == ROT_MODE_QUAT) {
                                pchan->quat[1]=pchan->quat[2]=pchan->quat[3]= 0.0f; 
@@ -4916,19 +5055,44 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
                        }
                        else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
                                /* by default, make rotation of 0 radians around y-axis (roll) */
-                               pchan->quat[0]=pchan->quat[1]=pchan->quat[3]= 0.0f;
-                               pchan->quat[2]= 1.0f;
+                               pchan->rotAxis[0]=pchan->rotAxis[2]=pchan->rotAngle= 0.0f;
+                               pchan->rotAxis[1]= 1.0f;
                        }
                        else {
                                pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f;
                        }
                }
                
-               /* the current values from IPO's may not be zero, so tag as unkeyed */
-               //pchan->bone->flag |= BONE_UNKEYED;
+               /* do auto-keyframing as appropriate */
+               if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+                       /* clear any unkeyed tags */
+                       if (pchan->bone)
+                               pchan->bone->flag &= ~BONE_UNKEYED;
+                               
+                       /* tag for autokeying later */
+                       autokey = 1;
+               }
+               else {
+                       /* add unkeyed tags */
+                       if (pchan->bone)
+                               pchan->bone->flag |= BONE_UNKEYED;
+               }
        }
        CTX_DATA_END;
        
+       /* perform autokeying on the bones if needed */
+       if (autokey) {
+               /* get KeyingSet to use */
+               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Rotation");
+               
+               /* insert keyframes */
+               ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+               
+               /* now recalculate paths */
+               if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
+                       ED_pose_recalculate_paths(scene, ob);
+       }
+       
        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
@@ -4955,13 +5119,15 @@ void POSE_OT_rot_clear(wmOperatorType *ot)
 
 /* ***************** selections ********************** */
 
-static int pose_select_inverse_exec(bContext *C, wmOperator *op)
+static int pose_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
 {
        
        /*      Set the flags */
-       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) {
-               pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
-               pchan->bone->flag &= ~BONE_ACTIVE;
+       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 
+       {
+               if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+                       pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+               }
        }       
        CTX_DATA_END;
        
@@ -4987,31 +5153,58 @@ void POSE_OT_select_inverse(wmOperatorType *ot)
 }
 static int pose_de_select_all_exec(bContext *C, wmOperator *op)
 {
-       int     sel=1;
+       int action = RNA_enum_get(op->ptr, "action");
 
-       /*      Determine if there are any selected bones
-       And therefore whether we are selecting or deselecting */
-       if (CTX_DATA_COUNT(C, selected_pchans) > 0)     sel=0;
+       if (action == SEL_TOGGLE) {
+               bPoseChannel *pchan= CTX_data_active_pose_bone(C);
+               int num_sel = CTX_DATA_COUNT(C, selected_pose_bones);
+               
+               /* cases for deselect:
+                *      1) there's only one bone selected, and that is the active one
+                *      2) there's more than one bone selected
+                */
+               if ( ((num_sel == 1) && (pchan) && (pchan->bone->flag & BONE_SELECTED)) ||
+                        (num_sel > 1) )
+               {
+                       action = SEL_DESELECT;
+               }
+               else 
+                       action = SEL_SELECT;
+       }
        
        /*      Set the flags */
-       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) {
-               /* select pchan */
-               if (sel==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
-               else pchan->bone->flag |= BONE_SELECTED;
+       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) {
+               /* select pchan only if selectable, but deselect works always */
+               switch (action) {
+               case SEL_SELECT:
+                       if ((pchan->bone->flag & BONE_UNSELECTABLE)==0)
+                               pchan->bone->flag |= BONE_SELECTED;
+                       break;
+               case SEL_DESELECT:
+                       pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                       break;
+               case SEL_INVERT:
+                       if (pchan->bone->flag & BONE_SELECTED) {
+                               pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                       } else if ((pchan->bone->flag & BONE_UNSELECTABLE)==0) {
+                                       pchan->bone->flag |= BONE_SELECTED;
+                       }
+                       break;
+               }
        }
-       CTX_DATA_END;   
+       CTX_DATA_END;
 
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-void POSE_OT_select_all_toggle(wmOperatorType *ot)
+void POSE_OT_select_all(wmOperatorType *ot)
 {
        
        /* identifiers */
-       ot->name= "deselect all bones";
-       ot->idname= "POSE_OT_select_all_toggle";
+       ot->name= "Select or Deselect All";
+       ot->idname= "POSE_OT_select_all";
        
        /* api callbacks */
        ot->exec= pose_de_select_all_exec;
@@ -5020,21 +5213,22 @@ void POSE_OT_select_all_toggle(wmOperatorType *ot)
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
+       WM_operator_properties_select_all(ot);
 }
 
-static int pose_select_parent_exec(bContext *C, wmOperator *op)
+static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
 {
-       Object *ob= CTX_data_active_object(C);
+       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
        bPoseChannel *pchan,*parent;
 
        /*      Determine if there is an active bone */
-       pchan=CTX_data_active_pchan(C);
+       pchan=CTX_data_active_pose_bone(C);
        if (pchan) {
+               bArmature *arm= ob->data;
                parent=pchan->parent;
-               if ((parent) && !(parent->bone->flag & BONE_HIDDEN_P)) {
+               if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P|BONE_UNSELECTABLE))) {
                        parent->bone->flag |= BONE_SELECTED;
-                       parent->bone->flag |= BONE_ACTIVE;
-                       pchan->bone->flag &= ~BONE_ACTIVE;
+                       arm->act_bone= parent->bone;
                }
                else {
                        return OPERATOR_CANCELLED;
@@ -5066,28 +5260,31 @@ void POSE_OT_select_parent(wmOperatorType *ot)
 
 /* ************* hide/unhide pose bones ******************* */
 
-static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr
+static int hide_selected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)
 {
        bArmature *arm= ob->data;
        
        if (arm->layer & bone->layer) {
                if (bone->flag & BONE_SELECTED) {
                        bone->flag |= BONE_HIDDEN_P;
-                       bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE);
+                       bone->flag &= ~BONE_SELECTED;
+                       if(arm->act_bone==bone)
+                               arm->act_bone= NULL;
                }
        }
        return 0;
 }
 
-static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr
+static int hide_unselected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)
 {
        bArmature *arm= ob->data;
        
        if (arm->layer & bone->layer) {
                // hrm... typo here?
-               if (~bone->flag & BONE_SELECTED) {
+               if ((bone->flag & BONE_SELECTED)==0) {
                        bone->flag |= BONE_HIDDEN_P;
-                       bone->flag &= ~BONE_ACTIVE;
+                       if(arm->act_bone==bone)
+                               arm->act_bone= NULL;
                }
        }
        return 0;
@@ -5096,15 +5293,13 @@ static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr)
 /* active object is armature in posemode, poll checked */
 static int pose_hide_exec(bContext *C, wmOperator *op) 
 {
-       Object *ob= CTX_data_active_object(C);
+       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
        bArmature *arm= ob->data;
 
        if(RNA_boolean_get(op->ptr, "unselected"))
-          bone_looper(ob, arm->bonebase.first, NULL, 
-                               hide_unselected_pose_bone);
+          bone_looper(ob, arm->bonebase.first, NULL, hide_unselected_pose_bone_cb);
        else
-          bone_looper(ob, arm->bonebase.first, NULL, 
-                                  hide_selected_pose_bone);
+          bone_looper(ob, arm->bonebase.first, NULL, hide_selected_pose_bone_cb);
        
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
@@ -5129,7 +5324,7 @@ void POSE_OT_hide(wmOperatorType *ot)
        RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
 }
 
-static int show_pose_bone(Object *ob, Bone *bone, void *ptr
+static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)
 {
        bArmature *arm= ob->data;
        
@@ -5144,12 +5339,12 @@ static int show_pose_bone(Object *ob, Bone *bone, void *ptr)
 }
 
 /* active object is armature in posemode, poll checked */
-static int pose_reveal_exec(bContext *C, wmOperator *op
+static int pose_reveal_exec(bContext *C, wmOperator *UNUSED(op)
 {
-       Object *ob= CTX_data_active_object(C);
+       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
        bArmature *arm= ob->data;
        
-       bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone);
+       bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone_cb);
        
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
@@ -5173,33 +5368,17 @@ void POSE_OT_reveal(wmOperatorType *ot)
 
 /* ************* RENAMING DISASTERS ************ */
 
-/* note: there's a unique_editbone_name() too! */
-void unique_bone_name (bArmature *arm, char *name)
+static int bone_unique_check(void *arg, const char *name)
 {
-       char            tempname[64];
-       int                     number;
-       char            *dot;
-       
-       if (get_named_bone(arm, name)) {
-               
-               /*      Strip off the suffix, if it's a number */
-               number= strlen(name);
-               if(number && isdigit(name[number-1])) {
-                       dot= strrchr(name, '.');        // last occurrance
-                       if (dot)
-                               *dot=0;
-               }
-               
-               for (number = 1; number <=999; number++) {
-                       sprintf (tempname, "%s.%03d", name, number);
-                       if (!get_named_bone(arm, tempname)) {
-                               BLI_strncpy (name, tempname, 32);
-                               return;
-                       }
-               }
-       }
+       return get_named_bone((bArmature *)arg, name) != NULL;
+}
+
+void unique_bone_name(bArmature *arm, char *name)
+{
+       BLI_uniquename_cb(bone_unique_check, (void *)arm, "Bone", '.', name, sizeof(((Bone *)NULL)->name));
 }
 
+
 #define MAXBONENAME 32
 /* helper call for armature_bone_rename */
 static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldname, char *newname)
@@ -5246,9 +5425,8 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
                
                /* now check if we're in editmode, we need to find the unique name */
                if (arm->edbo) {
-                       EditBone        *eBone;
+                       EditBone *eBone= editbone_name_exists(arm->edbo, oldname);
                        
-                       eBone= editbone_name_exists(arm->edbo, oldname);
                        if (eBone) {
                                unique_editbone_name(arm->edbo, newname, NULL);
                                BLI_strncpy(eBone->name, newname, MAXBONENAME);
@@ -5259,7 +5437,7 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
                        Bone *bone= get_named_bone(arm, oldname);
                        
                        if (bone) {
-                               unique_bone_name (arm, newname);
+                               unique_bone_name(arm, newname);
                                BLI_strncpy(bone->name, newname, MAXBONENAME);
                        }
                        else return;
@@ -5267,44 +5445,27 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
                
                /* do entire dbase - objects */
                for (ob= G.main->object.first; ob; ob= ob->id.next) {
+                       ModifierData *md;
+                       
                        /* we have the object using the armature */
                        if (arm==ob->data) {
                                Object *cob;
-                               //bAction  *act;
-                               //bActionChannel *achan;
-                               //bActionStrip *strip;
                                
-                               /* Rename action channel if necessary */
-#if 0 // XXX old animation system
-                               act = ob->action;
-                               if (act && !act->id.lib) {
-                                       /*      Find the appropriate channel */
-                                       achan= get_action_channel(act, oldname);
-                                       if (achan) 
-                                               BLI_strncpy(achan->name, newname, MAXBONENAME);
-                               }
-#endif // XXX old animation system
-               
                                /* Rename the pose channel, if it exists */
                                if (ob->pose) {
                                        bPoseChannel *pchan = get_pose_channel(ob->pose, oldname);
-                                       if (pchan)
+                                       if (pchan) {
                                                BLI_strncpy(pchan->name, newname, MAXBONENAME);
-                               }
-                               
-                               /* check all nla-strips too */
-#if 0 // XXX old animation system
-                               for (strip= ob->nlastrips.first; strip; strip= strip->next) {
-                                       /* Rename action channel if necessary */
-                                       act = strip->act;
-                                       if (act && !act->id.lib) {
-                                               /*      Find the appropriate channel */
-                                               achan= get_action_channel(act, oldname);
-                                               if (achan) 
-                                                       BLI_strncpy(achan->name, newname, MAXBONENAME);
+                                               
+                                               if (ob->pose->chanhash) {
+                                                       GHash *gh = ob->pose->chanhash;
+                                                       
+                                                       /* remove the old hash entry, and replace with the new name */
+                                                       BLI_ghash_remove(gh, oldname, NULL, NULL);
+                                                       BLI_ghash_insert(gh, pchan->name, pchan);
+                                               }
                                        }
                                }
-#endif // XXX old animation system
                                
                                /* Update any object constraints to use the new bone name */
                                for (cob= G.main->object.first; cob; cob= cob->id.next) {
@@ -5329,43 +5490,37 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
                        }
                        
                        if (modifiers_usesArmature(ob, arm)) { 
-                               bDeformGroup *dg;
-                               /* bone name in defgroup */
-                               for (dg=ob->defbase.first; dg; dg=dg->next) {
-                                       if (!strcmp(dg->name, oldname))
-                                          BLI_strncpy(dg->name, newname, MAXBONENAME);
+                               bDeformGroup *dg= defgroup_find_name(ob, oldname);
+                               if(dg) {
+                                       BLI_strncpy(dg->name, newname, MAXBONENAME);
                                }
                        }
-               }
-               
-               /* do entire db - ipo's for the drivers */
-#if 0 // XXX old animation system
-               for (ipo= G.main->ipo.first; ipo; ipo= ipo->id.next) {
-                       IpoCurve *icu;
                        
-                       /* check each curve's driver */
-                       for (icu= ipo->curve.first; icu; icu= icu->next) {
-                               IpoDriver *icd= icu->driver;
-                               
-                               if ((icd) && (icd->ob)) {
-                                       ob= icd->ob;
+                       /* fix modifiers that might be using this name */
+                       for (md= ob->modifiers.first; md; md= md->next) {
+                               if (md->type == eModifierType_Hook) {
+                                       HookModifierData *hmd = (HookModifierData *)md;
                                        
-                                       if (icu->driver->type == IPO_DRIVER_TYPE_NORMAL) {
-                                               if (!strcmp(oldname, icd->name))
-                                                       BLI_strncpy(icd->name, newname, MAXBONENAME);
-                                       }
-                                       else {
-                                               /* TODO: pydrivers need to be treated differently */
+                                       /* uses armature, so may use the affected bone name */
+                                       if (hmd->object && (hmd->object->data == arm)) {
+                                               if (!strcmp(hmd->subtarget, oldname))
+                                                       BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
                                        }
                                }
-                       }                       
+                       }
+                       
+                       /* Fix animation data attached to this object */
+                       // TODO: should we be using the database wide version instead (since drivers may break)
+                       if (ob->adt) {
+                               /* posechannels only... */
+                               BKE_animdata_fix_paths_rename(&ob->id, ob->adt, "pose.bones", oldname, newname, 0, 0, 1);
+                       }
                }
-#endif // XXX old animation system
        }
 }
 
 
-static int armature_flip_names_exec (bContext *C, wmOperator *op)
+static int armature_flip_names_exec (bContext *C, wmOperator *UNUSED(op))
 {
        Object *ob= CTX_data_edit_object(C);
        bArmature *arm;
@@ -5379,8 +5534,7 @@ static int armature_flip_names_exec (bContext *C, wmOperator *op)
        /* loop through selected bones, auto-naming them */
        CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
        {
-               BLI_strncpy(newname, ebone->name, sizeof(newname));
-               bone_flip_name(newname, 1);             // 1 = do strip off number extensions
+               flip_side_name(newname, ebone->name, TRUE); // 1 = do strip off number extensions
                ED_armature_bone_rename(arm, ebone->name, newname);
        }
        CTX_DATA_END;
@@ -5399,7 +5553,7 @@ void ARMATURE_OT_flip_names (wmOperatorType *ot)
        /* identifiers */
        ot->name= "Flip Names";
        ot->idname= "ARMATURE_OT_flip_names";
-       ot->description= "Flips (and corrects) the names of selected bones.";
+       ot->description= "Flips (and corrects) the names of selected bones";
        
        /* api callbacks */
        ot->exec= armature_flip_names_exec;
@@ -5426,8 +5580,8 @@ static int armature_autoside_names_exec (bContext *C, wmOperator *op)
        CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
        {
                BLI_strncpy(newname, ebone->name, sizeof(newname));
-               bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]);
-               ED_armature_bone_rename(arm, ebone->name, newname);
+               if(bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]))
+                       ED_armature_bone_rename(arm, ebone->name, newname);
        }
        CTX_DATA_END;
        
@@ -5443,7 +5597,7 @@ static int armature_autoside_names_exec (bContext *C, wmOperator *op)
 void ARMATURE_OT_autoside_names (wmOperatorType *ot)
 {
        static EnumPropertyItem axis_items[]= {
-               {0, "XAXIS", 0, "X-Axis", "Left/Right"},
+                {0, "XAXIS", 0, "X-Axis", "Left/Right"},
                {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
                {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
                {0, NULL, 0, NULL, NULL}};
@@ -5451,7 +5605,7 @@ void ARMATURE_OT_autoside_names (wmOperatorType *ot)
        /* identifiers */
        ot->name= "AutoName by Axis";
        ot->idname= "ARMATURE_OT_autoside_names";
-       ot->description= "Automatically renames the selected bones according to which side of the target axis they fall on.";
+       ot->description= "Automatically renames the selected bones according to which side of the target axis they fall on";
        
        /* api callbacks */
        ot->invoke= WM_menu_invoke;
@@ -5462,7 +5616,7 @@ void ARMATURE_OT_autoside_names (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* settings */
-       RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with.");
+       ot->prop= RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with.");
 }
 
 
@@ -5488,11 +5642,12 @@ void transform_armature_mirror_update(Object *obedit)
                                        eboflip->tail[1]= ebo->tail[1];
                                        eboflip->tail[2]= ebo->tail[2];
                                        eboflip->rad_tail= ebo->rad_tail;
+                                       eboflip->roll= -ebo->roll;
 
                                        /* Also move connected children, in case children's name aren't mirrored properly */
                                        for (children=arm->edbo->first; children; children=children->next) {
                                                if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
-                                                       VECCOPY(children->head, eboflip->tail);
+                                                       copy_v3_v3(children->head, eboflip->tail);
                                                        children->rad_head = ebo->rad_tail;
                                                }
                                        }
@@ -5502,12 +5657,13 @@ void transform_armature_mirror_update(Object *obedit)
                                        eboflip->head[1]= ebo->head[1];
                                        eboflip->head[2]= ebo->head[2];
                                        eboflip->rad_head= ebo->rad_head;
+                                       eboflip->roll= -ebo->roll;
                                        
                                        /* Also move connected parent, in case parent's name isn't mirrored properly */
                                        if (eboflip->parent && eboflip->flag & BONE_CONNECTED)
                                        {
                                                EditBone *parent = eboflip->parent;
-                                               VECCOPY(parent->tail, eboflip->head);
+                                               copy_v3_v3(parent->tail, eboflip->head);
                                                parent->rad_tail = ebo->rad_head;
                                        }
                                }
@@ -5546,9 +5702,9 @@ EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode
                EditBone *root = NULL;
                float angleLimit = (float)cos(scene->toolsettings->skgen_angle_limit * M_PI / 180.0f);
                
-               parent = add_editbone(obedit, "Bone");
+               parent = ED_armature_edit_bone_add(arm, "Bone");
                parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-               VECCOPY(parent->head, head->p);
+               copy_v3_v3(parent->head, head->p);
                
                root = parent;
                
@@ -5565,32 +5721,33 @@ EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode
                        
                        current = iter->p;
 
-                       VecSubf(vec1, previous, parent->head);
-                       VecSubf(vec2, current, previous);
+                       sub_v3_v3v3(vec1, previous, parent->head);
+                       sub_v3_v3v3(vec2, current, previous);
 
-                       len1 = Normalize(vec1);
-                       len2 = Normalize(vec2);
+                       len1 = normalize_v3(vec1);
+                       len2 = normalize_v3(vec2);
 
-                       if (len1 > 0.0f && len2 > 0.0f && Inpf(vec1, vec2) < angleLimit)
+                       if (len1 > 0.0f && len2 > 0.0f && dot_v3v3(vec1, vec2) < angleLimit)
                        {
-                               VECCOPY(parent->tail, previous);
+                               copy_v3_v3(parent->tail, previous);
 
-                               child = add_editbone(obedit, "Bone");
-                               VECCOPY(child->head, parent->tail);
+                               child = ED_armature_edit_bone_add(arm, "Bone");
+                               copy_v3_v3(child->head, parent->tail);
                                child->parent = parent;
                                child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
                                
                                parent = child; /* new child is next parent */
                        }
                }
-               VECCOPY(parent->tail, tail->p);
+               copy_v3_v3(parent->tail, tail->p);
                
                /* If the bone wasn't subdivided, delete it and return NULL
                 * to let subsequent subdivision methods do their thing. 
                 * */
                if (parent == root)
                {
-                       delete_bone(arm->edbo, parent);
+                       if(parent==arm->act_edbone) arm->act_edbone= NULL;
+                       ED_armature_edit_bone_remove(arm, parent);
                        parent = NULL;
                }
                
@@ -5622,7 +5779,7 @@ EditBone * test_subdivideByCorrelation(Scene *scene, Object *obedit, ReebArc *ar
                lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
        }
        
-       return lastBone;
+         return lastBone;
 }
 
 float arcLengthRatio(ReebArc *arc)
@@ -5631,18 +5788,18 @@ float arcLengthRatio(ReebArc *arc)
        float embedLength = 0.0f;
        int i;
        
-       arcLength = VecLenf(arc->head->p, arc->tail->p);
+       arcLength = len_v3v3(arc->head->p, arc->tail->p);
        
        if (arc->bcount > 0)
        {
                /* Add the embedding */
                for ( i = 1; i < arc->bcount; i++)
                {
-                       embedLength += VecLenf(arc->buckets[i - 1].p, arc->buckets[i].p);
+                       embedLength += len_v3v3(arc->buckets[i - 1].p, arc->buckets[i].p);
                }
                /* Add head and tail -> embedding vectors */
-               embedLength += VecLenf(arc->head->p, arc->buckets[0].p);
-               embedLength += VecLenf(arc->tail->p, arc->buckets[arc->bcount - 1].p);
+               embedLength += len_v3v3(arc->head->p, arc->buckets[0].p);
+               embedLength += len_v3v3(arc->tail->p, arc->buckets[arc->bcount - 1].p);
        }
        else
        {
@@ -5697,19 +5854,19 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
        }
        
        dst = add_object(scene, OB_ARMATURE);
-       ED_object_base_init_from_view(NULL, scene->basact);     // XXX NULL is C
+       ED_object_base_init_transform(NULL, scene->basact, NULL, NULL);         // XXX NULL is C, loc, rot
        obedit= scene->basact->object;
        
        /* Copy orientation from source */
-       VECCOPY(dst->loc, src->obmat[3]);
-       Mat4ToEul(src->obmat, dst->rot);
-       Mat4ToSize(src->obmat, dst->size);
+       copy_v3_v3(dst->loc, src->obmat[3]);
+       mat4_to_eul( dst->rot,src->obmat);
+       mat4_to_size( dst->size,src->obmat);
        
        where_is_object(scene, obedit);
        
        ED_armature_to_edit(obedit);
 
-       arcBoneMap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+       arcBoneMap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "SkeletonFromReebGraph gh");
        
        BLI_markdownSymmetry((BGraph*)rg, rg->nodes.first, scene->toolsettings->skgen_symmetry_limit);
        
@@ -5780,11 +5937,11 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
                if (lastBone == NULL)
                {
                        EditBone        *bone;
-                       bone = add_editbone(obedit, "Bone");
+                       bone = ED_armature_edit_bone_add(obedit->data, "Bone");
                        bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
                        
-                       VECCOPY(bone->head, head->p);
-                       VECCOPY(bone->tail, tail->p);
+                       copy_v3_v3(bone->head, head->p);
+                       copy_v3_v3(bone->tail, tail->p);
                        
                        /* set first and last bone, since there's only one */
                        lastBone = bone;
@@ -5848,8 +6005,6 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
        }
        
        BLI_ghash_free(arcBoneMap, NULL, NULL);
-       
-       BIF_undo_push("Generate Skeleton");
 }
 
 void generateSkeleton(Scene *scene)