2.5: Various Fixes
[blender.git] / source / blender / editors / armature / editarmature.c
index 803d9c63cf2fb6bdb1f59f97af7dfa6ed20c036f..97bf3492f7c93c2b47fb5c0b83609d4f6a0116e9 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "BMF_Api.h"
-
 #include "DNA_action_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_constraint_types.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_object.h"
+#include "BKE_report.h"
 #include "BKE_subsurf.h"
 #include "BKE_utildefines.h"
 #include "BKE_modifier.h"
 #include "PIL_time.h"
 
 #include "BIF_gl.h"
+#include "BIF_transform.h"
+#include "BIF_generate.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -87,6 +88,8 @@
 #include "ED_util.h"
 #include "ED_view3d.h"
 
+#include "UI_interface.h"
+
 #include "armature_intern.h"
 #include "meshlaplacian.h"
 
@@ -102,23 +105,23 @@ static void error() {};
 static void error_libdata() {}
 static void BIF_undo_push() {}
 static void adduplicate() {}
-static void countall() {}
 /* ************* 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;
        
        for (ebo=edbo->first; ebo; ebo= ebo->next) {
-               if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
+               if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
                        if (ebo->parent->flag & BONE_TIPSEL)
                                ebo->flag |= BONE_ROOTSEL;
                        else
                                ebo->flag &= ~BONE_ROOTSEL;
                }
+               
                if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
                        ebo->flag |= BONE_SELECTED;
                else
@@ -159,18 +162,18 @@ void make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent)
                VECCOPY(eBone->head, curBone->arm_head);
                VECCOPY(eBone->tail, curBone->arm_tail);                
                
-               eBone->roll= 0.0;
+               eBone->roll= 0.0f;
                
                /* roll fixing */
                VecSubf(delta, eBone->tail, eBone->head);
-               vec_roll_to_mat3(delta, 0.0, postmat);
+               vec_roll_to_mat3(delta, 0.0f, postmat);
                
                Mat3CpyMat4(premat, curBone->arm_mat);
                
                Mat3Inv(imat, postmat);
                Mat3MulMat3(difmat, imat, premat);
                
-               eBone->roll = atan2(difmat[2][0], difmat[2][2]);
+               eBone->roll = (float)atan2(difmat[2][0], difmat[2][2]);
                
                /* rest of stuff copy */
                eBone->length= curBone->length;
@@ -231,7 +234,7 @@ static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist)
                        printmatrix4("difmat", difmat);
                        printf ("Roll = %f\n",  (-atan2(difmat[2][0], difmat[2][2]) * (180.0/M_PI)));
 #endif
-                       curBone->roll = -atan2(difmat[2][0], difmat[2][2]);
+                       curBone->roll = (float)-atan2(difmat[2][0], difmat[2][2]);
                        
                        /* and set restposition again */
                        where_is_armature_bone(curBone, curBone->parent);
@@ -400,13 +403,13 @@ void docenter_armature (Scene *scene, View3D *v3d, Object *ob, int centermode)
                        DO_MINMAX(ebone->tail, min, max);
                }
                
-               cent[0]= (min[0]+max[0])/2.0f;
-               cent[1]= (min[1]+max[1])/2.0f;
-               cent[2]= (min[2]+max[2])/2.0f;
+               cent[0]= (min[0] + max[0]) / 2.0f;
+               cent[1]= (min[1] + max[1]) / 2.0f;
+               cent[2]= (min[2] + max[2]) / 2.0f;
        }
        
        /* Do the adjustments */
-       for (ebone= arm->edbo->first; ebone; ebone=ebone->next){
+       for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
                VecSubf(ebone->head, ebone->head, cent);
                VecSubf(ebone->tail, ebone->tail, cent);
        }
@@ -419,9 +422,9 @@ void docenter_armature (Scene *scene, View3D *v3d, Object *ob, int centermode)
                Mat3CpyMat4(omat, ob->obmat);
                
                Mat3MulVecfl(omat, cent);
-               ob->loc[0]+= cent[0];
-               ob->loc[1]+= cent[1];
-               ob->loc[2]+= cent[2];
+               ob->loc[0] += cent[0];
+               ob->loc[1] += cent[1];
+               ob->loc[2] += cent[2];
        }
        else 
                ED_armature_edit_free(ob);
@@ -459,13 +462,16 @@ static EditBone *editbone_name_exists (ListBase *edbo, char *name)
 }
 
 /* note: there's a unique_bone_name() too! */
-void unique_editbone_name (ListBase *edbo, char *name)
+void unique_editbone_name (ListBase *edbo, char *name, EditBone *bone)
 {
+       EditBone *dupli;
        char            tempname[64];
        int                     number;
        char            *dot;
+
+       dupli = editbone_name_exists(edbo, name);
        
-       if (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])) {
@@ -474,7 +480,7 @@ void unique_editbone_name (ListBase *edbo, char *name)
                                *dot=0;
                }
                
