converted more mixed tab/space indentations to tabs. only whitespace changes.
[blender.git] / source / blender / editors / armature / editarmature.c
index 3b5c07a..23f91f8 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/armature/editarmature.c
+ *  \ingroup edarmature
+ */
+
+
 #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_anim_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_scene_types.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
+#include "BLI_utildefines.h"
 #include "BLI_editVert.h"
 #include "BLI_ghash.h"
 
 #include "BKE_object.h"
 #include "BKE_report.h"
 #include "BKE_subsurf.h"
-#include "BKE_utildefines.h"
 #include "BKE_modifier.h"
+#include "DNA_object_types.h"
 
 #include "BIF_gl.h"
-#include "BIF_generate.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -79,6 +87,7 @@
 #include "ED_view3d.h"
 
 #include "UI_interface.h"
+#include "UI_resources.h"
 
 #include "armature_intern.h"
 #include "meshlaplacian.h"
 #include "reeb.h"
 #endif
 
-/* ************* XXX *************** */
-static void BIF_undo_push(const char *msg) {}
-/* ************* XXX *************** */
-
 /* **************** tools on Editmode Armature **************** */
 
 /* Sync selection to parent for connected children */
@@ -121,7 +126,7 @@ 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)
+               if(ebone->flag & BONE_HIDDEN_A)
                        arm->act_edbone= NULL;
        }
 }
@@ -154,6 +159,91 @@ void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
        bone_free(arm, exBone);
 }
 
+/* context: editmode armature */
+EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
+{
+       EditBone *eboflip= NULL;
+       char name[32];
+       
+       if (ebo == NULL)
+               return NULL;
+       
+       flip_side_name(name, ebo->name, FALSE);
+       
+       for (eboflip= edbo->first; eboflip; eboflip=eboflip->next) {
+               if (ebo != eboflip) {
+                       if (!strcmp (name, eboflip->name)) 
+                               break;
+               }
+       }
+       
+       return eboflip;
+}
+
+/* helper function for tools to work on mirrored parts.
+   it leaves mirrored bones selected then too, which is a good indication of what happened */
+static void armature_select_mirrored(bArmature *arm)
+{
+       /* Select mirrored bones */
+       if (arm->flag & ARM_MIRROR_EDIT) {
+               EditBone *curBone, *ebone_mirr;
+               
+               for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
+                       if (arm->layer & curBone->layer) {
+                               if (curBone->flag & BONE_SELECTED) {
+                                       ebone_mirr= ED_armature_bone_get_mirrored(arm->edbo, curBone);
+                                       if (ebone_mirr)
+                                               ebone_mirr->flag |= BONE_SELECTED;
+                               }
+                       }
+               }
+       }
+       
+}
+
+static void armature_tag_select_mirrored(bArmature *arm)
+{
+       EditBone *curBone;
+
+       /* always untag */
+       for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
+               curBone->flag &= ~BONE_DONE;
+       }
+
+       /* Select mirrored bones */
+       if (arm->flag & ARM_MIRROR_EDIT) {
+               for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
+                       if (arm->layer & curBone->layer) {
+                               if (curBone->flag & (BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL)) {
+                                       EditBone *ebone_mirr= ED_armature_bone_get_mirrored(arm->edbo, curBone);
+                                       if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
+                                               ebone_mirr->flag |= BONE_DONE;
+                                       }
+                               }
+                       }
+               }
+
+               for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
+                       if (curBone->flag & BONE_DONE) {
+                               EditBone *ebone_mirr= ED_armature_bone_get_mirrored(arm->edbo, curBone);
+                               curBone->flag |= ebone_mirr->flag & (BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL);
+                       }
+               }
+       }
+}
+
+
+/* only works when tagged */
+static void armature_tag_unselect(bArmature *arm)
+{
+       EditBone *curBone;
+
+       for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
+               if (curBone->flag & BONE_DONE) {
+                       curBone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_DONE);
+               }
+       }
+}
 
 /* converts Bones to EditBone list, used for tools as well */
 EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone)
@@ -162,46 +252,48 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
        EditBone        *eBoneAct= NULL;
        EditBone        *eBoneTest= NULL;
        Bone            *curBone;
-       float delta[3];
-       float premat[3][3];
-       float postmat[3][3];
-       float imat[3][3];
-       float difmat[3][3];
                
        for (curBone=bones->first; curBone; curBone=curBone->next) {
                eBone= MEM_callocN(sizeof(EditBone), "make_editbone");
                
                /*      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);                
-               
-               eBone->roll= 0.0f;
-               
-               /* roll fixing */
-               sub_v3_v3v3(delta, eBone->tail, eBone->head);
-               vec_roll_to_mat3(delta, 0.0f, postmat);
-               
-               copy_m3_m4(premat, curBone->arm_mat);
-               
-               invert_m3_m3(imat, postmat);
-               mul_m3_m3m3(difmat, imat, premat);
-               
-               eBone->roll = (float)atan2(difmat[2][0], difmat[2][2]);
+               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 = curBone->arm_roll;
                
                /* rest of stuff copy */
                eBone->length= curBone->length;
@@ -316,13 +408,17 @@ 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));
+               copy_v3_v3(newBone->arm_head, eBone->head);
+               copy_v3_v3(newBone->arm_tail, eBone->tail);
+               newBone->arm_roll = eBone->roll;
+               
                newBone->flag= eBone->flag;
                
                if (eBone == arm->act_edbone) {
-                       newBone->flag |= BONE_SELECTED; /* important, editbones can be active with only 1 point selected */
+                       /* don't change active selection, this messes up separate which uses
+                        * editmode toggle and can separate active bone which is de-selected originally */
+                       /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */
                        arm->act_edbone= NULL;
                        arm->act_bone= newBone;
                }
@@ -353,7 +449,6 @@ void ED_armature_from_edit(Object *obedit)
                        BLI_addtail(&newBone->parent->childbase, newBone);
                        
                        {
-                               float M_boneRest[3][3];
                                float M_parentRest[3][3];
                                float iM_parentRest[3][3];
                                float   delta[3];
@@ -362,10 +457,6 @@ void ED_armature_from_edit(Object *obedit)
                                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) */
-                               sub_v3_v3v3(delta, eBone->tail, eBone->head);
-                               vec_roll_to_mat3(delta, eBone->roll, M_boneRest);
-                               
                                /* Invert the parent matrix */
                                invert_m3_m3(iM_parentRest, M_parentRest);
                                
@@ -378,8 +469,11 @@ void ED_armature_from_edit(Object *obedit)
                        }
                }
                /*      ...otherwise add this bone to the armature's bonebase */
-               else
+               else {
+                       copy_v3_v3(newBone->head, eBone->head);
+                       copy_v3_v3(newBone->tail, eBone->tail);
                        BLI_addtail(&arm->bonebase, newBone);
+               }
        }
        
        /* Make a pass through the new armature to fix rolling */
@@ -392,7 +486,7 @@ void ED_armature_from_edit(Object *obedit)
                        armature_rebuild_pose(obt, arm);
        }
        
-       DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
 }
 
 void ED_armature_apply_transform(Object *ob, float mat[4][4])
@@ -412,6 +506,10 @@ void ED_armature_apply_transform(Object *ob, float mat[4][4])
                ebone->rad_head *= scale;
                ebone->rad_tail *= scale;
                ebone->dist             *= scale;
+
+               /* we could be smarter and scale by the matrix along the x & z axis */
+               ebone->xwidth   *= scale;
+               ebone->zwidth   *= scale;
        }
        
        /* Turn the list into an armature */
