2.5: Various Fixes
[blender.git] / source / blender / editors / armature / editarmature.c
index 004cfa078ea59581c7fe0e2207eeb86a05bf729f..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"
@@ -74,6 +72,8 @@
 #include "PIL_time.h"
 
 #include "BIF_gl.h"
+#include "BIF_transform.h"
+#include "BIF_generate.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -110,7 +110,7 @@ static void adduplicate() {}
 /* **************** 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;
        
@@ -462,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])) {
@@ -678,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();
@@ -716,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 */
                                        {
@@ -731,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);
@@ -1137,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;
@@ -1147,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);
@@ -1169,7 +1176,6 @@ static void bone_setflag (int *bone, int flag, short mode)
                                *bone &= ~flag;
                        else
                                *bone ^= flag;
-
                }
                else {
                        if (mode == 2)
@@ -1201,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;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       armature_sync_selection(arm->edbo);
-       
-       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)
@@ -1347,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){
@@ -1381,31 +1343,58 @@ void selectconnected_posearmature(bContext *C)
                selectconnected_posebonechildren (ob, curBone);
        }
        
-               // XXX this only counted the number of pose channels selected
+       // 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){
@@ -1446,10 +1435,30 @@ void selectconnected_armature(bContext *C)
 
        }
 
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
 
-       BIF_undo_push("Select connected");
+       /* BIF_undo_push("Select connected"); */
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
+
+       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 */
@@ -1579,15 +1588,22 @@ EditBone *ED_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) {
@@ -1652,9 +1668,26 @@ void delete_armature(Scene *scene)
        }
        
        
-       armature_sync_selection(arm->edbo);
+       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
@@ -1709,7 +1742,7 @@ void deselectall_armature(Object *obedit, int toggle, int doundo)
                }
        }
        
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        if (doundo) {
                if (sel==1) BIF_undo_push("Select All");
                else BIF_undo_push("Deselect All");
@@ -1728,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) {
 
@@ -1779,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 */
@@ -1821,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 */
 }
 
 
@@ -1920,9 +1957,9 @@ void auto_align_ebone_tocursor(Scene *scene, View3D *v3d, EditBone *ebone)
 
 
 static EnumPropertyItem prop_calc_roll_types[] = {
-       {0, "GLOBALUP", "Z-Axis Up", ""},
-       {1, "CURSOR", "Z-Axis to Cursor", ""},
-       {0, NULL, NULL, NULL}
+       {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) 
@@ -2055,14 +2092,12 @@ 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);
        
@@ -2081,7 +2116,16 @@ static EditBone *add_editbone(Object *obedit, char *name)
        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];
@@ -2093,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);
        
@@ -2108,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);
-       
-       //armature_sync_selection(arm->edbo); // XXX which armature?
-
-       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) {
@@ -2179,7 +2193,7 @@ void addvert_armature(Scene *scene, View3D *v3d)
                        }
                }
                if (ebone == NULL) 
-                       return;
+                       return OPERATOR_CANCELLED;
                
                to_root= 1;
        }
@@ -2232,9 +2246,84 @@ void addvert_armature(Scene *scene, View3D *v3d)
                
        }
        
-       armature_sync_selection(arm->edbo);
+       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) */
@@ -2265,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
@@ -2291,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);
                                                                }
@@ -2314,16 +2420,97 @@ 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;
        
-       armature_sync_selection(arm->edbo); // XXX why is this needed?
+       ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
+
+       preEditBoneDuplicate(arm->edbo);
 
        /* Select mirrored bones */
        if (arm->flag & ARM_MIRROR_EDIT) {
@@ -2337,6 +2524,7 @@ void adduplicate_armature(Scene *scene)
                        }
                }
        }
+
        
        /*      Find the selected bones and duplicate them as needed */
        for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
@@ -2345,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;
@@ -2363,7 +2551,7 @@ void adduplicate_armature(Scene *scene)
                                        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) {
@@ -2371,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;
@@ -2406,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 *************** */
@@ -2839,7 +3058,7 @@ void merge_armature(Scene *scene)
        }
        
        /* undo + updates */
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Merge Bones");
 }
 