-               for (number = 1; number <=999; number++) {
+               for (number = 1; number <= 999; number++) {
                        sprintf(tempname, "%s.%03d", name, number);
                        if (!editbone_name_exists(edbo, tempname)) {
                                BLI_strncpy(name, tempname, 32);
@@ -675,7 +681,7 @@ int join_armature(Scene *scene, View3D *v3d)
        
        /*      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 (arm->edbo) return 0;
        
        if (object_data_is_libdata(ob)) {
                error_libdata();
@@ -713,7 +719,7 @@ int join_armature(Scene *scene, View3D *v3d)
                                        curbone= editbone_name_exists(curarm->edbo, pchan->name);
                                        
                                        /* Get new name */
-                                       unique_editbone_name(arm->edbo, curbone->name);
+                                       unique_editbone_name(arm->edbo, curbone->name, NULL);
                                        
                                        /* Transform the bone */
                                        {
@@ -728,6 +734,7 @@ int join_armature(Scene *scene, View3D *v3d)
                                                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);
@@ -742,7 +749,7 @@ int join_armature(Scene *scene, View3D *v3d)
                                                Mat4Invert(imat, premat);
                                                Mat4MulMat4(difmat, postmat, imat);
                                                
-                                               curbone->roll -= atan2(difmat[2][0], difmat[2][2]);
+                                               curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
                                        }
                                        
                                        /* Fix Constraints and Other Links to this Bone and Armature */
@@ -1038,8 +1045,6 @@ void separate_armature (Scene *scene, View3D *v3d)
        
        /* recalc/redraw + cleanup */
        waitcursor(0);
-
-       countall(); // flush!
        
        BIF_undo_push("Separate Armature");
 }
@@ -1136,7 +1141,8 @@ static void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *
 
 /* used by posemode as well editmode */
 /* only checks scene->basact! */
-static void *get_nearest_bone (bContext *C, short findunsel)
+/* x and y are mouse coords (area space) */
+static void *get_nearest_bone (bContext *C, short findunsel, int x, int y)
 {
        ViewContext vc;
        rcti rect;
@@ -1146,6 +1152,8 @@ static void *get_nearest_bone (bContext *C, short findunsel)
        view3d_set_viewcontext(C, &vc);
        
        // rect.xmin= ... mouseco!
+       rect.xmin= rect.xmax= x;
+       rect.ymin= rect.ymax= y;
        
        glInitNames();
        hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
@@ -1168,7 +1176,6 @@ static void bone_setflag (int *bone, int flag, short mode)
                                *bone &= ~flag;
                        else
                                *bone ^= flag;
-
                }
                else {
                        if (mode == 2)
@@ -1200,60 +1207,6 @@ static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_
        return chbone;
 }
 
-void armature_select_hierarchy(Scene *scene, short direction, short add_to_sel)
-{
-       Object *obedit= scene->obedit; // XXX get from context
-       Object *ob;
-       bArmature *arm;
-       EditBone *curbone, *pabone, *chbone;
-
-       if (!obedit) return;
-       else ob= obedit;
-       arm= (bArmature *)ob->data;
-       
-       for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
-               if (EBONE_VISIBLE(arm, curbone)) {
-                       if (curbone->flag & (BONE_ACTIVE)) {
-                               if (direction == BONE_SELECT_PARENT) {
-                                       if (curbone->parent == NULL) continue;
-                                       else pabone = curbone->parent;
-                                       
-                                       if (EBONE_VISIBLE(arm, pabone)) {
-                                               pabone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
-                                               if (pabone->parent)     pabone->parent->flag |= BONE_TIPSEL;
-                                               
-                                               if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
-                                               curbone->flag &= ~BONE_ACTIVE;
-                                               break;
-                                       }
-                                       
-                               } 
-                               else { // BONE_SELECT_CHILD
-                                       chbone = editbone_get_child(arm, curbone, 1);
-                                       if (chbone == NULL) continue;
-                                       
-                                       if (EBONE_VISIBLE(arm, chbone)) {
-                                               chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
-                                               
-                                               if (!add_to_sel) {
-                                                       curbone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL);
-                                                       if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL;
-                                               }
-                                               curbone->flag &= ~BONE_ACTIVE;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       countall(); // flushes selection!
-       
-       if (direction==BONE_SELECT_PARENT)
-               BIF_undo_push("Select edit bone parent");
-       if (direction==BONE_SELECT_CHILD)
-               BIF_undo_push("Select edit bone child");
-}
 
 /* used by posemode and editmode */
 void setflag_armature (Scene *scene, short mode)
@@ -1346,19 +1299,29 @@ static void selectconnected_posebonechildren (Object *ob, Bone *bone)
 }
 
 /* within active object context */
-void selectconnected_posearmature(bContext *C)
-{
+/* previously known as "selectconnected_posearmature" */
+static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{  
+       Bone *bone, *curBone, *next= NULL;
+       int shift= 0; // XXX in pose mode, Shift+L is bound to another command
+                                 // named "PoseLib Add Current Pose"
+       int x, y;
+       ARegion *ar;
        Object *ob= CTX_data_edit_object(C);
-       Bone *bone, *curBone, *next;
-       int shift= 0; // XXX
+       ar= CTX_wm_region(C);
+
+       x= event->x - ar->winrct.xmin;
+       y= event->y - ar->winrct.ymin;
+
+       view3d_operator_needs_opengl(C);
        
        if (shift)
-               bone= get_nearest_bone(C, 0);
+               bone= get_nearest_bone(C, 0, x, y);
        else
-               bone = get_nearest_bone(C, 1);
+               bone= get_nearest_bone(C, 1, x, y);
        
        if (!bone)
-               return;
+               return OPERATOR_CANCELLED;
        
        /* Select parents */
        for (curBone=bone; curBone; curBone=next){
@@ -1380,30 +1343,58 @@ void selectconnected_posearmature(bContext *C)
                selectconnected_posebonechildren (ob, curBone);
        }
        
-       countall(); // flushes selection!
+       // XXX this only counted the number of pose channels selected
+       //countall(); // flushes selection!
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
 
-       BIF_undo_push("Select connected");
+       return OPERATOR_FINISHED;
+}
 
+void POSE_OT_select_linked(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Select Connected";
+       ot->idname= "POSE_OT_select_linked";
+       
+       /* api callbacks */
+       ot->exec= NULL;
+       ot->invoke= pose_select_connected_invoke;
+       ot->poll= ED_operator_posemode;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */     
 }
 
 /* **************** END Posemode stuff ********************** */
 /* **************** EditMode stuff ********************** */
 
 /* called in space.c */
-void selectconnected_armature(bContext *C)
+/* previously "selectconnected_armature" */
+static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       Object *obedit= CTX_data_edit_object(C);
-       bArmature *arm= obedit->data;
+       bArmature *arm;
        EditBone *bone, *curBone, *next;
        int shift= 0; // XXX
+       int x, y;
+       ARegion *ar;
+       Object *obedit= CTX_data_edit_object(C);
+       arm= obedit->data;
+       ar= CTX_wm_region(C);
+
+       x= event->x - ar->winrct.xmin;
+       y= event->y - ar->winrct.ymin;
+
+       view3d_operator_needs_opengl(C);
 
        if (shift)
-               bone= get_nearest_bone(C, 0);
+               bone= get_nearest_bone(C, 0, x, y);
        else
-               bone= get_nearest_bone(C, 1);
+               bone= get_nearest_bone(C, 1, x, y);
 
        if (!bone)
-               return;
+               return OPERATOR_CANCELLED;
 
        /* Select parents */
        for (curBone=bone; curBone; curBone=next){
@@ -1444,10 +1435,30 @@ void selectconnected_armature(bContext *C)
 
        }
 
-       countall(); // flushes selection!
+       ED_armature_sync_selection(arm->edbo);
+
+       /* BIF_undo_push("Select connected"); */
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
 
-       BIF_undo_push("Select connected");
+       return OPERATOR_FINISHED;
+}
 
+void ARMATURE_OT_select_linked(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Select Connected";
+       ot->idname= "ARMATURE_OT_select_linked";
+       
+       /* api callbacks */
+       ot->exec= NULL;
+       ot->invoke= armature_select_linked_invoke;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */     
 }
 
 /* does bones and points */
@@ -1556,11 +1567,14 @@ static void delete_bone(ListBase *edbo, EditBone* exBone)
 }
 
 /* context: editmode armature */
-EditBone *armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
+EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
 {
        EditBone *eboflip= NULL;
        char name[32];
        
+       if (ebo == NULL)
+               return NULL;
+       
        BLI_strncpy(name, ebo->name, sizeof(name));
        bone_flip_name(name, 0);                // 0 = don't strip off number extensions
        
@@ -1574,22 +1588,29 @@ EditBone *armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
        return eboflip;
 }
 
+
+/* previously delete_armature */
 /* only editmode! */
-void delete_armature(Scene *scene)
+static int armature_delete_selected_exec(bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
+       bArmature *arm;
        EditBone        *curBone, *next;
        bConstraint *con;
-       
-       if (okee("Erase selected bone(s)")==0) return;
+       Object *obedit= CTX_data_edit_object(C); // XXX get from context
+       arm = obedit->data;
+
+       /* cancel if nothing selected */
+       if (CTX_DATA_COUNT(C, selected_bones) == 0)
+         return OPERATOR_CANCELLED;
+
+       /* if (okee("Erase selected bone(s)")==0) return; */
 
        /* 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 = armature_bone_get_mirrored(arm->edbo, curBone);
+                                       next = ED_armature_bone_get_mirrored(arm->edbo, curBone);
                                        if (next)
                                                next->flag |= BONE_SELECTED;
                                }
@@ -1647,16 +1668,33 @@ void delete_armature(Scene *scene)
        }
        
        
-       countall(); // flushes selection!
+       ED_armature_sync_selection(arm->edbo);
+
+       WM_event_add_notifier(C, NC_OBJECT, obedit);
+
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_delete(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Delete Selected Bone(s)";
+       ot->idname= "ARMATURE_OT_delete";
+       
+       /* api callbacks */
+       ot->invoke = WM_operator_confirm;
+       ot->exec = armature_delete_selected_exec;
+       ot->poll = ED_operator_editarmature;
        
-       BIF_undo_push("Delete bone(s)");
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* toggle==0: deselect
-toggle==1: swap (based on test)
-toggle==2: only active tag
-toggle==3: swap (no test)
-*/
+ * toggle==1: swap (based on test)
+ * toggle==2: only active tag
+ * toggle==3: swap (no test)
+ */
 void deselectall_armature(Object *obedit, int toggle, int doundo)
 {
        bArmature *arm= obedit->data;
@@ -1704,7 +1742,7 @@ void deselectall_armature(Object *obedit, int toggle, int doundo)
                }
        }
        
-       countall(); // flushes selection!
+       ED_armature_sync_selection(arm->edbo);
        if (doundo) {
                if (sel==1) BIF_undo_push("Select All");
                else BIF_undo_push("Deselect All");
@@ -1723,6 +1761,8 @@ void mouse_armature(bContext *C, short mval[2], int extend)
 
        view3d_set_viewcontext(C, &vc);
        
+       BIF_sk_selectStroke(C, mval, extend);
+       
        nearBone= get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
        if (nearBone) {
 
@@ -1774,7 +1814,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 */
@@ -1816,6 +1856,8 @@ void ED_armature_to_edit(Object *ob)
        ED_armature_edit_free(ob);
        arm->edbo= MEM_callocN(sizeof(ListBase), "edbo armature");
        make_boneList(arm->edbo, &arm->bonebase,NULL);
+
+//     BIF_freeTemplates(); /* force template update when entering editmode */
 }
 
 
@@ -1900,7 +1942,7 @@ void auto_align_ebone_tocursor(Scene *scene, View3D *v3d, EditBone *ebone)
        /* 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] = atan2(vec[0], vec[2]);
+               rot[1] = (float)atan2(vec[0], vec[2]);
                rot[0] = rot[2] = 0.0f;
                EulToMat4(rot, rmat);
                
@@ -1913,20 +1955,22 @@ void auto_align_ebone_tocursor(Scene *scene, View3D *v3d, EditBone *ebone)
        }
 }
 
-/* Sets the roll value of selected bones, depending on the mode
- *     mode == 0: their z-axes point upwards 
- *     mode == 1: their z-axes point towards 3d-cursor
- */
-void auto_align_armature(Scene *scene, View3D *v3d, short mode)
+
+static EnumPropertyItem prop_calc_roll_types[] = {
+       {0, "GLOBALUP", 0, "Z-Axis Up", ""},
+       {1, "CURSOR", 0, "Z-Axis to Cursor", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+static int armature_calc_roll_exec(bContext *C, wmOperator *op) 
 {
-       Object *obedit= scene->obedit;
-       bArmature *arm= obedit->data;
-       EditBone *ebone;
-       EditBone *flipbone = NULL;
+       Scene *scene= CTX_data_scene(C);
+       View3D *v3d= (View3D *)CTX_wm_space_data(C);
+       Object *ob= CTX_data_edit_object(C);
        void (*roll_func)(Scene *, View3D *, EditBone *) = NULL;
        
        /* specific method used to calculate roll depends on mode */
-       switch (mode) {
+       switch (RNA_enum_get(op->ptr, "type")) {
                case 1:  /* Z-Axis point towards cursor */
                        roll_func= auto_align_ebone_tocursor;
                        break;
@@ -1935,19 +1979,36 @@ void auto_align_armature(Scene *scene, View3D *v3d, short mode)
                        break;
        }
        
-       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
-               if (EBONE_VISIBLE(arm, ebone)) {
-                       if (arm->flag & ARM_MIRROR_EDIT)
-                               flipbone = armature_bone_get_mirrored(arm->edbo, ebone);
-                       
-                       if ((ebone->flag & BONE_SELECTED) || 
-                               (flipbone && (flipbone->flag & BONE_SELECTED))) 
-                       {
-                               /* roll func is a callback which assumes that all is well */
-                               roll_func(scene, v3d, ebone);                   
-                       }
-               }
+       /* 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);
        }
+       CTX_DATA_END;
+       
+
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Recalculate Roll";
+       ot->idname= "ARMATURE_OT_calculate_roll";
+       
+       /* api callbacks */
+       ot->invoke = WM_menu_invoke;
+       ot->exec = armature_calc_roll_exec;
+       ot->poll = ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* properties */
+       RNA_def_enum(ot->srna, "type", prop_calc_roll_types, 0, "Type", "");
 }
 
 /* **************** undo for armatures ************** */
@@ -2031,33 +2092,40 @@ void undo_push_armature(bContext *C, char *name)
 /* *************** Adding stuff in editmode *************** */
 
 /* default bone add, returns it selected, but without tail set */
-static EditBone *add_editbone(Object *obedit, char *name)
+EditBone *addEditBone(bArmature *arm, char *name)
 {
-       bArmature *arm= obedit->data;
-       
        EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
        
        BLI_strncpy(bone->name, name, 32);
-       unique_editbone_name(arm->edbo, bone->name);
+       unique_editbone_name(arm->edbo, bone->name, NULL);
        
        BLI_addtail(arm->edbo, bone);
        
        bone->flag |= BONE_TIPSEL;
-       bone->weight= 1.0F;
-       bone->dist= 0.25F;
-       bone->xwidth= 0.1;
-       bone->zwidth= 0.1;
-       bone->ease1= 1.0;
-       bone->ease2= 1.0;
-       bone->rad_head= 0.10;
-       bone->rad_tail= 0.05;
+       bone->weight= 1.0f;
+       bone->dist= 0.25f;
+       bone->xwidth= 0.1f;
+       bone->zwidth= 0.1f;
+       bone->ease1= 1.0f;
+       bone->ease2= 1.0f;
+       bone->rad_head= 0.10f;
+       bone->rad_tail= 0.05f;
        bone->segments= 1;
        bone->layer= arm->layer;
        
        return bone;
 }
 
-static void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, short newob)
+/* default bone add, returns it selected, but without tail set */
+static EditBone *add_editbone(Object *obedit, char *name)
+{
+       bArmature *arm= obedit->data;
+
+       return addEditBone(arm, name);
+}
+
+/* v3d and rv3d are allowed to be NULL */
+void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
 {
        Object *obedit= scene->obedit; // XXX get from context
        float           obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
@@ -2069,7 +2137,7 @@ static void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, sh
        Mat4Invert(obedit->imat, obedit->obmat);
        Mat4MulVecfl(obedit->imat, curs);
 
-       if ( !(newob) || (U.flag & USER_ADD_VIEWALIGNED) ) 
+       if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
                Mat3CpyMat4(obmat, rv3d->viewmat);
        else Mat3One(obmat);
        
@@ -2084,60 +2152,30 @@ static void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, sh
 
        VECCOPY(bone->head, curs);
        
-       if ( !(newob) || (U.flag & USER_ADD_VIEWALIGNED) )
+       if ( (U.flag & USER_ADD_VIEWALIGNED) )
                VecAddf(bone->tail, bone->head, imat[1]);       // bone with unit length 1
        else
                VecAddf(bone->tail, bone->head, imat[2]);       // bone with unit length 1, pointing up Z
        
 }
 
-void add_primitiveArmature(Scene *scene, View3D *v3d, int type)
-{
-       RegionView3D *rv3d= NULL; // XXX get from context
-       Object *obedit= scene->obedit; // XXX get from context
-       short newob=0;
-       
-       if(scene->id.lib) return;
-       
-       G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE);
-//     setcursor_space(SPACE_VIEW3D, CURSOR_STD);
-
-// XXX check_editmode(OB_ARMATURE);
-       
-       /* If we're not the "obedit", make a new object and enter editmode */
-       if (obedit==NULL) {
-               add_object(scene, OB_ARMATURE);
-               ED_object_base_init_from_view(NULL, BASACT);    // XXX NULL is C
-               obedit= BASACT->object;
-               
-               where_is_object(scene, obedit);
-               
-               ED_armature_to_edit(obedit);
-//             setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
-               newob=1;
-       }
-       
-       /* no primitive support yet */
-       add_primitive_bone(scene, v3d, rv3d, newob);
-       
-       countall(); // flushes selection!
-
-       if ((newob) && !(U.flag & USER_ADD_EDITMODE)) {
-               ED_armature_from_edit(scene, obedit);
-               ED_armature_edit_free(obedit);
-       }
-       
-       BIF_undo_push("Add primitive");
-}
 
+/* previously addvert_armature */
 /* the ctrl-click method */
-void addvert_armature(Scene *scene, View3D *v3d)
+static int armature_click_extrude_exec(bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
+       View3D *v3d;
+       bArmature *arm;
        EditBone *ebone, *newbone, *flipbone;
        float *curs, mat[3][3],imat[3][3];
        int a, to_root= 0;
+       Object *obedit;
+       Scene *scene;
+
+       scene = CTX_data_scene(C);
+       v3d= CTX_wm_view3d(C);
+       obedit= CTX_data_edit_object(C);
+       arm= obedit->data;
        
        /* find the active or selected bone */
        for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
@@ -2155,7 +2193,7 @@ void addvert_armature(Scene *scene, View3D *v3d)
                        }
                }
                if (ebone == NULL) 
-                       return;
+                       return OPERATOR_CANCELLED;
                
                to_root= 1;
        }
@@ -2165,7 +2203,7 @@ void addvert_armature(Scene *scene, View3D *v3d)
        /* we re-use code for mirror editing... */
        flipbone= NULL;
        if (arm->flag & ARM_MIRROR_EDIT)
-               flipbone= armature_bone_get_mirrored(arm->edbo, ebone);
+               flipbone= ED_armature_bone_get_mirrored(arm->edbo, ebone);
 
        for (a=0; a<2; a++) {
                if (a==1) {
@@ -2208,9 +2246,84 @@ void addvert_armature(Scene *scene, View3D *v3d)
                
        }
        
-       countall();
+       ED_armature_sync_selection(arm->edbo);
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;
+}
+
+static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       /* TODO most of this code is copied from set3dcursor_invoke,
+          it would be better to reuse code in set3dcursor_invoke */
+
+       /* temporarily change 3d cursor position */
+       Scene *scene;
+       ARegion *ar;
+       View3D *v3d;
+       RegionView3D *rv3d;
+       float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3];
+       short mx, my, mval[2];
+       int retv;
+
+       scene= CTX_data_scene(C);
+       ar= CTX_wm_region(C);
+       v3d = CTX_wm_view3d(C);
+       rv3d= CTX_wm_region_view3d(C);
+       
+       fp= give_cursor(scene, v3d);
+       
+       VECCOPY(oldcurs, fp);
+       
+       mx= event->x - ar->winrct.xmin;
+       my= event->y - ar->winrct.ymin;
+       project_short_noclip(ar, fp, mval);
+       
+       initgrabz(rv3d, fp[0], fp[1], fp[2]);
+       
+       if(mval[0]!=IS_CLIPPED) {
+               
+               window_to_3d_delta(ar, dvec, mval[0]-mx, mval[1]-my);
+               VecSubf(fp, fp, dvec);
+       }
+       else {
+               
+               dx= ((float)(mx-(ar->winx/2)))*rv3d->zfac/(ar->winx/2);
+               dy= ((float)(my-(ar->winy/2)))*rv3d->zfac/(ar->winy/2);
+               
+               fz= rv3d->persmat[0][3]*fp[0]+ rv3d->persmat[1][3]*fp[1]+ rv3d->persmat[2][3]*fp[2]+ rv3d->persmat[3][3];
+               fz= fz/rv3d->zfac;
+               
+               fp[0]= (rv3d->persinv[0][0]*dx + rv3d->persinv[1][0]*dy+ rv3d->persinv[2][0]*fz)-rv3d->ofs[0];
+               fp[1]= (rv3d->persinv[0][1]*dx + rv3d->persinv[1][1]*dy+ rv3d->persinv[2][1]*fz)-rv3d->ofs[1];
+               fp[2]= (rv3d->persinv[0][2]*dx + rv3d->persinv[1][2]*dy+ rv3d->persinv[2][2]*fz)-rv3d->ofs[2];
+       }
+
+       /* extrude to the where new cursor is and store the operation result */
+       retv= armature_click_extrude_exec(C, op);
+
+       /* restore previous 3d cursor position */
+       VECCOPY(fp, oldcurs);
+
+       return retv;
+}
+
+void ARMATURE_OT_click_extrude(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Click-Extrude";
+       ot->idname= "ARMATURE_OT_click_extrude";
+       
+       /* api callbacks */
+       ot->invoke = armature_click_extrude_invoke;
+       ot->exec = armature_click_extrude_exec;
+       ot->poll = ED_operator_editarmature;
        
-       BIF_undo_push("Add Bone");
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* props */
 }
 
 /* adds an EditBone between the nominated locations (should be in the right space) */
