merging trunk 15964 -> 16116
[blender.git] / source / blender / src / editarmature.c
index 80a01bc5ccea6a9e374b31439f8361b063b2a39b..92c2db0eb5784e5b2e462a6aa2b856923f91a853 100644 (file)
@@ -854,6 +854,7 @@ static void separate_armature_bones (Object *ob, short sel)
        BLI_freelistN(&edbo);
 }
 
+/* separate selected bones into their armature */
 void separate_armature (void)
 {
        Object *oldob, *newob;
@@ -1094,13 +1095,13 @@ void armature_select_hierarchy(short direction, short add_to_sel)
        arm= (bArmature *)ob->data;
        
        for (curbone= G.edbo.first; curbone; curbone= curbone->next) {
-               if (arm->layer & curbone->layer) {
+               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 ((arm->layer & pabone->layer) && !(pabone->flag & BONE_HIDDEN_A)) {
+                                       if (EBONE_VISIBLE(arm, pabone)) {
                                                pabone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                                                if (pabone->parent)     pabone->parent->flag |= BONE_TIPSEL;
                                                
@@ -1109,11 +1110,12 @@ void armature_select_hierarchy(short direction, short add_to_sel)
                                                break;
                                        }
                                        
-                               } else { // BONE_SELECT_CHILD
+                               } 
+                               else { // BONE_SELECT_CHILD
                                        chbone = editbone_get_child(curbone, 1);
                                        if (chbone == NULL) continue;
                                        
-                                       if ((arm->layer & chbone->layer) && !(chbone->flag & BONE_HIDDEN_A)) {
+                                       if (EBONE_VISIBLE(arm, chbone)) {
                                                chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                                                
                                                if (!add_to_sel) {
@@ -1159,17 +1161,18 @@ void setflag_armature (short mode)
        
        /* get flag to set (sync these with the ones used in eBone_Flag */
        if (mode == 2)
-               flag= pupmenu("Disable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5");
+               flag= pupmenu("Disable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
        else if (mode == 1)
-               flag= pupmenu("Enable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5");
+               flag= pupmenu("Enable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
        else
-               flag= pupmenu("Toggle Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5");
+               flag= pupmenu("Toggle Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
        switch (flag) {
                case 1:         flag = BONE_DRAWWIRE;   break;
                case 2:         flag = BONE_NO_DEFORM; break;
                case 3:         flag = BONE_MULT_VG_ENV; break;
                case 4:         flag = BONE_HINGE; break;
                case 5:         flag = BONE_NO_SCALE; break;
+               case 6:         flag = BONE_EDITMODE_LOCKED; break;
                default:        return;
        }
        
@@ -1725,12 +1728,12 @@ void auto_align_armature(short mode)
        float   *cursor= give_cursor();
                
        for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
+               if (EBONE_VISIBLE(arm, ebone)) {
                        if (arm->flag & ARM_MIRROR_EDIT)
                                flipbone = armature_bone_get_mirrored(ebone);
                        
                        if ((ebone->flag & BONE_SELECTED) || 
-                               (flipbone && flipbone->flag & BONE_SELECTED)) 
+                               (flipbone && (flipbone->flag & BONE_SELECTED))) 
                        {
                                /* specific method used to calculate roll depends on mode */
                                if (mode == 1) {
@@ -1975,7 +1978,7 @@ void addvert_armature(void)
        
        /* find the active or selected bone */
        for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
+               if (EBONE_VISIBLE(arm, ebone)) {
                        if (ebone->flag & (BONE_ACTIVE|BONE_TIPSEL)) 
                                break;
                }
@@ -1983,7 +1986,7 @@ void addvert_armature(void)
        
        if (ebone==NULL) {
                for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-                       if (arm->layer & ebone->layer) {
+                       if (EBONE_VISIBLE(arm, ebone)) {
                                if (ebone->flag & (BONE_ACTIVE|BONE_ROOTSEL)) 
                                        break;
                        }
@@ -2066,11 +2069,12 @@ static EditBone *get_named_editbone(char *name)
 {
        EditBone  *eBone;
 
-       if (name)
+       if (name) {
                for (eBone=G.edbo.first; eBone; eBone=eBone->next) {
                        if (!strcmp(name, eBone->name))
                                return eBone;
                }
+       }
 
        return NULL;
 }
@@ -2136,7 +2140,7 @@ void adduplicate_armature(void)
        /* Select mirrored bones */
        if (arm->flag & ARM_MIRROR_EDIT) {
                for (curBone=G.edbo.first; curBone; curBone=curBone->next) {
-                       if (arm->layer & curBone->layer) {
+                       if (EBONE_VISIBLE(arm, curBone)) {
                                if (curBone->flag & BONE_SELECTED) {
                                        eBone = armature_bone_get_mirrored(curBone);
                                        if (eBone)
@@ -2148,13 +2152,13 @@ void adduplicate_armature(void)
        
        /*      Find the selected bones and duplicate them as needed */
        for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) {
-               if (arm->layer & curBone->layer) {
+               if (EBONE_VISIBLE(arm, curBone)) {
                        if (curBone->flag & BONE_SELECTED) {
                                eBone=MEM_callocN(sizeof(EditBone), "addup_editbone");
                                eBone->flag |= BONE_SELECTED;
                                
                                /*      Copy data from old bone to new bone */
-                               memcpy (eBone, curBone, sizeof(EditBone));
+                               memcpy(eBone, curBone, sizeof(EditBone));
                                
                                curBone->temp = eBone;
                                eBone->temp = curBone;
@@ -2204,7 +2208,7 @@ void adduplicate_armature(void)
 
        /*      Run though the list and fix the pointers */
        for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) {
-               if (arm->layer & curBone->layer) {
+               if (EBONE_VISIBLE(arm, curBone)) {
                        if (curBone->flag & BONE_SELECTED) {
                                eBone=(EditBone*) curBone->temp;
                                
@@ -2236,7 +2240,7 @@ void adduplicate_armature(void)
        /*      Deselect the old bones and select the new ones */
        
        for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) {
-               if (arm->layer & curBone->layer)
+               if (EBONE_VISIBLE(arm, curBone))
                        curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
        }
        
@@ -2373,7 +2377,7 @@ void fill_bones_armature(void)
        
        /* loop over all bones, and only consider if visible */
        for (ebo= G.edbo.first; ebo; ebo= ebo->next) {
-               if ((arm->layer & ebo->layer) && !(ebo->flag & BONE_HIDDEN_A)) {
+               if (EBONE_VISIBLE(arm, ebo)) {
                        if (!(ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL))
                                fill_add_joint(ebo, 0, &points);
                        if (ebo->flag & BONE_TIPSEL) 
@@ -2608,7 +2612,7 @@ void merge_armature(void)
                        /* only consider bones that are visible and selected */
                        for (ebo=chain->data; ebo; child=ebo, ebo=ebo->parent) {
                                /* check if visible + selected */
-                               if ( (arm->layer & ebo->layer) && !(ebo->flag & BONE_HIDDEN_A) &&
+                               if ( EBONE_VISIBLE(arm, ebo) &&
                                         ((ebo->flag & BONE_CONNECTED) || (ebo->parent==NULL)) &&
                                         (ebo->flag & (BONE_SELECTED|BONE_ACTIVE)) )
                                {
@@ -2659,7 +2663,7 @@ void hide_selected_armature_bones(void)
        EditBone *ebone;
        
        for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
+               if (EBONE_VISIBLE(arm, ebone)) {
                        if (ebone->flag & (BONE_SELECTED)) {
                                ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
                                ebone->flag |= BONE_HIDDEN_A;
@@ -2678,7 +2682,7 @@ void hide_unselected_armature_bones(void)
        
        for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
                bArmature *arm= G.obedit->data;
-               if (arm->layer & ebone->layer) {
+               if (EBONE_VISIBLE(arm, ebone)) {
                        if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL));
                        else {
                                ebone->flag &= ~BONE_ACTIVE;
@@ -2711,32 +2715,6 @@ void show_all_armature_bones(void)
        BIF_undo_push("Reveal Bones");
 }
 
-/* Sets editmode transform locks for bones (adds if lock==1, clears otherwise) */
-void set_locks_armature_bones(short lock)
-{
-       bArmature *arm= G.obedit->data;
-       EditBone *ebone;
-       
-       for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
-                       if (ebone->flag & BONE_SELECTED) {
-                               if (lock)
-                                       ebone->flag |= BONE_EDITMODE_LOCKED;
-                               else    
-                                       ebone->flag &= ~BONE_EDITMODE_LOCKED;
-                       }
-               }
-       }
-       countall();
-       allqueue(REDRAWVIEW3D, 0);
-       allqueue(REDRAWBUTSEDIT, 0);
-       
-       if (lock)
-               BIF_undo_push("Lock Bones");
-       else
-               BIF_undo_push("Unlock Bones");
-}
-
 /* check for null, before calling! */
 static void bone_connect_to_existing_parent(EditBone *bone)
 {
@@ -2803,7 +2781,7 @@ void make_bone_parent(void)
        
        /* find active bone to parent to */
        for (actbone = G.edbo.first; actbone; actbone=actbone->next) {
-               if (arm->layer & actbone->layer) {
+               if (EBONE_VISIBLE(arm, actbone)) {
                        if (actbone->flag & BONE_ACTIVE)
                                break;
                }
@@ -2815,7 +2793,7 @@ void make_bone_parent(void)
 
        /* find selected bones */
        for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
+               if (EBONE_VISIBLE(arm, ebone)) {
                        if ((ebone->flag & BONE_SELECTED) && (ebone != actbone)) {
                                foundselbone++;
                                if (ebone->parent != actbone) allchildbones= 1; 
@@ -2851,7 +2829,7 @@ void make_bone_parent(void)
        else {
                /* loop through all editbones, parenting all selected bones to the active bone */
                for (selbone = G.edbo.first; selbone; selbone=selbone->next) {
-                       if (arm->layer & selbone->layer) {
+                       if (EBONE_VISIBLE(arm, selbone)) {
                                if ((selbone->flag & BONE_SELECTED) && (selbone!=actbone)) {
                                        /* parent selbone to actbone */
                                        bone_connect_to_new_parent(selbone, actbone, val);
@@ -2909,7 +2887,7 @@ void clear_bone_parent(void)
        if (val<1) return;
        
        for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
+               if (EBONE_VISIBLE(arm, ebone)) {
                        if (ebone->flag & BONE_SELECTED) {
                                if (arm->flag & ARM_MIRROR_EDIT)
                                        flipbone = armature_bone_get_mirrored(ebone);
@@ -2959,7 +2937,7 @@ void unique_editbone_name (ListBase *ebones, char *name)
                }
                
                for (number = 1; number <=999; number++) {
-                       sprintf (tempname, "%s.%03d", name, number);
+                       sprintf(tempname, "%s.%03d", name, number);
                        if (!editbone_name_exists(ebones, tempname)) {
                                BLI_strncpy(name, tempname, 32);
                                return;
@@ -2980,7 +2958,7 @@ void extrude_armature(int forked)
        
        /* since we allow root extrude too, we have to make sure selection is OK */
        for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
+               if (EBONE_VISIBLE(arm, ebone)) {
                        if (ebone->flag & BONE_ROOTSEL) {
                                if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
                                        if (ebone->parent->flag & BONE_TIPSEL)
@@ -2992,7 +2970,7 @@ void extrude_armature(int forked)
        
        /* Duplicate the necessary bones */
        for (ebone = G.edbo.first; ((ebone) && (ebone!=first)); ebone=ebone->next) {
-               if (arm->layer & ebone->layer) {
+               if (EBONE_VISIBLE(arm, ebone)) {
                        /* we extrude per definition the tip */
                        do_extrude= 0;
                        if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED))
@@ -3006,7 +2984,7 @@ void extrude_armature(int forked)
                        if (do_extrude) {
                                /* we re-use code for mirror editing... */
                                flipbone= NULL;
-                               if(arm->flag & ARM_MIRROR_EDIT) {
+                               if (arm->flag & ARM_MIRROR_EDIT) {
                                        flipbone= armature_bone_get_mirrored(ebone);
                                        if (flipbone) {
                                                forked= 0;      // we extrude 2 different bones
@@ -3036,7 +3014,7 @@ void extrude_armature(int forked)
                                                newbone->parent = ebone;
                                                
                                                newbone->flag = ebone->flag & BONE_TIPSEL;      // copies it, in case mirrored bone
-
+                                               
                                                if (newbone->parent) newbone->flag |= BONE_CONNECTED;
                                        }
                                        else {
@@ -3046,7 +3024,7 @@ void extrude_armature(int forked)
                                                
                                                newbone->flag= BONE_TIPSEL;
                                                
-                                               if (newbone->parent && ebone->flag & BONE_CONNECTED) {
+                                               if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
                                                        newbone->flag |= BONE_CONNECTED;
                                                }
                                        }
@@ -3065,8 +3043,8 @@ void extrude_armature(int forked)
                                        BLI_strncpy (newbone->name, ebone->name, 32);
                                        
                                        if (flipbone && forked) {       // only set if mirror edit
-                                               if(strlen(newbone->name)<30) {
-                                                       if(a==0) strcat(newbone->name, "_L");
+                                               if (strlen(newbone->name)<30) {
+                                                       if (a==0) strcat(newbone->name, "_L");
                                                        else strcat(newbone->name, "_R");
                                                }
                                        }
@@ -3111,7 +3089,7 @@ void subdivide_armature(int numcuts)
        if (numcuts < 1) return;
 
        for (mbone = G.edbo.last; mbone; mbone= mbone->prev) {
-               if (arm->layer & mbone->layer) {
+               if (EBONE_VISIBLE(arm, mbone)) {
                        if (mbone->flag & BONE_SELECTED) {
                                for (i=numcuts+1; i>1; i--) {
                                        /* compute cut ratio first */
@@ -3176,6 +3154,59 @@ void subdivide_armature(int numcuts)
        else BIF_undo_push("Subdivide multi");
 }
 
+/* switch direction of bone chains */
+void switch_direction_armature (void)
+{
+       bArmature *arm= (G.obedit) ? G.obedit->data : NULL;
+       ListBase chains = {NULL, NULL};
+       LinkData *chain;
+       
+       /* error checking paranoia */
+       if (arm == NULL)
+               return;
+       
+       /* get chains of bones (ends on chains) */
+       chains_find_tips(&chains);
+       if (chains.first == NULL) return;
+       
+       /* loop over chains, only considering selected and visible bones */
+       for (chain= chains.first; chain; chain= chain->next) {
+               EditBone *ebo, *child=NULL, *parent=NULL;
+               
+               /* loop over bones in chain */
+               for (ebo= chain->data; ebo; child= ebo, ebo=parent) {
+                       parent= ebo->parent;
+                       
+                       /* only if selected and editable */
+                       if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {                           
+                               /* swap head and tail coordinates */
+                               SWAP(float, ebo->head[0], ebo->tail[0]);
+                               SWAP(float, ebo->head[1], ebo->tail[1]);
+                               SWAP(float, ebo->head[2], ebo->tail[2]);
+                               
+                               /* do parent swapping:
+                                *      - use 'child' as new parent
+                                *      - connected flag is only set if points are coincidental
+                                */
+                               ebo->parent= child;
+                               if ((child) && VecEqual(ebo->head, child->tail))
+                                       ebo->flag |= BONE_CONNECTED;
+                               else    
+                                       ebo->flag &= ~BONE_CONNECTED;
+                               
+                               /* FIXME: other things that need fixing?
+                                *              i.e. roll?
+                                */
+                       }
+               }
+       }
+       
+       /* free chains */
+       BLI_freelistN(&chains);
+       
+       BIF_undo_push("Switch Direction");
+}
+
 /* ***************** Pose tools ********************* */
 
 void clear_armature(Object *ob, char mode)