Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / source / blender / editors / armature / editarmature.c
index 7155bdd..bc210fb 100644 (file)
@@ -72,7 +72,6 @@
 #include "PIL_time.h"
 
 #include "BIF_gl.h"
-#include "BIF_transform.h"
 #include "BIF_generate.h"
 
 #include "RNA_access.h"
@@ -85,6 +84,7 @@
 #include "ED_mesh.h"
 #include "ED_object.h"
 #include "ED_screen.h"
+#include "ED_transform.h"
 #include "ED_util.h"
 #include "ED_view3d.h"
 
 
 /* ************* XXX *************** */
 static int okee() {return 0;}
-static int pupmenu() {return 0;}
-static void waitcursor() {};
-static void error() {};
-static void error_libdata() {}
-static void BIF_undo_push() {}
-static void adduplicate() {}
+static void BIF_undo_push(const char *msg) {}
 /* ************* XXX *************** */
 
 /* **************** tools on Editmode Armature **************** */
 
 /* Sync selection to parent for connected children */
-static void armature_sync_selection(ListBase *edbo)
+void ED_armature_sync_selection(ListBase *edbo)
 {
        EditBone *ebo;
        
@@ -244,7 +239,7 @@ static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist)
 }
 
 /* put EditMode back in Object */
-void ED_armature_from_edit(Scene *scene, Object *obedit)
+void ED_armature_from_edit(Object *obedit)
 {
        bArmature *arm= obedit->data;
        EditBone *eBone, *neBone;
@@ -345,24 +340,22 @@ void ED_armature_from_edit(Scene *scene, Object *obedit)
                        armature_rebuild_pose(obt, arm);
        }
        
-       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
 }
 
-
-
-void apply_rot_armature (Scene *scene, Object *ob, float mat[3][3])
+void ED_armature_apply_transform(Object *ob, float mat[4][4])
 {
        EditBone *ebone;
        bArmature *arm= ob->data;
-       float scale = Mat3ToScalef(mat);        /* store the scale of the matrix here to use on envelopes */
+       float scale = Mat4ToScalef(mat);        /* store the scale of the matrix here to use on envelopes */
        
        /* Put the armature into editmode */
        ED_armature_to_edit(ob);
 
        /* Do the rotations */
        for (ebone = arm->edbo->first; ebone; ebone=ebone->next){
-               Mat3MulVecfl(mat, ebone->head);
-               Mat3MulVecfl(mat, ebone->tail);
+               Mat4MulVecfl(mat, ebone->head);
+               Mat4MulVecfl(mat, ebone->tail);
                
                ebone->rad_head *= scale;
                ebone->rad_tail *= scale;
@@ -370,10 +363,11 @@ void apply_rot_armature (Scene *scene, Object *ob, float mat[3][3])
        }
        
        /* Turn the list into an armature */
-       ED_armature_from_edit(scene, ob);
+       ED_armature_from_edit(ob);
        ED_armature_edit_free(ob);
 }
 
+/* exported for use in editors/object/ */
 /* 0 == do center, 1 == center new, 2 == center cursor */
 void docenter_armature (Scene *scene, View3D *v3d, Object *ob, int centermode)
 {
@@ -415,7 +409,7 @@ void docenter_armature (Scene *scene, View3D *v3d, Object *ob, int centermode)
        }
        
        /* Turn the list into an armature */
-       ED_armature_from_edit(scene, ob);
+       ED_armature_from_edit(ob);
        
        /* Adjust object location for new centerpoint */
        if(centermode && obedit==NULL) {
@@ -430,25 +424,7 @@ void docenter_armature (Scene *scene, View3D *v3d, Object *ob, int centermode)
                ED_armature_edit_free(ob);
 }
 
-/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
-static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
-{
-       Object workob, *ob;
-       
-       /* go through all objects in database */
-       for (ob= G.main->object.first; ob; ob= ob->id.next) {
-               /* if parent is bone in this armature, apply corrections */
-               if ((ob->parent == armob) && (ob->partype == PARBONE)) {
-                       /* apply current transform from parent (not yet destroyed), 
-                        * then calculate new parent inverse matrix
-                        */
-                       ED_object_apply_obmat(ob);
-                       
-                       what_does_parent(scene, ob, &workob);
-                       Mat4Invert(ob->parentinv, workob.obmat);
-               }
-       }
-}
+/* ---------------------- */
 
 static EditBone *editbone_name_exists (ListBase *edbo, char *name)
 {
@@ -490,28 +466,52 @@ void unique_editbone_name (ListBase *edbo, char *name, EditBone *bone)
        }
 }
 
+/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
+static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
+{
+       Object workob, *ob;
+       
+       /* go through all objects in database */
+       for (ob= G.main->object.first; ob; ob= ob->id.next) {
+               /* if parent is bone in this armature, apply corrections */
+               if ((ob->parent == armob) && (ob->partype == PARBONE)) {
+                       /* apply current transform from parent (not yet destroyed), 
+                        * then calculate new parent inverse matrix
+                        */
+                       ED_object_apply_obmat(ob);
+                       
+                       what_does_parent(scene, ob, &workob);
+                       Mat4Invert(ob->parentinv, workob.obmat);
+               }
+       }
+}
+
 /* set the current pose as the restpose */
-void apply_armature_pose2bones(Scene *scene, Object *obedit)
+static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
 {
-       bArmature *arm= obedit->data;
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= CTX_data_active_object(C); // must be active object, not edit-object
+       bArmature *arm= get_armature(ob);
        bPose *pose;
        bPoseChannel *pchan;
        EditBone *curbone;
        
        /* don't check if editmode (should be done by caller) */
-       if (object_data_is_libdata(obedit)) {
-               error_libdata();
-               return;
+       if (ob->type!=OB_ARMATURE)
+               return OPERATOR_CANCELLED;
+       if (object_data_is_libdata(ob)) {
+               BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature."); //error_libdata();
+               return OPERATOR_CANCELLED;
        }
        
        /* helpful warnings... */
        // TODO: add warnings to be careful about actions, applying deforms first, etc.
        
        /* Get editbones of active armature to alter */
-       ED_armature_to_edit(obedit);    
+       ED_armature_to_edit(ob);        
        
        /* get pose of active object and move it out of posemode */
-       pose= obedit->pose;
+       pose= ob->pose;
        
        for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
                curbone= editbone_name_exists(arm->edbo, pchan->name);
@@ -530,7 +530,7 @@ void apply_armature_pose2bones(Scene *scene, Object *obedit)
                        
                        /* obtain new auto y-rotation */
                        VecSubf(delta, curbone->tail, curbone->head);
-                       vec_roll_to_mat3(delta, 0.0, premat);
+                       vec_roll_to_mat3(delta, 0.0f, premat);
                        Mat3Inv(imat, premat);
                        
                        /* get pchan 'visual' matrix */
@@ -545,26 +545,46 @@ void apply_armature_pose2bones(Scene *scene, Object *obedit)
                }
                
                /* clear transform values for pchan */
-               pchan->loc[0]= pchan->loc[1]= pchan->loc[2]= 0;
-               pchan->quat[1]= pchan->quat[2]= pchan->quat[3]= 0;
-               pchan->quat[0]= pchan->size[0]= pchan->size[1]= pchan->size[2]= 1;
+               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;
                
                /* set anim lock */
                curbone->flag |= BONE_UNKEYED;
        }
        
        /* convert editbones back to bones */