@@ -2241,19 +2354,35 @@ static EditBone *get_named_editbone(ListBase *edbo, char *name)
        return NULL;
 }
 
-static void update_dup_subtarget(Object *obedit, EditBone *dupBone)
+/* Call this before doing any duplications
+ * */
+void preEditBoneDuplicate(ListBase *editbones)
+{
+       EditBone *eBone;
+       
+       /* clear temp */
+       for (eBone = editbones->first; eBone; eBone = eBone->next)
+       {
+               eBone->temp = NULL;
+       }
+}
+
+/*
+ * Note: When duplicating cross objects, editbones here is the list of bones
+ * from the SOURCE object but ob is the DESTINATION object
+ * */
+void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Object *src_ob, Object *dst_ob)
 {
        /* If an edit bone has been duplicated, lets
         * update it's constraints if the subtarget
         * they point to has also been duplicated
         */
-       bArmature    *arm = obedit->data;
        EditBone     *oldtarget, *newtarget;
        bPoseChannel *chan;
        bConstraint  *curcon;
        ListBase     *conlist;
        
-       if ( (chan = verify_pose_channel(obedit->pose, dupBone->name)) ) {
+       if ( (chan = verify_pose_channel(dst_ob->pose, dupBone->name)) ) {
                if ( (conlist = &chan->constraints) ) {
                        for (curcon = conlist->first; curcon; curcon=curcon->next) {
                                /* does this constraint have a subtarget in
@@ -2267,14 +2396,15 @@ static void update_dup_subtarget(Object *obedit, EditBone *dupBone)
                                        cti->get_constraint_targets(curcon, &targets);
                                        
                                        for (ct= targets.first; ct; ct= ct->next) {
-                                               if ((ct->tar == obedit) && (ct->subtarget[0])) {
-                                                       oldtarget = get_named_editbone(arm->edbo, ct->subtarget);
+                                               if ((ct->tar == src_ob) && (ct->subtarget[0])) {
+                                                       ct->tar = dst_ob; /* update target */ 
+                                                       oldtarget = get_named_editbone(editbones, ct->subtarget);
                                                        if (oldtarget) {
                                                                /* was the subtarget bone duplicated too? If
                                                                 * so, update the constraint to point at the 
                                                                 * duplicate of the old subtarget.
                                                                 */
-                                                               if (oldtarget->flag & BONE_SELECTED){
+                                                               if (oldtarget->temp) {
                                                                        newtarget = (EditBone *) oldtarget->temp;
                                                                        strcpy(ct->subtarget, newtarget->name);
                                                                }
@@ -2290,29 +2420,111 @@ static void update_dup_subtarget(Object *obedit, EditBone *dupBone)
        }
 }
 
+void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob)
+{
+       updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
+}
 
-void adduplicate_armature(Scene *scene)
+
+EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
+       EditBone *eBone = MEM_callocN(sizeof(EditBone), "addup_editbone");
+       
+       /*      Copy data from old bone to new bone */
+       memcpy(eBone, curBone, sizeof(EditBone));
+       
+       curBone->temp = eBone;
+       eBone->temp = curBone;
+       
+       if (name != NULL)
+       {
+               BLI_strncpy(eBone->name, name, 32);
+       }
+
+       unique_editbone_name(editbones, eBone->name, NULL);
+       BLI_addtail(editbones, eBone);
+       
+       /* Lets duplicate the list of constraints that the
+        * current bone has.
+        */
+       if (src_ob->pose) {
+               bPoseChannel *chanold, *channew;
+               ListBase     *listold, *listnew;
+               
+               chanold = verify_pose_channel(src_ob->pose, curBone->name);
+               if (chanold) {
+                       listold = &chanold->constraints;
+                       if (listold) {
+                               /* WARNING: this creates a new posechannel, but there will not be an attached bone 
+                                *              yet as the new bones created here are still 'EditBones' not 'Bones'. 
+                                */
+                               channew = 
+                                       verify_pose_channel(dst_ob->pose, eBone->name);
+                               if (channew) {
+                                       /* copy transform locks */
+                                       channew->protectflag = chanold->protectflag;
+                                       
+                                       /* copy bone group */
+                                       channew->agrp_index= chanold->agrp_index;
+                                       
+                                       /* ik (dof) settings */
+                                       channew->ikflag = chanold->ikflag;
+                                       VECCOPY(channew->limitmin, chanold->limitmin);
+                                       VECCOPY(channew->limitmax, chanold->limitmax);
+                                       VECCOPY(channew->stiffness, chanold->stiffness);
+                                       channew->ikstretch= chanold->ikstretch;
+                                       
+                                       /* constraints */
+                                       listnew = &channew->constraints;
+                                       copy_constraints(listnew, listold);
+                                       
+                                       /* custom shape */
+                                       channew->custom= chanold->custom;
+                               }
+                       }
+               }
+       }
+       
+       return eBone;
+}
+
+EditBone *duplicateEditBone(EditBone *curBone, char *name, ListBase *editbones, Object *ob)
+{
+       return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
+}
+
+/* previously adduplicate_armature */
+static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
+{
+       bArmature *arm;
        EditBone        *eBone = NULL;
        EditBone        *curBone;
        EditBone        *firstDup=NULL; /*      The beginning of the duplicated bones in the edbo list */
+
+       Object *obedit= CTX_data_edit_object(C);
+       arm= obedit->data;
+
+       /* cancel if nothing selected */
+       if (CTX_DATA_COUNT(C, selected_bones) == 0)
+         return OPERATOR_CANCELLED;
        
-       countall(); // flushes selection!
+       ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
+
+       preEditBoneDuplicate(arm->edbo);
 
        /* Select mirrored bones */
        if (arm->flag & ARM_MIRROR_EDIT) {
                for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
                        if (EBONE_VISIBLE(arm, curBone)) {
                                if (curBone->flag & BONE_SELECTED) {
-                                       eBone = armature_bone_get_mirrored(arm->edbo, curBone);
+                                       eBone = ED_armature_bone_get_mirrored(arm->edbo, curBone);
                                        if (eBone)
                                                eBone->flag |= BONE_SELECTED;
                                }
                        }
                }
        }
+
        
        /*      Find the selected bones and duplicate them as needed */
        for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
@@ -2321,13 +2533,13 @@ void adduplicate_armature(Scene *scene)
                                eBone=MEM_callocN(sizeof(EditBone), "addup_editbone");
                                eBone->flag |= BONE_SELECTED;
                                
-                               /*      Copy data from old bone to new bone */
+                               /* Copy data from old bone to new bone */
                                memcpy(eBone, curBone, sizeof(EditBone));
                                
                                curBone->temp = eBone;
                                eBone->temp = curBone;
                                
-                               unique_editbone_name(arm->edbo, eBone->name);
+                               unique_editbone_name(arm->edbo, eBone->name, NULL);
                                BLI_addtail(arm->edbo, eBone);
                                if (!firstDup)
                                        firstDup=eBone;
@@ -2335,11 +2547,11 @@ void adduplicate_armature(Scene *scene)
                                /* Lets duplicate the list of constraints that the
                                 * current bone has.
                                 */
-                               if (OBACT->pose) {
+                               if (obedit->pose) {
                                        bPoseChannel *chanold, *channew;
                                        ListBase     *listold, *listnew;
                                        
-                                       chanold = verify_pose_channel(OBACT->pose, curBone->name);
+                                       chanold = verify_pose_channel(obedit->pose, curBone->name);
                                        if (chanold) {
                                                listold = &chanold->constraints;
                                                if (listold) {
@@ -2347,7 +2559,7 @@ void adduplicate_armature(Scene *scene)
                                                         *              yet as the new bones created here are still 'EditBones' not 'Bones'. 
                                                         */
                                                        channew = 
-                                                               verify_pose_channel(OBACT->pose, eBone->name);
+                                                               verify_pose_channel(obedit->pose, eBone->name);
                                                        if (channew) {
                                                                /* copy transform locks */
                                                                channew->protectflag = chanold->protectflag;
@@ -2382,43 +2594,74 @@ void adduplicate_armature(Scene *scene)
                        if (curBone->flag & BONE_SELECTED) {
                                eBone=(EditBone*) curBone->temp;
                                
-                               /*      If this bone has no parent,
-                               Set the duplicate->parent to NULL
-                               */
-                               if (!curBone->parent)
+                               if (!curBone->parent) {
+                                       /* If this bone has no parent,
+                                        * Set the duplicate->parent to NULL
+                                        */
                                        eBone->parent = NULL;
-                               /*      If this bone has a parent that IS selected,
-                                       Set the duplicate->parent to the curBone->parent->duplicate
-                                       */
-                               else if (curBone->parent->flag & BONE_SELECTED)
+                               }
+                               else if (curBone->parent->temp) {
+                                       /* If this bone has a parent that was duplicated,
+                                        * Set the duplicate->parent to the curBone->parent->temp
+                                        */
                                        eBone->parent= (EditBone *)curBone->parent->temp;
-                               /*      If this bone has a parent that IS not selected,
-                                       Set the duplicate->parent to the curBone->parent
-                                       */
+                               }
                                else {
+                                       /* If this bone has a parent that IS not selected,
+                                        * Set the duplicate->parent to the curBone->parent
+                                        */
                                        eBone->parent=(EditBone*) curBone->parent; 
                                        eBone->flag &= ~BONE_CONNECTED;
                                }
                                
                                /* Lets try to fix any constraint subtargets that might
-                                       have been duplicated */
-                               update_dup_subtarget(obedit, eBone);
+                                * have been duplicated 
+                                */
+                               updateDuplicateSubtarget(eBone, arm->edbo, obedit);
                        }
                }
        } 
        
        /*      Deselect the old bones and select the new ones */
-       
        for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
                if (EBONE_VISIBLE(arm, curBone))
                        curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
        }
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
        
-// XXX BIF_TransformSetUndo("Add Duplicate");
-//     initTransform(TFM_TRANSLATION, CTX_NO_PET);
-//     Transform();
+       return OPERATOR_FINISHED;
+}
+
+static int armature_duplicate_selected_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       int retv= armature_duplicate_selected_exec(C, op);
+
+       if (retv == OPERATOR_FINISHED) {
+               RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+               WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+       }
+
+       return retv;
 }
 
+void ARMATURE_OT_duplicate_selected(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Duplicate Selected Bone(s)";
+       ot->idname= "ARMATURE_OT_duplicate_selected";
+       
+       /* api callbacks */
+       ot->invoke = armature_duplicate_selected_invoke;
+       ot->exec = armature_duplicate_selected_exec;
+       ot->poll = ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* to give to transform */
+       RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
 
 
 /* *************** END Adding stuff in editmode *************** */
@@ -2815,7 +3058,7 @@ void merge_armature(Scene *scene)
        }
        
        /* undo + updates */
-       countall();
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Merge Bones");
 }
 
@@ -2837,7 +3080,7 @@ void hide_selected_armature_bones(Scene *scene)
                        }
                }
        }