@@ -2861,7 +3080,7 @@ void hide_selected_armature_bones(Scene *scene)
                        }
                }
        }
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Hide Bones");
 }
 
@@ -2881,7 +3100,7 @@ void hide_unselected_armature_bones(Scene *scene)
                        }
                }
        }
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Hide Unselected Bones");
 }
 
@@ -2899,19 +3118,24 @@ void show_all_armature_bones(Scene *scene)
                        }
                }
        }
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
        BIF_undo_push("Reveal Bones");
 }
 
+/* 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)) {
@@ -3004,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);
@@ -3023,16 +3247,109 @@ 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 */
-       armature_sync_selection(arm->edbo);
-// XXX BIF_TransformSetUndo("Extrude");
-//     initTransform(TFM_TRANSLATION, CTX_NO_PET);
-//     Transform();
-       
+       ED_armature_sync_selection(arm->edbo);
+
+       return OPERATOR_FINISHED;
 }
 
-/* ----------- */
+static int armature_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       if (OPERATOR_CANCELLED == armature_extrude_exec(C, op))
+               return OPERATOR_CANCELLED;
+
+       RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+       WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+       return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_extrude(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Extrude";
+       ot->idname= "ARMATURE_OT_extrude";
+       
+       /* api callbacks */
+       ot->invoke= armature_extrude_invoke;
+       ot->exec= armature_extrude_exec;
+       ot->poll= ED_operator_editarmature;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* 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 ********************/
+
+/*op makes a new bone and returns it with its tip selected */
+
+static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) 
+{
+       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];
+       
+       RNA_string_get(op->ptr, "name", name);
+       
+       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
@@ -3088,7 +3405,7 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
                        
                        newbone->flag |= BONE_CONNECTED;
                        
-                       unique_editbone_name(arm->edbo, newbone->name);
+                       unique_editbone_name(arm->edbo, newbone->name, NULL);
                        
                        /* correct parent bones */
                        for (tbone = arm->edbo->first; tbone; tbone=tbone->next) {
@@ -3142,11 +3459,13 @@ void ARMATURE_OT_subdivide_multi(wmOperatorType *ot)
 
 static int armature_subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       uiMenuItem *head;
+       uiPopupMenu *pup;
+       uiLayout *layout;
 
-       head= uiPupMenuBegin("Subdivision Type", 0);
-       uiMenuItemsEnumO(head, "ARMATURE_OT_subdivs", "type");
-       uiPupMenuEnd(C, head);
+       pup= uiPupMenuBegin(C, "Subdivision Type", 0);
+       layout= uiPupMenuLayout(pup);
+       uiItemsEnumO(layout, "ARMATURE_OT_subdivs", "type");
+       uiPupMenuEnd(C, pup);
        
        return OPERATOR_CANCELLED;
 }
@@ -3170,9 +3489,9 @@ static int armature_subdivs_exec(bContext *C, wmOperator *op)
 void ARMATURE_OT_subdivs(wmOperatorType *ot)
 {
        static EnumPropertyItem type_items[]= {
-               {0, "SIMPLE", "Simple", ""},
-               {1, "MULTI", "Multi", ""},
-               {0, NULL, NULL}};
+               {0, "SIMPLE", 0, "Simple", ""},
+               {1, "MULTI", 0, "Multi", ""},
+               {0, NULL, 0, NULL, NULL}};
 
        /* identifiers */
        ot->name= "subdivs";
@@ -3288,6 +3607,8 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 /* ***************** Parenting *********************** */
+
+/* armature parenting options */
 #define ARM_PAR_CONNECT 1
 #define ARM_PAR_OFFSET 2
 
@@ -3348,9 +3669,9 @@ static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBo
 }
 
 static EnumPropertyItem prop_editarm_make_parent_types[] = {
-       {ARM_PAR_CONNECT, "CONNECTED", "Connected", ""},
-       {ARM_PAR_OFFSET, "OFFSET", "Keep Offset", ""},
-       {0, NULL, NULL, NULL}
+       {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) 
@@ -3397,14 +3718,19 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
                /* 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
                 */
                
-               /* align selected bones to the active one */
+               /* parent selected bones to the active one */
                CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
-                       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);
+                       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;
        }