-       ED_armature_from_edit(scene, obedit);
+       ED_armature_from_edit(ob);
        
        /* flush positions of posebones */
-       where_is_pose(scene, obedit);
+       where_is_pose(scene, ob);
        
        /* fix parenting of objects which are bone-parented */
-       applyarmature_fix_boneparents(scene, obedit);
+       applyarmature_fix_boneparents(scene, ob);
+       
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+void POSE_OT_apply (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Apply Pose as Rest Pose";
+       ot->idname= "POSE_OT_apply";
+       ot->description= "Apply the current pose as the new rest pose.";
        
-       BIF_undo_push("Apply new restpose");
+       /* callbacks */
+       ot->exec= apply_armature_pose2bones_exec;
+       ot->poll= ED_operator_posemode;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/* ---------------------- */
 
 /* Helper function for armature joining - link fixing */
 static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
@@ -669,116 +689,116 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
        }       
 }
 
-int join_armature(Scene *scene, View3D *v3d)
+/* join armature exec is exported for use in object->join objects operator... */
+int join_armature_exec(bContext *C, wmOperator *op)
 {
-       Object  *ob= scene->basact->object; // XXX context
-       bArmature *arm= ob->data;
-       Base    *base, *nextbase;
+       Scene *scene= CTX_data_scene(C);
+       Object  *ob= CTX_data_active_object(C);
+       bArmature *arm= (ob)? ob->data: NULL;
        bPose *pose, *opose;
        bPoseChannel *pchan, *pchann;
        EditBone *curbone;
        float   mat[4][4], oimat[4][4];
        
        /*      Ensure we're not in editmode and that the active object is an armature*/
-       if (ob->type!=OB_ARMATURE) return 0;
-       if (arm->edbo) return 0;
-       
-       if (object_data_is_libdata(ob)) {
-               error_libdata();
-               return 0;
-       }
+       if (!ob || ob->type!=OB_ARMATURE)
+               return OPERATOR_CANCELLED;
+       if (!arm || arm->edbo)
+               return OPERATOR_CANCELLED;
        
        /* Get editbones of active armature to add editbones to */
        ED_armature_to_edit(ob);
        
        /* get pose of active object and move it out of posemode */
        pose= ob->pose;
-       ob->flag &= ~OB_POSEMODE;
-       
-       for (base=FIRSTBASE; base; base=nextbase) {
-               nextbase = base->next;
-               if (TESTBASE(v3d, base)){
-                       if ((base->object->type==OB_ARMATURE) && (base->object!=ob)) {
-                               bArmature *curarm= base->object->data;
-                               
-                               /* Make a list of editbones in current armature */
-                               ED_armature_to_edit(base->object);
-                               
-                               /* Get Pose of current armature */
-                               opose= base->object->pose;
-                               base->object->flag &= ~OB_POSEMODE;
-                               BASACT->flag &= ~OB_POSEMODE;
+       ob->mode &= ~OB_MODE_POSE;
+
+       CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+               if ((base->object->type==OB_ARMATURE) && (base->object!=ob)) {
+                       bArmature *curarm= base->object->data;
+                       
+                       /* Make a list of editbones in current armature */
+                       ED_armature_to_edit(base->object);
+                       
+                       /* Get Pose of current armature */
+                       opose= base->object->pose;
+                       base->object->mode &= ~OB_MODE_POSE;
+                       //BASACT->flag &= ~OB_MODE_POSE;
+                       
+                       /* Find the difference matrix */
+                       Mat4Invert(oimat, ob->obmat);
+                       Mat4MulMat4(mat, base->object->obmat, oimat);
+                       
+                       /* Copy bones and posechannels from the object to the edit armature */
+                       for (pchan=opose->chanbase.first; pchan; pchan=pchann) {
+                               pchann= pchan->next;
+                               curbone= editbone_name_exists(curarm->edbo, pchan->name);
                                
-                               /* Find the difference matrix */
-                               Mat4Invert(oimat, ob->obmat);
-                               Mat4MulMat4(mat, base->object->obmat, oimat);
+                               /* Get new name */
+                               unique_editbone_name(arm->edbo, curbone->name, NULL);
                                
-                               /* Copy bones and posechannels from the object to the edit armature */
-                               for (pchan=opose->chanbase.first; pchan; pchan=pchann) {
-                                       pchann= pchan->next;
-                                       curbone= editbone_name_exists(curarm->edbo, pchan->name);
+                               /* Transform the bone */
+                               {
+                                       float premat[4][4];
+                                       float postmat[4][4];
+                                       float difmat[4][4];
+                                       float imat[4][4];
+                                       float temp[3][3];
+                                       float delta[3];
                                        
-                                       /* Get new name */
-                                       unique_editbone_name(arm->edbo, curbone->name, NULL);
+                                       /* Get the premat */
+                                       VecSubf(delta, curbone->tail, curbone->head);
+                                       vec_roll_to_mat3(delta, curbone->roll, temp);
                                        
-                                       /* Transform the bone */
-                                       {
-                                               float premat[4][4];
-                                               float postmat[4][4];
-                                               float difmat[4][4];
-                                               float imat[4][4];
-                                               float temp[3][3];
-                                               float delta[3];
-                                               
-                                               /* Get the premat */
-                                               VecSubf(delta, curbone->tail, curbone->head);
-                                               vec_roll_to_mat3(delta, curbone->roll, temp);
-                                               
-                                               Mat4One(premat); /* Mat4MulMat34 only sets 3x3 part */
-                                               Mat4MulMat34(premat, temp, mat);
-                                               
-                                               Mat4MulVecfl(mat, curbone->head);
-                                               Mat4MulVecfl(mat, curbone->tail);
-                                               
-                                               /* Get the postmat */
-                                               VecSubf(delta, curbone->tail, curbone->head);
-                                               vec_roll_to_mat3(delta, curbone->roll, temp);
-                                               Mat4CpyMat3(postmat, temp);
-                                               
-                                               /* Find the roll */
-                                               Mat4Invert(imat, premat);
-                                               Mat4MulMat4(difmat, postmat, imat);
-                                               
-                                               curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
-                                       }
+                                       Mat4One(premat); /* Mat4MulMat34 only sets 3x3 part */
+                                       Mat4MulMat34(premat, temp, mat);
                                        
-                                       /* Fix Constraints and Other Links to this Bone and Armature */
-                                       joined_armature_fix_links(ob, base->object, pchan, curbone);
+                                       Mat4MulVecfl(mat, curbone->head);
+                                       Mat4MulVecfl(mat, curbone->tail);
                                        
-                                       /* Rename pchan */
-                                       BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
+                                       /* Get the postmat */
+                                       VecSubf(delta, curbone->tail, curbone->head);
+                                       vec_roll_to_mat3(delta, curbone->roll, temp);
+                                       Mat4CpyMat3(postmat, temp);
                                        
-                                       /* Jump Ship! */
-                                       BLI_remlink(curarm->edbo, curbone);
-                                       BLI_addtail(arm->edbo, curbone);
+                                       /* Find the roll */
+                                       Mat4Invert(imat, premat);
+                                       Mat4MulMat4(difmat, postmat, imat);
                                        
-                                       BLI_remlink(&opose->chanbase, pchan);
-                                       BLI_addtail(&pose->chanbase, pchan);
+                                       curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
                                }
                                
-                               ED_base_object_free_and_unlink(scene, base);
+                               /* Fix Constraints and Other Links to this Bone and Armature */
+                               joined_armature_fix_links(ob, base->object, pchan, curbone);
+                               
+                               /* Rename pchan */
+                               BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
+                               
+                               /* Jump Ship! */
+                               BLI_remlink(curarm->edbo, curbone);
+                               BLI_addtail(arm->edbo, curbone);
+                               
+                               BLI_remlink(&opose->chanbase, pchan);
+                               BLI_addtail(&pose->chanbase, pchan);
                        }
+                       
+                       ED_base_object_free_and_unlink(scene, base);
                }
        }
+       CTX_DATA_END;
        
        DAG_scene_sort(scene);  // because we removed object(s)
 
-       ED_armature_from_edit(scene, ob);
+       ED_armature_from_edit(ob);
        ED_armature_edit_free(ob);
+
+       WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
        
-       return 1;
+       return OPERATOR_FINISHED;
 }
 
+/* ---------------------- */
+
 /* Helper function for armature separating - link fixing */
 static void separated_armature_fix_links(Object *origArm, Object *newArm)
 {
@@ -972,24 +992,27 @@ static void separate_armature_bones (Scene *scene, Object *ob, short sel)
        }
        
        /* exit editmode (recalculates pchans too) */
-       ED_armature_from_edit(scene, ob);
+       ED_armature_from_edit(ob);
        ED_armature_edit_free(ob);
 }
 
 /* separate selected bones into their armature */
-void separate_armature (Scene *scene, View3D *v3d)
+static int separate_armature_exec (bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX get from context
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
        Object *oldob, *newob;
-       Base *base, *oldbase, *newbase;
+       Base *oldbase, *newbase;
        bArmature *arm;
        
-       if ( okee("Separate")==0 ) return;
-
-       waitcursor(1);
-       
+       /* sanity checks */
+       if (obedit == NULL)
+               return OPERATOR_CANCELLED;
        arm= obedit->data;
        
+       /* set wait cursor in case this takes a while */
+       WM_cursor_wait(1);
+       
        /* we are going to do this as follows (unlike every other instance of separate):
         *      1. exit editmode +posemode for active armature/base. Take note of what this is.
         *      2. duplicate base - BASACT is the new one now
@@ -999,27 +1022,24 @@ void separate_armature (Scene *scene, View3D *v3d)
         */
        
        /* 1) only edit-base selected */
-       base= FIRSTBASE;
-       for (base= FIRSTBASE; base; base= base->next) {
-               if (base->lay & v3d->lay) {
-                       if (base->object==obedit) base->flag |= 1;
-                       else base->flag &= ~1;
-               }
+       // TODO: use context iterators for this?
+       CTX_DATA_BEGIN(C, Base *, base, visible_bases) {
+               if (base->object==obedit) base->flag |= 1;
+               else base->flag &= ~1;
        }
+       CTX_DATA_END;
        
        /* 1) store starting settings and exit editmode */
        oldob= obedit;
        oldbase= BASACT;
-       oldob->flag &= ~OB_POSEMODE;
-       oldbase->flag &= ~OB_POSEMODE;
+       oldob->mode &= ~OB_MODE_POSE;
+       //oldbase->flag &= ~OB_POSEMODE;
        
-       ED_armature_from_edit(scene, obedit);
+       ED_armature_from_edit(obedit);
        ED_armature_edit_free(obedit);
        
        /* 2) duplicate base */
-       adduplicate(1, USER_DUP_ARM); /* no transform and zero so do get a linked dupli */
-       
-       newbase= BASACT; /* basact is set in adduplicate() */
+       newbase= ED_object_add_duplicate(scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
        newob= newbase->object;         
        newbase->flag &= ~SELECT;
        
@@ -1032,21 +1052,38 @@ void separate_armature (Scene *scene, View3D *v3d)
        /* 4) fix links before depsgraph flushes */ // err... or after?
        separated_armature_fix_links(oldob, newob);
        
-       DAG_object_flush_update(scene, oldob, OB_RECALC_DATA);  /* this is the original one */
-       DAG_object_flush_update(scene, newob, OB_RECALC_DATA);  /* this is the separated one */
+       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 */
        
        
        /* 5) restore original conditions */
        obedit= oldob;
-       BASACT= oldbase;
-       BASACT->flag |= SELECT;
        
        ED_armature_to_edit(obedit);
        
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
+       
        /* recalc/redraw + cleanup */
-       waitcursor(0);
+       WM_cursor_wait(0);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_separate (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Separate Armature";
+       ot->idname= "ARMATURE_OT_separate";
+       ot->description= "Isolate selected bones into a separate armature.";
        
-       BIF_undo_push("Separate Armature");
+       /* callbacks */
+       ot->invoke= WM_operator_confirm;
+       ot->exec= separate_armature_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* **************** END tools on Editmode Armature **************** */
@@ -1207,72 +1244,105 @@ static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_
        return chbone;
 }
 
-
-/* used by posemode and editmode */
-void setflag_armature (Scene *scene, short mode)
+/* callback for posemode setflag */
+static int pose_setflag_exec (bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       Object *ob;
-       bArmature *arm; 
-       int flag;
-       
-       /* get data */
-       if (obedit)
-               ob= obedit;
-       else if (OBACT)
-               ob= OBACT;
-       else
-               return;
-       arm= (bArmature *)ob->data;
+       int flag= RNA_enum_get(op->ptr, "type");
+       int mode= RNA_enum_get(op->ptr, "mode");
        
-       /* get flag to set (sync these with the ones used in eBone_Flag */
-       if (mode == 2)
-               flag= pupmenu("Disable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
-       else if (mode == 1)
-               flag= pupmenu("Enable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
-       else
-               flag= pupmenu("Toggle Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
-       switch (flag) {
-               case 1:         flag = BONE_DRAWWIRE;   break;
-               case 2:         flag = BONE_NO_DEFORM; break;
-               case 3:         flag = BONE_MULT_VG_ENV; break;
-               case 4:         flag = BONE_HINGE; break;
-               case 5:         flag = BONE_NO_SCALE; break;
-               case 6:         flag = BONE_EDITMODE_LOCKED; break;
-               default:        return;
-       }
-       
-       /* determine which mode armature is in */
-       if ((!obedit) && (ob->flag & OB_POSEMODE)) {
-               /* deal with pose channels */
-               bPoseChannel *pchan;
-               
-               /* set setting */
-               for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-                       if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
-                               if (pchan->bone->flag & BONE_SELECTED) {
-                                       bone_setflag(&pchan->bone->flag, flag, mode);
-                               }
-                       }
-               }
+       /* loop over all selected pchans */
+       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pchans) 
+       {
+               bone_setflag(&pchan->bone->flag, flag, mode);
        }
-       else if (obedit) {
-               /* deal with editbones */
-               EditBone *curbone;
-               
-               /* set setting */
-               for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
-                       if (arm->layer & curbone->layer) {
-                               if (curbone->flag & BONE_SELECTED) {
-                                       bone_setflag(&curbone->flag, flag, mode);
-                               }
-                       }
-               }
+       CTX_DATA_END;
+       
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, CTX_data_active_object(C));
+       
+       return OPERATOR_FINISHED;
+}
+
+/* callback for editbones setflag */
+static int armature_bones_setflag_exec (bContext *C, wmOperator *op)
+{
+       int flag= RNA_enum_get(op->ptr, "type");
+       int mode= RNA_enum_get(op->ptr, "mode");
+       
+       /* loop over all selected pchans */
+       CTX_DATA_BEGIN(C, EditBone *, ebone, selected_bones) 
+       {
+               bone_setflag(&ebone->flag, flag, mode);
        }
+       CTX_DATA_END;
+       
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, CTX_data_edit_object(C));
+       
+       return OPERATOR_FINISHED;
+}
+
+/* settings that can be changed */
+static EnumPropertyItem prop_bone_setting_types[] = {
+       {BONE_DRAWWIRE, "DRAWWIRE", 0, "Draw Wire", ""},
+       {BONE_NO_DEFORM, "DEFORM", 0, "Deform", ""},
+       {BONE_MULT_VG_ENV, "MULT_VG", 0, "Multiply Vertex Groups", ""},
+       {BONE_HINGE, "HINGE", 0, "Hinge", ""},
+       {BONE_NO_SCALE, "NO_SCALE", 0, "No Scale", ""},
+       {BONE_EDITMODE_LOCKED, "LOCKED", 0, "Locked", "(For EditMode only)"},
+       {0, NULL, 0, NULL, NULL}
+};
+
+/* ways that settings can be changed */
+static EnumPropertyItem prop_bone_setting_modes[] = {
+       {0, "CLEAR", 0, "Clear", ""},
+       {1, "ENABLE", 0, "Enable", ""},
+       {2, "TOGGLE", 0, "Toggle", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+
+void ARMATURE_OT_flags_set (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Set Bone Flags";
+       ot->idname= "ARMATURE_OT_flags_set";
+       ot->description= "Set flags for armature bones.";
+       
+       /* callbacks */
+       ot->invoke= WM_menu_invoke;
+       ot->exec= armature_bones_setflag_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* properties */
+       RNA_def_enum(ot->srna, "type", prop_bone_setting_types, 0, "Type", "");
+       RNA_def_enum(ot->srna, "mode", prop_bone_setting_modes, 0, "Mode", "");
+}
+
+void POSE_OT_flags_set (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Set Bone Flags";
+       ot->idname= "POSE_OT_flags_set";
+       ot->description= "Set flags for armature bones.";
        
-       BIF_undo_push("Change Bone Setting");
+       /* callbacks */
+       ot->invoke= WM_menu_invoke;
+       ot->exec= pose_setflag_exec;
+       ot->poll= ED_operator_posemode;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* properties */
+       RNA_def_enum(ot->srna, "type", prop_bone_setting_types, 0, "Type", "");
+       RNA_def_enum(ot->srna, "mode", prop_bone_setting_modes, 0, "Mode", "");
 }
 
+
 /* **************** END PoseMode & EditMode *************************** */
 /* **************** Posemode stuff ********************** */
 
@@ -1435,7 +1505,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e
 
        }
 
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
 
        /* BIF_undo_push("Select connected"); */
 
@@ -1457,8 +1527,6 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot)
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       /* props */     
 }
 
 /* does bones and points */
@@ -1601,10 +1669,8 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
 
        /* cancel if nothing selected */
        if (CTX_DATA_COUNT(C, selected_bones) == 0)
-         return OPERATOR_CANCELLED;
-
-       /* if (okee("Erase selected bone(s)")==0) return; */
-
+               return OPERATOR_CANCELLED;
+       
        /* Select mirrored bones */
        if (arm->flag & ARM_MIRROR_EDIT) {
                for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
@@ -1668,7 +1734,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
        }
        
        
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
 
        WM_event_add_notifier(C, NC_OBJECT, obedit);
 
@@ -1695,7 +1761,7 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
  * toggle==2: only active tag
  * toggle==3: swap (no test)
  */
-void deselectall_armature(Object *obedit, int toggle, int doundo)
+void ED_armature_deselectall(Object *obedit, int toggle, int doundo)
 {
        bArmature *arm= obedit->data;
        EditBone        *eBone;
@@ -1742,7 +1808,7 @@ void deselectall_armature(Object *obedit, int toggle, int doundo)
                }
        }
        
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        if (doundo) {
                if (sel==1) BIF_undo_push("Select All");
                else BIF_undo_push("Deselect All");
@@ -1767,7 +1833,7 @@ void mouse_armature(bContext *C, short mval[2], int extend)
        if (nearBone) {
 
                if (!extend)
-                       deselectall_armature(obedit, 0, 0);
+                       ED_armature_deselectall(obedit, 0, 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 */
@@ -1814,7 +1880,7 @@ void mouse_armature(bContext *C, short mval[2], int extend)
                                nearBone->flag |= selmask;
                }
                
-               armature_sync_selection(arm->edbo);
+               ED_armature_sync_selection(arm->edbo);
                
                if(nearBone) {
                        /* then now check for active status */
@@ -1822,7 +1888,7 @@ void mouse_armature(bContext *C, short mval[2], int extend)
                        if(nearBone->flag & BONE_SELECTED) nearBone->flag |= BONE_ACTIVE;
                }
                
-               WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+               WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, vc.obedit);
        }
 }
 
@@ -1965,7 +2031,7 @@ static EnumPropertyItem prop_calc_roll_types[] = {
 static int armature_calc_roll_exec(bContext *C, wmOperator *op) 
 {
        Scene *scene= CTX_data_scene(C);
-       View3D *v3d= (View3D *)CTX_wm_space_data(C);
+       View3D *v3d= CTX_wm_view3d(C);
        Object *ob= CTX_data_edit_object(C);
        void (*roll_func)(Scene *, View3D *, EditBone *) = NULL;
        
@@ -2145,7 +2211,7 @@ void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
        Mat3MulMat3(totmat, obmat, viewmat);
        Mat3Inv(imat, totmat);
        
-       deselectall_armature(obedit, 0, 0);
+       ED_armature_deselectall(obedit, 0, 0);
        
        /*      Create a bone   */
        bone= add_editbone(obedit, "Bone");
@@ -2198,7 +2264,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op)
                to_root= 1;
        }
        
-       deselectall_armature(obedit, 0, 0);
+       ED_armature_deselectall(obedit, 0, 0);
        
        /* we re-use code for mirror editing... */
        flipbone= NULL;
@@ -2246,7 +2312,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op)
                
        }
        
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
 
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
        