-       countall();
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Hide Bones");
 }
 
@@ -2857,7 +3100,7 @@ void hide_unselected_armature_bones(Scene *scene)
                        }
                }
        }
-       countall();
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Hide Unselected Bones");
 }
 
@@ -2875,207 +3118,24 @@ void show_all_armature_bones(Scene *scene)
                        }
                }
        }
-       countall();
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Reveal Bones");
 }
 
-/* check for null, before calling! */
-static void bone_connect_to_existing_parent(EditBone *bone)
-{
-       bone->flag |= BONE_CONNECTED;
-       VECCOPY(bone->head, bone->parent->tail);
-       bone->rad_head = bone->parent->rad_tail;
-}
-
-static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode)
-{
-       EditBone *ebone;
-       float offset[3];
-       
-       if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
-               selbone->parent->flag &= ~(BONE_TIPSEL);
-       
-       /* make actbone the parent of selbone */
-       selbone->parent= actbone;
-       
-       /* in actbone tree we cannot have a loop */
-       for (ebone= actbone->parent; ebone; ebone= ebone->parent) {
-               if (ebone->parent==selbone) {
-                       ebone->parent= NULL;
-                       ebone->flag &= ~BONE_CONNECTED;
-               }
-       }
-       
-       if (mode == 1) {        
-               /* Connected: Child bones will be moved to the parent tip */
-               selbone->flag |= BONE_CONNECTED;
-               VecSubf(offset, actbone->tail, selbone->head);
-               
-               VECCOPY(selbone->head, actbone->tail);
-               selbone->rad_head= actbone->rad_tail;
-               
-               VecAddf(selbone->tail, selbone->tail, offset);
-               
-               /* offset for all its children */
-               for (ebone = edbo->first; ebone; ebone=ebone->next) {
-                       EditBone *par;
-                       
-                       for (par= ebone->parent; par; par= par->parent) {
-                               if (par==selbone) {
-                                       VecAddf(ebone->head, ebone->head, offset);
-                                       VecAddf(ebone->tail, ebone->tail, offset);
-                                       break;
-                               }
-                       }
-               }
-       }
-       else {
-               /* Offset: Child bones will retain their distance from the parent tip */
-               selbone->flag &= ~BONE_CONNECTED;
-       }
-}
-
-void make_bone_parent(Scene *scene)
-{
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
-       EditBone *actbone, *ebone, *selbone;
-       EditBone *flipbone, *flippar;
-       short allchildbones= 0, foundselbone= 0;
-       short val;
-       
-       /* find active bone to parent to */
-       for (actbone = arm->edbo->first; actbone; actbone=actbone->next) {
-               if (EBONE_VISIBLE(arm, actbone)) {
-                       if (actbone->flag & BONE_ACTIVE)
-                               break;
-               }
-       }
-       if (actbone == NULL) {
-               error("Needs an active bone");
-               return; 
-       }
-
-       /* find selected bones */
-       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
-               if (EBONE_VISIBLE(arm, ebone)) {
-                       if ((ebone->flag & BONE_SELECTED) && (ebone != actbone)) {
-                               foundselbone++;
-                               if (ebone->parent != actbone) allchildbones= 1; 
-                       }       
-               }
-       }
-       /* abort if no selected bones, and active bone doesn't have a parent to work with instead */
-       if (foundselbone==0 && actbone->parent==NULL) {
-               error("Need selected bone(s)");
-               return;
-       }
-       
-       /* 'Keep Offset' option is only displayed if it's likely to be useful */
-       if (allchildbones)
-               val= pupmenu("Make Parent%t|Connected%x1|Keep Offset%x2");
-       else
-               val= pupmenu("Make Parent%t|Connected%x1");
-       
-       if (val < 1) return;
-
-       if (foundselbone==0 && actbone->parent) {
-               /* When only the active bone is selected, and it has a parent,
-                * connect it to the parent, as that is the only possible outcome. 
-                */
-               bone_connect_to_existing_parent(actbone);
-               
-               if (arm->flag & ARM_MIRROR_EDIT) {
-                       flipbone = armature_bone_get_mirrored(arm->edbo, actbone);
-                       if (flipbone)
-                               bone_connect_to_existing_parent(flipbone);
-               }
-       }
-       else {
-               /* loop through all editbones, parenting all selected bones to the active bone */
-               for (selbone = arm->edbo->first; selbone; selbone=selbone->next) {
-                       if (EBONE_VISIBLE(arm, selbone)) {
-                               if ((selbone->flag & BONE_SELECTED) && (selbone!=actbone)) {
-                                       /* parent selbone to actbone */
-                                       bone_connect_to_new_parent(arm->edbo, selbone, actbone, val);
-                                       
-                                       if (arm->flag & ARM_MIRROR_EDIT) {
-                                               /* - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
-                                                *      (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
-                                                *      This is useful for arm-chains, for example parenting lower arm to upper arm
-                                                * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
-                                                *      then just use actbone. Useful when doing upper arm to spine.
-                                                */
-                                               flipbone = armature_bone_get_mirrored(arm->edbo, selbone);
-                                               flippar = armature_bone_get_mirrored(arm->edbo, actbone);
-                                               
-                                               if (flipbone) {
-                                                       if (flippar)
-                                                               bone_connect_to_new_parent(arm->edbo, flipbone, flippar, val);
-                                                       else
-                                                               bone_connect_to_new_parent(arm->edbo, flipbone, actbone, val);
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       countall(); /* checks selection */
-       BIF_undo_push("Make Parent");
-
-       return;
-}
-
-static void editbone_clear_parent(EditBone *ebone, int mode)
-{
-       if (ebone->parent) {
-               /* for nice selection */
-               ebone->parent->flag &= ~(BONE_TIPSEL);
-       }
-       
-       if (mode==1) ebone->parent= NULL;
-       ebone->flag &= ~BONE_CONNECTED;
-}
-
-void clear_bone_parent(Scene *scene)
-{
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
-       EditBone *ebone;
-       EditBone *flipbone = NULL;
-       short val;
-       
-       val= pupmenu("Clear Parent%t|Clear Parent%x1|Disconnect Bone%x2");
-       if (val<1) return;
-       
-       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
-               if (EBONE_VISIBLE(arm, ebone)) {
-                       if (ebone->flag & BONE_SELECTED) {
-                               if (arm->flag & ARM_MIRROR_EDIT)
-                                       flipbone = armature_bone_get_mirrored(arm->edbo, ebone);
-                                       
-                               if (flipbone)
-                                       editbone_clear_parent(flipbone, val);
-                               editbone_clear_parent(ebone, val);
-                       }
-               }
-       }
-       
-       countall(); // checks selection
-       BIF_undo_push("Clear Parent");
-}
-       
-
+/* previously extrude_armature */
 /* context; editmode armature */
 /* if forked && mirror-edit: makes two bones with flipped names */
-void extrude_armature(Scene *scene, int forked)
+static int armature_extrude_exec(bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
+       Object *obedit;
+       bArmature *arm;
        EditBone *newbone, *ebone, *flipbone, *first=NULL;
        int a, totbone= 0, do_extrude;
-       
+       int forked = RNA_boolean_get(op->ptr, "forked");
+
+       obedit= CTX_data_edit_object(C);
+       arm= obedit->data;
+
        /* since we allow root extrude too, we have to make sure selection is OK */
        for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
                if (EBONE_VISIBLE(arm, ebone)) {
@@ -3105,7 +3165,7 @@ void extrude_armature(Scene *scene, int forked)
                                /* we re-use code for mirror editing... */
                                flipbone= NULL;
                                if (arm->flag & ARM_MIRROR_EDIT) {
-                                       flipbone= armature_bone_get_mirrored(arm->edbo, ebone);
+                                       flipbone= ED_armature_bone_get_mirrored(arm->edbo, ebone);
                                        if (flipbone) {
                                                forked= 0;      // we extrude 2 different bones
                                                if (flipbone->flag & (BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED))
@@ -3168,7 +3228,7 @@ void extrude_armature(Scene *scene, int forked)
                                                        else strcat(newbone->name, "_R");
                                                }
                                        }
-                                       unique_editbone_name(arm->edbo, newbone->name);
+                                       unique_editbone_name(arm->edbo, newbone->name, NULL);
                                        
                                        /* Add the new bone to the list */
                                        BLI_addtail(arm->edbo, newbone);
@@ -3187,178 +3247,767 @@ void extrude_armature(Scene *scene, int forked)
        }
        /* if only one bone, make this one active */
        if (totbone==1 && first) first->flag |= BONE_ACTIVE;
+
+       if (totbone==0) return OPERATOR_CANCELLED;
        
        /* Transform the endpoints */
-       countall(); // flushes selection!
-// XXX BIF_TransformSetUndo("Extrude");
-//     initTransform(TFM_TRANSLATION, CTX_NO_PET);
-//     Transform();
-       
+       ED_armature_sync_selection(arm->edbo);
+
+       return OPERATOR_FINISHED;
 }
 
-/* context; editmode armature */
-void subdivide_armature(Scene *scene, int numcuts)
+static int armature_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
-       EditBone *ebone, *newbone, *tbone, *mbone;
-       int a, i;
-       
-       if (numcuts < 1) return;
-
-       for (mbone = arm->edbo->last; mbone; mbone= mbone->prev) {
-               if (EBONE_VISIBLE(arm, mbone)) {
-                       if (mbone->flag & BONE_SELECTED) {
-                               for (i=numcuts+1; i>1; i--) {
-                                       /* compute cut ratio first */
-                                       float cutratio= 1/(float)i;
-                                       float cutratioI= 1-cutratio;
-                                       
-                                       /* take care of mirrored stuff */
-                                       for (a=0; a<2; a++) {
-                                               float val1[3];
-                                               float val2[3];
-                                               float val3[3];
-                                               
-                                               /* try to find mirrored bone on a != 0 */
-                                               if (a) {
-                                                       if (arm->flag & ARM_MIRROR_EDIT)
-                                                               ebone= armature_bone_get_mirrored(arm->edbo, mbone);
-                                                       else 
-                                                               ebone= NULL;
-                                               }
-                                               else
-                                                       ebone= mbone;
-                                                       
-                                               if (ebone) {
-                                                       newbone= MEM_mallocN(sizeof(EditBone), "ebone subdiv");
-                                                       *newbone = *ebone;
-                                                       BLI_addtail(arm->edbo, newbone);
-                                                       
-                                                       /* calculate location of newbone->head */
-                                                       VECCOPY(val1, ebone->head);
-                                                       VECCOPY(val2, ebone->tail);
-                                                       VECCOPY(val3, newbone->head);
-                                                       
-                                                       val3[0]= val1[0]*cutratio+val2[0]*cutratioI;
-                                                       val3[1]= val1[1]*cutratio+val2[1]*cutratioI;
-                                                       val3[2]= val1[2]*cutratio+val2[2]*cutratioI;
-                                                       
-                                                       VECCOPY(newbone->head, val3);
-                                                       VECCOPY(newbone->tail, ebone->tail);
-                                                       VECCOPY(ebone->tail, newbone->head);
-                                                       
-                                                       newbone->rad_head= 0.5*(ebone->rad_head+ebone->rad_tail);
-                                                       ebone->rad_tail= newbone->rad_head;
-                                                       
-                                                       newbone->flag |= BONE_CONNECTED;
-                                                       
-                                                       unique_editbone_name (arm->edbo, newbone->name);
-                                                       
-                                                       /* correct parent bones */
-                                                       for (tbone = arm->edbo->first; tbone; tbone=tbone->next) {
-                                                               if (tbone->parent==ebone)
-                                                                       tbone->parent= newbone;
-                                                       }
-                                                       newbone->parent= ebone;
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       
-       if (numcuts==1) BIF_undo_push("Subdivide");
-       else BIF_undo_push("Subdivide multi");
+       if (OPERATOR_CANCELLED == armature_extrude_exec(C, op))
+               return OPERATOR_CANCELLED;
+
+       RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+       WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+       return OPERATOR_FINISHED;
 }
 
-/* switch direction of bone chains */
-void switch_direction_armature (Scene *scene)
+void ARMATURE_OT_extrude(wmOperatorType *ot)
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= (obedit) ? obedit->data : NULL;
-       ListBase chains = {NULL, NULL};
-       LinkData *chain;
-       
-       /* error checking paranoia */
-       if (arm == NULL)
-               return;
-       
-       /* get chains of bones (ends on chains) */
-       chains_find_tips(arm->edbo, &chains);
-       if (chains.first == NULL) return;
+       /* identifiers */
+       ot->name= "Extrude";
+       ot->idname= "ARMATURE_OT_extrude";
        
-       /* loop over chains, only considering selected and visible bones */
-       for (chain= chains.first; chain; chain= chain->next) {
-               EditBone *ebo, *child=NULL, *parent=NULL;
-               
-               /* loop over bones in chain */
-               for (ebo= chain->data; ebo; ebo= parent) {
-                       /* parent is this bone's original parent
-                        *      - we store this, as the next bone that is checked is this one
-                        *        but the value of ebo->parent may change here...
-                        */
-                       parent= ebo->parent;
-                       
-                       /* only if selected and editable */
-                       if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {                           
-                               /* swap head and tail coordinates */
-                               SWAP(float, ebo->head[0], ebo->tail[0]);
-                               SWAP(float, ebo->head[1], ebo->tail[1]);
-                               SWAP(float, ebo->head[2], ebo->tail[2]);
-                               
-                               /* do parent swapping:
-                                *      - use 'child' as new parent
-                                *      - connected flag is only set if points are coincidental
-                                */
-                               ebo->parent= child;
-                               if ((child) && VecEqual(ebo->head, child->tail))
-                                       ebo->flag |= BONE_CONNECTED;
-                               else    
-                                       ebo->flag &= ~BONE_CONNECTED;
-                               
-                               /* get next bones 
-                                *      - child will become the new parent of next bone
-                                */
-                               child= ebo;
-                       }
-                       else {
-                               /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it 
-                                * as it will be facing in opposite direction
-                                */
-                               if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
-                                       ebo->parent= NULL;
-                                       ebo->flag &= ~BONE_CONNECTED;
-                               }
-                               
-                               /* get next bones
-                                *      - child will become new parent of next bone (not swapping occurred, 
-                                *        so set to NULL to prevent infinite-loop)
-                                */
-                               child= NULL;
-                       }
-               }
-       }
+       /* api callbacks */
+       ot->invoke= armature_extrude_invoke;
+       ot->exec= armature_extrude_exec;
+       ot->poll= ED_operator_editarmature;
        
-       /* free chains */
-       BLI_freelistN(&chains);
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
-       BIF_undo_push("Switch Direction");
+       /* props */
+       RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
+       /* to give to transform */
+       RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
 }
+/* ********************** Bone Add ********************/
 
-/* editbone alignment */
+/*op makes a new bone and returns it with its tip selected */
 
-/* helper to fix a ebone position if its parent has moved due to alignment*/
-static void fix_connected_bone(EditBone *ebone)
+static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) 
 {
-       float diff[3];
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       Object *obedit = CTX_data_edit_object(C);
+       EditBone *bone;
+       float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
+       char name[32];
        
-       if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || VecEqual(ebone->parent->tail, ebone->head))
-               return;
+       RNA_string_get(op->ptr, "name", name);
        
-       /* if the parent has moved we translate child's head and tail accordingly*/
-       VecSubf(diff, ebone->parent->tail, ebone->head);
-       VecAddf(ebone->head, ebone->head, diff);
+       VECCOPY(curs, give_cursor(CTX_data_scene(C),CTX_wm_view3d(C))); 
+
+       /* Get inverse point for head and orientation for tail */
+       Mat4Invert(obedit->imat, obedit->obmat);
+       Mat4MulVecfl(obedit->imat, curs);
+
+       if (U.flag & USER_ADD_VIEWALIGNED)
+               Mat3CpyMat4(obmat, rv3d->viewmat);
+       else Mat3One(obmat);
+       
+       Mat3CpyMat4(viewmat, obedit->obmat);
+       Mat3MulMat3(totmat, obmat, viewmat);
+       Mat3Inv(imat, totmat);
+       
+       deselectall_armature(obedit, 0, 0);
+       
+       /*      Create a bone   */
+       bone= add_editbone(obedit, name);
+
+       VECCOPY(bone->head, curs);
+       
+       if(U.flag & USER_ADD_VIEWALIGNED)
+               VecAddf(bone->tail, bone->head, imat[1]);       // bone with unit length 1
+       else
+               VecAddf(bone->tail, bone->head, imat[2]);       // bone with unit length 1, pointing up Z
+
+       WM_event_add_notifier(C, NC_OBJECT, obedit);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Bone";
+       ot->idname= "ARMATURE_OT_bone_primitive_add";
+       
+       /* api callbacks */
+       ot->exec = armature_bone_primitive_add_exec;
+       ot->poll = ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       RNA_def_string(ot->srna, "name", "Bone", 32, "Name", "Name of the newly created bone");
+       
+}
+
+
+/* ----------- */
+
+/* Subdivide Operators:
+ * This group of operators all use the same 'exec' callback, but they are called
+ * through several different operators - a combined menu (which just calls the exec in the 
+ * appropriate ways), and two separate ones.
+ */
+
+static int armature_subdivide_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       bArmature *arm= obedit->data;
+       EditBone *newbone, *tbone;
+       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;
+       
+       /* loop over all editable bones */
+       // XXX the old code did this in reverse order though!
+       CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) 
+       {
+               for (i=numcuts+1; i>1; i--) {
+                       /* compute cut ratio first */
+                       float cutratio= 1.0f / (float)i;
+                       float cutratioI= 1.0f - cutratio;
+                       
+                       float val1[3];
+                       float val2[3];
+                       float val3[3];
+                       
+                       newbone= MEM_mallocN(sizeof(EditBone), "ebone subdiv");
+                       *newbone = *ebone;
+                       BLI_addtail(arm->edbo, newbone);
+                       
+                       /* calculate location of newbone->head */
+                       VECCOPY(val1, ebone->head);
+                       VECCOPY(val2, ebone->tail);
+                       VECCOPY(val3, newbone->head);
+                       
+                       val3[0]= val1[0]*cutratio + val2[0]*cutratioI;
+                       val3[1]= val1[1]*cutratio + val2[1]*cutratioI;
+                       val3[2]= val1[2]*cutratio + val2[2]*cutratioI;
+                       
+                       VECCOPY(newbone->head, val3);
+                       VECCOPY(newbone->tail, ebone->tail);
+                       VECCOPY(ebone->tail, newbone->head);
+                       
+                       newbone->rad_head= 0.5f * (ebone->rad_head + ebone->rad_tail);
+                       ebone->rad_tail= newbone->rad_head;
+                       
+                       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_TRANSFORM, 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, 10, "Number of Cuts", "", 1, INT_MAX);
+}
+
+
+
+static int armature_subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       uiPopupMenu *pup;
+       uiLayout *layout;
+
+       pup= uiPupMenuBegin(C, "Subdivision Type", 0);
+       layout= uiPupMenuLayout(pup);
+       uiItemsEnumO(layout, "ARMATURE_OT_subdivs", "type");
+       uiPupMenuEnd(C, pup);
+       
+       return OPERATOR_CANCELLED;
+}
+
+static int armature_subdivs_exec(bContext *C, wmOperator *op)
+{      
+       switch (RNA_int_get(op->ptr, "type"))
+       {
+               case 0: /* simple */
+                       RNA_int_set(op->ptr, "number_cuts", 1);
+                       armature_subdivide_exec(C, op);
+                       break;
+               case 1: /* multi */
+                       armature_subdivide_exec(C, op);
+                       break;
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_subdivs(wmOperatorType *ot)
+{
+       static EnumPropertyItem type_items[]= {
+               {0, "SIMPLE", 0, "Simple", ""},
+               {1, "MULTI", 0, "Multi", ""},
+               {0, NULL, 0, NULL, NULL}};
+
+       /* identifiers */
+       ot->name= "subdivs";
+       ot->idname= "ARMATURE_OT_subdivs";
+       
+       /* api callbacks */
+       ot->invoke= armature_subdivs_invoke;
+       ot->exec= armature_subdivs_exec;
+       
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */
+       RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+       
+       /* this is temp, the ops are different, but they are called from subdivs, so all the possible props should be here as well*/
+       RNA_def_int(ot->srna, "number_cuts", 2, 1, 10, "Number of Cuts", "", 1, INT_MAX); 
+}
+
+/* ----------- */
+
+/* Switch Direction operator:
+ * Currently, this does not use context loops, as context loops do not make it
+ * easy to retrieve any hierarchial/chain relationships which are necessary for
+ * this to be done easily.
+ */
+
+static int armature_switch_direction_exec(bContext *C, wmOperator *op) 
+{
+       Object *ob= CTX_data_edit_object(C);
+       bArmature *arm= (bArmature *)ob->data;
+       ListBase chains = {NULL, NULL};
+       LinkData *chain;
+       
+       /* get chains of bones (ends on chains) */
+       chains_find_tips(arm->edbo, &chains);
+       if (chains.first == NULL) return OPERATOR_CANCELLED;
+       
+       /* loop over chains, only considering selected and visible bones */
+       for (chain= chains.first; chain; chain= chain->next) {
+               EditBone *ebo, *child=NULL, *parent=NULL;
+               
+               /* loop over bones in chain */
+               for (ebo= chain->data; ebo; ebo= parent) {
+                       /* parent is this bone's original parent
+                        *      - we store this, as the next bone that is checked is this one
+                        *        but the value of ebo->parent may change here...
+                        */
+                       parent= ebo->parent;
+                       
+                       /* only if selected and editable */
+                       if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {                           
+                               /* swap head and tail coordinates */
+                               SWAP(float, ebo->head[0], ebo->tail[0]);
+                               SWAP(float, ebo->head[1], ebo->tail[1]);
+                               SWAP(float, ebo->head[2], ebo->tail[2]);
+                               
+                               /* do parent swapping:
+                                *      - use 'child' as new parent
+                                *      - connected flag is only set if points are coincidental
+                                */
+                               ebo->parent= child;
+                               if ((child) && VecEqual(ebo->head, child->tail))
+                                       ebo->flag |= BONE_CONNECTED;
+                               else    
+                                       ebo->flag &= ~BONE_CONNECTED;
+                               
+                               /* get next bones 
+                                *      - child will become the new parent of next bone
+                                */
+                               child= ebo;
+                       }
+                       else {
+                               /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it 
+                                * as it will be facing in opposite direction
+                                */
+                               if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
+                                       ebo->parent= NULL;
+                                       ebo->flag &= ~BONE_CONNECTED;
+                               }
+                               
+                               /* get next bones
+                                *      - child will become new parent of next bone (not swapping occurred, 
+                                *        so set to NULL to prevent infinite-loop)
+                                */
+                               child= NULL;
+                       }
+               }
+       }
+       
+       /* free chains */
+       BLI_freelistN(&chains); 
+
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_switch_direction(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Switch Direction";
+       ot->idname= "ARMATURE_OT_switch_direction";
+       
+       /* api callbacks */
+       ot->exec = armature_switch_direction_exec;
+       ot->poll = ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+/* ***************** Parenting *********************** */
+
+/* armature parenting options */
+#define ARM_PAR_CONNECT 1
+#define ARM_PAR_OFFSET 2
+
+/* check for null, before calling! */
+static void bone_connect_to_existing_parent(EditBone *bone)
+{
+       bone->flag |= BONE_CONNECTED;
+       VECCOPY(bone->head, bone->parent->tail);
+       bone->rad_head = bone->parent->rad_tail;
+}
+
+static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode)
+{
+       EditBone *ebone;
+       float offset[3];
+       
+       if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
+               selbone->parent->flag &= ~(BONE_TIPSEL);
+       
+       /* make actbone the parent of selbone */
+       selbone->parent= actbone;
+       
+       /* in actbone tree we cannot have a loop */
+       for (ebone= actbone->parent; ebone; ebone= ebone->parent) {
+               if (ebone->parent==selbone) {
+                       ebone->parent= NULL;
+                       ebone->flag &= ~BONE_CONNECTED;
+               }
+       }
+       
+       if (mode == ARM_PAR_CONNECT) {  
+               /* Connected: Child bones will be moved to the parent tip */
+               selbone->flag |= BONE_CONNECTED;
+               VecSubf(offset, actbone->tail, selbone->head);
+               
+               VECCOPY(selbone->head, actbone->tail);
+               selbone->rad_head= actbone->rad_tail;
+               
+               VecAddf(selbone->tail, selbone->tail, offset);
+               
+               /* offset for all its children */
+               for (ebone = edbo->first; ebone; ebone=ebone->next) {
+                       EditBone *par;
+                       
+                       for (par= ebone->parent; par; par= par->parent) {
+                               if (par==selbone) {
+                                       VecAddf(ebone->head, ebone->head, offset);
+                                       VecAddf(ebone->tail, ebone->tail, offset);
+                                       break;
+                               }
+                       }
+               }
+       }
+       else {
+               /* Offset: Child bones will retain their distance from the parent tip */
+               selbone->flag &= ~BONE_CONNECTED;
+       }
+}
+
+static EnumPropertyItem prop_editarm_make_parent_types[] = {
+       {ARM_PAR_CONNECT, "CONNECTED", 0, "Connected", ""},
+       {ARM_PAR_OFFSET, "OFFSET", 0, "Keep Offset", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+static int armature_parent_set_exec(bContext *C, wmOperator *op) 
+{
+       Object *ob= CTX_data_edit_object(C);
+       bArmature *arm= (bArmature *)ob->data;
+       EditBone *actbone = CTX_data_active_bone(C);
+       EditBone *actmirb = NULL;
+       short val = RNA_enum_get(op->ptr, "type");
+       
+       /* there must be an active bone */
+       if (actbone == NULL) {
+               BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone");
+               return OPERATOR_CANCELLED;
+       }
+       else if (arm->flag & ARM_MIRROR_EDIT) {
+               /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
+                * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
+                *      (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+                *      This is useful for arm-chains, for example parenting lower arm to upper arm
+                * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+                *      then just use actbone. Useful when doing upper arm to spine.
+                */
+               actmirb= ED_armature_bone_get_mirrored(arm->edbo, actbone);
+               if (actmirb == NULL) 
+                       actmirb= actbone;
+       }
+       
+       /* if there is only 1 selected bone, we assume that that is the active bone, 
+        * since a user will need to have clicked on a bone (thus selecting it) to make it active
+        */
+       if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
+               /* When only the active bone is selected, and it has a parent,
+                * connect it to the parent, as that is the only possible outcome. 
+                */
+               if (actbone->parent) {
+                       bone_connect_to_existing_parent(actbone);
+                       
+                       if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
+                               bone_connect_to_existing_parent(actmirb);
+               }
+       }
+       else {
+               /* Parent 'selected' bones to the active one
+                * - the context iterator contains both selected bones and their mirrored copies,
+                *   so we assume that unselected bones are mirrored copies of some selected bone
+                * - since the active one (and/or its mirror) will also be selected, we also need 
+                *      to check that we are not trying to opearate on them, since such an operation 
+                *      would cause errors
+                */
+               
+               /* parent selected bones to the active one */
+               CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+                       if (ELEM(ebone, actbone, actmirb) == 0) {
+                               if (ebone->flag & BONE_SELECTED) 
+                                       bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
+                               else
+                                       bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
+                       }
+               }
+               CTX_DATA_END;
+       }
+       
+
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+static int armature_parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       EditBone *actbone = CTX_data_active_bone(C);
+       uiPopupMenu *pup= uiPupMenuBegin(C, "Make Parent ", 0);
+       uiLayout *layout= uiPupMenuLayout(pup);
+       int allchildbones = 0;
+       
+       CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+               if (ebone != actbone) {
+                       if (ebone->parent != actbone) allchildbones= 1; 
+               }       
+       }
+       CTX_DATA_END;
+
+       uiItemEnumO(layout, NULL, 0, "ARMATURE_OT_parent_set", "type", ARM_PAR_CONNECT);
+       
+       /* ob becomes parent, make the associated menus */
+       if (allchildbones)
+               uiItemEnumO(layout, NULL, 0, "ARMATURE_OT_parent_set", "type", ARM_PAR_OFFSET); 
+               
+       uiPupMenuEnd(C, pup);
+       
+       return OPERATOR_CANCELLED;
+}
+
+void ARMATURE_OT_parent_set(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Make Parent";
+       ot->idname= "ARMATURE_OT_parent_set";
+       
+       /* api callbacks */
+       ot->invoke = armature_parent_set_invoke;
+       ot->exec = armature_parent_set_exec;
+       ot->poll = ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       RNA_def_enum(ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
+}
+
+static EnumPropertyItem prop_editarm_clear_parent_types[] = {
+       {1, "CLEAR", 0, "Clear Parent", ""},
+       {2, "DISCONNECT", 0, "Disconnect Bone", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+static void editbone_clear_parent(EditBone *ebone, int mode)
+{
+       if (ebone->parent) {
+               /* for nice selection */
+               ebone->parent->flag &= ~(BONE_TIPSEL);
+       }
+       
+       if (mode==1) ebone->parent= NULL;
+       ebone->flag &= ~BONE_CONNECTED;
+}
+
+static int armature_parent_clear_exec(bContext *C, wmOperator *op) 
+{
+       Object *ob= CTX_data_edit_object(C);
+       bArmature *arm= (bArmature *)ob->data;
+       int val = RNA_enum_get(op->ptr, "type");
+               
+       CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+               editbone_clear_parent(ebone, val);
+       }
+       CTX_DATA_END;
+       
+       ED_armature_sync_selection(arm->edbo);
+
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_parent_clear(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Clear Parent";
+       ot->idname= "ARMATURE_OT_parent_clear";
+       
+       /* api callbacks */
+       ot->invoke = WM_menu_invoke;
+       ot->exec = armature_parent_clear_exec;
+       ot->poll = ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
+}
+
+/* ****************  Selections  ******************/
+
+static int armature_select_invert_exec(bContext *C, wmOperator *op)
+{
+       /*      Set the flags */
+       CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
+               /* select bone */
+               ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+               ebone->flag &= ~BONE_ACTIVE;
+       }
+       CTX_DATA_END;   
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_invert(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Invert Selection";
+       ot->idname= "ARMATURE_OT_select_invert";
+       
+       /* api callbacks */
+       ot->exec= armature_select_invert_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+}
+static int armature_de_select_all_exec(bContext *C, wmOperator *op)
+{
+       int     sel=1;
+
+       /*      Determine if there are any selected bones
+       And therefore whether we are selecting or deselecting */
+       if (CTX_DATA_COUNT(C, selected_bones) > 0)      sel=0;
+       
+       /*      Set the flags */
+       CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
+               if (sel==1) {
+                       /* select bone */
+                       ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+                       if(ebone->parent)
+                               ebone->parent->flag |= (BONE_TIPSEL);
+               }
+               else {
+                       /* deselect bone */
+                       ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
+               }
+       }
+       CTX_DATA_END;   
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_all_toggle(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "deselect all editbone";
+       ot->idname= "ARMATURE_OT_select_all_toggle";
+       
+       /* api callbacks */
+       ot->exec= armature_de_select_all_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+}
+
+/* ********************* select hierarchy operator ************** */
+
+static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       Object *ob;
+       bArmature *arm;
+       EditBone *curbone, *pabone, *chbone;
+       int direction = RNA_enum_get(op->ptr, "direction");
+       int add_to_sel = RNA_boolean_get(op->ptr, "extend");
+       
+       ob= obedit;
+       arm= (bArmature *)ob->data;
+       
+       for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
+               if (EBONE_VISIBLE(arm, curbone)) {
+                       if (curbone->flag & (BONE_ACTIVE)) {
+                               if (direction == BONE_SELECT_PARENT) {
+                                       if (curbone->parent == NULL) continue;
+                                       else pabone = curbone->parent;
+                                       
+                                       if (EBONE_VISIBLE(arm, pabone)) {
+                                               pabone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                               if (pabone->parent)     pabone->parent->flag |= BONE_TIPSEL;
+                                               
+                                               if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                               curbone->flag &= ~BONE_ACTIVE;
+                                               break;
+                                       }
+                                       
+                               } 
+                               else { // BONE_SELECT_CHILD
+                                       chbone = editbone_get_child(arm, curbone, 1);
+                                       if (chbone == NULL) continue;
+                                       
+                                       if (EBONE_VISIBLE(arm, chbone)) {
+                                               chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                               
+                                               if (!add_to_sel) {
+                                                       curbone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL);
+                                                       if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL;
+                                               }
+                                               curbone->flag &= ~BONE_ACTIVE;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       ED_armature_sync_selection(arm->edbo);
+       
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
+{
+       static EnumPropertyItem direction_items[]= {
+       {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
+       {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
+       {0, NULL, 0, NULL, NULL}
+       };
+       
+       /* identifiers */
+       ot->name= "Select Hierarchy";
+       ot->idname= "ARMATURE_OT_select_hierarchy";
+       
+       /* api callbacks */
+       ot->exec= armature_select_hierarchy_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* props */
+       RNA_def_enum(ot->srna, "direction", direction_items,
+                    BONE_SELECT_PARENT, "Direction", "");
+       RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
+}
+
+/* ***************** EditBone Alignment ********************* */
+
+/* helper to fix a ebone position if its parent has moved due to alignment*/
+static void fix_connected_bone(EditBone *ebone)
+{
+       float diff[3];
+       
+       if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || VecEqual(ebone->parent->tail, ebone->head))
+               return;
+       
+       /* if the parent has moved we translate child's head and tail accordingly*/
+       VecSubf(diff, ebone->parent->tail, ebone->head);
+       VecAddf(ebone->head, ebone->head, diff);
        VecAddf(ebone->tail, ebone->tail, diff);
        return;
 }
@@ -3398,87 +4047,86 @@ static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actb
        return;
 }
 
-void align_selected_bones(Scene *scene)
+static int armature_align_bones_exec(bContext *C, wmOperator *op) 
 {
-       Object *obedit= scene->obedit; // XXX get from context
-       bArmature *arm= obedit->data;
-       EditBone *actbone, *ebone, *selbone;
-       EditBone *flipbone, *flippar;
-       short allchildbones= 0, foundselbone= 0;
-       
-       /* find active bone to align to */
-       for (actbone = arm->edbo->first; actbone; actbone=actbone->next) {
-               if (arm->layer & actbone->layer) {
-                       if (actbone->flag & BONE_ACTIVE)
-                               break;
-               }
-       }
+       Object *ob= CTX_data_edit_object(C);
+       bArmature *arm= (bArmature *)ob->data;
+       EditBone *actbone= CTX_data_active_bone(C);
+       EditBone *actmirb= NULL;
+       
+       /* there must be an active bone */
        if (actbone == NULL) {
-               error("Needs an active bone");
-               return; 
-       }
-
-       /* find selected bones */
-       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
-                       if ((ebone->flag & BONE_SELECTED) && (ebone != actbone)) {
-                               foundselbone++;
-                               if (ebone->parent != actbone) allchildbones= 1; 
-                       }       
-               }
-       }
-       /* abort if no selected bones, and active bone doesn't have a parent to work with instead */
-       if (foundselbone==0 && actbone->parent==NULL) {
-               error("Need selected bone(s)");
-               return;
+               BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone");
+               return OPERATOR_CANCELLED;
+       }
+       else if (arm->flag & ARM_MIRROR_EDIT) {
+               /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
+                * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
+                *      (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+                *      This is useful for arm-chains, for example parenting lower arm to upper arm
+                * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+                *      then just use actbone. Useful when doing upper arm to spine.
+                */
+               actmirb= ED_armature_bone_get_mirrored(arm->edbo, actbone);
+               if (actmirb == NULL) 
+                       actmirb= actbone;
        }
        
-       if (foundselbone==0 && actbone->parent) {
+       /* if there is only 1 selected bone, we assume that that is the active bone, 
+        * since a user will need to have clicked on a bone (thus selecting it) to make it active
+        */
+       if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
                /* When only the active bone is selected, and it has a parent,
                 * align it to the parent, as that is the only possible outcome. 
                 */
-               bone_align_to_bone(arm->edbo, actbone, actbone->parent);
-               
-               if (arm->flag & ARM_MIRROR_EDIT) {
-                       flipbone = armature_bone_get_mirrored(arm->edbo, actbone);
-                       if (flipbone)
-                               bone_align_to_bone(arm->edbo, flipbone, flipbone->parent);
-               }
-       }
-       else {
-               /* loop through all editbones, aligning all selected bones to the active bone */
-               for (selbone = arm->edbo->first; selbone; selbone=selbone->next) {
-                       if (arm->layer & selbone->layer) {
-                               if ((selbone->flag & BONE_SELECTED) && (selbone!=actbone)) {
-                                       /* align selbone to actbone */
-                                       bone_align_to_bone(arm->edbo, selbone, actbone);
-                                       
-                                       if (arm->flag & ARM_MIRROR_EDIT) {
-                                               /* - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
-                                                *      (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
-                                                *      This is useful for arm-chains, for example parenting lower arm to upper arm
-                                                * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
-                                                *      then just use actbone. Useful when doing upper arm to spine.
-                                                */
-                                               flipbone = armature_bone_get_mirrored(arm->edbo, selbone);
-                                               flippar = armature_bone_get_mirrored(arm->edbo, actbone);
-                                               
-                                               if (flipbone) {
-                                                       if (flippar)
-                                                               bone_align_to_bone(arm->edbo, flipbone, flippar);
-                                                       else
-                                                               bone_align_to_bone(arm->edbo, flipbone, actbone);
-                                               }
-                                       }
-                               }
+               if (actbone->parent) {
+                       bone_align_to_bone(arm->edbo, actbone, actbone->parent);
+                       
+                       if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
+                               bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
+               }
+       }
+       else {
+               /* Align 'selected' bones to the active one
+                * - the context iterator contains both selected bones and their mirrored copies,
+                *   so we assume that unselected bones are mirrored copies of some selected bone
+                * - since the active one (and/or its mirror) will also be selected, we also need 
+                *      to check that we are not trying to opearate on them, since such an operation 
+                *      would cause errors
+                */
+               
+               /* align selected bones to the active one */
+               CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+                       if (ELEM(ebone, actbone, actmirb) == 0) {
+                               if (ebone->flag & BONE_SELECTED)
+                                       bone_align_to_bone(arm->edbo, ebone, actbone);
+                               else
+                                       bone_align_to_bone(arm->edbo, ebone, actmirb);
                        }
                }
+               CTX_DATA_END;
        }
+       
 
-       countall(); /* checks selection */
-       BIF_undo_push("Align bones");
+       /* note, notifier might evolve */
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+       
+       return OPERATOR_FINISHED;
+}
 
-       return;
+void ARMATURE_OT_bones_align(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Align Bones";
+       ot->idname= "ARMATURE_OT_bones_align";
+       
+       /* api callbacks */
+       ot->invoke = WM_operator_confirm;
+       ot->exec = armature_align_bones_exec;
+       ot->poll = ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* ***************** Pose tools ********************* */
@@ -3622,7 +4270,7 @@ void ED_pose_deselectall (Object *ob, int test, int doundo)
                }
        }
        
-       countall();
+       //countall(); // XXX need an equivalent to this...
        
        if (doundo) {
                if (selectmode==1) BIF_undo_push("Select All");
@@ -4012,32 +4660,27 @@ void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par)
        }
 } 
 /* ************* 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);
-       bArmature *arm= ob->data;
        
        /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans){
-               if (arm->layer & pchan->bone->layer) {
-                       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;
-                       /* the current values from IPO's may not be zero, so tag as unkeyed */
-                       pchan->bone->flag |= BONE_UNKEYED;
-               }
+       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
+               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;
+                       
+               /* the current values from IPO's may not be zero, so tag as unkeyed */
+               //pchan->bone->flag |= BONE_UNKEYED;
        }
        CTX_DATA_END;
-               
+       
        DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-       /* no update for this object, this will execute the action again */
-       /* is weak... like for ipo editing which uses ctime now... */
-       where_is_pose (scene, ob);
-       ob->recalc= 0;
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
@@ -4057,35 +4700,29 @@ void POSE_OT_scale_clear(wmOperatorType *ot)
        ot->poll = ED_operator_posemode;
        
        /* flags */
-       ot->flag= OPTYPE_UNDO;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 static int pose_clear_loc_exec(bContext *C, wmOperator *op) 
 {
        Scene *scene = CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
-       bArmature *arm= ob->data;
        
        /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans){
-               if (arm->layer & pchan->bone->layer) {
-                       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;
-                       /* the current values from IPO's may not be zero, so tag as unkeyed */
-                       pchan->bone->flag |= BONE_UNKEYED;
-               }
+       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
+               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;
+                       
+               /* the current values from IPO's may not be zero, so tag as unkeyed */
+               //pchan->bone->flag |= BONE_UNKEYED;
        }
        CTX_DATA_END;
-               
+       
        DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-       /* no update for this object, this will execute the action again */
-       /* is weak... like for ipo editing which uses ctime now... */
-       where_is_pose (scene, ob);
-       ob->recalc= 0;
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
@@ -4105,53 +4742,62 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
        ot->poll = ED_operator_posemode;
        
        /* flags */
-       ot->flag= OPTYPE_UNDO;
+       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);
-       bArmature *arm= ob->data;
        
        /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans){
-               if (arm->layer & pchan->bone->layer) {
-                       if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ)) {
-                               float eul[3], oldeul[3], quat1[4];
-                                       
+       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);
-                               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];
-                                                       
+                       }
+                       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 { 
-                               pchan->quat[1]=pchan->quat[2]=pchan->quat[3]=0.0F; 
-                               pchan->quat[0]=1.0F;
                        }
-                       /* the current values from IPO's may not be zero, so tag as unkeyed */
-                       pchan->bone->flag |= BONE_UNKEYED;
+                       else {
+                               VECCOPY(pchan->eul, eul);
+                       }
+               }                                               
+               else { 
+                       if (pchan->rotmode == PCHAN_ROT_QUAT) {
+                               pchan->quat[1]=pchan->quat[2]=pchan->quat[3]= 0.0f; 
+                               pchan->quat[0]= 1.0f;
+                       }
+                       else {
+                               pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f;
+                       }
                }
+               
+               /* the current values from IPO's may not be zero, so tag as unkeyed */
+               //pchan->bone->flag |= BONE_UNKEYED;
        }
        CTX_DATA_END;