@@ -3419,7 +3745,8 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
 static int armature_parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        EditBone *actbone = CTX_data_active_bone(C);
-       uiMenuItem *head= uiPupMenuBegin("Make Parent ", 0);
+       uiPopupMenu *pup= uiPupMenuBegin(C, "Make Parent ", 0);
+       uiLayout *layout= uiPupMenuLayout(pup);
        int allchildbones = 0;
        
        CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
@@ -3429,13 +3756,13 @@ static int armature_parent_set_invoke(bContext *C, wmOperator *op, wmEvent *even
        }
        CTX_DATA_END;
 
-       uiMenuItemEnumO(head, "", 0, "ARMATURE_OT_set_parent", "type", ARM_PAR_CONNECT);
+       uiItemEnumO(layout, NULL, 0, "ARMATURE_OT_parent_set", "type", ARM_PAR_CONNECT);
        
        /* ob becomes parent, make the associated menus */
        if (allchildbones)
-               uiMenuItemEnumO(head, "", 0, "ARMATURE_OT_set_parent", "type", ARM_PAR_OFFSET); 
+               uiItemEnumO(layout, NULL, 0, "ARMATURE_OT_parent_set", "type", ARM_PAR_OFFSET); 
                
-       uiPupMenuEnd(C, head);
+       uiPupMenuEnd(C, pup);
        
        return OPERATOR_CANCELLED;
 }
@@ -3444,7 +3771,7 @@ void ARMATURE_OT_parent_set(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Make Parent";
-       ot->idname= "ARMATURE_OT_set_parent";
+       ot->idname= "ARMATURE_OT_parent_set";
        
        /* api callbacks */
        ot->invoke = armature_parent_set_invoke;
@@ -3458,9 +3785,9 @@ void ARMATURE_OT_parent_set(wmOperatorType *ot)
 }
 
 static EnumPropertyItem prop_editarm_clear_parent_types[] = {
-       {1, "CLEAR", "Clear Parent", ""},
-       {2, "DISCONNECT", "Disconnect Bone", ""},
-       {0, NULL, NULL, NULL}
+       {1, "CLEAR", 0, "Clear Parent", ""},
+       {2, "DISCONNECT", 0, "Disconnect Bone", ""},
+       {0, NULL, 0, NULL, NULL}
 };
 
 static void editbone_clear_parent(EditBone *ebone, int mode)
@@ -3485,7 +3812,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op)
        }
        CTX_DATA_END;
        
-       armature_sync_selection(arm->edbo);
+       ED_armature_sync_selection(arm->edbo);
 
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT, ob);
@@ -3497,7 +3824,7 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Clear Parent";
-       ot->idname= "ARMATURE_OT_clear_parent";
+       ot->idname= "ARMATURE_OT_parent_clear";
        
        /* api callbacks */
        ot->invoke = WM_menu_invoke;
@@ -3512,7 +3839,7 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
 
 /* ****************  Selections  ******************/
 