@@ -486,42 +584,24 @@ void docenter_armature (Scene *scene, Object *ob, float cursor[3], int centermod
 /* 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 occurrence
-                       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 */
@@ -536,7 +616,7 @@ static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
                        /* apply current transform from parent (not yet destroyed), 
                         * then calculate new parent inverse matrix
                         */
-                       object_apply_mat4(ob, ob->obmat);
+                       object_apply_mat4(ob, ob->obmat, FALSE, FALSE);
                        
                        what_does_parent(scene, ob, &workob);
                        invert_m4_m4(ob->parentinv, workob.obmat);
@@ -548,7 +628,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;
@@ -564,6 +644,8 @@ static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
        
        /* helpful warnings... */
        // TODO: add warnings to be careful about actions, applying deforms first, etc.
+       if (ob->adt && ob->adt->action) 
+               BKE_report(op->reports, RPT_WARNING, "Actions on this armature will be destroyed by this new rest pose as the transforms stored are relative to the old rest pose");
        
        /* Get editbones of active armature to alter */
        ED_armature_to_edit(ob);        
@@ -575,8 +657,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
@@ -603,10 +685,11 @@ static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
                }
                
                /* clear transform values for pchan */
-               pchan->loc[0]= pchan->loc[1]= pchan->loc[2]= 0.0f;
-               pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f;
-               pchan->quat[1]= pchan->quat[2]= pchan->quat[3]= 0.0f;
-               pchan->quat[0]= pchan->size[0]= pchan->size[1]= pchan->size[2]= 1.0f;
+               zero_v3(pchan->loc);
+               zero_v3(pchan->eul);
+               unit_qt(pchan->quat);
+               unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+               pchan->size[0]= pchan->size[1]= pchan->size[2]= 1.0f;
                
                /* set anim lock */
                curbone->flag |= BONE_UNKEYED;
@@ -645,10 +728,9 @@ void POSE_OT_armature_apply (wmOperatorType *ot)
 
 
 /* set the current pose as the restpose */
-static int pose_visual_transform_apply_exec (bContext *C, wmOperator *op)
+static int pose_visual_transform_apply_exec (bContext *C, wmOperator *UNUSED(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
 
        /* don't check if editmode (should be done by caller) */
        if (ob->type!=OB_ARMATURE)
@@ -660,25 +742,19 @@ static int pose_visual_transform_apply_exec (bContext *C, wmOperator *op)
         * 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);
-
-               where_is_pose_bone(scene, ob, pchan, CFRA, 1);
+               float delta_mat[4][4];
+               
+               /* chan_mat already contains the delta transform from rest pose to pose-mode pose
+                * as that is baked into there so that B-Bones will work. Once we've set this as the
+                * new raw-transform components, don't recalc the poses yet, otherwise IK result will 
+                * change, thus changing the result we may be trying to record.
+                */
+               copy_m4_m4(delta_mat, pchan->chan_mat);
+               pchan_apply_mat4(pchan, delta_mat, TRUE);
        }
        CTX_DATA_END;
-
-       // ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
@@ -753,7 +829,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));
                                                        }
                                                }
                                        }
@@ -797,7 +873,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 */
@@ -807,7 +883,7 @@ 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);
@@ -923,7 +999,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
 static void separated_armature_fix_links(Object *origArm, Object *newArm)
 {
        Object *ob;
-       bPoseChannel *pchan, *pcha, *pchb;
+       bPoseChannel *pchan;
        bConstraint *con;
        ListBase *opchans, *npchans;
        
@@ -950,38 +1026,23 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
                                                         *      - the target isn't origArm/newArm itself
                                                         *      - the target is one that can be found in newArm/origArm
                                                         */
-                                                       if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
-                                                               for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                                                       /* check if either one matches */
-                                                                       if ( (strcmp(pcha->name, ct->subtarget)==0) ||
-                                                                                (strcmp(pchb->name, ct->subtarget)==0) )
-                                                                       {
+                                                       if (ct->subtarget[0] != 0) {
+                                                               if (ct->tar == origArm) {
+                                                                       if(BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
                                                                                ct->tar= newArm;
-                                                                               break;
                                                                        }
-                                                                       
-                                                                       /* check if both ends have met (to stop checking) */
-                                                                       if (pcha == pchb) break;
-                                                               }                                                               
-                                                       }
-                                                       else if ((ct->tar == newArm) && (ct->subtarget[0] != 0)) {
-                                                               for (pcha=opchans->first, pchb=opchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                                                       /* check if either one matches */
-                                                                       if ( (strcmp(pcha->name, ct->subtarget)==0) ||
-                                                                                (strcmp(pchb->name, ct->subtarget)==0) )
-                                                                       {
+                                                               }
+                                                               else if (ct->tar == newArm) {
+                                                                       if(BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
                                                                                ct->tar= origArm;
-                                                                               break;
                                                                        }
-                                                                       
-                                                                       /* check if both ends have met (to stop checking) */
-                                                                       if (pcha == pchb) break;
-                                                               }                                                               
+                                                               }
                                                        }
                                                }
-                                               
-                                               if (cti->flush_constraint_targets)
+
+                                               if (cti->flush_constraint_targets) {
                                                        cti->flush_constraint_targets(con, &targets, 0);
+                                               }
                                        }
                                }
                        }
@@ -1003,58 +1064,33 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
                                                 *      - the target isn't origArm/newArm itself
                                                 *      - the target is one that can be found in newArm/origArm
                                                 */
-                                               if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
-                                                       for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                                               /* check if either one matches */
-                                                               if ( (strcmp(pcha->name, ct->subtarget)==0) ||
-                                                                        (strcmp(pchb->name, ct->subtarget)==0) )
-                                                               {
+                                               if(ct->subtarget[0] != '\0')  {
+                                                       if (ct->tar == origArm) {
+                                                               if(BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
                                                                        ct->tar= newArm;
-                                                                       break;
                                                                }
-                                                               
-                                                               /* check if both ends have met (to stop checking) */
-                                                               if (pcha == pchb) break;
-                                                       }                                                               
-                                               }
-                                               else if ((ct->tar == newArm) && (ct->subtarget[0] != 0)) {
-                                                       for (pcha=opchans->first, pchb=opchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                                               /* check if either one matches */
-                                                               if ( (strcmp(pcha->name, ct->subtarget)==0) ||
-                                                                        (strcmp(pchb->name, ct->subtarget)==0) )
-                                                               {
+                                                       }
+                                                       else if (ct->tar == newArm) {
+                                                               if(BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
                                                                        ct->tar= origArm;
-                                                                       break;
                                                                }
-                                                               
-                                                               /* check if both ends have met (to stop checking) */
-                                                               if (pcha == pchb) break;
-                                                       }                                                               
+                                                       }
                                                }
                                        }
-                                       
-                                       if (cti->flush_constraint_targets)
+
+                                       if (cti->flush_constraint_targets) {
                                                cti->flush_constraint_targets(con, &targets, 0);
+                                       }
                                }
                        }
                }
                
                /* See if an object is parented to this armature */