-               
+       
        DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-       /* no update for this object, this will execute the action again */
-       /* is weak... like for ipo editing which uses ctime now... */
-       where_is_pose (scene, ob);
-       ob->recalc= 0;
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
@@ -4171,9 +4817,121 @@ void POSE_OT_rot_clear(wmOperatorType *ot)
        ot->poll = ED_operator_posemode;
        
        /* flags */
-       ot->flag= OPTYPE_UNDO;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+/* ***************** selections ********************** */
+
+static int pose_select_invert_exec(bContext *C, wmOperator *op)
+{
+       
+       /*      Set the flags */
+       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) {
+               pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+               pchan->bone->flag &= ~BONE_ACTIVE;
+       }       
+       CTX_DATA_END;
+       
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_invert(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Invert Selection";
+       ot->idname= "POSE_OT_select_invert";
+       
+       /* api callbacks */
+       ot->exec= pose_select_invert_exec;
+       ot->poll= ED_operator_posemode;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+}
+static int pose_de_select_all_exec(bContext *C, wmOperator *op)
+{
+       int     sel=1;
+
+       /*      Determine if there are any selected bones
+       And therefore whether we are selecting or deselecting */
+       if (CTX_DATA_COUNT(C, selected_pchans) > 0)     sel=0;
+       
+       /*      Set the flags */
+       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) {
+               /* select pchan */
+               if (sel==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+               else pchan->bone->flag |= BONE_SELECTED;
+       }
+       CTX_DATA_END;   
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_all_toggle(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "deselect all bones";
+       ot->idname= "POSE_OT_select_all_toggle";
+       
+       /* api callbacks */
+       ot->exec= pose_de_select_all_exec;
+       ot->poll= ED_operator_posemode;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+}
+
+static int pose_select_parent_exec(bContext *C, wmOperator *op)
+{
+       Object *ob= CTX_data_active_object(C);
+       bPoseChannel *pchan,*parent;
+
+       /*      Determine if there is an active bone */
+       pchan=CTX_data_active_pchan(C);
+       if (pchan) {
+               parent=pchan->parent;
+               if ((parent) && !(parent->bone->flag & BONE_HIDDEN_P)) {
+                       parent->bone->flag |= BONE_SELECTED;
+                       parent->bone->flag |= BONE_ACTIVE;
+                       pchan->bone->flag &= ~BONE_ACTIVE;
+               }
+               else {
+                       return OPERATOR_CANCELLED;
+               }
+       }
+       else {
+               return OPERATOR_CANCELLED;
+       }
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_parent(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "select parent bone";
+       ot->idname= "POSE_OT_select_parent";
+
+       /* api callbacks */
+       ot->exec= pose_select_parent_exec;
+       ot->poll= ED_operator_posemode;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+}
 
-} 
 /* ************* hide/unhide pose bones ******************* */
 
 static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr) 