@@ -2473,6 +2539,8 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *edit
                                        VECCOPY(channew->limitmax, chanold->limitmax);
                                        VECCOPY(channew->stiffness, chanold->stiffness);
                                        channew->ikstretch= chanold->ikstretch;
+                                       channew->ikrotweight= chanold->ikrotweight;
+                                       channew->iklinweight= chanold->iklinweight;
                                        
                                        /* constraints */
                                        listnew = &channew->constraints;
@@ -2508,7 +2576,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
        if (CTX_DATA_COUNT(C, selected_bones) == 0)
          return OPERATOR_CANCELLED;
        
-       armature_sync_selection(arm->edbo); // XXX why is this needed?
+       ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
 
        preEditBoneDuplicate(arm->edbo);
 
@@ -2564,6 +2632,9 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
                                                                /* copy transform locks */
                                                                channew->protectflag = chanold->protectflag;
                                                                
+                                                               /* copy rotation mode */
+                                                               channew->rotmode = chanold->rotmode;
+                                                               
                                                                /* copy bone group */
                                                                channew->agrp_index= chanold->agrp_index;
                                                                
@@ -2573,6 +2644,8 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
                                                                VECCOPY(channew->limitmax, chanold->limitmax);
                                                                VECCOPY(channew->stiffness, chanold->stiffness);
                                                                channew->ikstretch= chanold->ikstretch;