-               if ((ob->parent) && (ob->parent == origArm)) {
+               if (ob->parent && (ob->parent == origArm)) {
                        /* Is object parented to a bone of this src armature? */
-                       if (ob->partype==PARBONE) {
-                               /* bone name in object */
-                               for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                       /* check if either one matches */
-                                       if ( (strcmp(pcha->name, ob->parsubstr)==0) ||
-                                                (strcmp(pchb->name, ob->parsubstr)==0) )
-                                       {
-                                               ob->parent= newArm;
-                                               break;
-                                       }
-                                       
-                                       /* check if both ends have met (to stop checking) */
-                                       if (pcha == pchb) break;
+                       if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) {
+                               if(BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) {
+                                       ob->parent= newArm;
                                }
                        }
                }
@@ -1065,7 +1101,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;
@@ -1117,19 +1153,17 @@ 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;
        Base *oldbase, *newbase;
-       bArmature *arm;
        
        /* sanity checks */
        if (obedit == NULL)
                return OPERATOR_CANCELLED;
-       arm= obedit->data;
        
        /* set wait cursor in case this takes a while */
        WM_cursor_wait(1);
@@ -1166,15 +1200,15 @@ static int separate_armature_exec (bContext *C, wmOperator *op)
        
        
        /* 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?
        separated_armature_fix_links(oldob, newob);
        
-       DAG_id_flush_update(&oldob->id, OB_RECALC_DATA);        /* this is the original one */
-       DAG_id_flush_update(&newob->id, OB_RECALC_DATA);        /* this is the separated one */
+       DAG_id_tag_update(&oldob->id, OB_RECALC_DATA);  /* this is the original one */
+       DAG_id_tag_update(&newob->id, OB_RECALC_DATA);  /* this is the separated one */
        
        
        /* 5) restore original conditions */
@@ -1214,15 +1248,11 @@ void ARMATURE_OT_separate (wmOperatorType *ot)
 Bone *get_indexed_bone (Object *ob, int index)
 {
        bPoseChannel *pchan;
-       int a= 0;
-       
        if(ob->pose==NULL) return NULL;
        index>>=16;             // bone selection codes use left 2 bytes
        
-       for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, a++) {
-               if(a==index) return pchan->bone;
-       }
-       return NULL;
+       pchan= BLI_findlink(&ob->pose->chanbase, index);
+       return pchan ? pchan->bone : NULL;
 }
 
 /* See if there are any selected bones in this buffer */
@@ -1354,8 +1384,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;
@@ -1379,7 +1410,7 @@ static int pose_setflag_exec (bContext *C, wmOperator *op)
        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;
 }
@@ -1551,6 +1582,7 @@ void POSE_OT_select_linked(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Select Connected";
        ot->idname= "POSE_OT_select_linked";
+       ot->description= "Select bones related to selected ones by parent/child relationships";
        
        /* api callbacks */
        ot->exec= NULL;
@@ -1650,6 +1682,7 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Select Connected";
        ot->idname= "ARMATURE_OT_select_linked";
+       ot->description= "Select bones related to selected ones by parent/child relationships";
        
        /* api callbacks */
        ot->exec= NULL;
@@ -1753,34 +1786,12 @@ static EditBone *get_nearest_editbonepoint (ViewContext *vc, short mval[2], List
        return NULL;
 }
 
-/* context: editmode armature */
-EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
-{
-       EditBone *eboflip= NULL;
-       char name[32];
-       
-       if (ebo == NULL)
-               return NULL;
-
-       flip_side_name(name, ebo->name, FALSE);
-       
-       for (eboflip= edbo->first; eboflip; eboflip=eboflip->next) {
-               if (ebo != eboflip) {
-                       if (!strcmp (name, eboflip->name)) 
-                               break;
-               }
-       }
-       
-       return eboflip;
-}
-
-
 /* 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;
+       EditBone        *curBone, *ebone_next;
        bConstraint *con;
        Object *obedit= CTX_data_edit_object(C); // XXX get from context
        arm = obedit->data;
@@ -1789,24 +1800,13 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
        if (CTX_DATA_COUNT(C, selected_bones) == 0)
                return OPERATOR_CANCELLED;
        
-       /* Select mirrored bones */
-       if (arm->flag & ARM_MIRROR_EDIT) {
-               for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
-                       if (arm->layer & curBone->layer) {
-                               if (curBone->flag & BONE_SELECTED) {
-                                       next = ED_armature_bone_get_mirrored(arm->edbo, curBone);
-                                       if (next)
-                                               next->flag |= BONE_SELECTED;
-                               }
-                       }
-               }
-       }
+       armature_select_mirrored(arm);
        
        /*  First erase any associated pose channel */
        if (obedit->pose) {
-               bPoseChannel *pchan, *next;
-               for (pchan=obedit->pose->chanbase.first; pchan; pchan=next) {
-                       next= pchan->next;
+               bPoseChannel *pchan, *pchan_next;
+               for (pchan=obedit->pose->chanbase.first; pchan; pchan= pchan_next) {
+                       pchan_next= pchan->next;
                        curBone = editbone_name_exists(arm->edbo, pchan->name);
                        
                        if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
@@ -1844,8 +1844,8 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
        }
        
        
-       for (curBone=arm->edbo->first;curBone;curBone=next) {
-               next=curBone->next;
+       for (curBone=arm->edbo->first; curBone; curBone= ebone_next) {
+               ebone_next= curBone->next;
                if (arm->layer & curBone->layer) {
                        if (curBone->flag & BONE_SELECTED) {
                                if(curBone==arm->act_edbone) arm->act_edbone= NULL;
@@ -1867,6 +1867,7 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Delete Selected Bone(s)";
        ot->idname= "ARMATURE_OT_delete";
+       ot->description= "Remove selected bones from the armature";
        
        /* api callbacks */
        ot->invoke = WM_operator_confirm;
@@ -1879,10 +1880,9 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
 
 /* toggle==0: deselect
  * toggle==1: swap (based on test)
- * toggle==2: only active tag
- * toggle==3: swap (no test)
+ * toggle==2: swap (no test), CURRENTLY UNUSED
  */
-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;
@@ -1902,39 +1902,60 @@ void ED_armature_deselectall(Object *obedit, int toggle, int doundo)
        }
        else sel= toggle;
        
-       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 ((arm->layer & eBone->layer) && (eBone->flag & BONE_HIDDEN_A)==0) {
-                                       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 {
-                               /* deselect bone */
-                               eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+       /*      Set the flags */
+       for (eBone=arm->edbo->first;eBone;eBone=eBone->next) {
+               if (sel==2) {
+                       /* 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(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;
+               }
        }
        
        ED_armature_sync_selection(arm->edbo);
 }
 
+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);
+}
+
+/* accounts for connected parents */
+static int ebone_select_flag(EditBone *ebone)
+{
+       if(ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+               return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) | (ebone->flag & (BONE_SELECTED|BONE_TIPSEL));
+       }
+       else {
+               return ebone->flag & (BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL);
+       }
+}
 
 /* context: editmode armature in view3d */
 int mouse_armature(bContext *C, short mval[2], int extend)
@@ -1953,7 +1974,7 @@ int 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 */
@@ -2004,7 +2025,9 @@ int mouse_armature(bContext *C, short mval[2], int extend)
                
                if(nearBone) {
                        /* then now check for active status */
-                       if(nearBone->flag & BONE_SELECTED) arm->act_edbone= nearBone;
+                       if(ebone_select_flag(nearBone)) {
+                               arm->act_edbone= nearBone;
+                       }
                }
                
                WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, vc.obedit);
@@ -2053,136 +2076,140 @@ 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 ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const short axis_only)
 {
-       float mat[3][3], nor[3], up_axis[3], vec[3];
-       float roll;
+       float mat[3][3], nor[3];
 
        sub_v3_v3v3(nor, bone->tail, bone->head);
-       
-       vec_roll_to_mat3(nor, 0, mat);
-       VECCOPY(up_axis, mat[2]);
-       
-       roll = angle_normalized_v3v3(new_up_axis, up_axis);
-       
-       cross_v3_v3v3(vec, up_axis, new_up_axis);
-       
-       if (dot_v3v3(vec, nor) < 0)
-       {
-               roll = -roll;
-       }
-       
-       return roll;
-}
+       vec_roll_to_mat3(nor, 0.0f, mat);
 
+       /* 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 up (original method) */
-static 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 */
-       sub_v3_v3v3(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]);
-       
-       unit_m3(targetmat);
-       VECCOPY(targetmat[0], xaxis);
-       VECCOPY(targetmat[1], yaxis);
-       VECCOPY(targetmat[2], zaxis);
-       normalize_m3(targetmat);
-       
-       /* Find the difference between the two matrices */
-       invert_m3_m3(imat, targetmat);
-       mul_m3_m3m3(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);
-}
-
-void auto_align_ebone_topoint(EditBone *ebone, float *cursor)
-{
-       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) */
-       sub_v3_v3v3(delta, ebone->tail, ebone->head);
-       vec_roll_to_mat3(delta, ebone->roll, curmat);
-       copy_m4_m3(mat, curmat);
-       VECCOPY(mat[3], ebone->head);
-       
-       /* multiply bone-matrix by object matrix (so that bone-matrix is in WorldSpace) */
-       invert_m4_m4(imat, mat);
-       
-       /* find position of cursor relative to bone */
-       mul_v3_m4v3(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;
-               eul_to_mat4( rmat,rot);
+               /* 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]) > (float)(M_PI/2.0)) {
+                               negate_v3(align_axis_proj);
+                       }
+               }
                
-               /* Multiply the bone matrix by rotation matrix. This should be new bone-matrix */
-               mul_m4_m4m4(tmat, rmat, mat);
-               copy_m3_m4(curmat, tmat);
+               roll = angle_v3v3(align_axis_proj, mat[2]);
                
-               /* Now convert from new bone-matrix, back to a roll value (in radians) */
-               mat3_to_vec_roll(curmat, delta, &ebone->roll);
-       }
-}
+               cross_v3_v3v3(vec, mat[2], align_axis_proj);
+               
+               if (dot_v3v3(vec, nor) < 0) {
+                       roll = -roll;
+               }
 
-static void auto_align_ebone_tocursor(Scene *scene, View3D *v3d, EditBone *ebone)
-{
-       float cursor_local[3];
-       float   *cursor= give_cursor(scene, v3d);
-       float imat[3][3];
+               return roll;
+       }
 
-       copy_m3_m4(imat, scene->obedit->obmat);
-       invert_m3(imat);
-       copy_v3_v3(cursor_local, cursor);
-       mul_m3_v3(imat, cursor_local);
-       auto_align_ebone_topoint(ebone, cursor_local);
+       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", ""},
+       {5, "ACTIVE", 0, "Active Bone", ""},
+       {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];
+
+       bArmature *arm= ob->data;
+       EditBone *ebone;
+
+       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 */
+               for(ebone= arm->edbo->first; ebone; ebone= ebone->next) {
+                       if(EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
+                               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);
+                       }
+               }
        }
-       
-       /* 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]);
+                       mul_m3_v3(imat, vec);
+               }
+               else if (type==5) {
+                       float mat[3][3], nor[3];
+                       ebone= (EditBone *)arm->act_edbone;
+                       if(ebone==NULL) {
+                               BKE_report(op->reports, RPT_ERROR, "No active bone set");
+                               return OPERATOR_CANCELLED;
+                       }
+
+                       sub_v3_v3v3(nor, ebone->tail, ebone->head);
+                       vec_roll_to_mat3(nor, ebone->roll, mat);                        
+                       copy_v3_v3(vec, mat[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);
+
+               for(ebone= arm->edbo->first; ebone; ebone= ebone->next) {
+                       if(EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
+                               /* roll func is a callback which assumes that all is well */
+                               ebone->roll= ED_rollBoneToVector(ebone, vec, axis_only);
+                       }
+               }
+       }
+
+       if (arm->flag & ARM_MIRROR_EDIT) {
+               for(ebone= arm->edbo->first; ebone; ebone= ebone->next) {
+                       if((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
+                               EditBone *ebone_mirr= ED_armature_bone_get_mirrored(arm->edbo, ebone);
+                               if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
+                                       ebone->roll= -ebone_mirr->roll;
+                               }
+                       }
+               }
        }