@@ -4209,7 +4967,7 @@ static int pose_hide_exec(bContext *C, wmOperator *op)
        Object *ob= CTX_data_active_object(C);
        bArmature *arm= ob->data;
 
-       if(RNA_boolean_get(op->ptr, "invert"))
+       if(RNA_boolean_get(op->ptr, "unselected"))
           bone_looper(ob, arm->bonebase.first, NULL, 
                                hide_unselected_pose_bone);
        else
@@ -4225,7 +4983,7 @@ static int pose_hide_exec(bContext *C, wmOperator *op)
 void POSE_OT_hide(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Hide Selection";
+       ot->name= "Hide Selected";
        ot->idname= "POSE_OT_hide";
        
        /* api callbacks */
@@ -4236,7 +4994,7 @@ void POSE_OT_hide(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* props */
-       RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
+       RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
 }
 
 static int show_pose_bone(Object *ob, Bone *bone, void *ptr) 
@@ -4254,7 +5012,7 @@ static int show_pose_bone(Object *ob, Bone *bone, void *ptr)
 }
 
 /* active object is armature in posemode, poll checked */
-static int pose_reveil_exec(bContext *C, wmOperator *op) 
+static int pose_reveal_exec(bContext *C, wmOperator *op) 
 {
        Object *ob= CTX_data_active_object(C);
        bArmature *arm= ob->data;
@@ -4267,21 +5025,18 @@ static int pose_reveil_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void POSE_OT_reveil(wmOperatorType *ot)
+void POSE_OT_reveal(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Reveil Selection";
-       ot->idname= "POSE_OT_reveil";
+       ot->name= "Reveal Selected";
+       ot->idname= "POSE_OT_reveal";
        
        /* api callbacks */
-       ot->exec= pose_reveil_exec;
+       ot->exec= pose_reveal_exec;
        ot->poll= ED_operator_posemode;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       /* props */
-       RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
 }
 
 /* ************* RENAMING DISASTERS ************ */
@@ -4363,7 +5118,7 @@ void armature_bone_rename(Object *ob, char *oldnamep, char *newnamep)
                        
                        eBone= editbone_name_exists(arm->edbo, oldname);
                        if (eBone) {
-                               unique_editbone_name(arm->edbo, newname);
+                               unique_editbone_name(arm->edbo, newname, NULL);
                                BLI_strncpy(eBone->name, newname, MAXBONENAME);
                        }
                        else return;
@@ -4529,7 +5284,7 @@ void transform_armature_mirror_update(Object *obedit)
        for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
                /* no layer check, correct mirror is more important */
                if (ebo->flag & (BONE_TIPSEL|BONE_ROOTSEL)) {
-                       eboflip= armature_bone_get_mirrored(arm->edbo, ebo);
+                       eboflip= ED_armature_bone_get_mirrored(arm->edbo, ebo);
                        
                        if (eboflip) {
                                /* we assume X-axis flipping for now */
@@ -4590,9 +5345,9 @@ EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode
        
        if (scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE)
        {
-               ReebArcIterator iter;
-               EmbedBucket *current = NULL;
-               EmbedBucket *previous = NULL;
+               ReebArcIterator arc_iter;
+               BArcIterator *iter = (BArcIterator*)&arc_iter;
+               float *previous = NULL, *current = NULL;
                EditBone *child = NULL;
                EditBone *parent = NULL;
                EditBone *root = NULL;
@@ -4604,22 +5359,28 @@ EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode
                
                root = parent;
                
-               for (initArcIterator(&iter, arc, head), previous = nextBucket(&iter), current = nextBucket(&iter);
-                       current;
-                       previous = current, current = nextBucket(&iter))
+               initArcIterator(iter, arc, head);
+               IT_next(iter);
+               previous = iter->p;
+               
+               for (IT_next(iter);
+                       IT_stopped(iter) == 0;
+                       previous = iter->p, IT_next(iter))
                {
                        float vec1[3], vec2[3];
                        float len1, len2;
+                       
+                       current = iter->p;
 
-                       VecSubf(vec1, previous->p, parent->head);
-                       VecSubf(vec2, current->p, previous->p);
+                       VecSubf(vec1, previous, parent->head);
+                       VecSubf(vec2, current, previous);
 
                        len1 = Normalize(vec1);
                        len2 = Normalize(vec2);
 
                        if (len1 > 0.0f && len2 > 0.0f && Inpf(vec1, vec2) < angleLimit)
                        {
-                               VECCOPY(parent->tail, previous->p);
+                               VECCOPY(parent->tail, previous);
 
                                child = add_editbone(obedit, "Bone");
                                VECCOPY(child->head, parent->tail);
@@ -4646,182 +5407,29 @@ EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode
        return lastBone;
 }
 
-float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3])
-{
-       int len = 2 + abs(end - start);
-       
-       if (len > 2)
-       {
-               ReebArcIterator iter;
-               EmbedBucket *bucket = NULL;
-               float avg_t = 0.0f;
-               float s_t = 0.0f;
-               float s_xyz = 0.0f;
-               
-               /* First pass, calculate average */
-               for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter);
-                       bucket;
-                       bucket = nextBucket(&iter))
-               {
-                       float v[3];
-                       
-                       VecSubf(v, bucket->p, v0);
-                       avg_t += Inpf(v, n);
-               }
-               
-               avg_t /= Inpf(n, n);
-               avg_t += 1.0f; /* adding start (0) and end (1) values */
-               avg_t /= len;
-               
-               /* Second pass, calculate s_xyz and s_t */
-               for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter);
-                       bucket;
-                       bucket = nextBucket(&iter))
-               {
-                       float v[3], d[3];
-                       float dt;
-                       
-                       VecSubf(v, bucket->p, v0);
-                       Projf(d, v, n);
-                       VecSubf(v, v, d);
-                       
-                       dt = VecLength(d) - avg_t;
-                       
-                       s_t += dt * dt;
-                       s_xyz += Inpf(v, v);
-               }
-               
-               /* adding start(0) and end(1) values to s_t */
-               s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
-               
-               return s_xyz / s_t; 
-       }
-       else
-       {
-               return 0;
-       }
-}
-
-float calcDistance(ReebArc *arc, int start, int end, float head[3], float tail[3])
-{
-       ReebArcIterator iter;
-       EmbedBucket *bucket = NULL;
-       float max_dist = 0;
-       
-       /* calculate maximum distance */
-       for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter);
-               bucket;
-               bucket = nextBucket(&iter))
-       {
-               float v1[3], v2[3], c[3];
-               float dist;
-               
-               VecSubf(v1, head, tail);
-               VecSubf(v2, bucket->p, tail);
-
-               Crossf(c, v1, v2);
-               
-               dist = Inpf(c, c) / Inpf(v1, v1);
-               
-               max_dist = dist > max_dist ? dist : max_dist;
-       }
-       
-       
-       return max_dist; 
-}
-
-EditBone * subdivideByCorrelation(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
+EditBone * test_subdivideByCorrelation(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
 {
-       ReebArcIterator iter;
-       float n[3];
-       float ADAPTIVE_THRESHOLD = scene->toolsettings->skgen_correlation_limit;
        EditBone *lastBone = NULL;
-       
-       /* init iterator to get start and end from head */
-       initArcIterator(&iter, arc, head);
-       
-       /* Calculate overall */
-       VecSubf(n, arc->buckets[iter.end].p, head->p);
-       
+
        if (scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
        {
-               EmbedBucket *bucket = NULL;
-               EmbedBucket *previous = NULL;
-               EditBone *child = NULL;
-               EditBone *parent = NULL;
-               float normal[3] = {0, 0, 0};
-               float avg_normal[3];
-               int total = 0;
-               int boneStart = iter.start;
-               
-               parent = add_editbone(obedit, "Bone");
-               parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-               VECCOPY(parent->head, head->p);
+               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}};
+               ReebArcIterator arc_iter;
+               BArcIterator *iter = (BArcIterator*)&arc_iter;
+               bArmature *arm= obedit->data;
                
-               for (previous = nextBucket(&iter), bucket = nextBucket(&iter);
-                       bucket;
-                       previous = bucket, bucket = nextBucket(&iter))
-               {
-                       float btail[3];
-                       float value = 0;
-
-                       if (scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING)
-                       {
-                               VECCOPY(btail, bucket->p);
-                       }
-                       else
-                       {
-                               float length;
-                               
-                               /* Calculate normal */
-                               VecSubf(n, bucket->p, parent->head);
-                               length = Normalize(n);
-                               
-                               total += 1;
-                               VecAddf(normal, normal, n);
-                               VECCOPY(avg_normal, normal);
-                               VecMulf(avg_normal, 1.0f / total);
-                                
-                               VECCOPY(btail, avg_normal);
-                               VecMulf(btail, length);
-                               VecAddf(btail, btail, parent->head);
-                       }
-
-                       if (scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE)
-                       {
-                               value = calcDistance(arc, boneStart, iter.index, parent->head, btail);
-                       }
-                       else
-                       {
-                               float n[3];
-                               
-                               VecSubf(n, btail, parent->head);
-                               value = calcVariance(arc, boneStart, iter.index, parent->head, n);
-                       }
-
-                       if (value > ADAPTIVE_THRESHOLD)
-                       {
-                               VECCOPY(parent->tail, btail);
-
-                               child = add_editbone(obedit, "Bone");
-                               VECCOPY(child->head, parent->tail);
-                               child->parent = parent;
-                               child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-                               
-                               parent = child; // new child is next parent
-                               boneStart = iter.index; // start from end
-                               
-                               normal[0] = normal[1] = normal[2] = 0;
-                               total = 0;
-                       }
-               }
-
-               VECCOPY(parent->tail, tail->p);
+               initArcIterator(iter, arc, head);
                
-               lastBone = parent; /* set last bone in the chain */
+               lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
        }
        
-       return lastBone;
+       return lastBone;
 }
 
 float arcLengthRatio(ReebArc *arc)
@@ -4851,108 +5459,26 @@ float arcLengthRatio(ReebArc *arc)
        return embedLength / arcLength; 
 }
 
