svn merge -r40197:40311 ^/trunk/blender
[blender-staging.git] / source / blender / editors / armature / editarmature.c
index f82290333d04d888a68309996f2a7ac06fc4791f..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]);
                        
@@ -494,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;
@@ -628,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;
@@ -730,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)
@@ -1352,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)
 {
@@ -1396,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 ********************** */
 
@@ -1601,10 +1493,8 @@ 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");
-       ARegion *ar;
        Object *obedit= CTX_data_edit_object(C);
        arm= obedit->data;
-       ar= CTX_wm_region(C);
 
        view3d_operator_needs_opengl(C);
 
@@ -2356,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;
 
@@ -2374,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);
        
@@ -2488,20 +2381,19 @@ static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *e
        Scene *scene;
        ARegion *ar;
        View3D *v3d;
-       RegionView3D *rv3d;
-       float *fp = NULL, tvec[3], oldcurs[3];
+       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);
 
-       window_to_3d(ar, tvec, fp, event->mval[0], event->mval[1]);
+       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 */
@@ -3114,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;
                }
        }
        
@@ -3171,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;
@@ -3221,7 +3116,7 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
                }               
                
                armature_tag_unselect(arm);
-
+               
                BLI_freelistN(&chains);
        }
        
@@ -4381,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) {
@@ -4991,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 */
@@ -5166,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;
@@ -5195,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;
 }
 
@@ -5218,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 */
@@ -5294,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"))
@@ -5343,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);
@@ -5525,12 +5473,14 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
                                ScrArea *sa;
                                /* add regions */
                                for(sa= screen->areabase.first; sa; sa= sa->next) {
-                                       SpaceLink *sl= sa->spacedata.first;
-                                       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);
+                                       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);
+                                                               }
                                                        }
                                                }
                                        }