svn merge -r40197:40311 ^/trunk/blender
[blender-staging.git] / source / blender / editors / armature / editarmature.c
index 76a6cd8c998b7d733b02238812f9718400d6d4bc..9a6be695555f3f21e79a9351b1d4d0b97172d385 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -363,7 +361,7 @@ static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist)
                        print_m4("premat", premat);
                        print_m4("postmat", postmat);
                        print_m4("difmat", difmat);
-                       printf ("Roll = %f\n",  (-atan2(difmat[2][0], difmat[2][2]) * (180.0/M_PI)));
+                       printf ("Roll = %f\n",  RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
 #endif
                        curBone->roll = (float)-atan2(difmat[2][0], difmat[2][2]);
                        
@@ -416,7 +414,9 @@ void ED_armature_from_edit(Object *obedit)
                newBone->flag= eBone->flag;
                
                if (eBone == arm->act_edbone) {
-                       newBone->flag |= BONE_SELECTED; /* important, editbones can be active with only 1 point selected */
+                       /* don't change active selection, this messes up separate which uses
+                        * editmode toggle and can separate active bone which is de-selected originally */
+                       /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */
                        arm->act_edbone= NULL;
                        arm->act_bone= newBone;
                }
@@ -492,15 +492,32 @@ void ED_armature_apply_transform(Object *ob, float mat[4][4])
        EditBone *ebone;
        bArmature *arm= ob->data;
        float scale = mat4_to_scale(mat);       /* store the scale of the matrix here to use on envelopes */
-       
+       float mat3[3][3];
+
+       copy_m3_m4(mat3, mat);
+       normalize_m3(mat3);
+
        /* Put the armature into editmode */
        ED_armature_to_edit(ob);
 
        /* Do the rotations */
-       for (ebone = arm->edbo->first; ebone; ebone=ebone->next){
+       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+               float   delta[3], tmat[3][3];
+
+               /* find the current bone's roll matrix */
+               sub_v3_v3v3(delta, ebone->tail, ebone->head);
+               vec_roll_to_mat3(delta, ebone->roll, tmat);
+
+               /* transform the roll matrix */
+               mul_m3_m3m3(tmat, mat3, tmat);
+
+               /* transform the bone */
                mul_m4_v3(mat, ebone->head);
                mul_m4_v3(mat, ebone->tail);
-               
+
+               /* apply the transfiormed roll back */
+               mat3_to_vec_roll(tmat, NULL, &ebone->roll);
+
                ebone->rad_head *= scale;
                ebone->rad_tail *= scale;
                ebone->dist             *= scale;
@@ -626,7 +643,7 @@ static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
 static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
-       Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); // must be active object, not edit-object
+       Object *ob= object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
        bArmature *arm= get_armature(ob);
        bPose *pose;
        bPoseChannel *pchan;
@@ -728,7 +745,7 @@ void POSE_OT_armature_apply (wmOperatorType *ot)
 /* set the current pose as the restpose */
 static int pose_visual_transform_apply_exec (bContext *C, wmOperator *UNUSED(op))
 {
-       Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); // must be active object, not edit-object
+       Object *ob= object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
 
        /* don't check if editmode (should be done by caller) */
        if (ob->type!=OB_ARMATURE)
@@ -802,7 +819,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
                                                
                                                for (ct= targets.first; ct; ct= ct->next) {
                                                        if (ct->tar == srcArm) {
-                                                               if (strcmp(ct->subtarget, "")==0) {
+                                                               if (ct->subtarget[0] == '\0') {
                                                                        ct->tar = tarArm;
                                                                }
                                                                else if (strcmp(ct->subtarget, pchan->name)==0) {
@@ -849,7 +866,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
                                        
                                        for (ct= targets.first; ct; ct= ct->next) {
                                                if (ct->tar == srcArm) {
-                                                       if (strcmp(ct->subtarget, "")==0) {
+                                                       if (ct->subtarget[0] == '\0') {
                                                                ct->tar = tarArm;
                                                        }
                                                        else if (strcmp(ct->subtarget, pchan->name)==0) {
@@ -997,7 +1014,7 @@ int join_armature_exec(bContext *C, wmOperator *UNUSED(op))
 static void separated_armature_fix_links(Object *origArm, Object *newArm)
 {
        Object *ob;
-       bPoseChannel *pchan, *pcha, *pchb;
+       bPoseChannel *pchan;
        bConstraint *con;
        ListBase *opchans, *npchans;
        
@@ -1024,38 +1041,23 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
                                                         *      - the target isn't origArm/newArm itself
                                                         *      - the target is one that can be found in newArm/origArm
                                                         */
-                                                       if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
-                                                               for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                                                       /* check if either one matches */
-                                                                       if ( (strcmp(pcha->name, ct->subtarget)==0) ||
-                                                                                (strcmp(pchb->name, ct->subtarget)==0) )
-                                                                       {
+                                                       if (ct->subtarget[0] != 0) {
+                                                               if (ct->tar == origArm) {
+                                                                       if(BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
                                                                                ct->tar= newArm;
-                                                                               break;
                                                                        }
-                                                                       
-                                                                       /* check if both ends have met (to stop checking) */
-                                                                       if (pcha == pchb) break;
-                                                               }                                                               
-                                                       }
-                                                       else if ((ct->tar == newArm) && (ct->subtarget[0] != 0)) {
-                                                               for (pcha=opchans->first, pchb=opchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                                                       /* check if either one matches */
-                                                                       if ( (strcmp(pcha->name, ct->subtarget)==0) ||
-                                                                                (strcmp(pchb->name, ct->subtarget)==0) )
-                                                                       {
+                                                               }
+                                                               else if (ct->tar == newArm) {
+                                                                       if(BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
                                                                                ct->tar= origArm;
-                                                                               break;
                                                                        }
-                                                                       
-                                                                       /* check if both ends have met (to stop checking) */
-                                                                       if (pcha == pchb) break;
-                                                               }                                                               
+                                                               }
                                                        }
                                                }
-                                               
-                                               if (cti->flush_constraint_targets)
+
+                                               if (cti->flush_constraint_targets) {
                                                        cti->flush_constraint_targets(con, &targets, 0);
+                                               }
                                        }
                                }
                        }
@@ -1077,58 +1079,33 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
                                                 *      - the target isn't origArm/newArm itself
                                                 *      - the target is one that can be found in newArm/origArm
                                                 */
-                                               if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
-                                                       for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                                               /* check if either one matches */
-                                                               if ( (strcmp(pcha->name, ct->subtarget)==0) ||
-                                                                        (strcmp(pchb->name, ct->subtarget)==0) )
-                                                               {
+                                               if(ct->subtarget[0] != '\0')  {
+                                                       if (ct->tar == origArm) {
+                                                               if(BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
                                                                        ct->tar= newArm;
-                                                                       break;
                                                                }
-                                                               
-                                                               /* check if both ends have met (to stop checking) */
-                                                               if (pcha == pchb) break;
-                                                       }                                                               
-                                               }
-                                               else if ((ct->tar == newArm) && (ct->subtarget[0] != 0)) {
-                                                       for (pcha=opchans->first, pchb=opchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                                               /* check if either one matches */
-                                                               if ( (strcmp(pcha->name, ct->subtarget)==0) ||
-                                                                        (strcmp(pchb->name, ct->subtarget)==0) )
-                                                               {
+                                                       }
+                                                       else if (ct->tar == newArm) {
+                                                               if(BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
                                                                        ct->tar= origArm;
-                                                                       break;
                                                                }
-                                                               
-                                                               /* check if both ends have met (to stop checking) */
-                                                               if (pcha == pchb) break;
-                                                       }                                                               
+                                                       }
                                                }
                                        }
-                                       
-                                       if (cti->flush_constraint_targets)
+
+                                       if (cti->flush_constraint_targets) {
                                                cti->flush_constraint_targets(con, &targets, 0);
+                                       }
                                }
                        }
                }
                
                /* See if an object is parented to this armature */
-               if ((ob->parent) && (ob->parent == origArm)) {
+               if (ob->parent && (ob->parent == origArm)) {
                        /* Is object parented to a bone of this src armature? */
-                       if (ob->partype==PARBONE) {
-                               /* bone name in object */
-                               for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
-                                       /* check if either one matches */
-                                       if ( (strcmp(pcha->name, ob->parsubstr)==0) ||
-                                                (strcmp(pchb->name, ob->parsubstr)==0) )
-                                       {
-                                               ob->parent= newArm;
-                                               break;
-                                       }
-                                       
-                                       /* check if both ends have met (to stop checking) */
-                                       if (pcha == pchb) break;
+                       if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) {
+                               if(BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) {
+                                       ob->parent= newArm;
                                }
                        }
                }
@@ -1390,30 +1367,6 @@ static void *get_nearest_bone (bContext *C, short findunsel, int x, int y)
        return NULL;
 }
 
-/* helper for setflag_sel_bone() */
-static void bone_setflag (int *bone, int flag, short mode)
-{
-       if (bone && flag) {
-               /* exception for inverse flags */
-               if (flag == BONE_NO_DEFORM) {
-                       if (mode == 2)
-                               *bone |= flag;
-                       else if (mode == 1)
-                               *bone &= ~flag;
-                       else
-                               *bone ^= flag;
-               }
-               else {
-                       if (mode == 2)
-                               *bone &= ~flag;
-                       else if (mode == 1)
-                               *bone |= flag;
-                       else
-                               *bone ^= flag;
-               }
-       }
-}
-
 /* Get the first available child of an editbone */
 static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility)
 {
@@ -1434,105 +1387,6 @@ static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_
        return chbone;
 }
 
-/* callback for posemode setflag */
-static int pose_setflag_exec (bContext *C, wmOperator *op)
-{
-       int flag= RNA_enum_get(op->ptr, "type");
-       int mode= RNA_enum_get(op->ptr, "mode");
-       
-       /* loop over all selected pchans */
-       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones) 
-       {
-               bone_setflag(&pchan->bone->flag, flag, mode);
-       }
-       CTX_DATA_END;
-       
-       /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ED_object_pose_armature(CTX_data_active_object(C)));
-       
-       return OPERATOR_FINISHED;
-}
-
-/* callback for editbones setflag */
-static int armature_bones_setflag_exec (bContext *C, wmOperator *op)
-{
-       int flag= RNA_enum_get(op->ptr, "type");
-       int mode= RNA_enum_get(op->ptr, "mode");
-       
-       /* loop over all selected pchans */
-       CTX_DATA_BEGIN(C, EditBone *, ebone, selected_bones) 
-       {
-               bone_setflag(&ebone->flag, flag, mode);
-       }
-       CTX_DATA_END;
-       
-       /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, CTX_data_edit_object(C));
-       
-       return OPERATOR_FINISHED;
-}
-
-/* settings that can be changed */
-static EnumPropertyItem prop_bone_setting_types[] = {
-       {BONE_DRAWWIRE, "DRAWWIRE", 0, "Draw Wire", ""},
-       {BONE_NO_DEFORM, "DEFORM", 0, "Deform", ""},
-       {BONE_MULT_VG_ENV, "MULT_VG", 0, "Multiply Vertex Groups", ""},
-       {BONE_HINGE, "HINGE", 0, "Hinge", ""},
-       {BONE_NO_SCALE, "NO_SCALE", 0, "No Scale", ""},
-       {BONE_EDITMODE_LOCKED, "LOCKED", 0, "Locked", "(For EditMode only)"},
-       {0, NULL, 0, NULL, NULL}
-};
-
-/* ways that settings can be changed */
-static EnumPropertyItem prop_bone_setting_modes[] = {
-       {0, "CLEAR", 0, "Clear", ""},
-       {1, "ENABLE", 0, "Enable", ""},
-       {2, "TOGGLE", 0, "Toggle", ""},
-       {0, NULL, 0, NULL, NULL}
-};
-
-
-void ARMATURE_OT_flags_set (wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Set Bone Flags";
-       ot->idname= "ARMATURE_OT_flags_set";
-       ot->description= "Set flags for armature bones";
-       
-       /* callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= armature_bones_setflag_exec;
-       ot->poll= ED_operator_editarmature;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       /* properties */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_bone_setting_types, 0, "Type", "");
-       RNA_def_enum(ot->srna, "mode", prop_bone_setting_modes, 0, "Mode", "");
-}
-
-void POSE_OT_flags_set (wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Set Bone Flags";
-       ot->idname= "POSE_OT_flags_set";
-       ot->description= "Set flags for armature bones";
-       
-       /* callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= pose_setflag_exec;
-       ot->poll= ED_operator_posemode;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       /* properties */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_bone_setting_types, 0, "Type", "");
-       RNA_def_enum(ot->srna, "mode", prop_bone_setting_modes, 0, "Mode", "");
-}
-
-
 /* **************** END PoseMode & EditMode *************************** */
 /* **************** Posemode stuff ********************** */
 