-EditBone * subdivideByLength(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
+EditBone * test_subdivideByLength(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
 {
        EditBone *lastBone = NULL;
-       
        if ((scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) &&
-               arcLengthRatio(arc) >= scene->toolsettings->skgen_length_ratio)
+               arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio)
        {
-               ReebArcIterator iter;
-               EmbedBucket *bucket = NULL;
-               EmbedBucket *previous = NULL;
-               EditBone *child = NULL;
-               EditBone *parent = NULL;
-               float lengthLimit = scene->toolsettings->skgen_length_limit;
-               int same = 0;
-               
-               parent = add_editbone(obedit, "Bone");
-               parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-               VECCOPY(parent->head, head->p);
-
-               initArcIterator(&iter, arc, head);
-
-               bucket = nextBucket(&iter);
+               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}};
+               ReebArcIterator arc_iter;
+               BArcIterator *iter = (BArcIterator*)&arc_iter;
+               bArmature *arm= obedit->data;
                
-               while (bucket != NULL)
-               {
-                       float *vec0 = NULL;
-                       float *vec1 = bucket->p;
-
-                       /* first bucket. Previous is head */
-                       if (previous == NULL)
-                       {
-                               vec0 = head->p;
-                       }
-                       /* Previous is a valid bucket */
-                       else
-                       {
-                               vec0 = previous->p;
-                       }
-                       
-                       /* If lengthLimit hits the current segment */
-                       if (VecLenf(vec1, parent->head) > lengthLimit)
-                       {
-                               if (same == 0)
-                               {
-                                       float dv[3], off[3];
-                                       float a, b, c, f;
-                                       
-                                       /* Solve quadratic distance equation */
-                                       VecSubf(dv, vec1, vec0);
-                                       a = Inpf(dv, dv);
-                                       
-                                       VecSubf(off, vec0, parent->head);
-                                       b = 2 * Inpf(dv, off);
-                                       
-                                       c = Inpf(off, off) - (lengthLimit * lengthLimit);
-                                       
-                                       f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
-                                       
-                                       //printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
-                                       
-                                       if (isnan(f) == 0 && f < 1.0f)
-                                       {
-                                               VECCOPY(parent->tail, dv);
-                                               VecMulf(parent->tail, f);
-                                               VecAddf(parent->tail, parent->tail, vec0);
-                                       }
-                                       else
-                                       {
-                                               VECCOPY(parent->tail, vec1);
-                                       }
-                               }
-                               else
-                               {
-                                       float dv[3];
-                                       
-                                       VecSubf(dv, vec1, vec0);
-                                       Normalize(dv);
-                                        
-                                       VECCOPY(parent->tail, dv);
-                                       VecMulf(parent->tail, lengthLimit);
-                                       VecAddf(parent->tail, parent->tail, parent->head);
-                               }
-                               
-                               child = add_editbone(obedit, "Bone");
-                               VECCOPY(child->head, parent->tail);
-                               child->parent = parent;
-                               child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-                               
-                               parent = child; // new child is next parent
-                               
-                               same = 1; // mark as same
-                       }
-                       else
-                       {
-                               previous = bucket;
-                               bucket = nextBucket(&iter);
-                               same = 0; // Reset same
-                       }
-               }
-               VECCOPY(parent->tail, tail->p);
+               initArcIterator(iter, arc, head);
                
-               lastBone = parent; /* set last bone in the chain */
+               lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
        }
        
        return lastBone;
@@ -5047,13 +5573,13 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
                        switch(scene->toolsettings->skgen_subdivisions[i])
                        {
                                case SKGEN_SUB_LENGTH:
-                                       lastBone = subdivideByLength(scene, obedit, arc, head, tail);
+                                       lastBone = test_subdivideByLength(scene, obedit, arc, head, tail);
                                        break;
                                case SKGEN_SUB_ANGLE:
                                        lastBone = subdivideByAngle(scene, obedit, arc, head, tail);
                                        break;
                                case SKGEN_SUB_CORRELATION:
-                                       lastBone = subdivideByCorrelation(scene, obedit, arc, head, tail);
+                                       lastBone = test_subdivideByCorrelation(scene, obedit, arc, head, tail);
                                        break;
                        }
                }