-       CTX_DATA_END;
-       
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
@@ -2195,6 +2222,7 @@ void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Recalculate Roll";
        ot->idname= "ARMATURE_OT_calculate_roll";
+       ot->description= "Automatically fix alignment of select bones' axes";
        
        /* api callbacks */
        ot->invoke = WM_menu_invoke;
@@ -2203,9 +2231,11 @@ void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
+
        /* properties */
        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 ************** */
@@ -2235,6 +2265,8 @@ static void undoBones_to_editBones(void *uarmv, void *armv)
                ebo= uarm->act_edbone;
                arm->act_edbone= ebo->temp;
        }
+       else
+               arm->act_edbone= NULL;
 
        /* set pointers */
        for(newebo= arm->edbo->first; newebo; newebo= newebo->next) {
@@ -2293,7 +2325,7 @@ static void *get_armature_edit(bContext *C)
 }
 
 /* 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);
@@ -2305,11 +2337,11 @@ void undo_push_armature(bContext *C, char *name)
 /* *************** Adding stuff in editmode *************** */
 
 /* default bone add, returns it selected, but without tail set */
-EditBone *ED_armature_edit_bone_add(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);
@@ -2348,7 +2380,7 @@ void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
        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= ED_armature_edit_bone_add(obedit->data, "Bone");
@@ -2365,7 +2397,7 @@ void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
 
 /* 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;
@@ -2401,7 +2433,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;
@@ -2421,19 +2453,19 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op)
                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);
+               copy_v3_v3(newbone->tail, curs);
                sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
                
                if (a==1) 
@@ -2477,7 +2509,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;
@@ -2507,7 +2539,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;
 }
@@ -2517,6 +2549,7 @@ void ARMATURE_OT_click_extrude(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Click-Extrude";
        ot->idname= "ARMATURE_OT_click_extrude";
+       ot->description= "Create a new bone going from the last selected joint to the mouse position";
        
        /* api callbacks */
        ot->invoke = armature_click_extrude_invoke;
@@ -2536,8 +2569,8 @@ static EditBone *add_points_bone (Object *obedit, float head[], float tail[])
        
        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;
 }
@@ -2641,7 +2674,7 @@ 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);
@@ -2679,7 +2712,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;
@@ -2691,7 +2724,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
 
        /* cancel if nothing selected */
        if (CTX_DATA_COUNT(C, selected_bones) == 0)
-         return OPERATOR_CANCELLED;
+               return OPERATOR_CANCELLED;
        
        ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
 
@@ -2785,6 +2818,7 @@ void ARMATURE_OT_duplicate(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Duplicate Selected Bone(s)";
        ot->idname= "ARMATURE_OT_duplicate";
+       ot->description= "Make copies of the selected bones within the same armature";
        
        /* api callbacks */
        ot->exec = armature_duplicate_selected_exec;
@@ -2864,10 +2898,10 @@ 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) {
@@ -2896,11 +2930,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;
                }
                
@@ -2915,14 +2949,13 @@ static int armature_fill_bones_exec (bContext *C, wmOperator *op)
        bArmature *arm= (obedit) ? obedit->data : NULL;
        Scene *scene= CTX_data_scene(C);
        View3D *v3d= CTX_wm_view3d(C);
-       EditBone *newbone=NULL;
        ListBase points = {NULL, NULL};
        int count;
-       
+
        /* sanity checks */
-       if ELEM(NULL, obedit, arm)
+       if (ELEM(NULL, obedit, arm))
                return OPERATOR_CANCELLED;