-static int armature_selection_invert_exec(bContext *C, wmOperator *op)
+static int armature_select_invert_exec(bContext *C, wmOperator *op)
 {
        /*      Set the flags */
        CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
@@ -3527,15 +3854,15 @@ static int armature_selection_invert_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ARMATURE_OT_selection_invert(wmOperatorType *ot)
+void ARMATURE_OT_select_invert(wmOperatorType *ot)
 {
        
        /* identifiers */
        ot->name= "Invert Selection";
-       ot->idname= "ARMATURE_OT_selection_invert";
+       ot->idname= "ARMATURE_OT_select_invert";
        
        /* api callbacks */
-       ot->exec= armature_selection_invert_exec;
+       ot->exec= armature_select_invert_exec;
        ot->poll= ED_operator_editarmature;
        
        /* flags */
@@ -3570,12 +3897,12 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ARMATURE_OT_de_select_all(wmOperatorType *ot)
+void ARMATURE_OT_select_all_toggle(wmOperatorType *ot)
 {
        
        /* identifiers */
        ot->name= "deselect all editbone";
-       ot->idname= "ARMATURE_OT_de_select_all";
+       ot->idname= "ARMATURE_OT_select_all_toggle";
        
        /* api callbacks */
        ot->exec= armature_de_select_all_exec;
@@ -3585,6 +3912,89 @@ void ARMATURE_OT_de_select_all(wmOperatorType *ot)
        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*/
@@ -3680,14 +4090,19 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
                /* 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 (ebone->flag & BONE_SELECTED)
-                               bone_align_to_bone(arm->edbo, ebone, actbone);
-                       else
-                               bone_align_to_bone(arm->edbo, ebone, actmirb);
+                       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;
        }
@@ -3699,11 +4114,11 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ARMATURE_OT_align_bones(wmOperatorType *ot)
+void ARMATURE_OT_bones_align(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Align Bones";
-       ot->idname= "ARMATURE_OT_align_bones";
+       ot->idname= "ARMATURE_OT_bones_align";
        
        /* api callbacks */
        ot->invoke = WM_operator_confirm;
@@ -4408,11 +4823,8 @@ void POSE_OT_rot_clear(wmOperatorType *ot)
 
 /* ***************** selections ********************** */
 
-static int pose_selection_invert_exec(bContext *C, wmOperator *op)
+static int pose_select_invert_exec(bContext *C, wmOperator *op)
 {
-       Object *ob= CTX_data_active_object(C);
-       bArmature *arm= ob->data;
-       bPoseChannel *pchan;
        
        /*      Set the flags */
        CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) {
@@ -4426,15 +4838,15 @@ static int pose_selection_invert_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void POSE_OT_selection_invert(wmOperatorType *ot)
+void POSE_OT_select_invert(wmOperatorType *ot)
 {
        
        /* identifiers */
        ot->name= "Invert Selection";
-       ot->idname= "POSE_OT_selection_invert";
+       ot->idname= "POSE_OT_select_invert";
        
        /* api callbacks */
-       ot->exec= pose_selection_invert_exec;
+       ot->exec= pose_select_invert_exec;
        ot->poll= ED_operator_posemode;
        
        /* flags */
@@ -4462,12 +4874,12 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void POSE_OT_de_select_all(wmOperatorType *ot)
+void POSE_OT_select_all_toggle(wmOperatorType *ot)
 {
        
        /* identifiers */
        ot->name= "deselect all bones";
-       ot->idname= "POSE_OT_de_select_all";
+       ot->idname= "POSE_OT_select_all_toggle";
        
        /* api callbacks */
        ot->exec= pose_de_select_all_exec;
@@ -4519,6 +4931,7 @@ void POSE_OT_select_parent(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
 }
+
 /* ************* hide/unhide pose bones ******************* */
 
 static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr) 
@@ -4554,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
@@ -4570,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 */
@@ -4581,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) 
@@ -4615,7 +5028,7 @@ static int pose_reveal_exec(bContext *C, wmOperator *op)
 void POSE_OT_reveal(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Reveil Selection";
+       ot->name= "Reveal Selected";
        ot->idname= "POSE_OT_reveal";
        
        /* api callbacks */
@@ -4624,9 +5037,6 @@ void POSE_OT_reveal(wmOperatorType *ot)
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       /* props */
-       RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
 }
 
 /* ************* RENAMING DISASTERS ************ */
@@ -4708,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;
@@ -4935,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;
@@ -4949,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);
@@ -4991,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;
+               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;
                
-               parent = add_editbone(obedit, "Bone");
-               parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-               VECCOPY(parent->head, head->p);
+               initArcIterator(iter, arc, head);
                
-               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);
-               
-               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)
@@ -5196,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;
+               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;
                
-               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);
+               initArcIterator(iter, arc, head);
                
-               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);
-               
-               lastBone = parent; /* set last bone in the chain */
+               lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
        }
        
        return lastBone;
@@ -5392,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;
                        }
                }