+                                                               channew->ikrotweight= chanold->ikrotweight;
+                                                               channew->iklinweight= chanold->iklinweight;
                                                                
                                                                /* constraints */
                                                                listnew = &channew->constraints;
@@ -2645,11 +2718,11 @@ static int armature_duplicate_selected_invoke(bContext *C, wmOperator *op, wmEve
        return retv;
 }
 
-void ARMATURE_OT_duplicate_selected(wmOperatorType *ot)
+void ARMATURE_OT_duplicate(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Duplicate Selected Bone(s)";
-       ot->idname= "ARMATURE_OT_duplicate_selected";
+       ot->idname= "ARMATURE_OT_duplicate";
        
        /* api callbacks */
        ot->invoke = armature_duplicate_selected_invoke;
@@ -2724,6 +2797,7 @@ static void chains_find_tips (ListBase *edbo, ListBase *list)
        }
 }
 
+/* --------------------- */
 
 static void fill_add_joint (EditBone *ebo, short eb_tail, ListBase *points)
 {
@@ -2777,23 +2851,29 @@ static void fill_add_joint (EditBone *ebo, short eb_tail, ListBase *points)
 }
 
 /* bone adding between selected joints */
-void fill_bones_armature(Scene *scene, View3D *v3d)
+static int armature_fill_bones_exec (bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
-       EditBone *ebo, *newbone=NULL;
+       Object *obedit= CTX_data_edit_object(C);
+       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)
+               return OPERATOR_CANCELLED;
+       
        /* loop over all bones, and only consider if visible */