-       
+
        /* loop over all bones, and only consider if visible */
        CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
        {
@@ -2956,7 +2989,7 @@ static int armature_fill_bones_exec (bContext *C, wmOperator *op)
                mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
                
                /* Create a bone */
-               newbone= add_points_bone(obedit, ebp->vec, curs);
+               /* newbone= */ add_points_bone(obedit, ebp->vec, curs);
        }
        else if (count == 2) {
                EditBonePoint *ebp, *ebp2;
@@ -3017,7 +3050,7 @@ static int armature_fill_bones_exec (bContext *C, wmOperator *op)
                
                /* add new bone and parent it to the appropriate end */
                if (headtail) {
-                       newbone= add_points_bone(obedit, head, tail);
+                       EditBone *newbone= add_points_bone(obedit, head, tail);
                        
                        /* do parenting (will need to set connected flag too) */
                        if (headtail == 2) {
@@ -3094,13 +3127,13 @@ 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) || start==arm->act_edbone)==0) {
+       if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED)==0) {
                copy_v3_v3(head, start->tail);
        }
        else {
                copy_v3_v3(head, start->head);
        }
-       if ((end->flag & BONE_ROOTSEL) && ((end->flag & BONE_SELECTED) || end==arm->act_edbone)==0) {
+       if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED)==0) {
                copy_v3_v3(tail, end->head);
        }
        else {
@@ -3108,12 +3141,15 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
        }
        newbone= add_points_bone(obedit, head, tail);
        newbone->parent = start->parent;
+
+       /* TODO, copy more things to the new bone */
+       newbone->flag= start->flag & (BONE_HINGE|BONE_NO_DEFORM|BONE_NO_SCALE|BONE_NO_CYCLICOFFSET|BONE_NO_LOCAL_LOCATION|BONE_DONE);
        
        /* 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) {
@@ -3129,6 +3165,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) */
@@ -3140,6 +3179,9 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
                ebone= (ebo == start) ? (NULL) : (ebo->parent);
                bone_free(arm, ebo);
        }
+       
+       newbone->flag |= (BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
+       ED_armature_sync_selection(arm->edbo);
 }
 
 
@@ -3163,7 +3205,9 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
                /* get chains (ends on chains) */
                chains_find_tips(arm->edbo, &chains);
                if (chains.first == NULL) return OPERATOR_CANCELLED;
-               
+
+               armature_tag_select_mirrored(arm);
+
                /* each 'chain' is the last bone in the chain (with no children) */
                for (chain= chains.first; chain; chain= nchain) {
                        EditBone *bstart= NULL, *bend= NULL;
@@ -3178,7 +3222,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) || (ebo==arm->act_edbone)) )
+                                        (ebo->flag & BONE_SELECTED) )
                                {
                                        /* set either end or start (end gets priority, unless it is already set) */
                                        if (bend == NULL)  {
@@ -3207,6 +3251,8 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
                        BLI_insertlinkbefore(&chains, nchain, chain);
                }               
                
+               armature_tag_unselect(arm);
+
                BLI_freelistN(&chains);
        }
        
@@ -3244,8 +3290,90 @@ void ARMATURE_OT_merge (wmOperatorType *ot)
 /* ************** END Add/Remove stuff in editmode ************ */
 /* *************** Tools in editmode *********** */
 
+static int armature_hide_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       bArmature *arm= obedit->data;
+       EditBone *ebone;
+       const int invert= RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0;
+
+       /* 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) != invert) {
+                               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_BONE_SELECT, obedit);
+
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_hide(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Hide Selected Bones";
+       ot->idname= "ARMATURE_OT_hide";
+       ot->description= "Tag selected bones to not be visible in Edit Mode";
+       
+       /* api callbacks */
+       ot->exec= armature_hide_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* props */
+       RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
+}
 
-void hide_selected_armature_bones(Scene *scene)
+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_BONE_SELECT, obedit);
+
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_reveal(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Reveal Bones";
+       ot->idname= "ARMATURE_OT_reveal";
+       ot->description= "Unhide all bones that have been tagged to be hidden in Edit Mode";
+       
+       /* api callbacks */
+       ot->exec= armature_reveal_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+#if 0 // remove this?
+static void hide_selected_armature_bones(Scene *scene)
 {
        Object *obedit= scene->obedit; // XXX get from context
        bArmature *arm= obedit->data;
@@ -3261,11 +3389,8 @@ void hide_selected_armature_bones(Scene *scene)
        }
        ED_armature_validate_active(arm);
        ED_armature_sync_selection(arm->edbo);
-       BIF_undo_push("Hide Bones");
 }
 
-
-#if 0 // remove this?
 static void hide_unselected_armature_bones(Scene *scene)
 {
        Object *obedit= scene->obedit; // XXX get from context
@@ -3284,11 +3409,8 @@ static void hide_unselected_armature_bones(Scene *scene)
 
        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
@@ -3305,7 +3427,6 @@ void show_all_armature_bones(Scene *scene)
        }
        ED_armature_validate_active(arm);
        ED_armature_sync_selection(arm->edbo);
-       BIF_undo_push("Reveal Bones");
 }
 #endif
 
@@ -3407,7 +3528,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) {
@@ -3436,13 +3557,12 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
        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);
 
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
+
        return OPERATOR_FINISHED;
 }
 
@@ -3451,6 +3571,7 @@ void ARMATURE_OT_extrude(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Extrude";
        ot->idname= "ARMATURE_OT_extrude";
+       ot->description= "Create new bones from the selected joints";
        
        /* api callbacks */
        ot->exec= armature_extrude_exec;
@@ -3490,7 +3611,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
        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= ED_armature_edit_bone_add(obedit->data, name);
@@ -3503,8 +3624,8 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
                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_DRAW, obedit);
-       
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
+
        return OPERATOR_FINISHED;
 }
 
@@ -3513,6 +3634,7 @@ void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Add Bone";
        ot->idname= "ARMATURE_OT_bone_primitive_add";
+       ot->description= "Add a new bone located at the 3D-Cursor";
        
        /* api callbacks */
        ot->exec = armature_bone_primitive_add_exec;
@@ -3542,10 +3664,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!
@@ -3582,112 +3701,40 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
                        
                        newbone->flag |= BONE_CONNECTED;
                        
-                       unique_editbone_name(arm->edbo, newbone->name, NULL);
-                       
-                       /* correct parent bones */
-                       for (tbone = arm->edbo->first; tbone; tbone=tbone->next) {
-                               if (tbone->parent==ebone)
-                                       tbone->parent= newbone;
-                       }
-                       newbone->parent= ebone;
-               }
-       }
-       CTX_DATA_END;
-       
-       /* note, notifier might evolve */
-       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)
-{
-       /* identifiers */
-       ot->name= "Subdivide Multi";
-       ot->idname= "ARMATURE_OT_subdivide_multi";
-       
-       /* api callbacks */
-       ot->exec = armature_subdivide_exec;
-       ot->poll = ED_operator_editarmature;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       /* Properties */
-       RNA_def_int(ot->srna, "number_cuts", 2, 1, INT_MAX, "Number of Cuts", "", 1, 10);
-}
-
-
-
-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;
+                       unique_editbone_name(arm->edbo, newbone->name, NULL);
+                       
+                       /* correct parent bones */
+                       for (tbone = arm->edbo->first; tbone; tbone=tbone->next) {
+                               if (tbone->parent==ebone)
+                                       tbone->parent= newbone;
+                       }
+                       newbone->parent= ebone;
+               }
        }
+       CTX_DATA_END;
+       
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
        
        return OPERATOR_FINISHED;
 }
 
-void ARMATURE_OT_subdivs(wmOperatorType *ot)
+void ARMATURE_OT_subdivide(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";
+       ot->name= "Subdivide Multi";
+       ot->idname= "ARMATURE_OT_subdivide";
+       ot->description= "Break selected bones into chains of smaller bones";
        
        /* api callbacks */
-       ot->invoke= armature_subdivs_invoke;
-       ot->exec= armature_subdivs_exec;
-       
-       ot->poll= ED_operator_editarmature;
+       ot->exec = armature_subdivide_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, INT_MAX, "Number of Cuts", "", 1, 10); 
+       /* Properties */
+       RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
 }
 
 /* ----------- */