@@ -1560,22 +1414,17 @@ static void selectconnected_posebonechildren (Object *ob, Bone *bone, int extend
 /* within active object context */
 /* previously known as "selectconnected_posearmature" */
 static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{  
-       ARegion *ar= CTX_wm_region(C);
+{
        Object *ob= CTX_data_edit_object(C);
        Bone *bone, *curBone, *next= NULL;
        int extend= RNA_boolean_get(op->ptr, "extend");
-       int x, y;
-       
-       x= event->x - ar->winrct.xmin;
-       y= event->y - ar->winrct.ymin;
 
        view3d_operator_needs_opengl(C);
        
        if (extend)
-               bone= get_nearest_bone(C, 0, x, y);
+               bone= get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
        else
-               bone= get_nearest_bone(C, 1, x, y);
+               bone= get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
        
        if (!bone)
                return OPERATOR_CANCELLED;
@@ -1644,21 +1493,15 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e
        bArmature *arm;
        EditBone *bone, *curBone, *next;
        int extend= RNA_boolean_get(op->ptr, "extend");
-       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 (extend)
-               bone= get_nearest_bone(C, 0, x, y);
+               bone= get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
        else
-               bone= get_nearest_bone(C, 1, x, y);
+               bone= get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
 
        if (!bone)
                return OPERATOR_CANCELLED;
@@ -1736,7 +1579,7 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot)
 
 /* does bones and points */
 /* note that BONE ROOT only gets drawn for root bones (or without IK) */
-static EditBone *get_nearest_editbonepoint (ViewContext *vc, short mval[2], ListBase *edbo, int findunsel, int *selmask)
+static EditBone *get_nearest_editbonepoint (ViewContext *vc, const int mval[2], ListBase *edbo, int findunsel, int *selmask)
 {
        EditBone *ebone;
        rcti rect;
@@ -1996,7 +1839,7 @@ static int ebone_select_flag(EditBone *ebone)
 }
 
 /* context: editmode armature in view3d */
-int mouse_armature(bContext *C, short mval[2], int extend)
+int mouse_armature(bContext *C, const int mval[2], int extend)
 {
        Object *obedit= CTX_data_edit_object(C);
        bArmature *arm= obedit->data;
@@ -2403,6 +2246,7 @@ EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
 void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
 {
        Object *obedit= scene->obedit; // XXX get from context
+       bArmature *arm= obedit->data;
        float           obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
        EditBone        *bone;
 
@@ -2421,7 +2265,9 @@ void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
        ED_armature_deselect_all(obedit, 0);
        
        /*      Create a bone   */
-       bone= ED_armature_edit_bone_add(obedit->data, "Bone");
+       bone= ED_armature_edit_bone_add(arm, "Bone");
+
+       arm->act_edbone= bone;
 
        copy_v3_v3(bone->head, curs);
        
@@ -2535,43 +2381,20 @@ static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *e
        Scene *scene;
        ARegion *ar;
        View3D *v3d;
-       RegionView3D *rv3d;
-       float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3];
-       short mx, my, mval[2];
+       float *fp = NULL, tvec[3], oldcurs[3], mval_f[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);
        
        copy_v3_v3(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);
-               sub_v3_v3v3(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];
-       }
+
+       VECCOPY2D(mval_f, event->mval);
+       ED_view3d_win_to_3d(ar, fp, mval_f, tvec);
+       copy_v3_v3(fp, tvec);
 
        /* extrude to the where new cursor is and store the operation result */
        retv= armature_click_extrude_exec(C, op);
@@ -2762,7 +2585,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
 
        /* cancel if nothing selected */
        if (CTX_DATA_COUNT(C, selected_bones) == 0)
-         return OPERATOR_CANCELLED;
+               return OPERATOR_CANCELLED;
        
        ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
 
@@ -3183,28 +3006,31 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
        /* TODO, copy more things to the new bone */
        newbone->flag= start->flag & (BONE_HINGE|BONE_NO_DEFORM|BONE_NO_SCALE|BONE_NO_CYCLICOFFSET|BONE_NO_LOCAL_LOCATION|BONE_DONE);
        
-       /* step 2a: parent children of in-between bones to newbone */
-       for (chain= chains->first; chain; chain= chain->next) {
-               /* ick: we need to check if parent of each bone in chain is one of the bones in the */
-               short found= 0;
-               for (ebo= chain->data; ebo; ebo= ebo->parent) {
+       /* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge 
+        *      - potentially several tips for side chains leading to some tree exist...
+        */
+       for (chain = chains->first; chain; chain = chain->next) {
+               /* traverse down chain until we hit the bottom or if we run into the tip of the chain of bones we're 
+                * merging (need to stop in this case to avoid corrupting this chain too!) 
+                */
+               for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
+                       short found = 0;
                        
-                       /* try to find which bone from the list to be removed, is the parent */
-                       for (ebone= end; ebone; ebone= ebone->parent) {
-                               if (ebo->parent == ebone) {
-                                       found= 1;
+                       /* check if this bone is parented to one in the merging chain
+                        * ! WATCHIT: must only go check until end of checking chain
+                        */
+                       for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
+                               /* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
+                               if (ebone->parent == ebo) {
+                                       ebone->parent = newbone;
+                                       found = 1;
                                        break;
                                }
                        }
                        
-                       /* adjust this bone's parent to newbone then */
-                       if (found) {
-                               ebo->parent= newbone;
+                       /* carry on to the next tip now  */
+                       if (found) 
                                break;
-                       }
-               }
-               if (found) {
-                       break;
                }
        }
        
@@ -3240,12 +3066,12 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
                LinkData *chain, *nchain;
                EditBone *ebo;
                
+               armature_tag_select_mirrored(arm);
+               
                /* get chains (ends on chains) */
                chains_find_tips(arm->edbo, &chains);
                if (chains.first == NULL) return OPERATOR_CANCELLED;
-
-               armature_tag_select_mirrored(arm);
-
+               
                /* each 'chain' is the last bone in the chain (with no children) */
                for (chain= chains.first; chain; chain= nchain) {
                        EditBone *bstart= NULL, *bend= NULL;
@@ -3290,7 +3116,7 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
                }               
                
                armature_tag_unselect(arm);
-
+               
                BLI_freelistN(&chains);
        }
        
@@ -4450,30 +4276,74 @@ static int bone_looper(Object *ob, Bone *bone, void *data,
        
        return count;
 }
+// Jason
+Bone* get_other_selected_bone(Object *ob) {
+       Bone *bone;
+       int i;
+       bone = get_indexed_bone(ob, 0);
+       for(i = 0; bone;){
+               if(bone->flag & BONE_SELECTED) {
+                       return bone;
+               }
+               i++;
+               bone = get_indexed_bone(ob, i);
+       }
 
+       return NULL;
+}
 /* called from editview.c, for mode-less pose selection */
 /* assumes scene obact and basact is still on old situation */
 int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short extend)
 {
        Object *ob= base->object;
        Bone *nearBone;
-       
+
        if (!ob || !ob->pose) return 0;
 
        nearBone= get_bone_from_selectbuffer(scene, base, buffer, hits, 1);
-       
+
        /* if the bone cannot be affected, don't do anything */
        if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
                bArmature *arm= ob->data;
                
                /* since we do unified select, we don't shift+select a bone if the armature object was not active yet */
-               if (!(extend) || (base != scene->basact)) {
+               /* Jason was here, I'm doing a select for multibone painting */
+               if (scene->toolsettings->multipaint && (base != scene->basact)) {//if (!(extend) || (base != scene->basact)) {
+                       Bone *new_act_bone;
+                       /* Jason was here */
+                       /* only deselect all if they aren't using 'shift' */
+                       if(!extend) {
+                               ED_pose_deselectall(ob, 0);
+                               nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                               arm->act_bone= nearBone;
+                               ED_vgroup_select_by_name(OBACT, nearBone->name);
+                       }
+                       else {
+                               // Jason deselect this bone specifically if it is selected already
+                               if (nearBone->flag & BONE_SELECTED) {
+                                       nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                       if(nearBone == arm->act_bone) {
+                                               // make a different bone the active one if it exists
+                                               new_act_bone = get_other_selected_bone(ob);
+                                               if(new_act_bone) {
+                                                       new_act_bone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                                       arm->act_bone = new_act_bone;
+                                                       ED_vgroup_select_by_name(OBACT, new_act_bone->name);
+                                               }
+                                       }
+                               // or select the bone if they are using shift
+                               } else {
+                                       nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+                                       arm->act_bone= nearBone;
+                               }
+                       } 
+                       DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
+                               // XXX old cruft! use notifiers instead
+                       //select_actionchannel_by_name(ob->action, nearBone->name, 1);
+               } else if (!(extend) || (base != scene->basact)) {
                        ED_pose_deselectall(ob, 0);
                        nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                        arm->act_bone= nearBone;
-                       
-                               // XXX old cruft! use notifiers instead
-                       //select_actionchannel_by_name(ob->action, nearBone->name, 1);
                }
                else {
                        if (nearBone->flag & BONE_SELECTED) {
@@ -5060,7 +4930,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
                void (*clear_func)(bPoseChannel*), const char default_ksName[])
 {
        Scene *scene= CTX_data_scene(C);
-       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
+       Object *ob= object_pose_armature_get(CTX_data_active_object(C));
        short autokey = 0;
        
        /* sanity checks */
@@ -5235,6 +5105,10 @@ void POSE_OT_select_inverse(wmOperatorType *ot)
 static int pose_de_select_all_exec(bContext *C, wmOperator *op)
 {
        int action = RNA_enum_get(op->ptr, "action");
+       //Jason
+       Object *ob = NULL;
+       Scene *scene= CTX_data_scene(C);
+       int multipaint = scene->toolsettings->multipaint;
 
        if (action == SEL_TOGGLE) {
                action= CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
@@ -5264,7 +5138,12 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
        CTX_DATA_END;
 
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
-       
+       // Jason
+       if(multipaint) {
+               ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       }
+
        return OPERATOR_FINISHED;
 }
 
@@ -5287,7 +5166,7 @@ void POSE_OT_select_all(wmOperatorType *ot)
 
 static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
 {
-       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
+       Object *ob= object_pose_armature_get(CTX_data_active_object(C));
        bPoseChannel *pchan,*parent;
 
        /*      Determine if there is an active bone */
@@ -5363,7 +5242,7 @@ static int hide_unselected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr
 /* active object is armature in posemode, poll checked */
 static int pose_hide_exec(bContext *C, wmOperator *op) 
 {
-       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
+       Object *ob= object_pose_armature_get(CTX_data_active_object(C));
        bArmature *arm= ob->data;
 
        if(RNA_boolean_get(op->ptr, "unselected"))
@@ -5412,7 +5291,7 @@ static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
 /* active object is armature in posemode, poll checked */
 static int pose_reveal_exec(bContext *C, wmOperator *UNUSED(op)) 
 {
-       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
+       Object *ob= object_pose_armature_get(CTX_data_active_object(C));
        bArmature *arm= ob->data;
        
        bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone_cb);
@@ -5586,6 +5465,28 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
                                BKE_animdata_fix_paths_rename(&ob->id, ob->adt, "pose.bones", oldname, newname, 0, 0, 1);
                        }
                }
+
+               {
+                       /* correct view locking */
+                       bScreen *screen;
+                       for(screen= G.main->screen.first; screen; screen= screen->id.next) {
+                               ScrArea *sa;
+                               /* add regions */
+                               for(sa= screen->areabase.first; sa; sa= sa->next) {
+                                       SpaceLink *sl;
+                                       for (sl= sa->spacedata.first; sl; sl= sl->next) {
+                                               if(sl->spacetype==SPACE_VIEW3D) {
+                                                       View3D *v3d= (View3D *)sl;
+                                                       if(v3d->ob_centre && v3d->ob_centre->data == arm) {
+                                                               if (!strcmp(v3d->ob_centre_bone, oldname)) {
+                                                                       BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
 }
 
@@ -5844,7 +5745,7 @@ EditBone * test_subdivideByCorrelation(Scene *scene, Object *obedit, ReebArc *ar
                lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
        }
        
-         return lastBone;
+       return lastBone;
 }
 
 float arcLengthRatio(ReebArc *arc)