svn merge -r40197:40311 ^/trunk/blender
[blender-staging.git] / source / blender / editors / armature / editarmature.c
index 66fcced1d8e0a80da15e81a5a4de16bccf565e95..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);
 
@@ -2491,14 +2381,12 @@ 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], 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);
        
@@ -3118,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;
                }
        }
        
@@ -3175,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;
@@ -3225,7 +3116,7 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
                }               
                
                armature_tag_unselect(arm);
-
+               
                BLI_freelistN(&chains);
        }
        
@@ -4406,8 +4297,6 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
 {
        Object *ob= base->object;
        Bone *nearBone;
-       // Jason
-       Bone *new_act_bone;
 
        if (!ob || !ob->pose) return 0;
 
@@ -4419,7 +4308,8 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
                
                /* since we do unified select, we don't shift+select a bone if the armature object was not active yet */
                /* Jason was here, I'm doing a select for multibone painting */
-               if ((base != scene->basact)) {//if (!(extend) || (base != scene->basact)) {
+               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) {
@@ -4450,6 +4340,10 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
                        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;
                }
                else {
                        if (nearBone->flag & BONE_SELECTED) {
@@ -5036,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 */
@@ -5272,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 */
@@ -5348,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"))
@@ -5397,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);
@@ -5579,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);
+                                                               }
                                                        }
                                                }
                                        }