@@ -3698,7 +3745,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;
@@ -3708,7 +3755,9 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *op)
        /* get chains of bones (ends on chains) */
        chains_find_tips(arm->edbo, &chains);
        if (chains.first == NULL) return OPERATOR_CANCELLED;
-       
+
+       armature_tag_select_mirrored(arm);
+
        /* loop over chains, only considering selected and visible bones */
        for (chain= chains.first; chain; chain= chain->next) {
                EditBone *ebo, *child=NULL, *parent=NULL;
@@ -3764,8 +3813,10 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *op)
        /* free chains */
        BLI_freelistN(&chains); 
 
+       armature_tag_unselect(arm);
+
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -3775,6 +3826,7 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Switch Direction";
        ot->idname= "ARMATURE_OT_switch_direction";
+       ot->description= "Change the direction that a chain of bones points in (head <-> tail swap)";
        
        /* api callbacks */
        ot->exec = armature_switch_direction_exec;
@@ -3914,15 +3966,15 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
        
 
        /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, 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);
+       uiPopupMenu *pup= uiPupMenuBegin(C, "Make Parent ", ICON_NONE);
        uiLayout *layout= uiPupMenuLayout(pup);
        int allchildbones = 0;
        
@@ -3949,6 +4001,7 @@ void ARMATURE_OT_parent_set(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Make Parent";
        ot->idname= "ARMATURE_OT_parent_set";
+       ot->description= "Set the active bone as the parent of the selected bones";
        
        /* api callbacks */
        ot->invoke = armature_parent_set_invoke;
@@ -3992,7 +4045,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_POSE, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -4002,6 +4055,7 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Clear Parent";
        ot->idname= "ARMATURE_OT_parent_clear";
+       ot->description= "Remove the parent-child relationship between selected bones and their parents";
        
        /* api callbacks */
        ot->invoke = WM_menu_invoke;
@@ -4016,7 +4070,7 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
 
 /* ****************  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) {
@@ -4038,6 +4092,7 @@ void ARMATURE_OT_select_inverse(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Select Inverse";
        ot->idname= "ARMATURE_OT_select_inverse";
+       ot->description= "Flip the selection status of bones (selected -> unselected, unselected -> selected)";
        
        /* api callbacks */
        ot->exec= armature_select_inverse_exec;
@@ -4075,7 +4130,8 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op)
                        case SEL_INVERT:
                                if (ebone->flag & BONE_SELECTED) {
                                        ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
-                               } else {
+                               } 
+                               else {
                                        ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
                                        if(ebone->parent)
                                                ebone->parent->flag |= (BONE_TIPSEL);
@@ -4093,10 +4149,10 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op)
 
 void ARMATURE_OT_select_all(wmOperatorType *ot)
 {
-       
        /* identifiers */
        ot->name= "Select or Deselect All";
        ot->idname= "ARMATURE_OT_select_all";
+       ot->description= "Toggle selection status of all bones";
        
        /* api callbacks */
        ot->exec= armature_de_select_all_exec;
@@ -4177,6 +4233,7 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Select Hierarchy";
        ot->idname= "ARMATURE_OT_select_hierarchy";
+       ot->description= "Select immediate parent/children of selected bones";
        
        /* api callbacks */
        ot->exec= armature_select_hierarchy_exec;
@@ -4373,7 +4430,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
                
                /* 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);
+                       ED_pose_deselectall(ob, 0);
                        nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                        arm->act_bone= nearBone;
                        
@@ -4406,7 +4463,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
                if (OBACT && OBACT->mode & OB_MODE_WEIGHT_PAINT) {
                        if (nearBone == arm->act_bone) {
                                ED_vgroup_select_by_name(OBACT, nearBone->name);
-                               DAG_id_flush_update(&OBACT->id, OB_RECALC_DATA);
+                               DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
                        }
                }
                
@@ -4420,7 +4477,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;
@@ -4432,7 +4489,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;
                        }
@@ -4457,19 +4514,9 @@ void ED_pose_deselectall (Object *ob, int test, int doundo)
                        }
                }
        }
-       
-       if(arm->act_bone && (arm->act_bone->flag & BONE_SELECTED)==0)
-               arm->act_bone= NULL;
-
-       //countall(); // XXX need an equivalent to this...
-       
-       if (doundo) {
-               if (selectmode==1) BIF_undo_push("Select All");
-               else BIF_undo_push("Deselect All");
-       }
 }
 
-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
@@ -4518,7 +4565,7 @@ static int bone_skinnable(Object *ob, Bone *bone, void *datap)
        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). 
@@ -4533,7 +4580,7 @@ static int ED_vgroup_add_unique_bone(Object *ob, Bone *bone, void *data)
        return 0;
 }
 
-static int dgroup_skinnable(Object *ob, Bone *bone, void *datap) 
+static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap) 
 {
        /* Bones that are deforming
         * are regarded to be "skinnable" and are eligible for
@@ -4589,7 +4636,7 @@ static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
        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 */
 
@@ -4623,14 +4670,14 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
                                bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
                        
                        /* add the vert to the deform group if weight!=0.0 */
-                       if (distance!=0.0)
+                       if (distance != 0.0f)
                                ED_vgroup_vert_add (ob, dgroup, i, distance, WEIGHT_REPLACE);
                        else
                                ED_vgroup_vert_remove (ob, dgroup, i);
                        
                        /* do same for mirror */
                        if (dgroupflip && dgroupflip[j] && iflip >= 0) {
-                               if (distance!=0.0)
+                               if (distance != 0.0f)
                                        ED_vgroup_vert_add (ob, dgroupflip[j], iflip, distance,
                                                WEIGHT_REPLACE);
                                else
@@ -4640,7 +4687,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)
+static 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.
@@ -4657,7 +4704,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;
@@ -4672,7 +4719,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;
@@ -4681,7 +4728,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
@@ -4690,7 +4737,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 */
@@ -4751,13 +4798,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
 
                        // 0 = don't strip off number extensions
                        flip_side_name(name, dgroup->name, FALSE);
-
-                       for (curdg = ob->defbase.first; curdg; curdg=curdg->next) {
-                               if (!strcmp(curdg->name, name))
-                                       break;
-                       }
-                       
-                       dgroupflip[j] = curdg;
+                       dgroupflip[j] = defgroup_find_name(ob, name);
                }
        }
 