-       for (ebo= arm->edbo->first; ebo; ebo= ebo->next) {
-               if (EBONE_VISIBLE(arm, ebo)) {
-                       if (!(ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL))
-                               fill_add_joint(ebo, 0, &points);
-                       if (ebo->flag & BONE_TIPSEL) 
-                               fill_add_joint(ebo, 1, &points);
-               }
+       CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
+       {
+               if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
+                       fill_add_joint(ebone, 0, &points);
+               if (ebone->flag & BONE_TIPSEL) 
+                       fill_add_joint(ebone, 1, &points);
        }
+       CTX_DATA_END;
        
        /* the number of joints determines how we fill:
         *      1) between joint and cursor (joint=head, cursor=tail)
@@ -2803,8 +2883,8 @@ void fill_bones_armature(Scene *scene, View3D *v3d)
        count= BLI_countlist(&points);
        
        if (count == 0) {
-               error("No joints selected");
-               return;
+               BKE_report(op->reports, RPT_ERROR, "No joints selected");
+               return OPERATOR_CANCELLED;
        }
        else if (count == 1) {
                EditBonePoint *ebp;
@@ -2833,14 +2913,14 @@ void fill_bones_armature(Scene *scene, View3D *v3d)
                ebp2= ebp->next;
                
                if ((ebp->head_owner==ebp2->tail_owner) && (ebp->head_owner!=NULL)) {
-                       error("Same bone selected...");
+                       BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
                        BLI_freelistN(&points);
-                       return;
+                       return OPERATOR_CANCELLED;
                }
                if ((ebp->tail_owner==ebp2->head_owner) && (ebp->tail_owner!=NULL)) {
-                       error("Same bone selected...");
+                       BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
                        BLI_freelistN(&points);
-                       return;
+                       return OPERATOR_CANCELLED;
                }
                
                /* find which one should be the 'head' */
@@ -2907,19 +2987,35 @@ void fill_bones_armature(Scene *scene, View3D *v3d)
        }
        else {
                // FIXME.. figure out a method for multiple bones
-               error("Too many points selected"); 
+               BKE_report(op->reports, RPT_ERROR, "Too many points selected"); 
                printf("Points selected: %d \n", count);
                BLI_freelistN(&points);
-               return;
+               return OPERATOR_CANCELLED;
        }
        
        /* free points */
        BLI_freelistN(&points);
        