@@ -4793,14 +4834,22 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
 
        /* 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, mat4_to_scale(par->obmat));
        }
-       
+
+       /* 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);
@@ -4811,7 +4860,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, int mirror)
+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.
@@ -4822,7 +4871,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);
@@ -4832,28 +4881,162 @@ 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), mirror);
+               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) 
+/* clear scale of pose-channel */
+static void pchan_clear_scale(bPoseChannel *pchan)
+{
+       if ((pchan->protectflag & OB_LOCK_SCALEX)==0)
+               pchan->size[0]= 1.0f;
+       if ((pchan->protectflag & OB_LOCK_SCALEY)==0)
+               pchan->size[1]= 1.0f;
+       if ((pchan->protectflag & OB_LOCK_SCALEZ)==0)
+               pchan->size[2]= 1.0f;
+}
+
+/* clear location of pose-channel */
+static void pchan_clear_loc(bPoseChannel *pchan)
+{
+       if ((pchan->protectflag & OB_LOCK_LOCX)==0)
+               pchan->loc[0]= 0.0f;
+       if ((pchan->protectflag & OB_LOCK_LOCY)==0)
+               pchan->loc[1]= 0.0f;
+       if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
+               pchan->loc[2]= 0.0f;
+}
+
+/* clear rotation of pose-channel */
+static void pchan_clear_rot(bPoseChannel *pchan)
+{
+       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->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_EQF(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQF(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] = {0};
+                       float qlen = 0.0f;
+                       
+                       if (pchan->rotmode == ROT_MODE_QUAT) {
+                               qlen= normalize_qt_qt(quat1, pchan->quat);
+                               quat_to_eul(oldeul, quat1);
+                       }
+                       else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                               axis_angle_to_eulO( oldeul, EULER_ORDER_DEFAULT,pchan->rotAxis, pchan->rotAngle);
+                       }
+                       else {
+                               copy_v3_v3(oldeul, pchan->eul);
+                       }
+                       
+                       eul[0]= eul[1]= eul[2]= 0.0f;
+                       
+                       if (pchan->protectflag & OB_LOCK_ROTX)
+                               eul[0]= oldeul[0];
+                       if (pchan->protectflag & OB_LOCK_ROTY)
+                               eul[1]= oldeul[1];
+                       if (pchan->protectflag & OB_LOCK_ROTZ)
+                               eul[2]= oldeul[2];
+                       
+                       if (pchan->rotmode == ROT_MODE_QUAT) {
+                               eul_to_quat(pchan->quat, eul);
+                               
+                               /* restore original quat size */
+                               mul_qt_fl(pchan->quat, qlen);
+                               
+                               /* 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)) {
+                                       mul_qt_fl(pchan->quat, -1.0f);
+                               }
+                       }
+                       else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                               eulO_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,eul, EULER_ORDER_DEFAULT);
+                       }
+                       else {
+                               copy_v3_v3(pchan->eul, eul);
+                       }
+               }
+       }                                               // Duplicated in source/blender/editors/object/object_transform.c
+       else { 
+               if (pchan->rotmode == ROT_MODE_QUAT) {
+                       unit_qt(pchan->quat);
+               }
+               else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                       /* by default, make rotation of 0 radians around y-axis (roll) */
+                       unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+               }
+               else {
+                       zero_v3(pchan->eul);
+               }
+       }
+}
+
+/* clear loc/rot/scale of pose-channel */
+static void pchan_clear_transforms(bPoseChannel *pchan)
+{
+       pchan_clear_loc(pchan);
+       pchan_clear_rot(pchan);
+       pchan_clear_scale(pchan);
+}
+
+/* --------------- */
+
+/* generic exec for clear-pose operators */
+static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, 
+               void (*clear_func)(bPoseChannel*), const char default_ksName[])
 {
        Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       
-       KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Scaling");
+       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_pose_bones) {
-               if ((pchan->protectflag & OB_LOCK_SCALEX)==0)
-                       pchan->size[0]= 1.0f;
-               if ((pchan->protectflag & OB_LOCK_SCALEY)==0)
-                       pchan->size[1]= 1.0f;
-               if ((pchan->protectflag & OB_LOCK_SCALEZ)==0)
-                       pchan->size[2]= 1.0f;
-                       
+       /* sanity checks */
+       if ELEM(NULL, clear_func, default_ksName) {
+               BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform func or Keying Set Name");
+               return OPERATOR_CANCELLED;
+       }
+       
+       /* only clear relevant transforms for selected bones */
+       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 
+       {
+               /* run provided clearing function */
+               clear_func(pchan);
+               
                /* do auto-keyframing as appropriate */
                if (autokeyframe_cfra_can_key(scene, &ob->id)) {
                        /* clear any unkeyed tags */
@@ -4873,15 +5056,18 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *op)
        
        /* perform autokeying on the bones if needed */
        if (autokey) {
+               /* get KeyingSet to use */
+               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
+               
                /* 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(C, scene, ob);
+                       ED_pose_recalculate_paths(scene, ob);
        }
        
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
@@ -4889,14 +5075,21 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
+/* --------------- */
+
+static int pose_clear_scale_exec(bContext *C, wmOperator *op) 
+{
+       return pose_clear_transform_generic_exec(C, op, pchan_clear_scale, "Scaling");
+}
+
 void POSE_OT_scale_clear(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Clear Pose Scale";
        ot->idname= "POSE_OT_scale_clear";
+       ot->description = "Reset scaling of selected bones to their default values";
        
        /* api callbacks */
-       ot->invoke = WM_operator_confirm;
        ot->exec = pose_clear_scale_exec;
        ot->poll = ED_operator_posemode;
        
@@ -4904,57 +5097,31 @@ 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_rot_exec(bContext *C, wmOperator *op) 
 {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       
-       KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
-       short autokey = 0;
-       
-       /* only clear those channels that are not locked */
-       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)
-                       pchan->loc[1]= 0.0f;
-               if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
-                       pchan->loc[2]= 0.0f;
-                       
-               /* 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;
+       return pose_clear_transform_generic_exec(C, op, pchan_clear_rot, "Rotation");
+}
+
+void POSE_OT_rot_clear(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Clear Pose Rotation";
+       ot->idname= "POSE_OT_rot_clear";
+       ot->description = "Reset rotations of selected bones to their default values";
        
-       /* perform autokeying on the bones if needed */
-       if (autokey) {
-               /* 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(C, scene, ob);
-       }
+       /* api callbacks */
+       ot->exec = pose_clear_rot_exec;
+       ot->poll = ED_operator_posemode;
        
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
-       /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
-       
-       return OPERATOR_FINISHED;
+
+static int pose_clear_loc_exec(bContext *C, wmOperator *op) 
+{
+       return pose_clear_transform_generic_exec(C, op, pchan_clear_loc, "Location");
 }
 
 void POSE_OT_loc_clear(wmOperatorType *ot)
@@ -4962,9 +5129,9 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Clear Pose Location";
        ot->idname= "POSE_OT_loc_clear";
+       ot->description = "Reset locations of selected bones to their default values";
        
        /* api callbacks */
-       ot->invoke = WM_operator_confirm;
        ot->exec = pose_clear_loc_exec;
        ot->poll = ED_operator_posemode;
        
@@ -4972,162 +5139,30 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-static int pose_clear_rot_exec(bContext *C, wmOperator *op) 
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       
-       KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
-       short autokey = 0;
-       
-       /* only clear those channels that are not locked */
-       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->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] = {0};
-                               
-                               if (pchan->rotmode == ROT_MODE_QUAT) {
-                                       copy_qt_qt(quat1, pchan->quat);
-                                       quat_to_eul( oldeul,pchan->quat);
-                               }
-                               else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                                       axis_angle_to_eulO( oldeul, EULER_ORDER_DEFAULT,pchan->rotAxis, pchan->rotAngle);
-                               }
-                               else {
-                                       copy_v3_v3(oldeul, pchan->eul);
-                               }
-                               
-                               eul[0]= eul[1]= eul[2]= 0.0f;
-                               
-                               if (pchan->protectflag & OB_LOCK_ROTX)
-                                       eul[0]= oldeul[0];
-                               if (pchan->protectflag & OB_LOCK_ROTY)
-                                       eul[1]= oldeul[1];
-                               if (pchan->protectflag & OB_LOCK_ROTZ)
-                                       eul[2]= oldeul[2];
-                               
-                               if (pchan->rotmode == ROT_MODE_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)) {
-                                               mul_qt_fl(pchan->quat, -1.0f);
-                                       }
-                               }
-                               else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                                       eulO_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,eul, EULER_ORDER_DEFAULT);
-                               }
-                               else {
-                                       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; 
-                               pchan->quat[0]= 1.0f;
-                       }
-                       else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                               /* by default, make rotation of 0 radians around y-axis (roll) */
-                               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;
-                       }
-               }
-               
-               /* 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) {
-               /* 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(C, scene, ob);
-       }
-       
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
-       /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
-       
-       return OPERATOR_FINISHED;
+static int pose_clear_transforms_exec(bContext *C, wmOperator *op) 
+{
+       return pose_clear_transform_generic_exec(C, op, pchan_clear_transforms, "LocRotScale");
 }
 
-void POSE_OT_rot_clear(wmOperatorType *ot)
+void POSE_OT_transforms_clear(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Clear Pose Rotation";
-       ot->idname= "POSE_OT_rot_clear";
+       ot->name= "Clear Pose Transforms";
+       ot->idname= "POSE_OT_transforms_clear";
+       ot->description = "Reset location, rotation, and scaling of selected bones to their default values";
        
        /* api callbacks */