-       /* undo + updates */
-       BIF_undo_push("Fill Bones");
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_fill (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Fill Between Joints";
+       ot->idname= "ARMATURE_OT_fill";
+       ot->description= "Add bone between selected joint(s) and/or 3D-Cursor.";
+       
+       /* callbacks */
+       ot->exec= armature_fill_bones_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/* --------------------- */
+
 /* this function merges between two bones, removes them and those in-between, 
  * and adjusts the parent relationships for those in-between
  */
@@ -2989,19 +3085,19 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
        }
 }
 
-/* bone merging - has a menu! */
-void merge_armature(Scene *scene)
+
+static int armature_merge_exec (bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
-       short val= 0;
+       Object *obedit= CTX_data_edit_object(C);
+       bArmature *arm= (obedit) ? obedit->data : NULL;
+       short type= RNA_enum_get(op->ptr, "type");
        
-       /* process a menu to determine how to merge */
-       // TODO: there's room for more modes of merging stuff...
-       val= pupmenu("Merge Selected Bones%t|Within Chains%x1");
-       if (val <= 0) return;
+       /* sanity checks */
+       if ELEM(NULL, obedit, arm)
+               return OPERATOR_CANCELLED;
        
-       if (val == 1) {
+       /* for now, there's only really one type of merging that's performed... */
+       if (type == 1) {
                /* go down chains, merging bones */
                ListBase chains = {NULL, NULL};
                LinkData *chain, *nchain;
@@ -3009,7 +3105,7 @@ void merge_armature(Scene *scene)
                
                /* get chains (ends on chains) */
                chains_find_tips(arm->edbo, &chains);
-               if (chains.first == NULL) return;
+               if (chains.first == NULL) return OPERATOR_CANCELLED;
                
                /* each 'chain' is the last bone in the chain (with no children) */
                for (chain= chains.first; chain; chain= nchain) {
@@ -3057,9 +3153,35 @@ void merge_armature(Scene *scene)
                BLI_freelistN(&chains);
        }
        
-       /* undo + updates */
-       armature_sync_selection(arm->edbo);
-       BIF_undo_push("Merge Bones");
+       /* updates */
+       ED_armature_sync_selection(arm->edbo);
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_merge (wmOperatorType *ot)
+{
+       static EnumPropertyItem merge_types[] = {
+               {1, "WITHIN_CHAIN", 0, "Within Chains", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       /* identifiers */
+       ot->name= "Merge Bones";
+       ot->idname= "ARMATURE_OT_merge";
+       ot->description= "Merge continuous chains of selected bones.";
+       
+       /* callbacks */
+       ot->invoke= WM_menu_invoke;
+       ot->exec= armature_merge_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* properties */
+       RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", "");
 }
 
 /* ************** END Add/Remove stuff in editmode ************ */
@@ -3080,7 +3202,7 @@ void hide_selected_armature_bones(Scene *scene)
                        }
                }
        }
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Hide Bones");
 }
 
@@ -3100,7 +3222,7 @@ void hide_unselected_armature_bones(Scene *scene)
                        }
                }
        }
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Hide Unselected Bones");
 }
 
@@ -3118,7 +3240,7 @@ void show_all_armature_bones(Scene *scene)
                        }
                }
        }
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Reveal Bones");
 }
 
@@ -3251,7 +3373,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
        if (totbone==0) return OPERATOR_CANCELLED;
        
        /* Transform the endpoints */
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
 
        return OPERATOR_FINISHED;
 }
@@ -3314,7 +3436,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
        Mat3MulMat3(totmat, obmat, viewmat);
        Mat3Inv(imat, totmat);
        
-       deselectall_armature(obedit, 0, 0);
+       ED_armature_deselectall(obedit, 0, 0);
        
        /*      Create a bone   */
        bone= add_editbone(obedit, name);
@@ -3812,7 +3934,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op)
        }
        CTX_DATA_END;
        
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT, ob);
@@ -3839,7 +3961,7 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
 
 /* ****************  Selections  ******************/
 
-static int armature_select_invert_exec(bContext *C, wmOperator *op)
+static int armature_select_inverse_exec(bContext *C, wmOperator *op)
 {
        /*      Set the flags */
        CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
@@ -3854,15 +3976,15 @@ static int armature_select_invert_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ARMATURE_OT_select_invert(wmOperatorType *ot)
+void ARMATURE_OT_select_inverse(wmOperatorType *ot)
 {
        
        /* identifiers */
-       ot->name= "Invert Selection";
-       ot->idname= "ARMATURE_OT_select_invert";
+       ot->name= "Select Inverse";
+       ot->idname= "ARMATURE_OT_select_inverse";
        
        /* api callbacks */
-       ot->exec= armature_select_invert_exec;
+       ot->exec= armature_select_inverse_exec;
        ot->poll= ED_operator_editarmature;
        
        /* flags */
@@ -3963,7 +4085,7 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
                }
        }
        
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
        
@@ -4114,11 +4236,12 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ARMATURE_OT_bones_align(wmOperatorType *ot)
+void ARMATURE_OT_align(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Align Bones";
-       ot->idname= "ARMATURE_OT_bones_align";
+       ot->idname= "ARMATURE_OT_align";
+       ot->description= "Align selected bones to the active bone (or to their parent).";
        
        /* api callbacks */
        ot->invoke = WM_operator_confirm;
@@ -4214,10 +4337,10 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
                }
                
                /* in weightpaint we select the associated vertex group too */
-               if (G.f & G_WEIGHTPAINT) {
+               if (OBACT && OBACT->mode & OB_MODE_WEIGHT_PAINT) {
                        if (nearBone->flag & BONE_ACTIVE) {
-                               vertexgroup_select_by_name(OBACT, nearBone->name);
-                               DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
+                               ED_vgroup_select_by_name(OBACT, nearBone->name);
+                               DAG_id_flush_update(&OBACT->id, OB_RECALC_DATA);
                        }
                }
                
@@ -4306,7 +4429,7 @@ static int bone_skinnable(Object *ob, Bone *bone, void *datap)
        int a, segments;
        struct { Object *armob; void *list; int heat; } *data = datap;
 
-       if(!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
+       if(!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) {
                if (!(bone->flag & BONE_NO_DEFORM)) {
                        if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
                                segments = bone->segments;
@@ -4327,7 +4450,7 @@ static int bone_skinnable(Object *ob, Bone *bone, void *datap)
     return 0;
 }
 
-static int add_defgroup_unique_bone(Object *ob, Bone *bone, void *data) 
+static int ED_vgroup_add_unique_bone(Object *ob, Bone *bone, void *data) 
 {
     /* This group creates a vertex group to ob that has the
       * same name as bone (provided the bone is skinnable). 
@@ -4335,7 +4458,7 @@ static int add_defgroup_unique_bone(Object *ob, Bone *bone, void *data)
       */
        if (!(bone->flag & BONE_NO_DEFORM)) {
                if (!get_named_vertexgroup(ob,bone->name)) {
-                       add_defgroup_name(ob, bone->name);
+                       ED_vgroup_add_name(ob, bone->name);
                        return 1;
                }
     }
@@ -4371,7 +4494,7 @@ static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
        int a, segments;
        struct { Object *armob; void *list; int heat; } *data= datap;
 
-       if (!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
+       if (!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) {
           if (!(bone->flag & BONE_NO_DEFORM)) {
                        if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
                                segments = bone->segments;
@@ -4379,7 +4502,7 @@ static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
                                segments = 1;
                        
                        if (!(defgroup = get_named_vertexgroup(ob, bone->name)))
-                               defgroup = add_defgroup_name(ob, bone->name);
+                               defgroup = ED_vgroup_add_name(ob, bone->name);
                        
                        if (data->list != NULL) {
                                hgroup = (bDeformGroup ***) &data->list;
@@ -4430,17 +4553,17 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
                        
                        /* add the vert to the deform group if weight!=0.0 */
                        if (distance!=0.0)
-                               add_vert_to_defgroup (ob, dgroup, i, distance, WEIGHT_REPLACE);
+                               ED_vgroup_vert_add (ob, dgroup, i, distance, WEIGHT_REPLACE);
                        else
-                               remove_vert_defgroup (ob, dgroup, i);
+                               ED_vgroup_vert_remove (ob, dgroup, i);
                        
                        /* do same for mirror */
                        if (dgroupflip && dgroupflip[j] && iflip >= 0) {
                                if (distance!=0.0)
-                                       add_vert_to_defgroup (ob, dgroupflip[j], iflip, distance,
+                                       ED_vgroup_vert_add (ob, dgroupflip[j], iflip, distance,
                                                WEIGHT_REPLACE);
                                else
-                                       remove_vert_defgroup (ob, dgroupflip[j], iflip);
+                                       ED_vgroup_vert_remove (ob, dgroupflip[j], iflip);
                        }
                }
        }
@@ -4470,7 +4593,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
        float (*root)[3], (*tip)[3], (*verts)[3];
        int *selected;
        int numbones, vertsfilled = 0, i, j, segments = 0;
-       int wpmode = (G.f & G_WEIGHTPAINT);
+       int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
        struct { Object *armob; void *list; int heat; } looper_data;
 
        looper_data.armob = par;
@@ -4619,51 +4742,34 @@ 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)
+void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par, int mode)
 {
        /* Lets try to create some vertex groups 
         * based on the bones of the parent armature.
         */
        bArmature *arm= par->data;
-       short mode;
 
-       /* Prompt the user on whether/how they want the vertex groups
-        * added to the child mesh */
-    mode= pupmenu("Create Vertex Groups? %t|"
-                                 "Don't Create Groups %x1|"
-                                 "Name Groups %x2|"
-                  "Create From Envelopes %x3|"
-                                 "Create From Bone Heat %x4|");
-       
-       mode= 3; // XXX
-       
-       switch (mode) {
-       case 2:
+       if(mode == ARM_GROUPS_NAME) {
                /* Traverse the bone list, trying to create empty vertex 
                 * groups cooresponding to the bone.
                 */
-               bone_looper(ob, arm->bonebase.first, NULL,
-                                       add_defgroup_unique_bone);
+               bone_looper(ob, arm->bonebase.first, NULL, ED_vgroup_add_unique_bone);
+
                if (ob->type == OB_MESH)
-                       create_dverts(ob->data);
-               
-               break;
-       
-       case 3:
-       case 4:
+                       ED_vgroup_data_create(ob->data);
+       }
+       else if(mode == ARM_GROUPS_ENVELOPE || mode == ARM_GROUPS_AUTO) {
                /* Traverse the bone list, trying to create vertex groups 
                 * that are populated with the vertices for which the
                 * bone is closest.
                 */
-               add_verts_to_dgroups(scene, ob, par, (mode == 4), 0);
-               break;
+               add_verts_to_dgroups(scene, ob, par, (mode == ARM_GROUPS_AUTO), 0);
        }
 } 
 /* ************* Clear Pose *****************************/
 
 static int pose_clear_scale_exec(bContext *C, wmOperator *op) 
 {
-       Scene *scene = CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
        
        /* only clear those channels that are not locked */
@@ -4680,7 +4786,7 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *op)
        }
        CTX_DATA_END;
        
-       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
@@ -4705,7 +4811,6 @@ void POSE_OT_scale_clear(wmOperatorType *ot)
 
 static int pose_clear_loc_exec(bContext *C, wmOperator *op) 
 {
-       Scene *scene = CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
        
        /* only clear those channels that are not locked */
@@ -4722,7 +4827,7 @@ static int pose_clear_loc_exec(bContext *C, wmOperator *op)
        }
        CTX_DATA_END;
        
-       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
@@ -4747,39 +4852,60 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
 
 static int pose_clear_rot_exec(bContext *C, wmOperator *op) 
 {
-       Scene *scene = CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
        
        /* only clear those channels that are not locked */
        CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
-               if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ)) {
-                       float eul[3], oldeul[3], quat1[4];
-                       
-                       if (pchan->rotmode == PCHAN_ROT_QUAT) {
-                               QUATCOPY(quat1, pchan->quat);
-                               QuatToEul(pchan->quat, oldeul);
+               if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
+                       /* check if convert to eulers for locking... */
+                       if (pchan->protectflag & OB_LOCK_ROT4D) {
+                               /* perform clamping on a component by component basis */
+                               if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+                                       pchan->quat[0]= (pchan->rotmode == PCHAN_ROT_AXISANGLE) ? 0.0f : 1.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+                                       pchan->quat[1]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+                                       pchan->quat[2]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+                                       pchan->quat[3]= 0.0f;
                        }
                        else {
-                               VECCOPY(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 == PCHAN_ROT_QUAT) {
-                               EulToQuat(eul, pchan->quat);
-                               /* quaternions flip w sign to accumulate rotations correctly */
-                               if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
-                                       QuatMulf(pchan->quat, -1.0f);
+                               /* perform clamping using euler form (3-components) */
+                               float eul[3], oldeul[3], quat1[4];
+                               
+                               if (pchan->rotmode == PCHAN_ROT_QUAT) {
+                                       QUATCOPY(quat1, pchan->quat);
+                                       QuatToEul(pchan->quat, oldeul);
+                               }
+                               else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+                                       AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
+                               }
+                               else {
+                                       VECCOPY(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 == PCHAN_ROT_QUAT) {
+                                       EulToQuat(eul, pchan->quat);
+                                       /* quaternions flip w sign to accumulate rotations correctly */
+                                       if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
+                                               QuatMulf(pchan->quat, -1.0f);
+                                       }
+                               }
+                               else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+                                       AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
+                               }
+                               else {
+                                       VECCOPY(pchan->eul, eul);
                                }
-                       }
-                       else {
-                               VECCOPY(pchan->eul, eul);
                        }
                }                                               
                else { 
@@ -4787,6 +4913,11 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
                                pchan->quat[1]=pchan->quat[2]=pchan->quat[3]= 0.0f; 
                                pchan->quat[0]= 1.0f;
                        }
+                       else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+                               /* by default, make rotation of 0 radians around y-axis (roll) */
+                               pchan->quat[0]=pchan->quat[1]=pchan->quat[3]= 0.0f;
+                               pchan->quat[2]= 1.0f;
+                       }
                        else {
                                pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f;
                        }
@@ -4797,7 +4928,7 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
        }
        CTX_DATA_END;
        
-       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
@@ -4823,7 +4954,7 @@ void POSE_OT_rot_clear(wmOperatorType *ot)
 
 /* ***************** selections ********************** */
 
-static int pose_select_invert_exec(bContext *C, wmOperator *op)
+static int pose_select_inverse_exec(bContext *C, wmOperator *op)
 {
        
        /*      Set the flags */
@@ -4838,15 +4969,15 @@ static int pose_select_invert_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void POSE_OT_select_invert(wmOperatorType *ot)
+void POSE_OT_select_inverse(wmOperatorType *ot)
 {
        
        /* identifiers */
-       ot->name= "Invert Selection";
-       ot->idname= "POSE_OT_select_invert";
+       ot->name= "Select Inverse";
+       ot->idname= "POSE_OT_select_inverse";
        
        /* api callbacks */
-       ot->exec= pose_select_invert_exec;
+       ot->exec= pose_select_inverse_exec;
        ot->poll= ED_operator_posemode;
        
        /* flags */
@@ -5098,9 +5229,9 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldnam
 /* called by UI for renaming a bone */
 /* warning: make sure the original bone was not renamed yet! */
 /* seems messy, but thats what you get with not using pointers but channel names :) */
-void armature_bone_rename(Object *ob, char *oldnamep, char *newnamep)
+void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
 {
-       bArmature *arm= ob->data;
+       Object *ob;
        char newname[MAXBONENAME];
        char oldname[MAXBONENAME];
        
@@ -5232,48 +5363,109 @@ void armature_bone_rename(Object *ob, char *oldnamep, char *newnamep)
        }
 }
 
-/* context editmode object */
-void armature_flip_names(Scene *scene)
+
+static int armature_flip_names_exec (bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
-       EditBone *ebone;
+       Object *ob= CTX_data_edit_object(C);
+       bArmature *arm;
        char newname[32];
        
-       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
-                       if (ebone->flag & BONE_SELECTED) {
-                               BLI_strncpy(newname, ebone->name, sizeof(newname));
-                               bone_flip_name(newname, 1);             // 1 = do strip off number extensions
-                               armature_bone_rename(obedit, ebone->name, newname);
-                       }
-               }
+       /* paranoia checks */
+       if (ELEM(NULL, ob, ob->pose)) 
+               return OPERATOR_CANCELLED;
+       arm= ob->data;
+       
+       /* loop through selected bones, auto-naming them */
+       CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+       {
+               BLI_strncpy(newname, ebone->name, sizeof(newname));
+               bone_flip_name(newname, 1);             // 1 = do strip off number extensions
+               ED_armature_bone_rename(arm, ebone->name, newname);
        }
+       CTX_DATA_END;
+       
+       /* since we renamed stuff... */
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
        
-       BIF_undo_push("Flip names");
+       return OPERATOR_FINISHED;
 }
 
-/* context: edtimode armature */
-void armature_autoside_names(Scene *scene, short axis)
+void ARMATURE_OT_flip_names (wmOperatorType *ot)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
-       EditBone *ebone;
+       /* identifiers */
+       ot->name= "Flip Names";
+       ot->idname= "ARMATURE_OT_flip_names";
+       ot->description= "Flips (and corrects) the names of selected bones.";
+       
+       /* api callbacks */
+       ot->exec= armature_flip_names_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int armature_autoside_names_exec (bContext *C, wmOperator *op)
+{
+       Object *ob= CTX_data_edit_object(C);
+       bArmature *arm;
        char newname[32];
+       short axis= RNA_enum_get(op->ptr, "type");
        
-       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
-                       if (ebone->flag & BONE_SELECTED) {
-                               BLI_strncpy(newname, ebone->name, sizeof(newname));
-                               bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]);
-                               armature_bone_rename(obedit, ebone->name, newname);
-                       }
-               }
+       /* paranoia checks */
+       if (ELEM(NULL, ob, ob->pose)) 
+               return OPERATOR_CANCELLED;
+       arm= ob->data;
+       
+       /* loop through selected bones, auto-naming them */
+       CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+       {
+               BLI_strncpy(newname, ebone->name, sizeof(newname));
+               bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]);
+               ED_armature_bone_rename(arm, ebone->name, newname);
        }
+       CTX_DATA_END;
+       
+       /* since we renamed stuff... */
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_autoside_names (wmOperatorType *ot)
+{
+       static EnumPropertyItem axis_items[]= {
+               {0, "XAXIS", 0, "X-Axis", "Left/Right"},
+               {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
+               {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
+               {0, NULL, 0, NULL, NULL}};
        
-       BIF_undo_push("Auto-side name");
+       /* identifiers */
+       ot->name= "AutoName by Axis";
+       ot->idname= "ARMATURE_OT_autoside_names";
+       ot->description= "Automatically renames the selected bones according to which side of the target axis they fall on.";
+       
+       /* api callbacks */
+       ot->invoke= WM_menu_invoke;
+       ot->exec= armature_autoside_names_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* settings */
+       RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with.");
 }
 
+
+
 /* if editbone (partial) selected, copy data */
 /* context; editmode armature, with mirror editing enabled */
 void transform_armature_mirror_update(Object *obedit)
@@ -5499,7 +5691,7 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
        
        if (obedit != NULL)
        {
-               ED_armature_from_edit(scene, obedit);
+               ED_armature_from_edit(obedit);
                ED_armature_edit_free(obedit);
        }