-       ot->invoke = WM_operator_confirm;
-       ot->exec = pose_clear_rot_exec;
+       ot->exec = pose_clear_transforms_exec;
        ot->poll = ED_operator_posemode;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
 }
 
 /* ***************** 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 */
@@ -5146,10 +5181,10 @@ static int pose_select_inverse_exec(bContext *C, wmOperator *op)
 
 void POSE_OT_select_inverse(wmOperatorType *ot)
 {
-       
        /* identifiers */
        ot->name= "Select Inverse";
        ot->idname= "POSE_OT_select_inverse";
+       ot->description= "Flip the selection status of bones (selected -> unselected, unselected -> selected)";
        
        /* api callbacks */
        ot->exec= pose_select_inverse_exec;
@@ -5164,20 +5199,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
        int action = RNA_enum_get(op->ptr, "action");
 
        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;
+               action= CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
        }
        
        /*      Set the flags */
@@ -5194,7 +5216,8 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
                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) {
+                       } 
+                       else if ((pchan->bone->flag & BONE_UNSELECTABLE)==0) {
                                        pchan->bone->flag |= BONE_SELECTED;
                        }
                        break;
@@ -5209,10 +5232,10 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
 
 void POSE_OT_select_all(wmOperatorType *ot)
 {
-       
        /* identifiers */
        ot->name= "Select or Deselect All";
        ot->idname= "POSE_OT_select_all";
+       ot->description= "Toggle selection status of all bones";
        
        /* api callbacks */
        ot->exec= pose_de_select_all_exec;
@@ -5224,9 +5247,9 @@ void POSE_OT_select_all(wmOperatorType *ot)
        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 */
@@ -5254,8 +5277,9 @@ static int pose_select_parent_exec(bContext *C, wmOperator *op)
 void POSE_OT_select_parent(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "select parent bone";
+       ot->name= "Select Parent Bone";
        ot->idname= "POSE_OT_select_parent";
+       ot->description= "Select bones that are parents of the currently selected bones";
 
        /* api callbacks */
        ot->exec= pose_select_parent_exec;
@@ -5268,13 +5292,14 @@ 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;
                        if(arm->act_bone==bone)
                                arm->act_bone= NULL;
                }
@@ -5282,7 +5307,7 @@ static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr)
        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;
        
@@ -5300,15 +5325,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);
@@ -5321,6 +5344,7 @@ void POSE_OT_hide(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Hide Selected";
        ot->idname= "POSE_OT_hide";
+       ot->description= "Tag selected bones to not be visible in Pose Mode";
        
        /* api callbacks */
        ot->exec= pose_hide_exec;
@@ -5333,7 +5357,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;
        
@@ -5348,12 +5372,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);
@@ -5366,6 +5390,7 @@ void POSE_OT_reveal(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Reveal Selected";
        ot->idname= "POSE_OT_reveal";
+       ot->description= "Unhide all bones that have been tagged to be hidden in Pose Mode";
        
        /* api callbacks */
        ot->exec= pose_reveal_exec;
@@ -5377,34 +5402,16 @@ 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 occurrence
-                       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;
+}
+
+static 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)
 {
@@ -5470,6 +5477,8 @@ 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;
@@ -5513,11 +5522,22 @@ 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);
+                               }
+                       }
+                       
+                       /* 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;
+                                       
+                                       /* 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);
+                                       }
                                }
                        }
                        
@@ -5532,7 +5552,7 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
 }
 
 
-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;
@@ -5552,7 +5572,7 @@ static int armature_flip_names_exec (bContext *C, wmOperator *op)
        CTX_DATA_END;
        
        /* since we renamed stuff... */
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
@@ -5565,7 +5585,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 axis suffixes of the names of selected bones";
        
        /* api callbacks */
        ot->exec= armature_flip_names_exec;
@@ -5598,7 +5618,7 @@ static int armature_autoside_names_exec (bContext *C, wmOperator *op)
        CTX_DATA_END;
        
        /* since we renamed stuff... */
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
@@ -5654,11 +5674,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;
                                                }
                                        }
@@ -5668,12 +5689,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;
                                        }
                                }
@@ -5714,7 +5736,7 @@ EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode
                
                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;
                
@@ -5739,17 +5761,17 @@ EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode
 
                        if (len1 > 0.0f && len2 > 0.0f && dot_v3v3(vec1, vec2) < angleLimit)
                        {
-                               VECCOPY(parent->tail, previous);
+                               copy_v3_v3(parent->tail, previous);
 
                                child = ED_armature_edit_bone_add(arm, "Bone");
-                               VECCOPY(child->head, parent->tail);
+                               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. 
@@ -5773,13 +5795,8 @@ EditBone * test_subdivideByCorrelation(Scene *scene, Object *obedit, ReebArc *ar
 
        if (scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
        {
-               float invmat[4][4] = {  {1, 0, 0, 0},
-                                                               {0, 1, 0, 0},
-                                                               {0, 0, 1, 0},
-                                                               {0, 0, 0, 1}};
-               float tmat[3][3] = {    {1, 0, 0},
-                                                               {0, 1, 0},
-                                                               {0, 0, 1}};
+               float invmat[4][4]= MAT4_UNITY;
+               float tmat[3][3]= MAT3_UNITY;
                ReebArcIterator arc_iter;
                BArcIterator *iter = (BArcIterator*)&arc_iter;
                bArmature *arm= obedit->data;
@@ -5789,7 +5806,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)
@@ -5825,13 +5842,8 @@ EditBone * test_subdivideByLength(Scene *scene, Object *obedit, ReebArc *arc, Re
        if ((scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) &&
                arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio)
        {
-               float invmat[4][4] = {  {1, 0, 0, 0},
-                                                               {0, 1, 0, 0},
-                                                               {0, 0, 1, 0},
-                                                               {0, 0, 0, 1}};
-               float tmat[3][3] = {    {1, 0, 0},
-                                                               {0, 1, 0},
-                                                               {0, 0, 1}};
+               float invmat[4][4]= MAT4_UNITY;
+               float tmat[3][3]= MAT3_UNITY;
                ReebArcIterator arc_iter;
                BArcIterator *iter = (BArcIterator*)&arc_iter;
                bArmature *arm= obedit->data;
@@ -5868,7 +5880,7 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
        obedit= scene->basact->object;
        
        /* Copy orientation from source */
-       VECCOPY(dst->loc, src->obmat[3]);
+       copy_v3_v3(dst->loc, src->obmat[3]);
        mat4_to_eul( dst->rot,src->obmat);
        mat4_to_size( dst->size,src->obmat);
        
@@ -5950,8 +5962,8 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
                        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;
@@ -6015,8 +6027,6 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
        }
        
        BLI_ghash_free(arcBoneMap, NULL, NULL);
-       
-       BIF_undo_push("Generate Skeleton");
 }
 
 void generateSkeleton(Scene *scene)