Blender V2.61 - r43446

editarmature.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Blender Foundation, 2002-2009 full recode.
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <ctype.h>
00032 #include <stdlib.h>
00033 #include <stddef.h>
00034 #include <string.h>
00035 #include <math.h> 
00036 #include <float.h> 
00037 #include <assert.h> 
00038 
00039 
00040 #include "DNA_anim_types.h"
00041 #include "DNA_armature_types.h"
00042 #include "DNA_constraint_types.h"
00043 #include "DNA_meshdata_types.h"
00044 #include "DNA_scene_types.h"
00045 
00046 #include "MEM_guardedalloc.h"
00047 
00048 #include "BLI_blenlib.h"
00049 #include "BLI_math.h"
00050 #include "BLI_utildefines.h"
00051 #include "BLI_editVert.h"
00052 #include "BLI_ghash.h"
00053 
00054 #include "BKE_animsys.h"
00055 #include "BKE_action.h"
00056 #include "BKE_armature.h"
00057 #include "BKE_constraint.h"
00058 #include "BKE_context.h"
00059 #include "BKE_deform.h"
00060 #include "BKE_depsgraph.h"
00061 #include "BKE_DerivedMesh.h"
00062 #include "BKE_global.h"
00063 #include "BKE_idprop.h"
00064 #include "BKE_main.h"
00065 #include "BKE_object.h"
00066 #include "BKE_report.h"
00067 #include "BKE_subsurf.h"
00068 #include "BKE_modifier.h"
00069 #include "DNA_object_types.h"
00070 
00071 #include "BIF_gl.h"
00072 
00073 #include "RNA_access.h"
00074 #include "RNA_define.h"
00075 
00076 #include "WM_api.h"
00077 #include "WM_types.h"
00078 
00079 #include "ED_armature.h"
00080 #include "ED_keyframing.h"
00081 #include "ED_mesh.h"
00082 #include "ED_object.h"
00083 #include "ED_screen.h"
00084 #include "ED_util.h"
00085 #include "ED_view3d.h"
00086 
00087 #include "UI_interface.h"
00088 #include "UI_resources.h"
00089 
00090 #include "armature_intern.h"
00091 #include "meshlaplacian.h"
00092 
00093 #if 0
00094 #include "reeb.h"
00095 #endif
00096 
00097 /* **************** tools on Editmode Armature **************** */
00098 
00099 /* Sync selection to parent for connected children */
00100 void ED_armature_sync_selection(ListBase *edbo)
00101 {
00102     EditBone *ebo;
00103     
00104     for (ebo=edbo->first; ebo; ebo= ebo->next) {
00105         /* if bone is not selectable, we shouldn't alter this setting... */
00106         if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
00107             if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
00108                 if (ebo->parent->flag & BONE_TIPSEL)
00109                     ebo->flag |= BONE_ROOTSEL;
00110                 else
00111                     ebo->flag &= ~BONE_ROOTSEL;
00112             }
00113             
00114             if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
00115                 ebo->flag |= BONE_SELECTED;
00116             else
00117                 ebo->flag &= ~BONE_SELECTED;
00118         }
00119     }               
00120 }
00121 
00122 void ED_armature_validate_active(struct bArmature *arm)
00123 {
00124     EditBone *ebone= arm->act_edbone;
00125 
00126     if(ebone) { 
00127         if(ebone->flag & BONE_HIDDEN_A)
00128             arm->act_edbone= NULL;
00129     }
00130 }
00131 
00132 static void bone_free(bArmature *arm, EditBone *bone)
00133 {
00134     if(arm->act_edbone==bone)
00135         arm->act_edbone= NULL;
00136 
00137     if(bone->prop) {
00138         IDP_FreeProperty(bone->prop);
00139         MEM_freeN(bone->prop);
00140     }
00141 
00142     BLI_freelinkN(arm->edbo, bone);
00143 }
00144 
00145 void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
00146 {
00147     EditBone *curBone;
00148 
00149     /* Find any bones that refer to this bone */
00150     for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
00151         if (curBone->parent==exBone) {
00152             curBone->parent=exBone->parent;
00153             curBone->flag &= ~BONE_CONNECTED;
00154         }
00155     }
00156 
00157     bone_free(arm, exBone);
00158 }
00159 
00160 /* context: editmode armature */
00161 EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
00162 {
00163     EditBone *eboflip= NULL;
00164     char name[MAXBONENAME];
00165     
00166     if (ebo == NULL)
00167         return NULL;
00168     
00169     flip_side_name(name, ebo->name, FALSE);
00170     
00171     for (eboflip= edbo->first; eboflip; eboflip=eboflip->next) {
00172         if (ebo != eboflip) {
00173             if (!strcmp (name, eboflip->name)) 
00174                 break;
00175         }
00176     }
00177     
00178     return eboflip;
00179 }
00180 
00181 /* helper function for tools to work on mirrored parts.
00182    it leaves mirrored bones selected then too, which is a good indication of what happened */
00183 static void armature_select_mirrored(bArmature *arm)
00184 {
00185     /* Select mirrored bones */
00186     if (arm->flag & ARM_MIRROR_EDIT) {
00187         EditBone *curBone, *ebone_mirr;
00188         
00189         for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
00190             if (arm->layer & curBone->layer) {
00191                 if (curBone->flag & BONE_SELECTED) {
00192                     ebone_mirr= ED_armature_bone_get_mirrored(arm->edbo, curBone);
00193                     if (ebone_mirr)
00194                         ebone_mirr->flag |= BONE_SELECTED;
00195                 }
00196             }
00197         }
00198     }
00199     
00200 }
00201 
00202 static void armature_tag_select_mirrored(bArmature *arm)
00203 {
00204     EditBone *curBone;
00205 
00206     /* always untag */
00207     for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
00208         curBone->flag &= ~BONE_DONE;
00209     }
00210 
00211     /* Select mirrored bones */
00212     if (arm->flag & ARM_MIRROR_EDIT) {
00213         for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
00214             if (arm->layer & curBone->layer) {
00215                 if (curBone->flag & (BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL)) {
00216                     EditBone *ebone_mirr= ED_armature_bone_get_mirrored(arm->edbo, curBone);
00217                     if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
00218                         ebone_mirr->flag |= BONE_DONE;
00219                     }
00220                 }
00221             }
00222         }
00223 
00224         for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
00225             if (curBone->flag & BONE_DONE) {
00226                 EditBone *ebone_mirr= ED_armature_bone_get_mirrored(arm->edbo, curBone);
00227                 curBone->flag |= ebone_mirr->flag & (BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL);
00228             }
00229         }
00230     }
00231 }
00232 
00233 
00234 /* only works when tagged */
00235 static void armature_tag_unselect(bArmature *arm)
00236 {
00237     EditBone *curBone;
00238 
00239     for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
00240         if (curBone->flag & BONE_DONE) {
00241             curBone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_DONE);
00242         }
00243     }
00244 }
00245 
00246 /* converts Bones to EditBone list, used for tools as well */
00247 EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone)
00248 {
00249     EditBone    *eBone;
00250     EditBone    *eBoneAct= NULL;
00251     EditBone    *eBoneTest= NULL;
00252     Bone        *curBone;
00253         
00254     for (curBone=bones->first; curBone; curBone=curBone->next) {
00255         eBone= MEM_callocN(sizeof(EditBone), "make_editbone");
00256         
00257         /*  Copy relevant data from bone to eBone */
00258         eBone->parent= parent;
00259         BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
00260         eBone->flag = curBone->flag;
00261         
00262         /* fix selection flags */
00263 
00264         if (eBone->flag & BONE_SELECTED) {
00265             /* if the bone is selected the copy its root selection to the parents tip */
00266             eBone->flag |= BONE_TIPSEL;
00267             if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
00268                 eBone->parent->flag |= BONE_TIPSEL;
00269                 eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */
00270             }
00271             else {
00272                 eBone->flag |= BONE_ROOTSEL;
00273             }
00274         }
00275         else {
00276             /* if the bone is not selected, but connected to its parent
00277              *  copy the parents tip selection state */
00278             if(eBone->parent &&  (eBone->flag & BONE_CONNECTED)) {
00279                 /* selecting with the mouse gives this behavior */
00280                 if(eBone->parent->flag & BONE_TIPSEL) {
00281                     eBone->flag |= BONE_ROOTSEL;
00282                 }
00283                 else {
00284                     eBone->flag &= ~BONE_ROOTSEL;
00285                 }
00286 
00287                 /* probably not selected but just incase */
00288                 eBone->flag &= ~BONE_TIPSEL;
00289             }
00290         }
00291 
00292         copy_v3_v3(eBone->head, curBone->arm_head);
00293         copy_v3_v3(eBone->tail, curBone->arm_tail);
00294         eBone->roll = curBone->arm_roll;
00295         
00296         /* rest of stuff copy */
00297         eBone->length= curBone->length;
00298         eBone->dist= curBone->dist;
00299         eBone->weight= curBone->weight;
00300         eBone->xwidth= curBone->xwidth;
00301         eBone->zwidth= curBone->zwidth;
00302         eBone->ease1= curBone->ease1;
00303         eBone->ease2= curBone->ease2;
00304         eBone->rad_head= curBone->rad_head;
00305         eBone->rad_tail= curBone->rad_tail;
00306         eBone->segments = curBone->segments;        
00307         eBone->layer = curBone->layer;
00308 
00309         if(curBone->prop)
00310             eBone->prop= IDP_CopyProperty(curBone->prop);
00311         
00312         BLI_addtail(edbo, eBone);
00313         
00314         /*  Add children if necessary */
00315         if (curBone->childbase.first) {
00316             eBoneTest= make_boneList(edbo, &curBone->childbase, eBone, actBone);
00317             if(eBoneTest)
00318                 eBoneAct= eBoneTest;
00319         }
00320 
00321         if(curBone==actBone)
00322             eBoneAct= eBone;
00323     }
00324 
00325     return eBoneAct;
00326 }
00327 
00328 /* nasty stuff for converting roll in editbones into bones */
00329 /* also sets restposition in armature (arm_mat) */
00330 static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist)
00331 {
00332     Bone *curBone;
00333     EditBone *ebone;
00334     float premat[3][3];
00335     float postmat[3][3];
00336     float difmat[3][3];
00337     float imat[3][3];
00338     float delta[3];
00339     
00340     for (curBone=bonelist->first; curBone; curBone=curBone->next) {
00341         /* sets local matrix and arm_mat (restpos) */
00342         where_is_armature_bone(curBone, curBone->parent);
00343         
00344         /* Find the associated editbone */
00345         for (ebone = editbonelist->first; ebone; ebone=ebone->next)
00346             if ((Bone*)ebone->temp == curBone)
00347                 break;
00348         
00349         if (ebone) {
00350             /* Get the ebone premat */
00351             sub_v3_v3v3(delta, ebone->tail, ebone->head);
00352             vec_roll_to_mat3(delta, ebone->roll, premat);
00353             
00354             /* Get the bone postmat */
00355             copy_m3_m4(postmat, curBone->arm_mat);
00356             
00357             invert_m3_m3(imat, premat);
00358             mul_m3_m3m3(difmat, imat, postmat);
00359 #if 0
00360             printf ("Bone %s\n", curBone->name);
00361             print_m4("premat", premat);
00362             print_m4("postmat", postmat);
00363             print_m4("difmat", difmat);
00364             printf ("Roll = %f\n",  RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
00365 #endif
00366             curBone->roll = (float)-atan2(difmat[2][0], difmat[2][2]);
00367             
00368             /* and set restposition again */
00369             where_is_armature_bone(curBone, curBone->parent);
00370         }
00371         fix_bonelist_roll(&curBone->childbase, editbonelist);
00372     }
00373 }
00374 
00375 /* put EditMode back in Object */
00376 void ED_armature_from_edit(Object *obedit)
00377 {
00378     bArmature *arm= obedit->data;
00379     EditBone *eBone, *neBone;
00380     Bone    *newBone;
00381     Object *obt;
00382     
00383     /* armature bones */
00384     free_bonelist(&arm->bonebase);
00385     
00386     /* remove zero sized bones, this gives instable restposes */
00387     for (eBone=arm->edbo->first; eBone; eBone= neBone) {
00388         float len= len_v3v3(eBone->head, eBone->tail);
00389         neBone= eBone->next;
00390         if (len <= 0.000001f) {     /* FLT_EPSILON is too large? */
00391             EditBone *fBone;
00392             
00393             /*  Find any bones that refer to this bone  */
00394             for (fBone=arm->edbo->first; fBone; fBone= fBone->next) {
00395                 if (fBone->parent==eBone)
00396                     fBone->parent= eBone->parent;
00397             }
00398             if (G.f & G_DEBUG)
00399                 printf("Warning: removed zero sized bone: %s\n", eBone->name);
00400             bone_free(arm, eBone);
00401         }
00402     }
00403     
00404     /*  Copy the bones from the editData into the armature */
00405     for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
00406         newBone= MEM_callocN(sizeof(Bone), "bone");
00407         eBone->temp= newBone;   /* Associate the real Bones with the EditBones */
00408         
00409         BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
00410         copy_v3_v3(newBone->arm_head, eBone->head);
00411         copy_v3_v3(newBone->arm_tail, eBone->tail);
00412         newBone->arm_roll = eBone->roll;
00413         
00414         newBone->flag= eBone->flag;
00415         
00416         if (eBone == arm->act_edbone) {
00417             /* don't change active selection, this messes up separate which uses
00418              * editmode toggle and can separate active bone which is de-selected originally */
00419             /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */
00420             arm->act_edbone= NULL;
00421             arm->act_bone= newBone;
00422         }
00423         newBone->roll = 0.0f;
00424         
00425         newBone->weight = eBone->weight;
00426         newBone->dist = eBone->dist;
00427         
00428         newBone->xwidth = eBone->xwidth;
00429         newBone->zwidth = eBone->zwidth;
00430         newBone->ease1= eBone->ease1;
00431         newBone->ease2= eBone->ease2;
00432         newBone->rad_head= eBone->rad_head;
00433         newBone->rad_tail= eBone->rad_tail;
00434         newBone->segments= eBone->segments;
00435         newBone->layer = eBone->layer;
00436         
00437         if(eBone->prop)
00438             newBone->prop= IDP_CopyProperty(eBone->prop);
00439     }
00440     
00441     /*  Fix parenting in a separate pass to ensure ebone->bone connections
00442         are valid at this point */
00443     for (eBone=arm->edbo->first;eBone;eBone=eBone->next) {
00444         newBone= (Bone *)eBone->temp;
00445         if (eBone->parent) {
00446             newBone->parent= (Bone *)eBone->parent->temp;
00447             BLI_addtail(&newBone->parent->childbase, newBone);
00448             
00449             {
00450                 float M_parentRest[3][3];
00451                 float iM_parentRest[3][3];
00452                 float   delta[3];
00453                 
00454                 /* Get the parent's  matrix (rotation only) */
00455                 sub_v3_v3v3(delta, eBone->parent->tail, eBone->parent->head);
00456                 vec_roll_to_mat3(delta, eBone->parent->roll, M_parentRest);
00457                 
00458                 /* Invert the parent matrix */
00459                 invert_m3_m3(iM_parentRest, M_parentRest);
00460                 
00461                 /* Get the new head and tail */
00462                 sub_v3_v3v3(newBone->head, eBone->head, eBone->parent->tail);
00463                 sub_v3_v3v3(newBone->tail, eBone->tail, eBone->parent->tail);
00464                 
00465                 mul_m3_v3(iM_parentRest, newBone->head);
00466                 mul_m3_v3(iM_parentRest, newBone->tail);
00467             }
00468         }
00469         /*  ...otherwise add this bone to the armature's bonebase */
00470         else {
00471             copy_v3_v3(newBone->head, eBone->head);
00472             copy_v3_v3(newBone->tail, eBone->tail);
00473             BLI_addtail(&arm->bonebase, newBone);
00474         }
00475     }
00476     
00477     /* Make a pass through the new armature to fix rolling */
00478     /* also builds restposition again (like where_is_armature) */
00479     fix_bonelist_roll(&arm->bonebase, arm->edbo);
00480     
00481     /* so all users of this armature should get rebuilt */
00482     for (obt= G.main->object.first; obt; obt= obt->id.next) {
00483         if (obt->data==arm)
00484             armature_rebuild_pose(obt, arm);
00485     }
00486     
00487     DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
00488 }
00489 
00490 void ED_armature_apply_transform(Object *ob, float mat[4][4])
00491 {
00492     EditBone *ebone;
00493     bArmature *arm= ob->data;
00494     float scale = mat4_to_scale(mat);   /* store the scale of the matrix here to use on envelopes */
00495     float mat3[3][3];
00496 
00497     copy_m3_m4(mat3, mat);
00498     normalize_m3(mat3);
00499 
00500     /* Put the armature into editmode */
00501     ED_armature_to_edit(ob);
00502 
00503     /* Do the rotations */
00504     for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
00505         float   delta[3], tmat[3][3];
00506 
00507         /* find the current bone's roll matrix */
00508         sub_v3_v3v3(delta, ebone->tail, ebone->head);
00509         vec_roll_to_mat3(delta, ebone->roll, tmat);
00510 
00511         /* transform the roll matrix */
00512         mul_m3_m3m3(tmat, mat3, tmat);
00513 
00514         /* transform the bone */
00515         mul_m4_v3(mat, ebone->head);
00516         mul_m4_v3(mat, ebone->tail);
00517 
00518         /* apply the transfiormed roll back */
00519         mat3_to_vec_roll(tmat, NULL, &ebone->roll);
00520 
00521         ebone->rad_head *= scale;
00522         ebone->rad_tail *= scale;
00523         ebone->dist     *= scale;
00524 
00525         /* we could be smarter and scale by the matrix along the x & z axis */
00526         ebone->xwidth   *= scale;
00527         ebone->zwidth   *= scale;
00528     }
00529     
00530     /* Turn the list into an armature */
00531     ED_armature_from_edit(ob);
00532     ED_armature_edit_free(ob);
00533 }
00534 
00535 /* exported for use in editors/object/ */
00536 /* 0 == do center, 1 == center new, 2 == center cursor */
00537 void docenter_armature (Scene *scene, Object *ob, float cursor[3], int centermode, int around)
00538 {
00539     Object *obedit= scene->obedit; // XXX get from context
00540     EditBone *ebone;
00541     bArmature *arm= ob->data;
00542     float cent[3];
00543 
00544     /* Put the armature into editmode */
00545     if(ob != obedit) {
00546         ED_armature_to_edit(ob);
00547         obedit= NULL; /* we cant use this so behave as if there is no obedit */
00548     }
00549 
00550     /* Find the centerpoint */
00551     if (centermode == 2) {
00552         copy_v3_v3(cent, cursor);
00553         invert_m4_m4(ob->imat, ob->obmat);
00554         mul_m4_v3(ob->imat, cent);
00555     }
00556     else {
00557         if(around==V3D_CENTROID) {
00558             int total= 0;
00559             zero_v3(cent);
00560             for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
00561                 total+=2;
00562                 add_v3_v3(cent, ebone->head);
00563                 add_v3_v3(cent, ebone->tail);
00564             }
00565             mul_v3_fl(cent, 1.0f/(float)total);
00566         }
00567         else {
00568             float min[3], max[3];
00569             INIT_MINMAX(min, max);
00570             for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
00571                 DO_MINMAX(ebone->head, min, max);
00572                 DO_MINMAX(ebone->tail, min, max);
00573             }
00574             mid_v3_v3v3(cent, min, max);
00575         }
00576     }
00577     
00578     /* Do the adjustments */
00579     for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
00580         sub_v3_v3(ebone->head, cent);
00581         sub_v3_v3(ebone->tail, cent);
00582     }
00583     
00584     /* Turn the list into an armature */
00585     if(obedit==NULL) {
00586         ED_armature_from_edit(ob);
00587         ED_armature_edit_free(ob);
00588     }
00589 
00590     /* Adjust object location for new centerpoint */
00591     if(centermode && obedit==NULL) {
00592         mul_mat3_m4_v3(ob->obmat, cent); /* ommit translation part */
00593         add_v3_v3(ob->loc, cent);
00594     }
00595 }
00596 
00597 /* ---------------------- */
00598 
00599 /* checks if an EditBone with a matching name already, returning the matching bone if it exists */
00600 static EditBone *editbone_name_exists (ListBase *edbo, const char *name)
00601 {
00602     return BLI_findstring(edbo, name, offsetof(EditBone, name));
00603 }
00604 
00605 /* note: there's a unique_bone_name() too! */
00606 static int editbone_unique_check(void *arg, const char *name)
00607 {
00608     struct {ListBase *lb;void *bone;} *data= arg;
00609     EditBone *dupli= editbone_name_exists(data->lb, name);
00610     return dupli && dupli != data->bone;
00611 }
00612 
00613 void unique_editbone_name (ListBase *edbo, char *name, EditBone *bone)
00614 {
00615     struct {ListBase *lb; void *bone;} data;
00616     data.lb= edbo;
00617     data.bone= bone;
00618 
00619     BLI_uniquename_cb(editbone_unique_check, &data, "Bone", '.', name, sizeof(bone->name));
00620 }
00621 
00622 /* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
00623 static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
00624 {
00625     Object workob, *ob;
00626     
00627     /* go through all objects in database */
00628     for (ob= G.main->object.first; ob; ob= ob->id.next) {
00629         /* if parent is bone in this armature, apply corrections */
00630         if ((ob->parent == armob) && (ob->partype == PARBONE)) {
00631             /* apply current transform from parent (not yet destroyed), 
00632              * then calculate new parent inverse matrix
00633              */
00634             object_apply_mat4(ob, ob->obmat, FALSE, FALSE);
00635             
00636             what_does_parent(scene, ob, &workob);
00637             invert_m4_m4(ob->parentinv, workob.obmat);
00638         }
00639     }
00640 }
00641 
00642 /* set the current pose as the restpose */
00643 static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
00644 {
00645     Scene *scene= CTX_data_scene(C);
00646     Object *ob= object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
00647     bArmature *arm= get_armature(ob);
00648     bPose *pose;
00649     bPoseChannel *pchan;
00650     EditBone *curbone;
00651     
00652     /* don't check if editmode (should be done by caller) */
00653     if (ob->type!=OB_ARMATURE)
00654         return OPERATOR_CANCELLED;
00655     if (object_data_is_libdata(ob)) {
00656         BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); //error_libdata();
00657         return OPERATOR_CANCELLED;
00658     }
00659     
00660     /* helpful warnings... */
00661     // TODO: add warnings to be careful about actions, applying deforms first, etc.
00662     if (ob->adt && ob->adt->action) 
00663         BKE_report(op->reports, RPT_WARNING, "Actions on this armature will be destroyed by this new rest pose as the transforms stored are relative to the old rest pose");
00664     
00665     /* Get editbones of active armature to alter */
00666     ED_armature_to_edit(ob);    
00667     
00668     /* get pose of active object and move it out of posemode */
00669     pose= ob->pose;
00670     
00671     for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
00672         curbone= editbone_name_exists(arm->edbo, pchan->name);
00673         
00674         /* simply copy the head/tail values from pchan over to curbone */
00675         copy_v3_v3(curbone->head, pchan->pose_head);
00676         copy_v3_v3(curbone->tail, pchan->pose_tail);
00677         
00678         /* fix roll:
00679          *  1. find auto-calculated roll value for this bone now
00680          *  2. remove this from the 'visual' y-rotation
00681          */
00682         {
00683             float premat[3][3], imat[3][3],pmat[3][3], tmat[3][3];
00684             float delta[3], eul[3];
00685             
00686             /* obtain new auto y-rotation */
00687             sub_v3_v3v3(delta, curbone->tail, curbone->head);
00688             vec_roll_to_mat3(delta, 0.0f, premat);
00689             invert_m3_m3(imat, premat);
00690             
00691             /* get pchan 'visual' matrix */
00692             copy_m3_m4(pmat, pchan->pose_mat);
00693             
00694             /* remove auto from visual and get euler rotation */
00695             mul_m3_m3m3(tmat, imat, pmat);
00696             mat3_to_eul( eul,tmat);
00697             
00698             /* just use this euler-y as new roll value */
00699             curbone->roll= eul[1];
00700         }
00701         
00702         /* clear transform values for pchan */
00703         zero_v3(pchan->loc);
00704         zero_v3(pchan->eul);
00705         unit_qt(pchan->quat);
00706         unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
00707         pchan->size[0]= pchan->size[1]= pchan->size[2]= 1.0f;
00708         
00709         /* set anim lock */
00710         curbone->flag |= BONE_UNKEYED;
00711     }
00712     
00713     /* convert editbones back to bones, and then free the edit-data */
00714     ED_armature_from_edit(ob);
00715     ED_armature_edit_free(ob);
00716     
00717     /* flush positions of posebones */
00718     where_is_pose(scene, ob);
00719     
00720     /* fix parenting of objects which are bone-parented */
00721     applyarmature_fix_boneparents(scene, ob);
00722     
00723     /* note, notifier might evolve */
00724     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
00725     
00726     return OPERATOR_FINISHED;
00727 }
00728 
00729 void POSE_OT_armature_apply (wmOperatorType *ot)
00730 {
00731     /* identifiers */
00732     ot->name= "Apply Pose as Rest Pose";
00733     ot->idname= "POSE_OT_armature_apply";
00734     ot->description= "Apply the current pose as the new rest pose";
00735     
00736     /* callbacks */
00737     ot->exec= apply_armature_pose2bones_exec;
00738     ot->poll= ED_operator_posemode;
00739     
00740     /* flags */
00741     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00742 }
00743 
00744 
00745 /* set the current pose as the restpose */
00746 static int pose_visual_transform_apply_exec (bContext *C, wmOperator *UNUSED(op))
00747 {
00748     Object *ob= object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
00749 
00750     /* don't check if editmode (should be done by caller) */
00751     if (ob->type!=OB_ARMATURE)
00752         return OPERATOR_CANCELLED;
00753 
00754     /* loop over all selected pchans
00755      *
00756      * TODO, loop over children before parents if multiple bones
00757      * at once are to be predictable*/
00758     CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
00759     {
00760         float delta_mat[4][4];
00761         
00762         /* chan_mat already contains the delta transform from rest pose to pose-mode pose
00763          * as that is baked into there so that B-Bones will work. Once we've set this as the
00764          * new raw-transform components, don't recalc the poses yet, otherwise IK result will 
00765          * change, thus changing the result we may be trying to record.
00766          */
00767         copy_m4_m4(delta_mat, pchan->chan_mat);
00768         pchan_apply_mat4(pchan, delta_mat, TRUE);
00769     }
00770     CTX_DATA_END;
00771     
00772     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00773 
00774     /* note, notifier might evolve */
00775     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
00776 
00777     return OPERATOR_FINISHED;
00778 }
00779 
00780 void POSE_OT_visual_transform_apply (wmOperatorType *ot)
00781 {
00782     /* identifiers */
00783     ot->name= "Apply Visual Transform to Pose";
00784     ot->idname= "POSE_OT_visual_transform_apply";
00785     ot->description= "Apply final constrained position of pose bones to their transform";
00786     
00787     /* callbacks */
00788     ot->exec= pose_visual_transform_apply_exec;
00789     ot->poll= ED_operator_posemode;
00790     
00791     /* flags */
00792     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00793 }
00794 
00795 /* ---------------------- */
00796 
00797 /* Helper function for armature joining - link fixing */
00798 static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
00799 {
00800     Object *ob;
00801     bPose *pose;
00802     bPoseChannel *pchant;
00803     bConstraint *con;
00804     
00805     /* let's go through all objects in database */
00806     for (ob= G.main->object.first; ob; ob= ob->id.next) {
00807         /* do some object-type specific things */
00808         if (ob->type == OB_ARMATURE) {
00809             pose= ob->pose;
00810             for (pchant= pose->chanbase.first; pchant; pchant= pchant->next) {
00811                 for (con= pchant->constraints.first; con; con= con->next) {
00812                     bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00813                     ListBase targets = {NULL, NULL};
00814                     bConstraintTarget *ct;
00815                     
00816                     /* constraint targets */
00817                     if (cti && cti->get_constraint_targets) {
00818                         cti->get_constraint_targets(con, &targets);
00819                         
00820                         for (ct= targets.first; ct; ct= ct->next) {
00821                             if (ct->tar == srcArm) {
00822                                 if (ct->subtarget[0] == '\0') {
00823                                     ct->tar = tarArm;
00824                                 }
00825                                 else if (strcmp(ct->subtarget, pchan->name)==0) {
00826                                     ct->tar = tarArm;
00827                                     BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
00828                                 }
00829                             }
00830                         }
00831                         
00832                         if (cti->flush_constraint_targets)
00833                             cti->flush_constraint_targets(con, &targets, 0);
00834                     }
00835                     
00836                     /* action constraint? */
00837                     if (con->type == CONSTRAINT_TYPE_ACTION) {
00838                         bActionConstraint *data= con->data; // XXX old animation system
00839                         bAction *act;
00840                         bActionChannel *achan;
00841                         
00842                         if (data->act) {
00843                             act= data->act;
00844                             
00845                             for (achan= act->chanbase.first; achan; achan= achan->next) {
00846                                 if (strcmp(achan->name, pchan->name)==0)
00847                                     BLI_strncpy(achan->name, curbone->name, sizeof(achan->name));
00848                             }
00849                         }
00850                     }
00851                     
00852                 }
00853             }
00854         }
00855             
00856         /* fix object-level constraints */
00857         if (ob != srcArm) {
00858             for (con= ob->constraints.first; con; con= con->next) {
00859                 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00860                 ListBase targets = {NULL, NULL};
00861                 bConstraintTarget *ct;
00862                 
00863                 /* constraint targets */
00864                 if (cti && cti->get_constraint_targets) {
00865                     cti->get_constraint_targets(con, &targets);
00866                     
00867                     for (ct= targets.first; ct; ct= ct->next) {
00868                         if (ct->tar == srcArm) {
00869                             if (ct->subtarget[0] == '\0') {
00870                                 ct->tar = tarArm;
00871                             }
00872                             else if (strcmp(ct->subtarget, pchan->name)==0) {
00873                                 ct->tar = tarArm;
00874                                 BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
00875                             }
00876                         }
00877                     }
00878                     
00879                     if (cti->flush_constraint_targets)
00880                         cti->flush_constraint_targets(con, &targets, 0);
00881                 }
00882             }
00883         }
00884         
00885         /* See if an object is parented to this armature */
00886         if (ob->parent && (ob->parent == srcArm)) {
00887             /* Is object parented to a bone of this src armature? */
00888             if (ob->partype==PARBONE) {
00889                 /* bone name in object */
00890                 if (!strcmp(ob->parsubstr, pchan->name))
00891                     BLI_strncpy(ob->parsubstr, curbone->name, sizeof(ob->parsubstr));
00892             }
00893             
00894             /* make tar armature be new parent */
00895             ob->parent = tarArm;
00896         }
00897     }   
00898 }
00899 
00900 /* join armature exec is exported for use in object->join objects operator... */
00901 int join_armature_exec(bContext *C, wmOperator *UNUSED(op))
00902 {
00903     Main *bmain= CTX_data_main(C);
00904     Scene *scene= CTX_data_scene(C);
00905     Object  *ob= CTX_data_active_object(C);
00906     bArmature *arm= (ob)? ob->data: NULL;
00907     bPose *pose, *opose;
00908     bPoseChannel *pchan, *pchann;
00909     EditBone *curbone;
00910     float   mat[4][4], oimat[4][4];
00911     
00912     /*  Ensure we're not in editmode and that the active object is an armature*/
00913     if (!ob || ob->type!=OB_ARMATURE)
00914         return OPERATOR_CANCELLED;
00915     if (!arm || arm->edbo)
00916         return OPERATOR_CANCELLED;
00917     
00918     /* Get editbones of active armature to add editbones to */
00919     ED_armature_to_edit(ob);
00920     
00921     /* get pose of active object and move it out of posemode */
00922     pose= ob->pose;
00923     ob->mode &= ~OB_MODE_POSE;
00924 
00925     CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
00926         if ((base->object->type==OB_ARMATURE) && (base->object!=ob)) {
00927             bArmature *curarm= base->object->data;
00928             
00929             /* Make a list of editbones in current armature */
00930             ED_armature_to_edit(base->object);
00931             
00932             /* Get Pose of current armature */
00933             opose= base->object->pose;
00934             base->object->mode &= ~OB_MODE_POSE;
00935             //BASACT->flag &= ~OB_MODE_POSE;
00936             
00937             /* Find the difference matrix */
00938             invert_m4_m4(oimat, ob->obmat);
00939             mult_m4_m4m4(mat, oimat, base->object->obmat);
00940             
00941             /* Copy bones and posechannels from the object to the edit armature */
00942             for (pchan=opose->chanbase.first; pchan; pchan=pchann) {
00943                 pchann= pchan->next;
00944                 curbone= editbone_name_exists(curarm->edbo, pchan->name);
00945                 
00946                 /* Get new name */
00947                 unique_editbone_name(arm->edbo, curbone->name, NULL);
00948                 
00949                 /* Transform the bone */
00950                 {
00951                     float premat[4][4];
00952                     float postmat[4][4];
00953                     float difmat[4][4];
00954                     float imat[4][4];
00955                     float temp[3][3];
00956                     float delta[3];
00957                     
00958                     /* Get the premat */
00959                     sub_v3_v3v3(delta, curbone->tail, curbone->head);
00960                     vec_roll_to_mat3(delta, curbone->roll, temp);
00961                     
00962                     unit_m4(premat); /* Mat4MulMat34 only sets 3x3 part */
00963                     mul_m4_m3m4(premat, temp, mat);
00964                     
00965                     mul_m4_v3(mat, curbone->head);
00966                     mul_m4_v3(mat, curbone->tail);
00967                     
00968                     /* Get the postmat */
00969                     sub_v3_v3v3(delta, curbone->tail, curbone->head);
00970                     vec_roll_to_mat3(delta, curbone->roll, temp);
00971                     copy_m4_m3(postmat, temp);
00972                     
00973                     /* Find the roll */
00974                     invert_m4_m4(imat, premat);
00975                     mult_m4_m4m4(difmat, imat, postmat);
00976                     
00977                     curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
00978                 }
00979                 
00980                 /* Fix Constraints and Other Links to this Bone and Armature */
00981                 joined_armature_fix_links(ob, base->object, pchan, curbone);
00982                 
00983                 /* Rename pchan */
00984                 BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
00985                 
00986                 /* Jump Ship! */
00987                 BLI_remlink(curarm->edbo, curbone);
00988                 BLI_addtail(arm->edbo, curbone);
00989                 
00990                 BLI_remlink(&opose->chanbase, pchan);
00991                 BLI_addtail(&pose->chanbase, pchan);
00992                 free_pose_channels_hash(opose);
00993                 free_pose_channels_hash(pose);
00994             }
00995             
00996             ED_base_object_free_and_unlink(bmain, scene, base);
00997         }
00998     }
00999     CTX_DATA_END;
01000     
01001     DAG_scene_sort(bmain, scene);   // because we removed object(s)
01002 
01003     ED_armature_from_edit(ob);
01004     ED_armature_edit_free(ob);
01005 
01006     WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
01007     
01008     return OPERATOR_FINISHED;
01009 }
01010 
01011 /* ---------------------- */
01012 
01013 /* Helper function for armature separating - link fixing */
01014 static void separated_armature_fix_links(Object *origArm, Object *newArm)
01015 {
01016     Object *ob;
01017     bPoseChannel *pchan;
01018     bConstraint *con;
01019     ListBase *opchans, *npchans;
01020     
01021     /* get reference to list of bones in original and new armatures  */
01022     opchans= &origArm->pose->chanbase;
01023     npchans= &newArm->pose->chanbase;
01024     
01025     /* let's go through all objects in database */
01026     for (ob= G.main->object.first; ob; ob= ob->id.next) {
01027         /* do some object-type specific things */
01028         if (ob->type == OB_ARMATURE) {
01029             for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01030                 for (con= pchan->constraints.first; con; con= con->next) {
01031                     bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
01032                     ListBase targets = {NULL, NULL};
01033                     bConstraintTarget *ct;
01034                     
01035                     /* constraint targets */
01036                     if (cti && cti->get_constraint_targets) {
01037                         cti->get_constraint_targets(con, &targets);
01038                         
01039                         for (ct= targets.first; ct; ct= ct->next) {
01040                             /* any targets which point to original armature are redirected to the new one only if:
01041                              *  - the target isn't origArm/newArm itself
01042                              *  - the target is one that can be found in newArm/origArm
01043                              */
01044                             if (ct->subtarget[0] != 0) {
01045                                 if (ct->tar == origArm) {
01046                                     if(BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
01047                                         ct->tar= newArm;
01048                                     }
01049                                 }
01050                                 else if (ct->tar == newArm) {
01051                                     if(BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
01052                                         ct->tar= origArm;
01053                                     }
01054                                 }
01055                             }
01056                         }
01057 
01058                         if (cti->flush_constraint_targets) {
01059                             cti->flush_constraint_targets(con, &targets, 0);
01060                         }
01061                     }
01062                 }
01063             }
01064         }
01065             
01066         /* fix object-level constraints */
01067         if (ob != origArm) {
01068             for (con= ob->constraints.first; con; con= con->next) {
01069                 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
01070                 ListBase targets = {NULL, NULL};
01071                 bConstraintTarget *ct;
01072                 
01073                 /* constraint targets */
01074                 if (cti && cti->get_constraint_targets) {
01075                     cti->get_constraint_targets(con, &targets);
01076                     
01077                     for (ct= targets.first; ct; ct= ct->next) {
01078                         /* any targets which point to original armature are redirected to the new one only if:
01079                          *  - the target isn't origArm/newArm itself
01080                          *  - the target is one that can be found in newArm/origArm
01081                          */
01082                         if(ct->subtarget[0] != '\0')  {
01083                             if (ct->tar == origArm) {
01084                                 if(BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
01085                                     ct->tar= newArm;
01086                                 }
01087                             }
01088                             else if (ct->tar == newArm) {
01089                                 if(BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
01090                                     ct->tar= origArm;
01091                                 }
01092                             }
01093                         }
01094                     }
01095 
01096                     if (cti->flush_constraint_targets) {
01097                         cti->flush_constraint_targets(con, &targets, 0);
01098                     }
01099                 }
01100             }
01101         }
01102         
01103         /* See if an object is parented to this armature */
01104         if (ob->parent && (ob->parent == origArm)) {
01105             /* Is object parented to a bone of this src armature? */
01106             if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) {
01107                 if(BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) {
01108                     ob->parent= newArm;
01109                 }
01110             }
01111         }
01112     }   
01113 }
01114 
01115 /* Helper function for armature separating - remove certain bones from the given armature 
01116  *  sel: remove selected bones from the armature, otherwise the unselected bones are removed
01117  *  (ob is not in editmode)
01118  */
01119 static void separate_armature_bones(Object *ob, short sel) 
01120 {
01121     bArmature *arm= (bArmature *)ob->data;
01122     bPoseChannel *pchan, *pchann;
01123     EditBone *curbone;
01124     
01125     /* make local set of editbones to manipulate here */
01126     ED_armature_to_edit(ob);
01127     
01128     /* go through pose-channels, checking if a bone should be removed */
01129     for (pchan=ob->pose->chanbase.first; pchan; pchan=pchann) {
01130         pchann= pchan->next;
01131         curbone= editbone_name_exists(arm->edbo, pchan->name);
01132         
01133         /* check if bone needs to be removed */
01134         if ( (sel && (curbone->flag & BONE_SELECTED)) ||
01135              (!sel && !(curbone->flag & BONE_SELECTED)) )
01136         {
01137             EditBone *ebo;
01138             bPoseChannel *pchn;
01139             
01140             /* clear the bone->parent var of any bone that had this as its parent  */
01141             for (ebo= arm->edbo->first; ebo; ebo= ebo->next) {
01142                 if (ebo->parent == curbone) {
01143                     ebo->parent= NULL;
01144                     ebo->temp= NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */
01145                     ebo->flag &= ~BONE_CONNECTED;
01146                 }
01147             }
01148             
01149             /* clear the pchan->parent var of any pchan that had this as its parent */
01150             for (pchn= ob->pose->chanbase.first; pchn; pchn=pchn->next) {
01151                 if (pchn->parent == pchan)
01152                     pchn->parent= NULL;
01153             }
01154             
01155             /* free any of the extra-data this pchan might have */
01156             free_pose_channel(pchan);
01157             free_pose_channels_hash(ob->pose);
01158             
01159             /* get rid of unneeded bone */
01160             bone_free(arm, curbone);
01161             BLI_freelinkN(&ob->pose->chanbase, pchan);
01162         }
01163     }
01164     
01165     /* exit editmode (recalculates pchans too) */
01166     ED_armature_from_edit(ob);
01167     ED_armature_edit_free(ob);
01168 }
01169 
01170 /* separate selected bones into their armature */
01171 static int separate_armature_exec (bContext *C, wmOperator *UNUSED(op))
01172 {
01173     Main *bmain= CTX_data_main(C);
01174     Scene *scene= CTX_data_scene(C);
01175     Object *obedit= CTX_data_edit_object(C);
01176     Object *oldob, *newob;
01177     Base *oldbase, *newbase;
01178     
01179     /* sanity checks */
01180     if (obedit == NULL)
01181         return OPERATOR_CANCELLED;
01182     
01183     /* set wait cursor in case this takes a while */
01184     WM_cursor_wait(1);
01185     
01186     /* we are going to do this as follows (unlike every other instance of separate):
01187      *  1. exit editmode +posemode for active armature/base. Take note of what this is.
01188      *  2. duplicate base - BASACT is the new one now
01189      *  3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
01190      *  4. fix constraint links
01191      *  5. make original armature active and enter editmode
01192      */
01193     
01194     /* 1) only edit-base selected */
01195     // TODO: use context iterators for this?
01196     CTX_DATA_BEGIN(C, Base *, base, visible_bases) {
01197         if (base->object==obedit) base->flag |= 1;
01198         else base->flag &= ~1;
01199     }
01200     CTX_DATA_END;
01201     
01202     /* 1) store starting settings and exit editmode */
01203     oldob= obedit;
01204     oldbase= BASACT;
01205     oldob->mode &= ~OB_MODE_POSE;
01206     //oldbase->flag &= ~OB_POSEMODE;
01207     
01208     ED_armature_from_edit(obedit);
01209     ED_armature_edit_free(obedit);
01210     
01211     /* 2) duplicate base */
01212     newbase= ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
01213     newob= newbase->object;     
01214     newbase->flag &= ~SELECT;
01215     
01216     
01217     /* 3) remove bones that shouldn't still be around on both armatures */
01218     separate_armature_bones(oldob, 1);
01219     separate_armature_bones(newob, 0);
01220     
01221     
01222     /* 4) fix links before depsgraph flushes */ // err... or after?
01223     separated_armature_fix_links(oldob, newob);
01224     
01225     DAG_id_tag_update(&oldob->id, OB_RECALC_DATA);  /* this is the original one */
01226     DAG_id_tag_update(&newob->id, OB_RECALC_DATA);  /* this is the separated one */
01227     
01228     
01229     /* 5) restore original conditions */
01230     obedit= oldob;
01231     
01232     ED_armature_to_edit(obedit);
01233     
01234     /* note, notifier might evolve */
01235     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, obedit);
01236     
01237     /* recalc/redraw + cleanup */
01238     WM_cursor_wait(0);
01239     
01240     return OPERATOR_FINISHED;
01241 }
01242 
01243 void ARMATURE_OT_separate (wmOperatorType *ot)
01244 {
01245     /* identifiers */
01246     ot->name= "Separate Bones";
01247     ot->idname= "ARMATURE_OT_separate";
01248     ot->description= "Isolate selected bones into a separate armature";
01249     
01250     /* callbacks */
01251     ot->invoke= WM_operator_confirm;
01252     ot->exec= separate_armature_exec;
01253     ot->poll= ED_operator_editarmature;
01254     
01255     /* flags */
01256     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01257 }
01258 
01259 /* **************** END tools on Editmode Armature **************** */
01260 /* **************** PoseMode & EditMode *************************** */
01261 
01262 /* only for opengl selection indices */
01263 Bone *get_indexed_bone (Object *ob, int index)
01264 {
01265     bPoseChannel *pchan;
01266     if(ob->pose==NULL) return NULL;
01267     index>>=16;     // bone selection codes use left 2 bytes
01268     
01269     pchan= BLI_findlink(&ob->pose->chanbase, index);
01270     return pchan ? pchan->bone : NULL;
01271 }
01272 
01273 /* See if there are any selected bones in this buffer */
01274 /* only bones from base are checked on */
01275 static void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel)
01276 {
01277     Object *obedit= scene->obedit; // XXX get from context
01278     Bone *bone;
01279     EditBone *ebone;
01280     void *firstunSel=NULL, *firstSel=NULL, *data;
01281     unsigned int hitresult;
01282     short i, takeNext=0, sel;
01283     
01284     for (i=0; i< hits; i++){
01285         hitresult = buffer[3+(i*4)];
01286         
01287         if (!(hitresult & BONESEL_NOSEL)) { // -1
01288             if(hitresult & BONESEL_ANY) {   // to avoid including objects in selection
01289                 
01290                 hitresult &= ~(BONESEL_ANY);
01291                 /* Determine what the current bone is */
01292                 if (obedit==NULL || base->object!=obedit) {
01293                     /* no singular posemode, so check for correct object */
01294                     if(base->selcol == (hitresult & 0xFFFF)) {
01295                         bone = get_indexed_bone(base->object, hitresult);
01296                         
01297                         if (findunsel)
01298                             sel = (bone->flag & BONE_SELECTED);
01299                         else
01300                             sel = !(bone->flag & BONE_SELECTED);
01301                         
01302                         data = bone;
01303                     }
01304                     else {
01305                         data= NULL;
01306                         sel= 0;
01307                     }
01308                 }
01309                 else{
01310                     bArmature *arm= obedit->data;
01311                     
01312                     ebone = BLI_findlink(arm->edbo, hitresult);
01313                     if (findunsel)
01314                         sel = (ebone->flag & BONE_SELECTED);
01315                     else
01316                         sel = !(ebone->flag & BONE_SELECTED);
01317                     
01318                     data = ebone;
01319                 }
01320                 
01321                 if(data) {
01322                     if (sel) {
01323                         if(!firstSel) firstSel= data;
01324                         takeNext=1;
01325                     }
01326                     else {
01327                         if (!firstunSel)
01328                             firstunSel=data;
01329                         if (takeNext)
01330                             return data;
01331                     }
01332                 }
01333             }
01334         }
01335     }
01336     
01337     if (firstunSel)
01338         return firstunSel;
01339     else 
01340         return firstSel;
01341 }
01342 
01343 
01344 
01345 /* used by posemode as well editmode */
01346 /* only checks scene->basact! */
01347 /* x and y are mouse coords (area space) */
01348 static void *get_nearest_bone (bContext *C, short findunsel, int x, int y)
01349 {
01350     ViewContext vc;
01351     rcti rect;
01352     unsigned int buffer[MAXPICKBUF];
01353     short hits;
01354     
01355     view3d_set_viewcontext(C, &vc);
01356     
01357     // rect.xmin= ... mouseco!
01358     rect.xmin= rect.xmax= x;
01359     rect.ymin= rect.ymax= y;
01360     
01361     glInitNames();
01362     hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
01363 
01364     if (hits>0)
01365         return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel);
01366     
01367     return NULL;
01368 }
01369 
01370 /* Get the first available child of an editbone */
01371 static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility)
01372 {
01373     EditBone *curbone, *chbone=NULL;
01374     
01375     for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
01376         if (curbone->parent == pabone) {
01377             if (use_visibility) {
01378                 if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) {
01379                     chbone = curbone;
01380                 }
01381             }
01382             else
01383                 chbone = curbone;
01384         }
01385     }
01386     
01387     return chbone;
01388 }
01389 
01390 /* **************** END PoseMode & EditMode *************************** */
01391 /* **************** Posemode stuff ********************** */
01392 
01393 
01394 static void selectconnected_posebonechildren (Object *ob, Bone *bone, int extend)
01395 {
01396     Bone *curBone;
01397     
01398     /* stop when unconnected child is encontered, or when unselectable bone is encountered */
01399     if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
01400         return;
01401     
01402         // XXX old cruft! use notifiers instead
01403     //select_actionchannel_by_name (ob->action, bone->name, !(shift));
01404     
01405     if (extend)
01406         bone->flag &= ~BONE_SELECTED;
01407     else
01408         bone->flag |= BONE_SELECTED;
01409     
01410     for (curBone=bone->childbase.first; curBone; curBone=curBone->next)
01411         selectconnected_posebonechildren(ob, curBone, extend);
01412 }
01413 
01414 /* within active object context */
01415 /* previously known as "selectconnected_posearmature" */
01416 static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event)
01417 {
01418     Object *ob= CTX_data_edit_object(C);
01419     Bone *bone, *curBone, *next= NULL;
01420     int extend= RNA_boolean_get(op->ptr, "extend");
01421 
01422     view3d_operator_needs_opengl(C);
01423     
01424     if (extend)
01425         bone= get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
01426     else
01427         bone= get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
01428     
01429     if (!bone)
01430         return OPERATOR_CANCELLED;
01431     
01432     /* Select parents */
01433     for (curBone=bone; curBone; curBone=next){
01434         /* ignore bone if cannot be selected */
01435         if ((curBone->flag & BONE_UNSELECTABLE) == 0) { 
01436                 // XXX old cruft! use notifiers instead
01437             //select_actionchannel_by_name (ob->action, curBone->name, !(shift));
01438             
01439             if (extend)
01440                 curBone->flag &= ~BONE_SELECTED;
01441             else
01442                 curBone->flag |= BONE_SELECTED;
01443             
01444             if (curBone->flag & BONE_CONNECTED)
01445                 next=curBone->parent;
01446             else
01447                 next=NULL;
01448         }
01449         else
01450             next= NULL;
01451     }
01452     
01453     /* Select children */
01454     for (curBone=bone->childbase.first; curBone; curBone=next)
01455         selectconnected_posebonechildren(ob, curBone, extend);
01456     
01457     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
01458 
01459     return OPERATOR_FINISHED;
01460 }
01461 
01462 static int pose_select_linked_poll(bContext *C)
01463 {
01464     return ( ED_operator_view3d_active(C) && ED_operator_posemode(C) );
01465 }
01466 
01467 void POSE_OT_select_linked(wmOperatorType *ot)
01468 {
01469     /* identifiers */
01470     ot->name= "Select Connected";
01471     ot->idname= "POSE_OT_select_linked";
01472     ot->description= "Select bones related to selected ones by parent/child relationships";
01473     
01474     /* api callbacks */
01475     ot->exec= NULL;
01476     ot->invoke= pose_select_connected_invoke;
01477     ot->poll= pose_select_linked_poll;
01478     
01479     /* flags */
01480     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01481     
01482     /* props */ 
01483     RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
01484 }
01485 
01486 /* **************** END Posemode stuff ********************** */
01487 /* **************** EditMode stuff ********************** */
01488 
01489 /* called in space.c */
01490 /* previously "selectconnected_armature" */
01491 static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event)
01492 {
01493     bArmature *arm;
01494     EditBone *bone, *curBone, *next;
01495     int extend= RNA_boolean_get(op->ptr, "extend");
01496     Object *obedit= CTX_data_edit_object(C);
01497     arm= obedit->data;
01498 
01499     view3d_operator_needs_opengl(C);
01500 
01501     if (extend)
01502         bone= get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
01503     else
01504         bone= get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
01505 
01506     if (!bone)
01507         return OPERATOR_CANCELLED;
01508 
01509     /* Select parents */
01510     for (curBone=bone; curBone; curBone=next) {
01511         if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
01512             if (extend) {
01513                 curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
01514             }
01515             else{
01516                 curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
01517             }
01518         }
01519         
01520         if (curBone->flag & BONE_CONNECTED)
01521             next=curBone->parent;
01522         else
01523             next=NULL;
01524     }
01525 
01526     /* Select children */
01527     while (bone) {
01528         for (curBone=arm->edbo->first; curBone; curBone=next) {
01529             next = curBone->next;
01530             if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE)==0) {
01531                 if (curBone->flag & BONE_CONNECTED) {
01532                     if (extend)
01533                         curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
01534                     else
01535                         curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
01536                     bone=curBone;
01537                     break;
01538                 }
01539                 else { 
01540                     bone=NULL;
01541                     break;
01542                 }
01543             }
01544         }
01545         if (!curBone)
01546             bone=NULL;
01547     }
01548     
01549     ED_armature_sync_selection(arm->edbo);
01550     
01551     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
01552     
01553     return OPERATOR_FINISHED;
01554 }
01555 
01556 static int armature_select_linked_poll(bContext *C)
01557 {
01558     return ( ED_operator_view3d_active(C) && ED_operator_editarmature(C) );
01559 }
01560 
01561 void ARMATURE_OT_select_linked(wmOperatorType *ot)
01562 {
01563     /* identifiers */
01564     ot->name= "Select Connected";
01565     ot->idname= "ARMATURE_OT_select_linked";
01566     ot->description= "Select bones related to selected ones by parent/child relationships";
01567     
01568     /* api callbacks */
01569     ot->exec= NULL;
01570     ot->invoke= armature_select_linked_invoke;
01571     ot->poll= armature_select_linked_poll;
01572     
01573     /* flags */
01574     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01575     
01576     /* properties s*/
01577     RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
01578 }
01579 
01580 /* does bones and points */
01581 /* note that BONE ROOT only gets drawn for root bones (or without IK) */
01582 static EditBone *get_nearest_editbonepoint (ViewContext *vc, const int mval[2], ListBase *edbo, int findunsel, int *selmask)
01583 {
01584     EditBone *ebone;
01585     rcti rect;
01586     unsigned int buffer[MAXPICKBUF];
01587     unsigned int hitresult, besthitresult=BONESEL_NOSEL;
01588     int i, mindep= 4;
01589     short hits;
01590 
01591     glInitNames();
01592     
01593     rect.xmin= mval[0]-5;
01594     rect.xmax= mval[0]+5;
01595     rect.ymin= mval[1]-5;
01596     rect.ymax= mval[1]+5;
01597     
01598     hits= view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
01599     if(hits==0) {
01600         rect.xmin= mval[0]-12;
01601         rect.xmax= mval[0]+12;
01602         rect.ymin= mval[1]-12;
01603         rect.ymax= mval[1]+12;
01604         hits= view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
01605     }
01606     /* See if there are any selected bones in this group */
01607     if (hits>0) {
01608         
01609         if(hits==1) {
01610             if (!(buffer[3] & BONESEL_NOSEL)) 
01611                 besthitresult= buffer[3];
01612         }
01613         else {
01614             for (i=0; i< hits; i++) {
01615                 hitresult= buffer[3+(i*4)];
01616                 if (!(hitresult & BONESEL_NOSEL)) {
01617                     int dep;
01618                     
01619                     ebone = BLI_findlink(edbo, hitresult & ~BONESEL_ANY);
01620                     
01621                     /* clicks on bone points get advantage */
01622                     if( hitresult & (BONESEL_ROOT|BONESEL_TIP)) {
01623                         /* but also the unselected one */
01624                         if(findunsel) {
01625                             if( (hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL)==0) 
01626                                 dep= 1;
01627                             else if( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL)==0) 
01628                                 dep= 1;
01629                             else 
01630                                 dep= 2;
01631                         }
01632                         else dep= 2;
01633                     }
01634                     else {
01635                         /* bone found */
01636                         if(findunsel) {
01637                             if((ebone->flag & BONE_SELECTED)==0)
01638                                 dep= 2;
01639                             else
01640                                 dep= 3;
01641                         }
01642                         else dep= 3;
01643                     }
01644                     if(dep < mindep) {
01645                         mindep= dep;
01646                         besthitresult= hitresult;
01647                     }
01648                 }
01649             }
01650         }
01651         
01652         if (!(besthitresult & BONESEL_NOSEL)) {
01653             
01654             ebone= BLI_findlink(edbo, besthitresult & ~BONESEL_ANY);
01655             
01656             *selmask = 0;
01657             if (besthitresult & BONESEL_ROOT)
01658                 *selmask |= BONE_ROOTSEL;
01659             if (besthitresult & BONESEL_TIP)
01660                 *selmask |= BONE_TIPSEL;
01661             if (besthitresult & BONESEL_BONE)
01662                 *selmask |= BONE_SELECTED;
01663             return ebone;
01664         }
01665     }
01666     *selmask = 0;
01667     return NULL;
01668 }
01669 
01670 /* previously delete_armature */
01671 /* only editmode! */
01672 static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
01673 {
01674     bArmature *arm;
01675     EditBone    *curBone, *ebone_next;
01676     bConstraint *con;
01677     Object *obedit= CTX_data_edit_object(C); // XXX get from context
01678     arm = obedit->data;
01679 
01680     /* cancel if nothing selected */
01681     if (CTX_DATA_COUNT(C, selected_bones) == 0)
01682         return OPERATOR_CANCELLED;
01683     
01684     armature_select_mirrored(arm);
01685     
01686     /*  First erase any associated pose channel */
01687     if (obedit->pose) {
01688         bPoseChannel *pchan, *pchan_next;
01689         for (pchan=obedit->pose->chanbase.first; pchan; pchan= pchan_next) {
01690             pchan_next= pchan->next;
01691             curBone = editbone_name_exists(arm->edbo, pchan->name);
01692             
01693             if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
01694                 free_pose_channel(pchan);
01695                 free_pose_channels_hash(obedit->pose);
01696                 BLI_freelinkN (&obedit->pose->chanbase, pchan);
01697             }
01698             else {
01699                 for (con= pchan->constraints.first; con; con= con->next) {
01700                     bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
01701                     ListBase targets = {NULL, NULL};
01702                     bConstraintTarget *ct;
01703                     
01704                     if (cti && cti->get_constraint_targets) {
01705                         cti->get_constraint_targets(con, &targets);
01706                         
01707                         for (ct= targets.first; ct; ct= ct->next) {
01708                             if (ct->tar == obedit) {
01709                                 if (ct->subtarget[0]) {
01710                                     curBone = editbone_name_exists(arm->edbo, ct->subtarget);
01711                                     if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
01712                                         con->flag |= CONSTRAINT_DISABLE;
01713                                         ct->subtarget[0]= 0;
01714                                     }
01715                                 }
01716                             }
01717                         }
01718                         
01719                         if (cti->flush_constraint_targets)
01720                             cti->flush_constraint_targets(con, &targets, 0);
01721                     }
01722                 }
01723             }
01724         }
01725     }
01726     
01727     
01728     for (curBone=arm->edbo->first; curBone; curBone= ebone_next) {
01729         ebone_next= curBone->next;
01730         if (arm->layer & curBone->layer) {
01731             if (curBone->flag & BONE_SELECTED) {
01732                 if(curBone==arm->act_edbone) arm->act_edbone= NULL;
01733                 ED_armature_edit_bone_remove(arm, curBone);
01734             }
01735         }
01736     }
01737     
01738     
01739     ED_armature_sync_selection(arm->edbo);
01740 
01741     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
01742 
01743     return OPERATOR_FINISHED;
01744 }
01745 
01746 void ARMATURE_OT_delete(wmOperatorType *ot)
01747 {
01748     /* identifiers */
01749     ot->name= "Delete Selected Bone(s)";
01750     ot->idname= "ARMATURE_OT_delete";
01751     ot->description= "Remove selected bones from the armature";
01752     
01753     /* api callbacks */
01754     ot->invoke = WM_operator_confirm;
01755     ot->exec = armature_delete_selected_exec;
01756     ot->poll = ED_operator_editarmature;
01757     
01758     /* flags */
01759     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01760 }
01761 
01762 /* toggle==0: deselect
01763  * toggle==1: swap (based on test)
01764  * toggle==2: swap (no test), CURRENTLY UNUSED
01765  */
01766 void ED_armature_deselect_all(Object *obedit, int toggle)
01767 {
01768     bArmature *arm= obedit->data;
01769     EditBone    *eBone;
01770     int         sel=1;
01771     
01772     if(toggle==1) {
01773         /*  Determine if there are any selected bones
01774         And therefore whether we are selecting or deselecting */
01775         for (eBone=arm->edbo->first;eBone;eBone=eBone->next){
01776             //          if(arm->layer & eBone->layer) {
01777             if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)){
01778                 sel=0;
01779                 break;
01780             }
01781             //          }
01782         }
01783     }
01784     else sel= toggle;
01785     
01786     /*  Set the flags */
01787     for (eBone=arm->edbo->first;eBone;eBone=eBone->next) {
01788         if (sel==2) {
01789             /* invert selection of bone */
01790             if(EBONE_VISIBLE(arm, eBone)) {
01791                 eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
01792                 if(arm->act_edbone==eBone)
01793                     arm->act_edbone= NULL;
01794             }
01795         }
01796         else if (sel==1) {
01797             /* select bone */
01798             if(EBONE_VISIBLE(arm, eBone)) {
01799                 eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
01800                 if(eBone->parent)
01801                     eBone->parent->flag |= (BONE_TIPSEL);
01802             }
01803         }
01804         else {
01805             /* deselect bone */
01806             eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
01807             if(arm->act_edbone==eBone)
01808                 arm->act_edbone= NULL;
01809         }
01810     }
01811     
01812     ED_armature_sync_selection(arm->edbo);
01813 }
01814 
01815 void ED_armature_deselect_all_visible(Object *obedit)
01816 {
01817     bArmature *arm= obedit->data;
01818     EditBone    *ebone;
01819 
01820     for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
01821         /* first and foremost, bone must be visible and selected */
01822         if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE)==0) {
01823             ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
01824         }
01825     }
01826 
01827     ED_armature_sync_selection(arm->edbo);
01828 }
01829 
01830 /* accounts for connected parents */
01831 static int ebone_select_flag(EditBone *ebone)
01832 {
01833     if(ebone->parent && (ebone->flag & BONE_CONNECTED)) {
01834         return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) | (ebone->flag & (BONE_SELECTED|BONE_TIPSEL));
01835     }
01836     else {
01837         return ebone->flag & (BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL);
01838     }
01839 }
01840 
01841 /* context: editmode armature in view3d */
01842 int mouse_armature(bContext *C, const int mval[2], int extend)
01843 {
01844     Object *obedit= CTX_data_edit_object(C);
01845     bArmature *arm= obedit->data;
01846     ViewContext vc;
01847     EditBone *nearBone = NULL;
01848     int selmask;
01849 
01850     view3d_set_viewcontext(C, &vc);
01851     
01852     BIF_sk_selectStroke(C, mval, extend);
01853     
01854     nearBone= get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
01855     if (nearBone) {
01856 
01857         if (!extend)
01858             ED_armature_deselect_all(obedit, 0);
01859         
01860         /* by definition the non-root connected bones have no root point drawn,
01861            so a root selection needs to be delivered to the parent tip */
01862         
01863         if(selmask & BONE_SELECTED) {
01864             if(nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
01865                 /* click in a chain */
01866                 if(extend) {
01867                     /* hold shift inverts this bone's selection */
01868                     if(nearBone->flag & BONE_SELECTED) {
01869                         /* deselect this bone */
01870                         nearBone->flag &= ~(BONE_TIPSEL|BONE_SELECTED);
01871                         /* only deselect parent tip if it is not selected */
01872                         if(!(nearBone->parent->flag & BONE_SELECTED))
01873                             nearBone->parent->flag &= ~BONE_TIPSEL;
01874                     }
01875                     else {
01876                         /* select this bone */
01877                         nearBone->flag |= BONE_TIPSEL;
01878                         nearBone->parent->flag |= BONE_TIPSEL;
01879                     }
01880                 }
01881                 else {
01882                     /* select this bone */
01883                     nearBone->flag |= BONE_TIPSEL;
01884                     nearBone->parent->flag |= BONE_TIPSEL;
01885                 }
01886             }
01887             else {
01888                 if(extend) {
01889                     /* hold shift inverts this bone's selection */
01890                     if(nearBone->flag & BONE_SELECTED)
01891                        nearBone->flag &= ~(BONE_TIPSEL|BONE_ROOTSEL);
01892                     else
01893                         nearBone->flag |= (BONE_TIPSEL|BONE_ROOTSEL);
01894                 }
01895                 else nearBone->flag |= (BONE_TIPSEL|BONE_ROOTSEL);
01896             }
01897         }
01898         else {
01899             if (extend && (nearBone->flag & selmask))
01900                 nearBone->flag &= ~selmask;
01901             else
01902                 nearBone->flag |= selmask;
01903         }
01904         
01905         ED_armature_sync_selection(arm->edbo);
01906         
01907         if(nearBone) {
01908             /* then now check for active status */
01909             if(ebone_select_flag(nearBone)) {
01910                 arm->act_edbone= nearBone;
01911             }
01912         }
01913         
01914         WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, vc.obedit);
01915         return 1;
01916     }
01917 
01918     return 0;
01919 }
01920 
01921 void ED_armature_edit_free(struct Object *ob)
01922 {
01923     bArmature *arm= ob->data;
01924     EditBone *eBone;
01925     
01926     /*  Clear the editbones list */
01927     if (arm->edbo) {
01928         if (arm->edbo->first) {
01929             for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
01930                 if (eBone->prop) {
01931                     IDP_FreeProperty(eBone->prop);
01932                     MEM_freeN(eBone->prop);
01933                 }
01934             }
01935 
01936             BLI_freelistN(arm->edbo);
01937         }
01938         MEM_freeN(arm->edbo);
01939         arm->edbo= NULL;
01940     }
01941 }
01942 
01943 /* Put armature in EditMode */
01944 void ED_armature_to_edit(Object *ob)
01945 {
01946     bArmature *arm= ob->data;
01947     
01948     ED_armature_edit_free(ob);
01949     arm->edbo= MEM_callocN(sizeof(ListBase), "edbo armature");
01950     arm->act_edbone= make_boneList(arm->edbo, &arm->bonebase, NULL, arm->act_bone);
01951     arm->act_bone= NULL;
01952 
01953 //  BIF_freeTemplates(); /* force template update when entering editmode */
01954 }
01955 
01956 
01957 /* adjust bone roll to align Z axis with vector
01958  * vec is in local space and is normalized
01959  */
01960 
01961 float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const short axis_only)
01962 {
01963     float mat[3][3], nor[3];
01964 
01965     sub_v3_v3v3(nor, bone->tail, bone->head);
01966     vec_roll_to_mat3(nor, 0.0f, mat);
01967 
01968     /* check the bone isnt aligned with the axis */
01969     if(!is_zero_v3(align_axis) && angle_v3v3(align_axis, mat[2]) > FLT_EPSILON) {
01970         float vec[3], align_axis_proj[3], roll;
01971 
01972         /* project the new_up_axis along the normal */
01973         project_v3_v3v3(vec, align_axis, nor);
01974         sub_v3_v3v3(align_axis_proj, align_axis, vec);
01975         
01976         if(axis_only) {
01977             if(angle_v3v3(align_axis_proj, mat[2]) > (float)(M_PI/2.0)) {
01978                 negate_v3(align_axis_proj);
01979             }
01980         }
01981         
01982         roll = angle_v3v3(align_axis_proj, mat[2]);
01983         
01984         cross_v3_v3v3(vec, mat[2], align_axis_proj);
01985         
01986         if (dot_v3v3(vec, nor) < 0) {
01987             roll = -roll;
01988         }
01989 
01990         return roll;
01991     }
01992 
01993     return 0.0f;
01994 }
01995 
01996 
01997 static EnumPropertyItem prop_calc_roll_types[] = {
01998     {0, "X", 0, "X Axis", ""},
01999     {1, "Y", 0, "Y Axis", ""},
02000     {2, "Z", 0, "Z Axis", ""},
02001     {5, "ACTIVE", 0, "Active Bone", ""},
02002     {6, "VIEW", 0, "View Axis", ""},
02003     {7, "CURSOR", 0, "Cursor", ""},
02004     {0, NULL, 0, NULL, NULL}
02005 };
02006 
02007 
02008 static int armature_calc_roll_exec(bContext *C, wmOperator *op) 
02009 {
02010     Object *ob= CTX_data_edit_object(C);
02011     const short type= RNA_enum_get(op->ptr, "type");
02012     const short axis_only= RNA_boolean_get(op->ptr, "axis_only");
02013     const short axis_flip= RNA_boolean_get(op->ptr, "axis_flip");
02014 
02015     float imat[3][3];
02016 
02017     bArmature *arm= ob->data;
02018     EditBone *ebone;
02019 
02020     copy_m3_m4(imat, ob->obmat);
02021     invert_m3(imat);
02022 
02023     if(type==7) { /* Cursor */
02024         Scene *scene= CTX_data_scene(C);
02025         View3D *v3d= CTX_wm_view3d(C); /* can be NULL */
02026         float cursor_local[3];
02027         float   *cursor= give_cursor(scene, v3d);
02028     
02029 
02030         copy_v3_v3(cursor_local, cursor);
02031         mul_m3_v3(imat, cursor_local);
02032 
02033         /* cursor */
02034         for(ebone= arm->edbo->first; ebone; ebone= ebone->next) {
02035             if(EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
02036                 float cursor_rel[3];
02037                 sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
02038                 if(axis_flip) negate_v3(cursor_rel);
02039                 ebone->roll= ED_rollBoneToVector(ebone, cursor_rel, axis_only);
02040             }
02041         }
02042     }
02043     else {
02044         float vec[3]= {0.0f, 0.0f, 0.0f};
02045         if(type==6) { /* View */
02046             RegionView3D *rv3d= CTX_wm_region_view3d(C);
02047             if(rv3d==NULL) {
02048                 BKE_report(op->reports, RPT_ERROR, "No region view3d available");
02049                 return OPERATOR_CANCELLED;
02050             }
02051 
02052             copy_v3_v3(vec, rv3d->viewinv[2]);
02053             mul_m3_v3(imat, vec);
02054         }
02055         else if (type==5) {
02056             float mat[3][3], nor[3];
02057             ebone= (EditBone *)arm->act_edbone;
02058             if(ebone==NULL) {
02059                 BKE_report(op->reports, RPT_ERROR, "No active bone set");
02060                 return OPERATOR_CANCELLED;
02061             }
02062 
02063             sub_v3_v3v3(nor, ebone->tail, ebone->head);
02064             vec_roll_to_mat3(nor, ebone->roll, mat);            
02065             copy_v3_v3(vec, mat[2]);
02066         }
02067         else { /* Axis */
02068             assert(type >= 0 && type <= 5);
02069             if(type<3)  vec[type]= 1.0f; 
02070             else        vec[type-2]= -1.0f; 
02071             mul_m3_v3(imat, vec);
02072         }
02073 
02074         if(axis_flip) negate_v3(vec);
02075 
02076         for(ebone= arm->edbo->first; ebone; ebone= ebone->next) {
02077             if(EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
02078                 /* roll func is a callback which assumes that all is well */
02079                 ebone->roll= ED_rollBoneToVector(ebone, vec, axis_only);
02080             }
02081         }
02082     }
02083 
02084     if (arm->flag & ARM_MIRROR_EDIT) {
02085         for(ebone= arm->edbo->first; ebone; ebone= ebone->next) {
02086             if((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
02087                 EditBone *ebone_mirr= ED_armature_bone_get_mirrored(arm->edbo, ebone);
02088                 if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
02089                     ebone->roll= -ebone_mirr->roll;
02090                 }
02091             }
02092         }
02093     }
02094 
02095     /* note, notifier might evolve */
02096     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
02097     
02098     return OPERATOR_FINISHED;
02099 }
02100 
02101 void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
02102 {
02103     /* identifiers */
02104     ot->name= "Recalculate Roll";
02105     ot->idname= "ARMATURE_OT_calculate_roll";
02106     ot->description= "Automatically fix alignment of select bones' axes";
02107     
02108     /* api callbacks */
02109     ot->invoke = WM_menu_invoke;
02110     ot->exec = armature_calc_roll_exec;
02111     ot->poll = ED_operator_editarmature;
02112     
02113     /* flags */
02114     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
02115 
02116     /* properties */
02117     ot->prop= RNA_def_enum(ot->srna, "type", prop_calc_roll_types, 0, "Type", "");
02118     RNA_def_boolean(ot->srna, "axis_flip", 0, "Flip Axis", "Negate the alignment axis");
02119     RNA_def_boolean(ot->srna, "axis_only", 0, "Shortest Rotation", "Ignore the axis direction, use the shortest rotation to align");
02120 }
02121 
02122 /* **************** undo for armatures ************** */
02123 
02124 typedef struct UndoArmature {
02125     EditBone *act_edbone;
02126     ListBase lb;
02127 } UndoArmature;
02128 
02129 static void undoBones_to_editBones(void *uarmv, void *armv)
02130 {
02131     UndoArmature *uarm= uarmv;
02132     bArmature *arm= armv;
02133     EditBone *ebo, *newebo;
02134     
02135     BLI_freelistN(arm->edbo);
02136     
02137     /* copy  */
02138     for(ebo= uarm->lb.first; ebo; ebo= ebo->next) {
02139         newebo= MEM_dupallocN(ebo);
02140         ebo->temp= newebo;
02141         BLI_addtail(arm->edbo, newebo);
02142     }
02143     
02144     /* active bone */
02145     if(uarm->act_edbone) {
02146         ebo= uarm->act_edbone;
02147         arm->act_edbone= ebo->temp;
02148     }
02149     else
02150         arm->act_edbone= NULL;
02151 
02152     /* set pointers */
02153     for(newebo= arm->edbo->first; newebo; newebo= newebo->next) {
02154         if(newebo->parent) newebo->parent= newebo->parent->temp;
02155     }
02156     /* be sure they dont hang ever */
02157     for(newebo= arm->edbo->first; newebo; newebo= newebo->next) {
02158         newebo->temp= NULL;
02159     }
02160 }
02161 
02162 static void *editBones_to_undoBones(void *armv)
02163 {
02164     bArmature *arm= armv;
02165     UndoArmature *uarm;
02166     EditBone *ebo, *newebo;
02167     
02168     uarm= MEM_callocN(sizeof(UndoArmature), "listbase undo");
02169     
02170     /* copy */
02171     for(ebo= arm->edbo->first; ebo; ebo= ebo->next) {
02172         newebo= MEM_dupallocN(ebo);
02173         ebo->temp= newebo;
02174         BLI_addtail(&uarm->lb, newebo);
02175     }
02176     
02177     /* active bone */
02178     if(arm->act_edbone) {
02179         ebo= arm->act_edbone;
02180         uarm->act_edbone= ebo->temp;
02181     }
02182 
02183     /* set pointers */
02184     for(newebo= uarm->lb.first; newebo; newebo= newebo->next) {
02185         if(newebo->parent) newebo->parent= newebo->parent->temp;
02186     }
02187     
02188     return uarm;
02189 }
02190 
02191 static void free_undoBones(void *uarmv)
02192 {
02193     UndoArmature *uarm= uarmv;
02194     
02195     BLI_freelistN(&uarm->lb);
02196     MEM_freeN(uarm);
02197 }
02198 
02199 static void *get_armature_edit(bContext *C)
02200 {
02201     Object *obedit= CTX_data_edit_object(C);
02202     if(obedit && obedit->type==OB_ARMATURE) {
02203         return obedit->data;
02204     }
02205     return NULL;
02206 }
02207 
02208 /* and this is all the undo system needs to know */
02209 void undo_push_armature(bContext *C, const char *name)
02210 {
02211     // XXX solve getdata()
02212     undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
02213 }
02214 
02215 
02216 
02217 /* **************** END EditMode stuff ********************** */
02218 /* *************** Adding stuff in editmode *************** */
02219 
02220 /* default bone add, returns it selected, but without tail set */
02221 EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
02222 {
02223     EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
02224     
02225     BLI_strncpy(bone->name, name, sizeof(bone->name));
02226     unique_editbone_name(arm->edbo, bone->name, NULL);
02227     
02228     BLI_addtail(arm->edbo, bone);
02229     
02230     bone->flag |= BONE_TIPSEL;
02231     bone->weight= 1.0f;
02232     bone->dist= 0.25f;
02233     bone->xwidth= 0.1f;
02234     bone->zwidth= 0.1f;
02235     bone->ease1= 1.0f;
02236     bone->ease2= 1.0f;
02237     bone->rad_head= 0.10f;
02238     bone->rad_tail= 0.05f;
02239     bone->segments= 1;
02240     bone->layer= arm->layer;
02241     
02242     return bone;
02243 }
02244 
02245 /* v3d and rv3d are allowed to be NULL */
02246 void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
02247 {
02248     Object *obedit= scene->obedit; // XXX get from context
02249     bArmature *arm= obedit->data;
02250     float       obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
02251     EditBone    *bone;
02252 
02253     /* Get inverse point for head and orientation for tail */
02254     invert_m4_m4(obedit->imat, obedit->obmat);
02255     mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
02256 
02257     if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
02258         copy_m3_m4(obmat, rv3d->viewmat);
02259     else unit_m3(obmat);
02260     
02261     copy_m3_m4(viewmat, obedit->obmat);
02262     mul_m3_m3m3(totmat, obmat, viewmat);
02263     invert_m3_m3(imat, totmat);
02264     
02265     ED_armature_deselect_all(obedit, 0);
02266     
02267     /*  Create a bone   */
02268     bone= ED_armature_edit_bone_add(arm, "Bone");
02269 
02270     arm->act_edbone= bone;
02271 
02272     copy_v3_v3(bone->head, curs);
02273     
02274     if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
02275         add_v3_v3v3(bone->tail, bone->head, imat[1]);   // bone with unit length 1
02276     else
02277         add_v3_v3v3(bone->tail, bone->head, imat[2]);   // bone with unit length 1, pointing up Z
02278     
02279 }
02280 
02281 
02282 /* previously addvert_armature */
02283 /* the ctrl-click method */
02284 static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
02285 {
02286     View3D *v3d;
02287     bArmature *arm;
02288     EditBone *ebone, *newbone, *flipbone;
02289     float *curs, mat[3][3],imat[3][3];
02290     int a, to_root= 0;
02291     Object *obedit;
02292     Scene *scene;
02293 
02294     scene = CTX_data_scene(C);
02295     v3d= CTX_wm_view3d(C);
02296     obedit= CTX_data_edit_object(C);
02297     arm= obedit->data;
02298     
02299     /* find the active or selected bone */
02300     for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
02301         if (EBONE_VISIBLE(arm, ebone)) {
02302             if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
02303                 break;
02304         }
02305     }
02306     
02307     if (ebone==NULL) {
02308         for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
02309             if (EBONE_VISIBLE(arm, ebone)) {
02310                 if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
02311                     break;
02312             }
02313         }
02314         if (ebone == NULL) 
02315             return OPERATOR_CANCELLED;
02316         
02317         to_root= 1;
02318     }
02319     
02320     ED_armature_deselect_all(obedit, 0);
02321     
02322     /* we re-use code for mirror editing... */
02323     flipbone= NULL;
02324     if (arm->flag & ARM_MIRROR_EDIT)
02325         flipbone= ED_armature_bone_get_mirrored(arm->edbo, ebone);
02326 
02327     for (a=0; a<2; a++) {
02328         if (a==1) {
02329             if (flipbone==NULL)
02330                 break;
02331             else {
02332                 SWAP(EditBone *, flipbone, ebone);
02333             }
02334         }
02335         
02336         newbone= ED_armature_edit_bone_add(arm, ebone->name);
02337         arm->act_edbone= newbone;
02338         
02339         if (to_root) {
02340             copy_v3_v3(newbone->head, ebone->head);
02341             newbone->rad_head= ebone->rad_tail;
02342             newbone->parent= ebone->parent;
02343         }
02344         else {
02345             copy_v3_v3(newbone->head, ebone->tail);
02346             newbone->rad_head= ebone->rad_tail;
02347             newbone->parent= ebone;
02348             newbone->flag |= BONE_CONNECTED;
02349         }
02350         
02351         curs= give_cursor(scene, v3d);
02352         copy_v3_v3(newbone->tail, curs);
02353         sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
02354         
02355         if (a==1) 
02356             newbone->tail[0]= -newbone->tail[0];
02357         
02358         copy_m3_m4(mat, obedit->obmat);
02359         invert_m3_m3(imat, mat);
02360         mul_m3_v3(imat, newbone->tail);
02361         
02362         newbone->length= len_v3v3(newbone->head, newbone->tail);
02363         newbone->rad_tail= newbone->length*0.05f;
02364         newbone->dist= newbone->length*0.25f;
02365         
02366     }
02367     
02368     ED_armature_sync_selection(arm->edbo);
02369 
02370     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
02371     
02372     return OPERATOR_FINISHED;
02373 }
02374 
02375 static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
02376 {
02377     /* TODO most of this code is copied from set3dcursor_invoke,
02378        it would be better to reuse code in set3dcursor_invoke */
02379 
02380     /* temporarily change 3d cursor position */
02381     Scene *scene;
02382     ARegion *ar;
02383     View3D *v3d;
02384     float *fp = NULL, tvec[3], oldcurs[3], mval_f[2];
02385     int retv;
02386 
02387     scene= CTX_data_scene(C);
02388     ar= CTX_wm_region(C);
02389     v3d = CTX_wm_view3d(C);
02390     
02391     fp= give_cursor(scene, v3d);
02392     
02393     copy_v3_v3(oldcurs, fp);
02394 
02395     VECCOPY2D(mval_f, event->mval);
02396     ED_view3d_win_to_3d(ar, fp, mval_f, tvec);
02397     copy_v3_v3(fp, tvec);
02398 
02399     /* extrude to the where new cursor is and store the operation result */
02400     retv= armature_click_extrude_exec(C, op);
02401 
02402     /* restore previous 3d cursor position */
02403     copy_v3_v3(fp, oldcurs);
02404 
02405     return retv;
02406 }
02407 
02408 void ARMATURE_OT_click_extrude(wmOperatorType *ot)
02409 {
02410     /* identifiers */
02411     ot->name= "Click-Extrude";
02412     ot->idname= "ARMATURE_OT_click_extrude";
02413     ot->description= "Create a new bone going from the last selected joint to the mouse position";
02414     
02415     /* api callbacks */
02416     ot->invoke = armature_click_extrude_invoke;
02417     ot->exec = armature_click_extrude_exec;
02418     ot->poll = ED_operator_editarmature;
02419     
02420     /* flags */
02421     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
02422 
02423     /* props */
02424 }
02425 
02426 /* adds an EditBone between the nominated locations (should be in the right space) */
02427 static EditBone *add_points_bone (Object *obedit, float head[], float tail[]) 
02428 {
02429     EditBone *ebo;
02430     
02431     ebo= ED_armature_edit_bone_add(obedit->data, "Bone");
02432     
02433     copy_v3_v3(ebo->head, head);
02434     copy_v3_v3(ebo->tail, tail);
02435     
02436     return ebo;
02437 }
02438 
02439 
02440 static EditBone *get_named_editbone(ListBase *edbo, char *name)
02441 {
02442     EditBone  *eBone;
02443 
02444     if (name) {
02445         for (eBone=edbo->first; eBone; eBone=eBone->next) {
02446             if (!strcmp(name, eBone->name))
02447                 return eBone;
02448         }
02449     }
02450 
02451     return NULL;
02452 }
02453 
02454 /* Call this before doing any duplications
02455  * */
02456 void preEditBoneDuplicate(ListBase *editbones)
02457 {
02458     EditBone *eBone;
02459     
02460     /* clear temp */
02461     for (eBone = editbones->first; eBone; eBone = eBone->next)
02462     {
02463         eBone->temp = NULL;
02464     }
02465 }
02466 
02467 /*
02468  * Note: When duplicating cross objects, editbones here is the list of bones
02469  * from the SOURCE object but ob is the DESTINATION object
02470  * */
02471 void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Object *src_ob, Object *dst_ob)
02472 {
02473     /* If an edit bone has been duplicated, lets
02474      * update it's constraints if the subtarget
02475      * they point to has also been duplicated
02476      */
02477     EditBone     *oldtarget, *newtarget;
02478     bPoseChannel *pchan;
02479     bConstraint  *curcon;
02480     ListBase     *conlist;
02481     
02482     if ( (pchan = verify_pose_channel(dst_ob->pose, dupBone->name)) ) {
02483         if ( (conlist = &pchan->constraints) ) {
02484             for (curcon = conlist->first; curcon; curcon=curcon->next) {
02485                 /* does this constraint have a subtarget in
02486                  * this armature?
02487                  */
02488                 bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
02489                 ListBase targets = {NULL, NULL};
02490                 bConstraintTarget *ct;
02491                 
02492                 if (cti && cti->get_constraint_targets) {
02493                     cti->get_constraint_targets(curcon, &targets);
02494                     
02495                     for (ct= targets.first; ct; ct= ct->next) {
02496                         if ((ct->tar == src_ob) && (ct->subtarget[0])) {
02497                             ct->tar = dst_ob; /* update target */ 
02498                             oldtarget = get_named_editbone(editbones, ct->subtarget);
02499                             if (oldtarget) {
02500                                 /* was the subtarget bone duplicated too? If
02501                                  * so, update the constraint to point at the 
02502                                  * duplicate of the old subtarget.
02503                                  */
02504                                 if (oldtarget->temp) {
02505                                     newtarget = (EditBone *) oldtarget->temp;
02506                                     BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
02507                                 }
02508                             }
02509                         }
02510                     }
02511                     
02512                     if (cti->flush_constraint_targets)
02513                         cti->flush_constraint_targets(curcon, &targets, 0);
02514                 }
02515             }
02516         }
02517     }
02518 }
02519 
02520 void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob)
02521 {
02522     updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
02523 }
02524 
02525 
02526 EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
02527 {
02528     EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
02529     
02530     /*  Copy data from old bone to new bone */
02531     memcpy(eBone, curBone, sizeof(EditBone));
02532     
02533     curBone->temp = eBone;
02534     eBone->temp = curBone;
02535     
02536     if (name != NULL)
02537     {
02538         BLI_strncpy(eBone->name, name, sizeof(eBone->name));
02539     }
02540 
02541     unique_editbone_name(editbones, eBone->name, NULL);
02542     BLI_addtail(editbones, eBone);
02543     
02544     /* copy the ID property */
02545     if(curBone->prop)
02546         eBone->prop= IDP_CopyProperty(curBone->prop);
02547 
02548     /* Lets duplicate the list of constraints that the
02549      * current bone has.
02550      */
02551     if (src_ob->pose) {
02552         bPoseChannel *chanold, *channew;
02553         
02554         chanold = verify_pose_channel(src_ob->pose, curBone->name);
02555         if (chanold) {
02556             /* WARNING: this creates a new posechannel, but there will not be an attached bone
02557              *      yet as the new bones created here are still 'EditBones' not 'Bones'.
02558              */
02559             channew= verify_pose_channel(dst_ob->pose, eBone->name);
02560 
02561             if(channew) {
02562                 duplicate_pose_channel_data(channew, chanold);
02563             }
02564         }
02565     }
02566     
02567     return eBone;
02568 }
02569 
02570 EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editbones, Object *ob)
02571 {
02572     return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
02573 }
02574 
02575 /* previously adduplicate_armature */
02576 static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
02577 {
02578     bArmature *arm;
02579     EditBone    *eBone = NULL;
02580     EditBone    *curBone;
02581     EditBone    *firstDup=NULL; /*  The beginning of the duplicated bones in the edbo list */
02582 
02583     Object *obedit= CTX_data_edit_object(C);
02584     arm= obedit->data;
02585 
02586     /* cancel if nothing selected */
02587     if (CTX_DATA_COUNT(C, selected_bones) == 0)
02588         return OPERATOR_CANCELLED;
02589     
02590     ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
02591 
02592     preEditBoneDuplicate(arm->edbo);
02593 
02594     /* Select mirrored bones */
02595     if (arm->flag & ARM_MIRROR_EDIT) {
02596         for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
02597             if (EBONE_VISIBLE(arm, curBone)) {
02598                 if (curBone->flag & BONE_SELECTED) {
02599                     eBone = ED_armature_bone_get_mirrored(arm->edbo, curBone);
02600                     if (eBone)
02601                         eBone->flag |= BONE_SELECTED;
02602                 }
02603             }
02604         }
02605     }
02606 
02607     
02608     /*  Find the selected bones and duplicate them as needed */
02609     for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
02610         if (EBONE_VISIBLE(arm, curBone)) {
02611             if (curBone->flag & BONE_SELECTED) {
02612                 
02613                 eBone= duplicateEditBone(curBone, curBone->name, arm->edbo, obedit);
02614                 
02615                 if (!firstDup)
02616                     firstDup=eBone;
02617 
02618             }
02619         }
02620     }
02621 
02622     /*  Run though the list and fix the pointers */
02623     for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
02624         if (EBONE_VISIBLE(arm, curBone)) {
02625             if (curBone->flag & BONE_SELECTED) {
02626                 eBone=(EditBone*) curBone->temp;
02627                 
02628                 if (!curBone->parent) {
02629                     /* If this bone has no parent,
02630                      * Set the duplicate->parent to NULL
02631                      */
02632                     eBone->parent = NULL;
02633                 }
02634                 else if (curBone->parent->temp) {
02635                     /* If this bone has a parent that was duplicated,
02636                      * Set the duplicate->parent to the curBone->parent->temp
02637                      */
02638                     eBone->parent= (EditBone *)curBone->parent->temp;
02639                 }
02640                 else {
02641                     /* If this bone has a parent that IS not selected,
02642                      * Set the duplicate->parent to the curBone->parent
02643                      */
02644                     eBone->parent=(EditBone*) curBone->parent; 
02645                     eBone->flag &= ~BONE_CONNECTED;
02646                 }
02647                 
02648                 /* Lets try to fix any constraint subtargets that might
02649                  * have been duplicated 
02650                  */
02651                 updateDuplicateSubtarget(eBone, arm->edbo, obedit);
02652             }
02653         }
02654     } 
02655     
02656     /* correct the active bone */
02657     if(arm->act_edbone) {
02658         eBone= arm->act_edbone;
02659         if(eBone->temp)
02660             arm->act_edbone= eBone->temp;
02661     }
02662 
02663     /*  Deselect the old bones and select the new ones */
02664     for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
02665         if (EBONE_VISIBLE(arm, curBone))
02666             curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
02667     }
02668 
02669     ED_armature_validate_active(arm);
02670 
02671     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
02672     
02673     return OPERATOR_FINISHED;
02674 }
02675 
02676 
02677 void ARMATURE_OT_duplicate(wmOperatorType *ot)
02678 {
02679     /* identifiers */
02680     ot->name= "Duplicate Selected Bone(s)";
02681     ot->idname= "ARMATURE_OT_duplicate";
02682     ot->description= "Make copies of the selected bones within the same armature";
02683     
02684     /* api callbacks */
02685     ot->exec = armature_duplicate_selected_exec;
02686     ot->poll = ED_operator_editarmature;
02687     
02688     /* flags */
02689     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
02690 }
02691 
02692 
02693 /* *************** END Adding stuff in editmode *************** */
02694 /* ************** Add/Remove stuff in editmode **************** */
02695 
02696 /* temporary data-structure for merge/fill bones */
02697 typedef struct EditBonePoint {
02698     struct EditBonePoint *next, *prev;
02699     
02700     EditBone *head_owner;       /* EditBone which uses this point as a 'head' point */
02701     EditBone *tail_owner;       /* EditBone which uses this point as a 'tail' point */
02702     
02703     float vec[3];               /* the actual location of the point in local/EditMode space */
02704 } EditBonePoint;
02705 
02706 /* find chain-tips (i.e. bones without children) */
02707 static void chains_find_tips (ListBase *edbo, ListBase *list)
02708 {
02709     EditBone *curBone, *ebo;
02710     LinkData *ld;
02711     
02712     /* note: this is potentially very slow ... there's got to be a better way */
02713     for (curBone= edbo->first; curBone; curBone= curBone->next) {
02714         short stop= 0;
02715         
02716         /* is this bone contained within any existing chain? (skip if so) */
02717         for (ld= list->first; ld; ld= ld->next) {
02718             for (ebo= ld->data; ebo; ebo= ebo->parent) {
02719                 if (ebo == curBone) {
02720                     stop= 1;
02721                     break;
02722                 }
02723             }
02724             
02725             if (stop) break;
02726         }
02727         /* skip current bone if it is part of an existing chain */
02728         if (stop) continue;
02729         
02730         /* is any existing chain part of the chain formed by this bone? */
02731         stop= 0;
02732         for (ebo= curBone->parent; ebo; ebo= ebo->parent) {
02733             for (ld= list->first; ld; ld= ld->next) {
02734                 if (ld->data == ebo) {
02735                     ld->data= curBone;
02736                     stop= 1;
02737                     break;
02738                 }
02739             }
02740             
02741             if (stop) break;
02742         }
02743         /* current bone has already been added to a chain? */
02744         if (stop) continue;
02745         
02746         /* add current bone to a new chain */
02747         ld= MEM_callocN(sizeof(LinkData), "BoneChain");
02748         ld->data= curBone;
02749         BLI_addtail(list, ld);
02750     }
02751 }
02752 
02753 /* --------------------- */
02754 
02755 static void fill_add_joint (EditBone *ebo, short eb_tail, ListBase *points)
02756 {
02757     EditBonePoint *ebp;
02758     float vec[3];
02759     short found= 0;
02760     
02761     if (eb_tail) {
02762         copy_v3_v3(vec, ebo->tail);
02763     }
02764     else {
02765         copy_v3_v3(vec, ebo->head);
02766     }
02767     
02768     for (ebp= points->first; ebp; ebp= ebp->next) {
02769         if (equals_v3v3(ebp->vec, vec)) {           
02770             if (eb_tail) {
02771                 if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
02772                     /* so this bone's tail owner is this bone */
02773                     ebp->tail_owner= ebo;
02774                     found= 1;
02775                     break;
02776                 }
02777             }
02778             else {
02779                 if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) {
02780                     /* so this bone's head owner is this bone */
02781                     ebp->head_owner= ebo;
02782                     found = 1;
02783                     break;
02784                 }
02785             }
02786         }
02787     }
02788     
02789     /* allocate a new point if no existing point was related */
02790     if (found == 0) {
02791         ebp= MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
02792         
02793         if (eb_tail) {
02794             copy_v3_v3(ebp->vec, ebo->tail);
02795             ebp->tail_owner= ebo;
02796         }
02797         else {
02798             copy_v3_v3(ebp->vec, ebo->head);
02799             ebp->head_owner= ebo;
02800         }
02801         
02802         BLI_addtail(points, ebp);
02803     }
02804 }
02805 
02806 /* bone adding between selected joints */
02807 static int armature_fill_bones_exec (bContext *C, wmOperator *op)
02808 {
02809     Object *obedit= CTX_data_edit_object(C);
02810     bArmature *arm= (obedit) ? obedit->data : NULL;
02811     Scene *scene= CTX_data_scene(C);
02812     View3D *v3d= CTX_wm_view3d(C);
02813     ListBase points = {NULL, NULL};
02814     int count;
02815 
02816     /* sanity checks */
02817     if (ELEM(NULL, obedit, arm))
02818         return OPERATOR_CANCELLED;
02819 
02820     /* loop over all bones, and only consider if visible */
02821     CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
02822     {
02823         if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
02824             fill_add_joint(ebone, 0, &points);
02825         if (ebone->flag & BONE_TIPSEL) 
02826             fill_add_joint(ebone, 1, &points);
02827     }
02828     CTX_DATA_END;
02829     
02830     /* the number of joints determines how we fill:
02831      *  1) between joint and cursor (joint=head, cursor=tail)
02832      *  2) between the two joints (order is dependent on active-bone/hierachy)
02833      *  3+) error (a smarter method involving finding chains needs to be worked out
02834      */
02835     count= BLI_countlist(&points);
02836     
02837     if (count == 0) {
02838         BKE_report(op->reports, RPT_ERROR, "No joints selected");
02839         return OPERATOR_CANCELLED;
02840     }
02841     else if (count == 1) {
02842         EditBonePoint *ebp;
02843         float curs[3];
02844         
02845         /* Get Points - selected joint */
02846         ebp= (EditBonePoint *)points.first;
02847         
02848         /* Get points - cursor (tail) */
02849         invert_m4_m4(obedit->imat, obedit->obmat);
02850         mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
02851         
02852         /* Create a bone */
02853         /* newbone= */ add_points_bone(obedit, ebp->vec, curs);
02854     }
02855     else if (count == 2) {
02856         EditBonePoint *ebp, *ebp2;
02857         float head[3], tail[3];
02858         short headtail = 0;
02859         
02860         /* check that the points don't belong to the same bone */
02861         ebp= (EditBonePoint *)points.first;
02862         ebp2= ebp->next;
02863         
02864         if ((ebp->head_owner==ebp2->tail_owner) && (ebp->head_owner!=NULL)) {
02865             BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
02866             BLI_freelistN(&points);
02867             return OPERATOR_CANCELLED;
02868         }
02869         if ((ebp->tail_owner==ebp2->head_owner) && (ebp->tail_owner!=NULL)) {
02870             BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
02871             BLI_freelistN(&points);
02872             return OPERATOR_CANCELLED;
02873         }
02874         
02875         /* find which one should be the 'head' */
02876         if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) {
02877             /* rule: whichever one is closer to 3d-cursor */
02878             float curs[3];
02879             float vecA[3], vecB[3];
02880             float distA, distB;
02881             
02882             /* get cursor location */
02883             invert_m4_m4(obedit->imat, obedit->obmat);
02884             mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
02885             
02886             /* get distances */
02887             sub_v3_v3v3(vecA, ebp->vec, curs);
02888             sub_v3_v3v3(vecB, ebp2->vec, curs);
02889             distA= len_v3(vecA);
02890             distB= len_v3(vecB);
02891             
02892             /* compare distances - closer one therefore acts as direction for bone to go */
02893             headtail= (distA < distB) ? 2 : 1;
02894         }
02895         else if (ebp->head_owner) {
02896             headtail = 1;
02897         }
02898         else if (ebp2->head_owner) {
02899             headtail = 2;
02900         }
02901         
02902         /* assign head/tail combinations */
02903         if (headtail == 2) {
02904             copy_v3_v3(head, ebp->vec);
02905             copy_v3_v3(tail, ebp2->vec);
02906         }
02907         else if (headtail == 1) {
02908             copy_v3_v3(head, ebp2->vec);
02909             copy_v3_v3(tail, ebp->vec);
02910         }
02911         
02912         /* add new bone and parent it to the appropriate end */
02913         if (headtail) {
02914             EditBone *newbone= add_points_bone(obedit, head, tail);
02915             
02916             /* do parenting (will need to set connected flag too) */
02917             if (headtail == 2) {
02918                 /* ebp tail or head - tail gets priority */
02919                 if (ebp->tail_owner)
02920                     newbone->parent= ebp->tail_owner;
02921                 else
02922                     newbone->parent= ebp->head_owner;
02923             }
02924             else {
02925                 /* ebp2 tail or head - tail gets priority */
02926                 if (ebp2->tail_owner)
02927                     newbone->parent= ebp2->tail_owner;
02928                 else
02929                     newbone->parent= ebp2->head_owner;
02930             }
02931             
02932             newbone->flag |= BONE_CONNECTED;
02933         }
02934     }
02935     else {
02936         // FIXME.. figure out a method for multiple bones
02937         BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d \n", count); 
02938         BLI_freelistN(&points);
02939         return OPERATOR_CANCELLED;
02940     }
02941     
02942     /* updates */
02943     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, obedit);
02944     
02945     /* free points */
02946     BLI_freelistN(&points);
02947     
02948     return OPERATOR_FINISHED;
02949 }
02950 
02951 void ARMATURE_OT_fill (wmOperatorType *ot)
02952 {
02953     /* identifiers */
02954     ot->name= "Fill Between Joints";
02955     ot->idname= "ARMATURE_OT_fill";
02956     ot->description= "Add bone between selected joint(s) and/or 3D-Cursor";
02957     
02958     /* callbacks */
02959     ot->exec= armature_fill_bones_exec;
02960     ot->poll= ED_operator_editarmature;
02961     
02962     /* flags */
02963     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
02964 }
02965 
02966 /* --------------------- */
02967 
02968 /* this function merges between two bones, removes them and those in-between, 
02969  * and adjusts the parent relationships for those in-between
02970  */
02971 static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone *endchild, ListBase *chains)
02972 {
02973     bArmature *arm= obedit->data;
02974     EditBone *ebo, *ebone, *newbone;
02975     LinkData *chain;
02976     float head[3], tail[3];
02977     
02978     /* check if same bone */
02979     if (start == end) {
02980         if (G.f & G_DEBUG) {
02981             printf("Error: same bone! \n");
02982             printf("\tstart = %s, end = %s \n", start->name, end->name);
02983         }
02984     }
02985     
02986     /* step 1: add a new bone
02987      *  - head = head/tail of start (default head)
02988      *  - tail = head/tail of end (default tail)
02989      *  - parent = parent of start
02990      */
02991     if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED)==0) {
02992         copy_v3_v3(head, start->tail);
02993     }
02994     else {
02995         copy_v3_v3(head, start->head);
02996     }
02997     if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED)==0) {
02998         copy_v3_v3(tail, end->head);
02999     }
03000     else {
03001         copy_v3_v3(tail, end->tail);
03002     }
03003     newbone= add_points_bone(obedit, head, tail);
03004     newbone->parent = start->parent;
03005 
03006     /* TODO, copy more things to the new bone */
03007     newbone->flag= start->flag & (BONE_HINGE|BONE_NO_DEFORM|BONE_NO_SCALE|BONE_NO_CYCLICOFFSET|BONE_NO_LOCAL_LOCATION|BONE_DONE);
03008     
03009     /* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge 
03010      *  - potentially several tips for side chains leading to some tree exist...
03011      */
03012     for (chain = chains->first; chain; chain = chain->next) {
03013         /* traverse down chain until we hit the bottom or if we run into the tip of the chain of bones we're 
03014          * merging (need to stop in this case to avoid corrupting this chain too!) 
03015          */
03016         for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
03017             short found = 0;
03018             
03019             /* check if this bone is parented to one in the merging chain
03020              * ! WATCHIT: must only go check until end of checking chain
03021              */
03022             for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
03023                 /* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
03024                 if (ebone->parent == ebo) {
03025                     ebone->parent = newbone;
03026                     found = 1;
03027                     break;
03028                 }
03029             }
03030             
03031             /* carry on to the next tip now  */
03032             if (found) 
03033                 break;
03034         }
03035     }
03036     
03037     /* step 2b: parent child of end to newbone (child from this chain) */
03038     if (endchild)
03039         endchild->parent= newbone;
03040     
03041     /* step 3: delete all bones between and including start and end */
03042     for (ebo= end; ebo; ebo= ebone) {
03043         ebone= (ebo == start) ? (NULL) : (ebo->parent);
03044         bone_free(arm, ebo);
03045     }
03046     
03047     newbone->flag |= (BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
03048     ED_armature_sync_selection(arm->edbo);
03049 }
03050 
03051 
03052 static int armature_merge_exec (bContext *C, wmOperator *op)
03053 {
03054     Object *obedit= CTX_data_edit_object(C);
03055     bArmature *arm= (obedit) ? obedit->data : NULL;
03056     short type= RNA_enum_get(op->ptr, "type");
03057     
03058     /* sanity checks */
03059     if ELEM(NULL, obedit, arm)
03060         return OPERATOR_CANCELLED;
03061     
03062     /* for now, there's only really one type of merging that's performed... */
03063     if (type == 1) {
03064         /* go down chains, merging bones */
03065         ListBase chains = {NULL, NULL};
03066         LinkData *chain, *nchain;
03067         EditBone *ebo;
03068         
03069         armature_tag_select_mirrored(arm);
03070         
03071         /* get chains (ends on chains) */
03072         chains_find_tips(arm->edbo, &chains);
03073         if (chains.first == NULL) return OPERATOR_CANCELLED;
03074         
03075         /* each 'chain' is the last bone in the chain (with no children) */
03076         for (chain= chains.first; chain; chain= nchain) {
03077             EditBone *bstart= NULL, *bend= NULL;
03078             EditBone *bchild= NULL, *child=NULL;
03079             
03080             /* temporarily remove chain from list of chains */
03081             nchain= chain->next;
03082             BLI_remlink(&chains, chain);
03083             
03084             /* only consider bones that are visible and selected */
03085             for (ebo=chain->data; ebo; child=ebo, ebo=ebo->parent) {
03086                 /* check if visible + selected */
03087                 if ( EBONE_VISIBLE(arm, ebo) &&
03088                      ((ebo->flag & BONE_CONNECTED) || (ebo->parent==NULL)) &&
03089                      (ebo->flag & BONE_SELECTED) )
03090                 {
03091                     /* set either end or start (end gets priority, unless it is already set) */
03092                     if (bend == NULL)  {
03093                         bend= ebo;
03094                         bchild= child;
03095                     }
03096                     else 
03097                         bstart= ebo;
03098                 }
03099                 else {
03100                     /* chain is broken... merge any continous segments then clear */
03101                     if (bstart && bend)
03102                         bones_merge(obedit, bstart, bend, bchild, &chains);
03103                     
03104                     bstart = NULL;
03105                     bend = NULL;
03106                     bchild = NULL;
03107                 }
03108             }
03109             
03110             /* merge from bstart to bend if something not merged */
03111             if (bstart && bend)
03112                 bones_merge(obedit, bstart, bend, bchild, &chains);
03113             
03114             /* put back link */
03115             BLI_insertlinkbefore(&chains, nchain, chain);
03116         }       
03117         
03118         armature_tag_unselect(arm);
03119         
03120         BLI_freelistN(&chains);
03121     }
03122     
03123     /* updates */
03124     ED_armature_sync_selection(arm->edbo);
03125     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, obedit);
03126     
03127     return OPERATOR_FINISHED;
03128 }
03129 
03130 void ARMATURE_OT_merge (wmOperatorType *ot)
03131 {
03132     static EnumPropertyItem merge_types[] = {
03133         {1, "WITHIN_CHAIN", 0, "Within Chains", ""},
03134         {0, NULL, 0, NULL, NULL}
03135     };
03136 
03137     /* identifiers */
03138     ot->name= "Merge Bones";
03139     ot->idname= "ARMATURE_OT_merge";
03140     ot->description= "Merge continuous chains of selected bones";
03141     
03142     /* callbacks */
03143     ot->invoke= WM_menu_invoke;
03144     ot->exec= armature_merge_exec;
03145     ot->poll= ED_operator_editarmature;
03146     
03147     /* flags */
03148     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03149     
03150     /* properties */
03151     ot->prop= RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", "");
03152 }
03153 
03154 /* ************** END Add/Remove stuff in editmode ************ */
03155 /* *************** Tools in editmode *********** */
03156 
03157 static int armature_hide_exec(bContext *C, wmOperator *op)
03158 {
03159     Object *obedit= CTX_data_edit_object(C);
03160     bArmature *arm= obedit->data;
03161     EditBone *ebone;
03162     const int invert= RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0;
03163 
03164     /* cancel if nothing selected */
03165     if (CTX_DATA_COUNT(C, selected_bones) == 0)
03166         return OPERATOR_CANCELLED;
03167 
03168     for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
03169         if (EBONE_VISIBLE(arm, ebone)) {
03170             if ((ebone->flag & BONE_SELECTED) != invert) {
03171                 ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
03172                 ebone->flag |= BONE_HIDDEN_A;
03173             }
03174         }
03175     }
03176     ED_armature_validate_active(arm);
03177     ED_armature_sync_selection(arm->edbo);
03178 
03179     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
03180 
03181     return OPERATOR_FINISHED;
03182 }
03183 
03184 void ARMATURE_OT_hide(wmOperatorType *ot)
03185 {
03186     /* identifiers */
03187     ot->name= "Hide Selected Bones";
03188     ot->idname= "ARMATURE_OT_hide";
03189     ot->description= "Tag selected bones to not be visible in Edit Mode";
03190     
03191     /* api callbacks */
03192     ot->exec= armature_hide_exec;
03193     ot->poll= ED_operator_editarmature;
03194     
03195     /* flags */
03196     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03197 
03198     /* props */
03199     RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
03200 }
03201 
03202 static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
03203 {
03204     Object *obedit= CTX_data_edit_object(C);
03205     bArmature *arm= obedit->data;
03206     EditBone *ebone;
03207     
03208     for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
03209         if(arm->layer & ebone->layer) {
03210             if (ebone->flag & BONE_HIDDEN_A) {
03211                 ebone->flag |= (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
03212                 ebone->flag &= ~BONE_HIDDEN_A;
03213             }
03214         }
03215     }
03216     ED_armature_validate_active(arm);
03217     ED_armature_sync_selection(arm->edbo);
03218 
03219     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
03220 
03221     return OPERATOR_FINISHED;
03222 }
03223 
03224 void ARMATURE_OT_reveal(wmOperatorType *ot)
03225 {
03226     /* identifiers */
03227     ot->name= "Reveal Bones";
03228     ot->idname= "ARMATURE_OT_reveal";
03229     ot->description= "Unhide all bones that have been tagged to be hidden in Edit Mode";
03230     
03231     /* api callbacks */
03232     ot->exec= armature_reveal_exec;
03233     ot->poll= ED_operator_editarmature;
03234     
03235     /* flags */
03236     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03237 
03238 }
03239 #if 0 // remove this?
03240 static void hide_selected_armature_bones(Scene *scene)
03241 {
03242     Object *obedit= scene->obedit; // XXX get from context
03243     bArmature *arm= obedit->data;
03244     EditBone *ebone;
03245     
03246     for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
03247         if (EBONE_VISIBLE(arm, ebone)) {
03248             if (ebone->flag & BONE_SELECTED) {
03249                 ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
03250                 ebone->flag |= BONE_HIDDEN_A;
03251             }
03252         }
03253     }
03254     ED_armature_validate_active(arm);
03255     ED_armature_sync_selection(arm->edbo);
03256 }
03257 
03258 static void hide_unselected_armature_bones(Scene *scene)
03259 {
03260     Object *obedit= scene->obedit; // XXX get from context
03261     bArmature *arm= obedit->data;
03262     EditBone *ebone;
03263     
03264     for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
03265         bArmature *arm= obedit->data;
03266         if (EBONE_VISIBLE(arm, ebone)) {
03267             if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL));
03268             else {
03269                 ebone->flag |= BONE_HIDDEN_A;
03270             }
03271         }
03272     }
03273 
03274     ED_armature_validate_active(arm);
03275     ED_armature_sync_selection(arm->edbo);
03276 }
03277 
03278 void show_all_armature_bones(Scene *scene)
03279 {
03280     Object *obedit= scene->obedit; // XXX get from context
03281     bArmature *arm= obedit->data;
03282     EditBone *ebone;
03283     
03284     for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
03285         if(arm->layer & ebone->layer) {
03286             if (ebone->flag & BONE_HIDDEN_A) {
03287                 ebone->flag |= (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
03288                 ebone->flag &= ~BONE_HIDDEN_A;
03289             }
03290         }
03291     }
03292     ED_armature_validate_active(arm);
03293     ED_armature_sync_selection(arm->edbo);
03294 }
03295 #endif
03296 
03297 /* previously extrude_armature */
03298 /* context; editmode armature */
03299 /* if forked && mirror-edit: makes two bones with flipped names */
03300 static int armature_extrude_exec(bContext *C, wmOperator *op)
03301 {
03302     Object *obedit;
03303     bArmature *arm;
03304     EditBone *newbone, *ebone, *flipbone, *first=NULL;
03305     int a, totbone= 0, do_extrude;
03306     int forked = RNA_boolean_get(op->ptr, "forked");
03307 
03308     obedit= CTX_data_edit_object(C);
03309     arm= obedit->data;
03310 
03311     /* since we allow root extrude too, we have to make sure selection is OK */
03312     for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
03313         if (EBONE_VISIBLE(arm, ebone)) {
03314             if (ebone->flag & BONE_ROOTSEL) {
03315                 if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
03316                     if (ebone->parent->flag & BONE_TIPSEL)
03317                         ebone->flag &= ~BONE_ROOTSEL;
03318                 }
03319             }
03320         }
03321     }
03322     
03323     /* Duplicate the necessary bones */
03324     for (ebone = arm->edbo->first; ((ebone) && (ebone!=first)); ebone=ebone->next) {
03325         if (EBONE_VISIBLE(arm, ebone)) {
03326             /* we extrude per definition the tip */
03327             do_extrude= 0;
03328             if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED))
03329                 do_extrude= 1;
03330             else if (ebone->flag & BONE_ROOTSEL) {
03331                 /* but, a bone with parent deselected we do the root... */
03332                 if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL));
03333                 else do_extrude= 2;
03334             }
03335             
03336             if (do_extrude) {
03337                 /* we re-use code for mirror editing... */
03338                 flipbone= NULL;
03339                 if (arm->flag & ARM_MIRROR_EDIT) {
03340                     flipbone= ED_armature_bone_get_mirrored(arm->edbo, ebone);
03341                     if (flipbone) {
03342                         forked= 0;  // we extrude 2 different bones
03343                         if (flipbone->flag & (BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED))
03344                             /* don't want this bone to be selected... */
03345                             flipbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
03346                     }
03347                     if ((flipbone==NULL) && (forked))
03348                         flipbone= ebone;
03349                 }
03350                 
03351                 for (a=0; a<2; a++) {
03352                     if (a==1) {
03353                         if (flipbone==NULL)
03354                             break;
03355                         else {
03356                             SWAP(EditBone *, flipbone, ebone);
03357                         }
03358                     }
03359                     
03360                     totbone++;
03361                     newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
03362                     
03363                     if (do_extrude==1) {
03364                         copy_v3_v3(newbone->head, ebone->tail);
03365                         copy_v3_v3(newbone->tail, newbone->head);
03366                         newbone->parent = ebone;
03367                         
03368                         newbone->flag = ebone->flag & BONE_TIPSEL;  // copies it, in case mirrored bone
03369                         
03370                         if (newbone->parent) newbone->flag |= BONE_CONNECTED;
03371                     }
03372                     else {
03373                         copy_v3_v3(newbone->head, ebone->head);
03374                         copy_v3_v3(newbone->tail, ebone->head);
03375                         newbone->parent= ebone->parent;
03376                         
03377                         newbone->flag= BONE_TIPSEL;
03378                         
03379                         if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
03380                             newbone->flag |= BONE_CONNECTED;
03381                         }
03382                     }
03383                     
03384                     newbone->weight= ebone->weight;
03385                     newbone->dist= ebone->dist;
03386                     newbone->xwidth= ebone->xwidth;
03387                     newbone->zwidth= ebone->zwidth;
03388                     newbone->ease1= ebone->ease1;
03389                     newbone->ease2= ebone->ease2;
03390                     newbone->rad_head= ebone->rad_tail; // dont copy entire bone...
03391                     newbone->rad_tail= ebone->rad_tail;
03392                     newbone->segments= 1;
03393                     newbone->layer= ebone->layer;
03394                     
03395                     BLI_strncpy (newbone->name, ebone->name, sizeof(newbone->name));
03396                     
03397                     if (flipbone && forked) {   // only set if mirror edit
03398                         if (strlen(newbone->name)<30) {
03399                             if (a==0) strcat(newbone->name, "_L");
03400                             else strcat(newbone->name, "_R");
03401                         }
03402                     }
03403                     unique_editbone_name(arm->edbo, newbone->name, NULL);
03404                     
03405                     /* Add the new bone to the list */
03406                     BLI_addtail(arm->edbo, newbone);
03407                     if (!first)
03408                         first = newbone;
03409                     
03410                     /* restore ebone if we were flipping */
03411                     if (a==1 && flipbone) 
03412                         SWAP(EditBone *, flipbone, ebone);
03413                 }
03414             }
03415             
03416             /* Deselect the old bone */
03417             ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
03418         }       
03419     }
03420     /* if only one bone, make this one active */
03421     if (totbone==1 && first) arm->act_edbone= first;
03422 
03423     if (totbone==0) return OPERATOR_CANCELLED;
03424 
03425     /* Transform the endpoints */
03426     ED_armature_sync_selection(arm->edbo);
03427 
03428     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
03429 
03430     return OPERATOR_FINISHED;
03431 }
03432 
03433 void ARMATURE_OT_extrude(wmOperatorType *ot)
03434 {
03435     /* identifiers */
03436     ot->name= "Extrude";
03437     ot->idname= "ARMATURE_OT_extrude";
03438     ot->description= "Create new bones from the selected joints";
03439     
03440     /* api callbacks */
03441     ot->exec= armature_extrude_exec;
03442     ot->poll= ED_operator_editarmature;
03443     
03444     /* flags */
03445     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03446     
03447     /* props */
03448     RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
03449 }
03450 /* ********************** Bone Add ********************/
03451 
03452 /*op makes a new bone and returns it with its tip selected */
03453 
03454 static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) 
03455 {
03456     RegionView3D *rv3d= CTX_wm_region_view3d(C);
03457     Object *obedit = CTX_data_edit_object(C);
03458     EditBone *bone;
03459     float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
03460     char name[MAXBONENAME];
03461     
03462     RNA_string_get(op->ptr, "name", name);
03463     
03464     copy_v3_v3(curs, give_cursor(CTX_data_scene(C),CTX_wm_view3d(C)));  
03465 
03466     /* Get inverse point for head and orientation for tail */
03467     invert_m4_m4(obedit->imat, obedit->obmat);
03468     mul_m4_v3(obedit->imat, curs);
03469 
03470     if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
03471         copy_m3_m4(obmat, rv3d->viewmat);
03472     else unit_m3(obmat);
03473     
03474     copy_m3_m4(viewmat, obedit->obmat);
03475     mul_m3_m3m3(totmat, obmat, viewmat);
03476     invert_m3_m3(imat, totmat);
03477     
03478     ED_armature_deselect_all(obedit, 0);
03479     
03480     /*  Create a bone   */
03481     bone= ED_armature_edit_bone_add(obedit->data, name);
03482 
03483     copy_v3_v3(bone->head, curs);
03484     
03485     if(rv3d && (U.flag & USER_ADD_VIEWALIGNED))
03486         add_v3_v3v3(bone->tail, bone->head, imat[1]);   // bone with unit length 1
03487     else
03488         add_v3_v3v3(bone->tail, bone->head, imat[2]);   // bone with unit length 1, pointing up Z
03489 
03490     /* note, notifier might evolve */
03491     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
03492 
03493     return OPERATOR_FINISHED;
03494 }
03495 
03496 void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
03497 {
03498     /* identifiers */
03499     ot->name= "Add Bone";
03500     ot->idname= "ARMATURE_OT_bone_primitive_add";
03501     ot->description= "Add a new bone located at the 3D-Cursor";
03502     
03503     /* api callbacks */
03504     ot->exec = armature_bone_primitive_add_exec;
03505     ot->poll = ED_operator_editarmature;
03506     
03507     /* flags */
03508     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03509     
03510     RNA_def_string(ot->srna, "name", "Bone", MAXBONENAME, "Name", "Name of the newly created bone");
03511     
03512 }
03513 
03514 
03515 /* ----------- */
03516 
03517 /* Subdivide Operators:
03518  * This group of operators all use the same 'exec' callback, but they are called
03519  * through several different operators - a combined menu (which just calls the exec in the 
03520  * appropriate ways), and two separate ones.
03521  */
03522 
03523 static int armature_subdivide_exec(bContext *C, wmOperator *op)
03524 {
03525     Object *obedit= CTX_data_edit_object(C);
03526     bArmature *arm= obedit->data;
03527     EditBone *newbone, *tbone;
03528     int numcuts, i;
03529     
03530     /* there may not be a number_cuts property defined (for 'simple' subdivide) */
03531     numcuts= RNA_int_get(op->ptr, "number_cuts");
03532     
03533     /* loop over all editable bones */
03534     // XXX the old code did this in reverse order though!
03535     CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) 
03536     {
03537         for (i=numcuts+1; i>1; i--) {
03538             /* compute cut ratio first */
03539             float cutratio= 1.0f / (float)i;
03540             float cutratioI= 1.0f - cutratio;
03541             
03542             float val1[3];
03543             float val2[3];
03544             float val3[3];
03545             
03546             newbone= MEM_mallocN(sizeof(EditBone), "ebone subdiv");
03547             *newbone = *ebone;
03548             BLI_addtail(arm->edbo, newbone);
03549             
03550             /* calculate location of newbone->head */
03551             copy_v3_v3(val1, ebone->head);
03552             copy_v3_v3(val2, ebone->tail);
03553             copy_v3_v3(val3, newbone->head);
03554             
03555             val3[0]= val1[0]*cutratio + val2[0]*cutratioI;
03556             val3[1]= val1[1]*cutratio + val2[1]*cutratioI;
03557             val3[2]= val1[2]*cutratio + val2[2]*cutratioI;
03558             
03559             copy_v3_v3(newbone->head, val3);
03560             copy_v3_v3(newbone->tail, ebone->tail);
03561             copy_v3_v3(ebone->tail, newbone->head);
03562             
03563             newbone->rad_head= 0.5f * (ebone->rad_head + ebone->rad_tail);
03564             ebone->rad_tail= newbone->rad_head;
03565             
03566             newbone->flag |= BONE_CONNECTED;
03567             
03568             unique_editbone_name(arm->edbo, newbone->name, NULL);
03569             
03570             /* correct parent bones */
03571             for (tbone = arm->edbo->first; tbone; tbone=tbone->next) {
03572                 if (tbone->parent==ebone)
03573                     tbone->parent= newbone;
03574             }
03575             newbone->parent= ebone;
03576         }
03577     }
03578     CTX_DATA_END;
03579     
03580     /* note, notifier might evolve */
03581     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
03582     
03583     return OPERATOR_FINISHED;
03584 }
03585 
03586 void ARMATURE_OT_subdivide(wmOperatorType *ot)
03587 {
03588     /* identifiers */
03589     ot->name= "Subdivide Multi";
03590     ot->idname= "ARMATURE_OT_subdivide";
03591     ot->description= "Break selected bones into chains of smaller bones";
03592     
03593     /* api callbacks */
03594     ot->exec = armature_subdivide_exec;
03595     ot->poll = ED_operator_editarmature;
03596     
03597     /* flags */
03598     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03599     
03600     /* Properties */
03601     RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
03602 }
03603 
03604 /* ----------- */
03605 
03606 /* Switch Direction operator:
03607  * Currently, this does not use context loops, as context loops do not make it
03608  * easy to retrieve any hierarchial/chain relationships which are necessary for
03609  * this to be done easily.
03610  */
03611 
03612 static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) 
03613 {
03614     Object *ob= CTX_data_edit_object(C);
03615     bArmature *arm= (bArmature *)ob->data;
03616     ListBase chains = {NULL, NULL};
03617     LinkData *chain;
03618     
03619     /* get chains of bones (ends on chains) */
03620     chains_find_tips(arm->edbo, &chains);
03621     if (chains.first == NULL) return OPERATOR_CANCELLED;
03622 
03623     armature_tag_select_mirrored(arm);
03624 
03625     /* loop over chains, only considering selected and visible bones */
03626     for (chain= chains.first; chain; chain= chain->next) {
03627         EditBone *ebo, *child=NULL, *parent=NULL;
03628         
03629         /* loop over bones in chain */
03630         for (ebo= chain->data; ebo; ebo= parent) {
03631             /* parent is this bone's original parent
03632              *  - we store this, as the next bone that is checked is this one
03633              *    but the value of ebo->parent may change here...
03634              */
03635             parent= ebo->parent;
03636             
03637             /* only if selected and editable */
03638             if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {               
03639                 /* swap head and tail coordinates */
03640                 SWAP(float, ebo->head[0], ebo->tail[0]);
03641                 SWAP(float, ebo->head[1], ebo->tail[1]);
03642                 SWAP(float, ebo->head[2], ebo->tail[2]);
03643                 
03644                 /* do parent swapping:
03645                  *  - use 'child' as new parent
03646                  *  - connected flag is only set if points are coincidental
03647                  */
03648                 ebo->parent= child;
03649                 if ((child) && equals_v3v3(ebo->head, child->tail))
03650                     ebo->flag |= BONE_CONNECTED;
03651                 else    
03652                     ebo->flag &= ~BONE_CONNECTED;
03653                 
03654                 /* get next bones 
03655                  *  - child will become the new parent of next bone
03656                  */
03657                 child= ebo;
03658             }
03659             else {
03660                 /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it 
03661                  * as it will be facing in opposite direction
03662                  */
03663                 if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
03664                     ebo->parent= NULL;
03665                     ebo->flag &= ~BONE_CONNECTED;
03666                 }
03667                 
03668                 /* get next bones
03669                  *  - child will become new parent of next bone (not swapping occurred, 
03670                  *    so set to NULL to prevent infinite-loop)
03671                  */
03672                 child= NULL;
03673             }
03674         }
03675     }
03676     
03677     /* free chains */
03678     BLI_freelistN(&chains); 
03679 
03680     armature_tag_unselect(arm);
03681 
03682     /* note, notifier might evolve */
03683     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
03684     
03685     return OPERATOR_FINISHED;
03686 }
03687 
03688 void ARMATURE_OT_switch_direction(wmOperatorType *ot)
03689 {
03690     /* identifiers */
03691     ot->name= "Switch Direction";
03692     ot->idname= "ARMATURE_OT_switch_direction";
03693     ot->description= "Change the direction that a chain of bones points in (head <-> tail swap)";
03694     
03695     /* api callbacks */
03696     ot->exec = armature_switch_direction_exec;
03697     ot->poll = ED_operator_editarmature;
03698     
03699     /* flags */
03700     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03701 }
03702 /* ***************** Parenting *********************** */
03703 
03704 /* armature parenting options */
03705 #define ARM_PAR_CONNECT 1
03706 #define ARM_PAR_OFFSET  2
03707 
03708 /* check for null, before calling! */
03709 static void bone_connect_to_existing_parent(EditBone *bone)
03710 {
03711     bone->flag |= BONE_CONNECTED;
03712     copy_v3_v3(bone->head, bone->parent->tail);
03713     bone->rad_head = bone->parent->rad_tail;
03714 }
03715 
03716 static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode)
03717 {
03718     EditBone *ebone;
03719     float offset[3];
03720     
03721     if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
03722         selbone->parent->flag &= ~(BONE_TIPSEL);
03723     
03724     /* make actbone the parent of selbone */
03725     selbone->parent= actbone;
03726     
03727     /* in actbone tree we cannot have a loop */
03728     for (ebone= actbone->parent; ebone; ebone= ebone->parent) {
03729         if (ebone->parent==selbone) {
03730             ebone->parent= NULL;
03731             ebone->flag &= ~BONE_CONNECTED;
03732         }
03733     }
03734     
03735     if (mode == ARM_PAR_CONNECT) {  
03736         /* Connected: Child bones will be moved to the parent tip */
03737         selbone->flag |= BONE_CONNECTED;
03738         sub_v3_v3v3(offset, actbone->tail, selbone->head);
03739         
03740         copy_v3_v3(selbone->head, actbone->tail);
03741         selbone->rad_head= actbone->rad_tail;
03742         
03743         add_v3_v3(selbone->tail, offset);
03744         
03745         /* offset for all its children */
03746         for (ebone = edbo->first; ebone; ebone=ebone->next) {
03747             EditBone *par;
03748             
03749             for (par= ebone->parent; par; par= par->parent) {
03750                 if (par==selbone) {
03751                     add_v3_v3(ebone->head, offset);
03752                     add_v3_v3(ebone->tail, offset);
03753                     break;
03754                 }
03755             }
03756         }
03757     }
03758     else {
03759         /* Offset: Child bones will retain their distance from the parent tip */
03760         selbone->flag &= ~BONE_CONNECTED;
03761     }
03762 }
03763 
03764 static EnumPropertyItem prop_editarm_make_parent_types[] = {
03765     {ARM_PAR_CONNECT, "CONNECTED", 0, "Connected", ""},
03766     {ARM_PAR_OFFSET, "OFFSET", 0, "Keep Offset", ""},
03767     {0, NULL, 0, NULL, NULL}
03768 };
03769 
03770 static int armature_parent_set_exec(bContext *C, wmOperator *op) 
03771 {
03772     Object *ob= CTX_data_edit_object(C);
03773     bArmature *arm= (bArmature *)ob->data;
03774     EditBone *actbone = CTX_data_active_bone(C);
03775     EditBone *actmirb = NULL;
03776     short val = RNA_enum_get(op->ptr, "type");
03777     
03778     /* there must be an active bone */
03779     if (actbone == NULL) {
03780         BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone");
03781         return OPERATOR_CANCELLED;
03782     }
03783     else if (arm->flag & ARM_MIRROR_EDIT) {
03784         /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
03785          * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
03786          *  (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
03787          *  This is useful for arm-chains, for example parenting lower arm to upper arm
03788          * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
03789          *  then just use actbone. Useful when doing upper arm to spine.
03790          */
03791         actmirb= ED_armature_bone_get_mirrored(arm->edbo, actbone);
03792         if (actmirb == NULL) 
03793             actmirb= actbone;
03794     }
03795     
03796     /* if there is only 1 selected bone, we assume that that is the active bone, 
03797      * since a user will need to have clicked on a bone (thus selecting it) to make it active
03798      */
03799     if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
03800         /* When only the active bone is selected, and it has a parent,
03801          * connect it to the parent, as that is the only possible outcome. 
03802          */
03803         if (actbone->parent) {
03804             bone_connect_to_existing_parent(actbone);
03805             
03806             if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
03807                 bone_connect_to_existing_parent(actmirb);
03808         }
03809     }
03810     else {
03811         /* Parent 'selected' bones to the active one
03812          * - the context iterator contains both selected bones and their mirrored copies,
03813          *   so we assume that unselected bones are mirrored copies of some selected bone
03814          * - since the active one (and/or its mirror) will also be selected, we also need 
03815          *  to check that we are not trying to opearate on them, since such an operation 
03816          *  would cause errors
03817          */
03818         
03819         /* parent selected bones to the active one */
03820         CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
03821             if (ELEM(ebone, actbone, actmirb) == 0) {
03822                 if (ebone->flag & BONE_SELECTED) 
03823                     bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
03824                 else
03825                     bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
03826             }
03827         }
03828         CTX_DATA_END;
03829     }
03830     
03831 
03832     /* note, notifier might evolve */
03833     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
03834     
03835     return OPERATOR_FINISHED;
03836 }
03837 
03838 static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
03839 {
03840     EditBone *actbone = CTX_data_active_bone(C);
03841     uiPopupMenu *pup= uiPupMenuBegin(C, "Make Parent ", ICON_NONE);
03842     uiLayout *layout= uiPupMenuLayout(pup);
03843     int allchildbones = 0;
03844     
03845     CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
03846         if (ebone != actbone) {
03847             if (ebone->parent != actbone) allchildbones= 1; 
03848         }   
03849     }
03850     CTX_DATA_END;
03851 
03852     uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
03853     
03854     /* ob becomes parent, make the associated menus */
03855     if (allchildbones)
03856         uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET); 
03857         
03858     uiPupMenuEnd(C, pup);
03859     
03860     return OPERATOR_CANCELLED;
03861 }
03862 
03863 void ARMATURE_OT_parent_set(wmOperatorType *ot)
03864 {
03865     /* identifiers */
03866     ot->name= "Make Parent";
03867     ot->idname= "ARMATURE_OT_parent_set";
03868     ot->description= "Set the active bone as the parent of the selected bones";
03869     
03870     /* api callbacks */
03871     ot->invoke = armature_parent_set_invoke;
03872     ot->exec = armature_parent_set_exec;
03873     ot->poll = ED_operator_editarmature;
03874     
03875     /* flags */
03876     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03877     
03878     RNA_def_enum(ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
03879 }
03880 
03881 static EnumPropertyItem prop_editarm_clear_parent_types[] = {
03882     {1, "CLEAR", 0, "Clear Parent", ""},
03883     {2, "DISCONNECT", 0, "Disconnect Bone", ""},
03884     {0, NULL, 0, NULL, NULL}
03885 };
03886 
03887 static void editbone_clear_parent(EditBone *ebone, int mode)
03888 {
03889     if (ebone->parent) {
03890         /* for nice selection */
03891         ebone->parent->flag &= ~(BONE_TIPSEL);
03892     }
03893     
03894     if (mode==1) ebone->parent= NULL;
03895     ebone->flag &= ~BONE_CONNECTED;
03896 }
03897 
03898 static int armature_parent_clear_exec(bContext *C, wmOperator *op) 
03899 {
03900     Object *ob= CTX_data_edit_object(C);
03901     bArmature *arm= (bArmature *)ob->data;
03902     int val = RNA_enum_get(op->ptr, "type");
03903         
03904     CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
03905         editbone_clear_parent(ebone, val);
03906     }
03907     CTX_DATA_END;
03908     
03909     ED_armature_sync_selection(arm->edbo);
03910 
03911     /* note, notifier might evolve */
03912     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
03913     
03914     return OPERATOR_FINISHED;
03915 }
03916 
03917 void ARMATURE_OT_parent_clear(wmOperatorType *ot)
03918 {
03919     /* identifiers */
03920     ot->name= "Clear Parent";
03921     ot->idname= "ARMATURE_OT_parent_clear";
03922     ot->description= "Remove the parent-child relationship between selected bones and their parents";
03923     
03924     /* api callbacks */
03925     ot->invoke = WM_menu_invoke;
03926     ot->exec = armature_parent_clear_exec;
03927     ot->poll = ED_operator_editarmature;
03928     
03929     /* flags */
03930     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03931     
03932     ot->prop= RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
03933 }
03934 
03935 /* ****************  Selections  ******************/
03936 
03937 static int armature_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
03938 {
03939     /*  Set the flags */
03940     CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
03941         /* ignore bone if selection can't change */
03942         if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
03943             /* select bone */
03944             ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
03945         }
03946     }
03947     CTX_DATA_END;   
03948 
03949     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
03950     
03951     return OPERATOR_FINISHED;
03952 }
03953 
03954 void ARMATURE_OT_select_inverse(wmOperatorType *ot)
03955 {
03956     /* identifiers */
03957     ot->name= "Select Inverse";
03958     ot->idname= "ARMATURE_OT_select_inverse";
03959     ot->description= "Flip the selection status of bones (selected -> unselected, unselected -> selected)";
03960     
03961     /* api callbacks */
03962     ot->exec= armature_select_inverse_exec;
03963     ot->poll= ED_operator_editarmature;
03964     
03965     /* flags */
03966     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
03967     
03968 }
03969 static int armature_de_select_all_exec(bContext *C, wmOperator *op)
03970 {
03971     int action = RNA_enum_get(op->ptr, "action");
03972 
03973     if (action == SEL_TOGGLE) {
03974         action = SEL_SELECT;
03975         /*  Determine if there are any selected bones
03976         And therefore whether we are selecting or deselecting */
03977         if (CTX_DATA_COUNT(C, selected_bones) > 0)
03978             action = SEL_DESELECT;
03979     }
03980     
03981     /*  Set the flags */
03982     CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
03983         /* ignore bone if selection can't change */
03984         if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
03985             switch (action) {
03986             case SEL_SELECT:
03987                 ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
03988                 if(ebone->parent)
03989                     ebone->parent->flag |= (BONE_TIPSEL);
03990                 break;
03991             case SEL_DESELECT:
03992                 ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
03993                 break;
03994             case SEL_INVERT:
03995                 if (ebone->flag & BONE_SELECTED) {
03996                     ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
03997                 } 
03998                 else {
03999                     ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
04000                     if(ebone->parent)
04001                         ebone->parent->flag |= (BONE_TIPSEL);
04002                 }
04003                 break;
04004             }
04005         }
04006     }
04007     CTX_DATA_END;   
04008 
04009     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
04010     
04011     return OPERATOR_FINISHED;
04012 }
04013 
04014 void ARMATURE_OT_select_all(wmOperatorType *ot)
04015 {
04016     /* identifiers */
04017     ot->name= "Select or Deselect All";
04018     ot->idname= "ARMATURE_OT_select_all";
04019     ot->description= "Toggle selection status of all bones";
04020     
04021     /* api callbacks */
04022     ot->exec= armature_de_select_all_exec;
04023     ot->poll= ED_operator_editarmature;
04024     
04025     /* flags */
04026     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
04027     
04028     WM_operator_properties_select_all(ot);
04029 }
04030 
04031 /* ********************* select hierarchy operator ************** */
04032 
04033 static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
04034 {
04035     Object *obedit= CTX_data_edit_object(C);
04036     Object *ob;
04037     bArmature *arm;
04038     EditBone *curbone, *pabone, *chbone;
04039     int direction = RNA_enum_get(op->ptr, "direction");
04040     int add_to_sel = RNA_boolean_get(op->ptr, "extend");
04041     
04042     ob= obedit;
04043     arm= (bArmature *)ob->data;
04044     
04045     for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
04046         /* only work on bone if it is visible and its selection can change */
04047         if (EBONE_VISIBLE(arm, curbone) && (curbone->flag & BONE_UNSELECTABLE)==0) {
04048             if (curbone == arm->act_edbone) {
04049                 if (direction == BONE_SELECT_PARENT) {
04050                     if (curbone->parent == NULL) continue;
04051                     else pabone = curbone->parent;
04052                     
04053                     if (EBONE_VISIBLE(arm, pabone)) {
04054                         pabone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
04055                         arm->act_edbone= pabone;
04056                         if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL;
04057                         
04058                         if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
04059                         break;
04060                     }
04061                     
04062                 } 
04063                 else { // BONE_SELECT_CHILD
04064                     chbone = editbone_get_child(arm, curbone, 1);
04065                     if (chbone == NULL) continue;
04066                     
04067                     if (EBONE_VISIBLE(arm, chbone) && (chbone->flag & BONE_UNSELECTABLE)==0) {
04068                         chbone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
04069                         arm->act_edbone= chbone;
04070                         
04071                         if (!add_to_sel) {
04072                             curbone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL);
04073                             if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL;
04074                         }
04075                         break;
04076                     }
04077                 }
04078             }
04079         }
04080     }
04081     
04082     ED_armature_sync_selection(arm->edbo);
04083     
04084     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
04085     
04086     return OPERATOR_FINISHED;
04087 }
04088 
04089 void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
04090 {
04091     static EnumPropertyItem direction_items[]= {
04092     {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
04093     {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
04094     {0, NULL, 0, NULL, NULL}
04095     };
04096     
04097     /* identifiers */
04098     ot->name= "Select Hierarchy";
04099     ot->idname= "ARMATURE_OT_select_hierarchy";
04100     ot->description= "Select immediate parent/children of selected bones";
04101     
04102     /* api callbacks */
04103     ot->exec= armature_select_hierarchy_exec;
04104     ot->poll= ED_operator_editarmature;
04105     
04106     /* flags */
04107     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
04108 
04109     /* props */
04110     RNA_def_enum(ot->srna, "direction", direction_items,
04111                  BONE_SELECT_PARENT, "Direction", "");
04112     RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
04113 }
04114 
04115 /* ***************** EditBone Alignment ********************* */
04116 
04117 /* helper to fix a ebone position if its parent has moved due to alignment*/
04118 static void fix_connected_bone(EditBone *ebone)
04119 {
04120     float diff[3];
04121     
04122     if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || equals_v3v3(ebone->parent->tail, ebone->head))
04123         return;
04124     
04125     /* if the parent has moved we translate child's head and tail accordingly*/
04126     sub_v3_v3v3(diff, ebone->parent->tail, ebone->head);
04127     add_v3_v3(ebone->head, diff);
04128     add_v3_v3(ebone->tail, diff);
04129     return;
04130 }
04131 
04132 /* helper to recursively find chains of connected bones starting at ebone and fix their position */
04133 static void fix_editbone_connected_children(ListBase *edbo, EditBone *ebone)
04134 {
04135     EditBone *selbone;
04136     
04137     for (selbone = edbo->first; selbone; selbone=selbone->next) {
04138         if ((selbone->parent) && (selbone->parent == ebone) && (selbone->flag & BONE_CONNECTED)) {
04139             fix_connected_bone(selbone);
04140             fix_editbone_connected_children(edbo, selbone);
04141         }
04142     }
04143     return;
04144 }           
04145 
04146 static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
04147 {
04148     float selboneaxis[3], actboneaxis[3], length;
04149 
04150     sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head);
04151     normalize_v3(actboneaxis);
04152 
04153     sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head);
04154     length =  len_v3(selboneaxis);
04155 
04156     mul_v3_fl(actboneaxis, length);
04157     add_v3_v3v3(selbone->tail, selbone->head, actboneaxis);
04158     selbone->roll = actbone->roll;
04159     
04160     /* if the bone being aligned has connected descendants they must be moved
04161     according to their parent new position, otherwise they would be left
04162     in an unconsistent state: connected but away from the parent*/
04163     fix_editbone_connected_children(edbo, selbone);
04164     return;
04165 }
04166 
04167 static int armature_align_bones_exec(bContext *C, wmOperator *op) 
04168 {
04169     Object *ob= CTX_data_edit_object(C);
04170     bArmature *arm= (bArmature *)ob->data;
04171     EditBone *actbone= CTX_data_active_bone(C);
04172     EditBone *actmirb= NULL;
04173     
04174     /* there must be an active bone */
04175     if (actbone == NULL) {
04176         BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone");
04177         return OPERATOR_CANCELLED;
04178     }
04179     else if (arm->flag & ARM_MIRROR_EDIT) {
04180         /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
04181          * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
04182          *  (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
04183          *  This is useful for arm-chains, for example parenting lower arm to upper arm
04184          * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
04185          *  then just use actbone. Useful when doing upper arm to spine.
04186          */
04187         actmirb= ED_armature_bone_get_mirrored(arm->edbo, actbone);
04188         if (actmirb == NULL) 
04189             actmirb= actbone;
04190     }
04191     
04192     /* if there is only 1 selected bone, we assume that that is the active bone, 
04193      * since a user will need to have clicked on a bone (thus selecting it) to make it active
04194      */
04195     if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
04196         /* When only the active bone is selected, and it has a parent,
04197          * align it to the parent, as that is the only possible outcome. 
04198          */
04199         if (actbone->parent) {
04200             bone_align_to_bone(arm->edbo, actbone, actbone->parent);
04201             
04202             if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
04203                 bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
04204         }
04205     }
04206     else {
04207         /* Align 'selected' bones to the active one
04208          * - the context iterator contains both selected bones and their mirrored copies,
04209          *   so we assume that unselected bones are mirrored copies of some selected bone
04210          * - since the active one (and/or its mirror) will also be selected, we also need 
04211          *  to check that we are not trying to opearate on them, since such an operation 
04212          *  would cause errors
04213          */
04214         
04215         /* align selected bones to the active one */
04216         CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
04217             if (ELEM(ebone, actbone, actmirb) == 0) {
04218                 if (ebone->flag & BONE_SELECTED)
04219                     bone_align_to_bone(arm->edbo, ebone, actbone);
04220                 else
04221                     bone_align_to_bone(arm->edbo, ebone, actmirb);
04222             }
04223         }
04224         CTX_DATA_END;
04225     }
04226     
04227 
04228     /* note, notifier might evolve */
04229     WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
04230     
04231     return OPERATOR_FINISHED;
04232 }
04233 
04234 void ARMATURE_OT_align(wmOperatorType *ot)
04235 {
04236     /* identifiers */
04237     ot->name= "Align Bones";
04238     ot->idname= "ARMATURE_OT_align";
04239     ot->description= "Align selected bones to the active bone (or to their parent)";
04240     
04241     /* api callbacks */
04242     ot->invoke = WM_operator_confirm;
04243     ot->exec = armature_align_bones_exec;
04244     ot->poll = ED_operator_editarmature;
04245     
04246     /* flags */
04247     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
04248 }
04249 
04250 /* ***************** Pose tools ********************* */
04251 
04252 // XXX bone_looper is only to be used when we want to access settings (i.e. editability/visibility/selected) that context doesn't offer 
04253 static int bone_looper(Object *ob, Bone *bone, void *data,
04254                 int (*bone_func)(Object *, Bone *, void *)) 
04255 {
04256     /* We want to apply the function bone_func to every bone 
04257     * in an armature -- feed bone_looper the first bone and 
04258     * a pointer to the bone_func and watch it go!. The int count 
04259     * can be useful for counting bones with a certain property
04260     * (e.g. skinnable)
04261     */
04262     int count = 0;
04263     
04264     if (bone) {
04265         /* only do bone_func if the bone is non null */
04266         count += bone_func(ob, bone, data);
04267         
04268         /* try to execute bone_func for the first child */
04269         count += bone_looper(ob, bone->childbase.first, data, bone_func);
04270         
04271         /* try to execute bone_func for the next bone at this
04272             * depth of the recursion.
04273             */
04274         count += bone_looper(ob, bone->next, data, bone_func);
04275     }
04276     
04277     return count;
04278 }
04279 
04280 /* called from editview.c, for mode-less pose selection */
04281 /* assumes scene obact and basact is still on old situation */
04282 int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short extend)
04283 {
04284     Object *ob= base->object;
04285     Bone *nearBone;
04286     
04287     if (!ob || !ob->pose) return 0;
04288 
04289     nearBone= get_bone_from_selectbuffer(scene, base, buffer, hits, 1);
04290     
04291     /* if the bone cannot be affected, don't do anything */
04292     if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
04293         Object *ob_act= OBACT;
04294         bArmature *arm= ob->data;
04295         
04296         /* since we do unified select, we don't shift+select a bone if the
04297          * armature object was not active yet.
04298          * note, special exception for armature mode so we can do multi-select
04299          * we could check for multi-select explicitly but think its fine to
04300          * always give pradictable behavior in weight paint mode - campbell */
04301         if (!extend || ((ob_act && (ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT)==0))) {
04302             ED_pose_deselectall(ob, 0);
04303             nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
04304             arm->act_bone= nearBone;
04305             
04306                 // XXX old cruft! use notifiers instead
04307             //select_actionchannel_by_name(ob->action, nearBone->name, 1);
04308         }
04309         else {
04310             if (nearBone->flag & BONE_SELECTED) {
04311                 /* if not active, we make it active */
04312                 if(nearBone != arm->act_bone) {
04313                     arm->act_bone= nearBone;
04314                 }
04315                 else {
04316                     nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
04317                     
04318                         // XXX old cruft! use notifiers instead
04319                     //select_actionchannel_by_name(ob->action, nearBone->name, 0);
04320                 }
04321             }
04322             else {
04323                 nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
04324                 arm->act_bone= nearBone;
04325                 
04326                     // XXX old cruft! use notifiers instead
04327                 //select_actionchannel_by_name(ob->action, nearBone->name, 1);
04328             }
04329         }
04330         
04331         /* in weightpaint we select the associated vertex group too */
04332         if (ob_act && ob_act->mode & OB_MODE_WEIGHT_PAINT) {
04333             if (nearBone == arm->act_bone) {
04334                 ED_vgroup_select_by_name(OBACT, nearBone->name);
04335                 DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
04336             }
04337         }
04338         
04339     }
04340     
04341     return nearBone!=NULL;
04342 }
04343 
04344 /* test==0: deselect all
04345    test==1: swap select (apply to all the opposite of current situation) 
04346    test==2: only clear active tag
04347    test==3: swap select (no test / inverse selection status of all independently)
04348 */
04349 void ED_pose_deselectall (Object *ob, int test)
04350 {
04351     bArmature *arm= ob->data;
04352     bPoseChannel *pchan;
04353     int selectmode= 0;
04354     
04355     /* we call this from outliner too */
04356     if (ELEM(NULL, ob, ob->pose)) return;
04357     
04358     /*  Determine if we're selecting or deselecting */
04359     if (test==1) {
04360         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
04361             if (PBONE_VISIBLE(arm, pchan->bone)) {
04362                 if (pchan->bone->flag & BONE_SELECTED)
04363                     break;
04364             }
04365         }
04366         
04367         if (pchan == NULL)
04368             selectmode= 1;
04369     }
04370     else if (test == 2)
04371         selectmode= 2;
04372     
04373     /*  Set the flags accordingly   */
04374     for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
04375         /* ignore the pchan if it isn't visible or if its selection cannot be changed */
04376         if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & (BONE_HIDDEN_P|BONE_UNSELECTABLE))) {
04377             if (test==3) {
04378                 pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
04379             }
04380             else {
04381                 if (selectmode==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
04382                 else if (selectmode==1) pchan->bone->flag |= BONE_SELECTED;
04383             }
04384         }
04385     }
04386 }
04387 
04388 static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap)
04389 {
04390     /* Bones that are deforming
04391      * are regarded to be "skinnable" and are eligible for
04392      * auto-skinning.
04393      *
04394      * This function performs 2 functions:
04395      *
04396      *   a) It returns 1 if the bone is skinnable.
04397      *      If we loop over all bones with this 
04398      *      function, we can count the number of
04399      *      skinnable bones.
04400      *   b) If the pointer data is non null,
04401      *      it is treated like a handle to a
04402      *      bone pointer -- the bone pointer
04403      *      is set to point at this bone, and
04404      *      the pointer the handle points to
04405      *      is incremented to point to the
04406      *      next member of an array of pointers
04407      *      to bones. This way we can loop using
04408      *      this function to construct an array of
04409      *      pointers to bones that point to all
04410      *      skinnable bones.
04411      */
04412     Bone ***hbone;
04413     int a, segments;
04414     struct { Object *armob; void *list; int heat; } *data = datap;
04415 
04416     if(!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) {
04417         if (!(bone->flag & BONE_NO_DEFORM)) {
04418             if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
04419                 segments = bone->segments;
04420             else
04421                 segments = 1;
04422             
04423             if (data->list != NULL) {
04424                 hbone = (Bone ***) &data->list;
04425                 
04426                 for (a=0; a<segments; a++) {
04427                     **hbone = bone;
04428                     ++*hbone;
04429                 }
04430             }
04431             return segments;
04432         }
04433     }
04434     return 0;
04435 }
04436 
04437 static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)) 
04438 {
04439     /* This group creates a vertex group to ob that has the
04440       * same name as bone (provided the bone is skinnable). 
04441      * If such a vertex group aleady exist the routine exits.
04442       */
04443     if (!(bone->flag & BONE_NO_DEFORM)) {
04444         if (!defgroup_find_name(ob,bone->name)) {
04445             ED_vgroup_add_name(ob, bone->name);
04446             return 1;
04447         }
04448     }
04449     return 0;
04450 }
04451 
04452 static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap) 
04453 {
04454     /* Bones that are deforming
04455      * are regarded to be "skinnable" and are eligible for
04456      * auto-skinning.
04457      *
04458      * This function performs 2 functions:
04459      *
04460      *   a) If the bone is skinnable, it creates 
04461      *      a vertex group for ob that has
04462      *      the name of the skinnable bone
04463      *      (if one doesn't exist already).
04464      *   b) If the pointer data is non null,
04465      *      it is treated like a handle to a
04466      *      bDeformGroup pointer -- the 
04467      *      bDeformGroup pointer is set to point
04468      *      to the deform group with the bone's
04469      *      name, and the pointer the handle 
04470      *      points to is incremented to point to the
04471      *      next member of an array of pointers
04472      *      to bDeformGroups. This way we can loop using
04473      *      this function to construct an array of
04474      *      pointers to bDeformGroups, all with names
04475      *      of skinnable bones.
04476      */
04477     bDeformGroup ***hgroup, *defgroup= NULL;
04478     int a, segments;
04479     struct { Object *armob; void *list; int heat; } *data= datap;
04480     int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
04481     bArmature *arm= data->armob->data;
04482 
04483     if (!wpmode || !(bone->flag & BONE_HIDDEN_P)) {
04484        if (!(bone->flag & BONE_NO_DEFORM)) {
04485             if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
04486                 segments = bone->segments;
04487             else
04488                 segments = 1;
04489 
04490             if(!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED)))
04491                 if (!(defgroup = defgroup_find_name(ob, bone->name)))
04492                     defgroup = ED_vgroup_add_name(ob, bone->name);
04493             
04494             if (data->list != NULL) {
04495                 hgroup = (bDeformGroup ***) &data->list;
04496                 
04497                 for (a=0; a<segments; a++) {
04498                     **hgroup = defgroup;
04499                     ++*hgroup;
04500                 }
04501             }
04502             return segments;
04503         }
04504     }
04505     return 0;
04506 }
04507 
04508 static void add_vgroups__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
04509 {
04510     /* DerivedMesh mapFunc for getting final coords in weight paint mode */
04511 
04512     float (*verts)[3] = userData;
04513     copy_v3_v3(verts[index], co);
04514 }
04515 
04516 static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, float scale)
04517 {
04518     /* Create vertex group weights from envelopes */
04519 
04520     Bone *bone;
04521     bDeformGroup *dgroup;
04522     float distance;
04523     int i, iflip, j;
04524 
04525     /* for each vertex in the mesh */
04526     for (i=0; i < mesh->totvert; i++) {
04527         iflip = (dgroupflip)? mesh_get_x_mirror_vert(ob, i): 0;
04528         
04529         /* for each skinnable bone */
04530         for (j=0; j < numbones; ++j) {
04531             if (!selected[j])
04532                 continue;
04533             
04534             bone = bonelist[j];
04535             dgroup = dgrouplist[j];
04536             
04537             /* store the distance-factor from the vertex to the bone */
04538             distance = distfactor_to_bone (verts[i], root[j], tip[j],
04539                 bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
04540             
04541             /* add the vert to the deform group if weight!=0.0 */
04542             if (distance != 0.0f)
04543                 ED_vgroup_vert_add (ob, dgroup, i, distance, WEIGHT_REPLACE);
04544             else
04545                 ED_vgroup_vert_remove (ob, dgroup, i);
04546             
04547             /* do same for mirror */
04548             if (dgroupflip && dgroupflip[j] && iflip >= 0) {
04549                 if (distance != 0.0f)
04550                     ED_vgroup_vert_add (ob, dgroupflip[j], iflip, distance,
04551                         WEIGHT_REPLACE);
04552                 else
04553                     ED_vgroup_vert_remove (ob, dgroupflip[j], iflip);
04554             }
04555         }
04556     }
04557 }
04558 
04559 static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par, int heat, int mirror)
04560 {
04561     /* This functions implements the automatic computation of vertex group
04562      * weights, either through envelopes or using a heat equilibrium.
04563      *
04564      * This function can be called both when parenting a mesh to an armature,
04565      * or in weightpaint + posemode. In the latter case selection is taken
04566      * into account and vertex weights can be mirrored.
04567      *
04568      * The mesh vertex positions used are either the final deformed coords
04569      * from the derivedmesh in weightpaint mode, the final subsurf coords
04570      * when parenting, or simply the original mesh coords.
04571      */
04572 
04573     bArmature *arm= par->data;
04574     Bone **bonelist, *bone;
04575     bDeformGroup **dgrouplist, **dgroupflip;
04576     bDeformGroup *dgroup;
04577     bPoseChannel *pchan;
04578     Mesh *mesh;
04579     Mat4 *bbone = NULL;
04580     float (*root)[3], (*tip)[3], (*verts)[3];
04581     int *selected;
04582     int numbones, vertsfilled = 0, i, j, segments = 0;
04583     int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
04584     struct { Object *armob; void *list; int heat; } looper_data;
04585 
04586     looper_data.armob = par;
04587     looper_data.heat= heat;
04588     looper_data.list= NULL;
04589 
04590     /* count the number of skinnable bones */
04591     numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
04592     
04593     if (numbones == 0)
04594         return;
04595     
04596     /* create an array of pointer to bones that are skinnable
04597      * and fill it with all of the skinnable bones */
04598     bonelist = MEM_callocN(numbones*sizeof(Bone *), "bonelist");
04599     looper_data.list= bonelist;
04600     bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
04601 
04602     /* create an array of pointers to the deform groups that
04603      * coorespond to the skinnable bones (creating them
04604      * as necessary. */
04605     dgrouplist = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgrouplist");
04606     dgroupflip = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgroupflip");
04607 
04608     looper_data.list= dgrouplist;
04609     bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
04610 
04611     /* create an array of root and tip positions transformed into
04612      * global coords */
04613     root = MEM_callocN(numbones*sizeof(float)*3, "root");
04614     tip = MEM_callocN(numbones*sizeof(float)*3, "tip");
04615     selected = MEM_callocN(numbones*sizeof(int), "selected");
04616 
04617     for (j=0; j < numbones; ++j) {
04618         bone = bonelist[j];
04619         dgroup = dgrouplist[j];
04620         
04621         /* handle bbone */
04622         if (heat) {
04623             if (segments == 0) {
04624                 segments = 1;
04625                 bbone = NULL;
04626                 
04627                 if ((par->pose) && (pchan=get_pose_channel(par->pose, bone->name))) {
04628                     if (bone->segments > 1) {
04629                         segments = bone->segments;
04630                         bbone = b_bone_spline_setup(pchan, 1);
04631                     }
04632                 }
04633             }
04634             
04635             segments--;
04636         }
04637         
04638         /* compute root and tip */
04639         if (bbone) {
04640             mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
04641             if ((segments+1) < bone->segments) {
04642                 mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments+1].mat[3]);
04643             }
04644             else {
04645                 copy_v3_v3(tip[j], bone->arm_tail);
04646             }
04647         }
04648         else {
04649             copy_v3_v3(root[j], bone->arm_head);
04650             copy_v3_v3(tip[j], bone->arm_tail);
04651         }
04652         
04653         mul_m4_v3(par->obmat, root[j]);
04654         mul_m4_v3(par->obmat, tip[j]);
04655         
04656         /* set selected */
04657         if (wpmode) {
04658             if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))
04659                 selected[j] = 1;
04660         }
04661         else
04662             selected[j] = 1;
04663         
04664         /* find flipped group */
04665         if (dgroup && mirror) {
04666             char name[MAXBONENAME];
04667 
04668             // 0 = don't strip off number extensions
04669             flip_side_name(name, dgroup->name, FALSE);
04670             dgroupflip[j] = defgroup_find_name(ob, name);
04671         }
04672     }
04673 
04674     /* create verts */
04675     mesh = (Mesh*)ob->data;
04676     verts = MEM_callocN(mesh->totvert*sizeof(*verts), "closestboneverts");
04677 
04678     if (wpmode) {
04679         /* if in weight paint mode, use final verts from derivedmesh */
04680         DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
04681         
04682         if (dm->foreachMappedVert) {
04683             dm->foreachMappedVert(dm, add_vgroups__mapFunc, (void*)verts);
04684             vertsfilled = 1;
04685         }
04686         
04687         dm->release(dm);
04688     }
04689     else if (modifiers_findByType(ob, eModifierType_Subsurf)) {
04690         /* is subsurf on? Lets use the verts on the limit surface then.
04691           * = same amount of vertices as mesh, but vertices  moved to the
04692          * subsurfed position, like for 'optimal'. */
04693         subsurf_calculate_limit_positions(mesh, verts);
04694         vertsfilled = 1;
04695     }
04696 
04697     /* transform verts to global space */
04698     for (i=0; i < mesh->totvert; i++) {
04699         if (!vertsfilled)
04700             copy_v3_v3(verts[i], mesh->mvert[i].co);
04701         mul_m4_v3(ob->obmat, verts[i]);
04702     }
04703 
04704     /* compute the weights based on gathered vertices and bones */
04705     if (heat) {
04706         const char *error= NULL;
04707         heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
04708             root, tip, selected, &error);
04709         
04710         if(error) {
04711             BKE_report(reports, RPT_WARNING, error);
04712         }
04713     }
04714     else {
04715         envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist,
04716             dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
04717     }
04718 
04719     /* only generated in some cases but can call anyway */
04720     mesh_octree_table(ob, NULL, NULL, 'e');
04721 
04722     /* free the memory allocated */
04723     MEM_freeN(bonelist);
04724     MEM_freeN(dgrouplist);
04725     MEM_freeN(dgroupflip);
04726     MEM_freeN(root);
04727     MEM_freeN(tip);
04728     MEM_freeN(selected);
04729     MEM_freeN(verts);
04730 }
04731 
04732 void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par, int mode, int mirror)
04733 {
04734     /* Lets try to create some vertex groups 
04735      * based on the bones of the parent armature.
04736      */
04737     bArmature *arm= par->data;
04738 
04739     if(mode == ARM_GROUPS_NAME) {
04740         /* Traverse the bone list, trying to create empty vertex 
04741          * groups cooresponding to the bone.
04742          */
04743         bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
04744 
04745         if (ob->type == OB_MESH)
04746             ED_vgroup_data_create(ob->data);
04747     }
04748     else if(mode == ARM_GROUPS_ENVELOPE || mode == ARM_GROUPS_AUTO) {
04749         /* Traverse the bone list, trying to create vertex groups 
04750          * that are populated with the vertices for which the
04751          * bone is closest.
04752          */
04753         add_verts_to_dgroups(reports, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
04754     }
04755 } 
04756 /* ************* Clear Pose *****************************/
04757 
04758 /* clear scale of pose-channel */
04759 static void pchan_clear_scale(bPoseChannel *pchan)
04760 {
04761     if ((pchan->protectflag & OB_LOCK_SCALEX)==0)
04762         pchan->size[0]= 1.0f;
04763     if ((pchan->protectflag & OB_LOCK_SCALEY)==0)
04764         pchan->size[1]= 1.0f;
04765     if ((pchan->protectflag & OB_LOCK_SCALEZ)==0)
04766         pchan->size[2]= 1.0f;
04767 }
04768 
04769 /* clear location of pose-channel */
04770 static void pchan_clear_loc(bPoseChannel *pchan)
04771 {
04772     if ((pchan->protectflag & OB_LOCK_LOCX)==0)
04773         pchan->loc[0]= 0.0f;
04774     if ((pchan->protectflag & OB_LOCK_LOCY)==0)
04775         pchan->loc[1]= 0.0f;
04776     if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
04777         pchan->loc[2]= 0.0f;
04778 }
04779 
04780 /* clear rotation of pose-channel */
04781 static void pchan_clear_rot(bPoseChannel *pchan)
04782 {
04783     if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
04784         /* check if convert to eulers for locking... */
04785         if (pchan->protectflag & OB_LOCK_ROT4D) {
04786             /* perform clamping on a component by component basis */
04787             if (pchan->rotmode == ROT_MODE_AXISANGLE) {
04788                 if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
04789                     pchan->rotAngle= 0.0f;
04790                 if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
04791                     pchan->rotAxis[0]= 0.0f;
04792                 if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
04793                     pchan->rotAxis[1]= 0.0f;
04794                 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
04795                     pchan->rotAxis[2]= 0.0f;
04796                     
04797                 /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
04798                 if (IS_EQF(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQF(pchan->rotAxis[1], pchan->rotAxis[2]))
04799                     pchan->rotAxis[1] = 1.0f;
04800             }
04801             else if (pchan->rotmode == ROT_MODE_QUAT) {
04802                 if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
04803                     pchan->quat[0]= 1.0f;
04804                 if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
04805                     pchan->quat[1]= 0.0f;
04806                 if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
04807                     pchan->quat[2]= 0.0f;
04808                 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
04809                     pchan->quat[3]= 0.0f;
04810             }
04811             else {
04812                 /* the flag may have been set for the other modes, so just ignore the extra flag... */
04813                 if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
04814                     pchan->eul[0]= 0.0f;
04815                 if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
04816                     pchan->eul[1]= 0.0f;
04817                 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
04818                     pchan->eul[2]= 0.0f;
04819             }
04820         }
04821         else {
04822             /* perform clamping using euler form (3-components) */
04823             float eul[3], oldeul[3], quat1[4] = {0};
04824             float qlen = 0.0f;
04825             
04826             if (pchan->rotmode == ROT_MODE_QUAT) {
04827                 qlen= normalize_qt_qt(quat1, pchan->quat);
04828                 quat_to_eul(oldeul, quat1);
04829             }
04830             else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
04831                 axis_angle_to_eulO( oldeul, EULER_ORDER_DEFAULT,pchan->rotAxis, pchan->rotAngle);
04832             }
04833             else {
04834                 copy_v3_v3(oldeul, pchan->eul);
04835             }
04836             
04837             eul[0]= eul[1]= eul[2]= 0.0f;
04838             
04839             if (pchan->protectflag & OB_LOCK_ROTX)
04840                 eul[0]= oldeul[0];
04841             if (pchan->protectflag & OB_LOCK_ROTY)
04842                 eul[1]= oldeul[1];
04843             if (pchan->protectflag & OB_LOCK_ROTZ)
04844                 eul[2]= oldeul[2];
04845             
04846             if (pchan->rotmode == ROT_MODE_QUAT) {
04847                 eul_to_quat(pchan->quat, eul);
04848                 
04849                 /* restore original quat size */
04850                 mul_qt_fl(pchan->quat, qlen);
04851                 
04852                 /* quaternions flip w sign to accumulate rotations correctly */
04853                 if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
04854                     mul_qt_fl(pchan->quat, -1.0f);
04855                 }
04856             }
04857             else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
04858                 eulO_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,eul, EULER_ORDER_DEFAULT);
04859             }
04860             else {
04861                 copy_v3_v3(pchan->eul, eul);
04862             }
04863         }
04864     }                       // Duplicated in source/blender/editors/object/object_transform.c
04865     else { 
04866         if (pchan->rotmode == ROT_MODE_QUAT) {
04867             unit_qt(pchan->quat);
04868         }
04869         else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
04870             /* by default, make rotation of 0 radians around y-axis (roll) */
04871             unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
04872         }
04873         else {
04874             zero_v3(pchan->eul);
04875         }
04876     }
04877 }
04878 
04879 /* clear loc/rot/scale of pose-channel */
04880 static void pchan_clear_transforms(bPoseChannel *pchan)
04881 {
04882     pchan_clear_loc(pchan);
04883     pchan_clear_rot(pchan);
04884     pchan_clear_scale(pchan);
04885 }
04886 
04887 /* --------------- */
04888 
04889 /* generic exec for clear-pose operators */
04890 static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, 
04891         void (*clear_func)(bPoseChannel*), const char default_ksName[])
04892 {
04893     Scene *scene= CTX_data_scene(C);
04894     Object *ob= object_pose_armature_get(CTX_data_active_object(C));
04895     short autokey = 0;
04896     
04897     /* sanity checks */
04898     if ELEM(NULL, clear_func, default_ksName) {
04899         BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform func or Keying Set Name");
04900         return OPERATOR_CANCELLED;
04901     }
04902     
04903     /* only clear relevant transforms for selected bones */
04904     CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 
04905     {
04906         /* run provided clearing function */
04907         clear_func(pchan);
04908         
04909         /* do auto-keyframing as appropriate */
04910         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
04911             /* clear any unkeyed tags */
04912             if (pchan->bone)
04913                 pchan->bone->flag &= ~BONE_UNKEYED;
04914                 
04915             /* tag for autokeying later */
04916             autokey = 1;
04917         }
04918         else {
04919             /* add unkeyed tags */
04920             if (pchan->bone)
04921                 pchan->bone->flag |= BONE_UNKEYED;
04922         }
04923     }
04924     CTX_DATA_END;
04925     
04926     /* perform autokeying on the bones if needed */
04927     if (autokey) {
04928         /* get KeyingSet to use */
04929         KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
04930         
04931         /* insert keyframes */
04932         ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
04933         
04934         /* now recalculate paths */
04935         if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
04936             ED_pose_recalculate_paths(scene, ob);
04937     }
04938     
04939     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
04940 
04941     /* note, notifier might evolve */
04942     WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
04943     
04944     return OPERATOR_FINISHED;
04945 }
04946 
04947 /* --------------- */
04948 
04949 static int pose_clear_scale_exec(bContext *C, wmOperator *op) 
04950 {
04951     return pose_clear_transform_generic_exec(C, op, pchan_clear_scale, ANIM_KS_SCALING_ID);
04952 }
04953 
04954 void POSE_OT_scale_clear(wmOperatorType *ot)
04955 {
04956     /* identifiers */
04957     ot->name= "Clear Pose Scale";
04958     ot->idname= "POSE_OT_scale_clear";
04959     ot->description = "Reset scaling of selected bones to their default values";
04960     
04961     /* api callbacks */
04962     ot->exec = pose_clear_scale_exec;
04963     ot->poll = ED_operator_posemode;
04964     
04965     /* flags */
04966     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
04967 }
04968 
04969 
04970 static int pose_clear_rot_exec(bContext *C, wmOperator *op) 
04971 {
04972     return pose_clear_transform_generic_exec(C, op, pchan_clear_rot, ANIM_KS_ROTATION_ID);
04973 }
04974 
04975 void POSE_OT_rot_clear(wmOperatorType *ot)
04976 {
04977     /* identifiers */
04978     ot->name= "Clear Pose Rotation";
04979     ot->idname= "POSE_OT_rot_clear";
04980     ot->description = "Reset rotations of selected bones to their default values";
04981     
04982     /* api callbacks */
04983     ot->exec = pose_clear_rot_exec;
04984     ot->poll = ED_operator_posemode;
04985     
04986     /* flags */
04987     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
04988 }
04989 
04990 
04991 static int pose_clear_loc_exec(bContext *C, wmOperator *op) 
04992 {
04993     return pose_clear_transform_generic_exec(C, op, pchan_clear_loc, ANIM_KS_LOCATION_ID);
04994 }
04995 
04996 void POSE_OT_loc_clear(wmOperatorType *ot)
04997 {
04998     /* identifiers */
04999     ot->name= "Clear Pose Location";
05000     ot->idname= "POSE_OT_loc_clear";
05001     ot->description = "Reset locations of selected bones to their default values";
05002     
05003     /* api callbacks */
05004     ot->exec = pose_clear_loc_exec;
05005     ot->poll = ED_operator_posemode;
05006     
05007     /* flags */
05008     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05009 }
05010 
05011 
05012 static int pose_clear_transforms_exec(bContext *C, wmOperator *op) 
05013 {
05014     return pose_clear_transform_generic_exec(C, op, pchan_clear_transforms, ANIM_KS_LOC_ROT_SCALE_ID);
05015 }
05016 
05017 void POSE_OT_transforms_clear(wmOperatorType *ot)
05018 {
05019     /* identifiers */
05020     ot->name= "Clear Pose Transforms";
05021     ot->idname= "POSE_OT_transforms_clear";
05022     ot->description = "Reset location, rotation, and scaling of selected bones to their default values";
05023     
05024     /* api callbacks */
05025     ot->exec = pose_clear_transforms_exec;
05026     ot->poll = ED_operator_posemode;
05027     
05028     /* flags */
05029     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05030 }
05031 
05032 /* ***************** selections ********************** */
05033 
05034 static int pose_de_select_all_exec(bContext *C, wmOperator *op)
05035 {
05036     int action = RNA_enum_get(op->ptr, "action");
05037     
05038     Scene *scene= CTX_data_scene(C);
05039     int multipaint = scene->toolsettings->multipaint;
05040 
05041     if (action == SEL_TOGGLE) {
05042         action= CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
05043     }
05044     
05045     /*  Set the flags */
05046     CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) {
05047         /* select pchan only if selectable, but deselect works always */
05048         switch (action) {
05049         case SEL_SELECT:
05050             if ((pchan->bone->flag & BONE_UNSELECTABLE)==0)
05051                 pchan->bone->flag |= BONE_SELECTED;
05052             break;
05053         case SEL_DESELECT:
05054             pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
05055             break;
05056         case SEL_INVERT:
05057             if (pchan->bone->flag & BONE_SELECTED) {
05058                 pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
05059             } 
05060             else if ((pchan->bone->flag & BONE_UNSELECTABLE)==0) {
05061                     pchan->bone->flag |= BONE_SELECTED;
05062             }
05063             break;
05064         }
05065     }
05066     CTX_DATA_END;
05067 
05068     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
05069     
05070     if (multipaint) {
05071         Object *ob = ED_object_context(C);
05072         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
05073     }
05074 
05075     return OPERATOR_FINISHED;
05076 }
05077 
05078 void POSE_OT_select_all(wmOperatorType *ot)
05079 {
05080     /* identifiers */
05081     ot->name= "Select or Deselect All";
05082     ot->idname= "POSE_OT_select_all";
05083     ot->description= "Toggle selection status of all bones";
05084     
05085     /* api callbacks */
05086     ot->exec= pose_de_select_all_exec;
05087     ot->poll= ED_operator_posemode;
05088     
05089     /* flags */
05090     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05091     
05092     WM_operator_properties_select_all(ot);
05093 }
05094 
05095 static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
05096 {
05097     Object *ob= object_pose_armature_get(CTX_data_active_object(C));
05098     bPoseChannel *pchan,*parent;
05099 
05100     /*  Determine if there is an active bone */
05101     pchan=CTX_data_active_pose_bone(C);
05102     if (pchan) {
05103         bArmature *arm= ob->data;
05104         parent=pchan->parent;
05105         if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P|BONE_UNSELECTABLE))) {
05106             parent->bone->flag |= BONE_SELECTED;
05107             arm->act_bone= parent->bone;
05108         }
05109         else {
05110             return OPERATOR_CANCELLED;
05111         }
05112     }
05113     else {
05114         return OPERATOR_CANCELLED;
05115     }
05116 
05117     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
05118     
05119     return OPERATOR_FINISHED;
05120 }
05121 
05122 void POSE_OT_select_parent(wmOperatorType *ot)
05123 {
05124     /* identifiers */
05125     ot->name= "Select Parent Bone";
05126     ot->idname= "POSE_OT_select_parent";
05127     ot->description= "Select bones that are parents of the currently selected bones";
05128 
05129     /* api callbacks */
05130     ot->exec= pose_select_parent_exec;
05131     ot->poll= ED_operator_posemode;
05132 
05133     /* flags */
05134     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05135     
05136 }
05137 
05138 /* ************* hide/unhide pose bones ******************* */
05139 
05140 static int hide_selected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)) 
05141 {
05142     bArmature *arm= ob->data;
05143     
05144     if (arm->layer & bone->layer) {
05145         if (bone->flag & BONE_SELECTED) {
05146             bone->flag |= BONE_HIDDEN_P;
05147             bone->flag &= ~BONE_SELECTED;
05148             if(arm->act_bone==bone)
05149                 arm->act_bone= NULL;
05150         }
05151     }
05152     return 0;
05153 }
05154 
05155 static int hide_unselected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)) 
05156 {
05157     bArmature *arm= ob->data;
05158     
05159     if (arm->layer & bone->layer) {
05160         // hrm... typo here?
05161         if ((bone->flag & BONE_SELECTED)==0) {
05162             bone->flag |= BONE_HIDDEN_P;
05163             if(arm->act_bone==bone)
05164                 arm->act_bone= NULL;
05165         }
05166     }
05167     return 0;
05168 }
05169 
05170 /* active object is armature in posemode, poll checked */
05171 static int pose_hide_exec(bContext *C, wmOperator *op) 
05172 {
05173     Object *ob= object_pose_armature_get(CTX_data_active_object(C));
05174     bArmature *arm= ob->data;
05175 
05176     if(RNA_boolean_get(op->ptr, "unselected"))
05177         bone_looper(ob, arm->bonebase.first, NULL, hide_unselected_pose_bone_cb);
05178     else
05179         bone_looper(ob, arm->bonebase.first, NULL, hide_selected_pose_bone_cb);
05180     
05181     /* note, notifier might evolve */
05182     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
05183     
05184     return OPERATOR_FINISHED;
05185 }
05186 
05187 void POSE_OT_hide(wmOperatorType *ot)
05188 {
05189     /* identifiers */
05190     ot->name= "Hide Selected";
05191     ot->idname= "POSE_OT_hide";
05192     ot->description= "Tag selected bones to not be visible in Pose Mode";
05193     
05194     /* api callbacks */
05195     ot->exec= pose_hide_exec;
05196     ot->poll= ED_operator_posemode;
05197     
05198     /* flags */
05199     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05200     
05201     /* props */
05202     RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
05203 }
05204 
05205 static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)) 
05206 {
05207     bArmature *arm= ob->data;
05208     
05209     if (arm->layer & bone->layer) {
05210         if (bone->flag & BONE_HIDDEN_P) {
05211             bone->flag &= ~BONE_HIDDEN_P;
05212             bone->flag |= BONE_SELECTED;
05213         }
05214     }
05215     
05216     return 0;
05217 }
05218 
05219 /* active object is armature in posemode, poll checked */
05220 static int pose_reveal_exec(bContext *C, wmOperator *UNUSED(op)) 
05221 {
05222     Object *ob= object_pose_armature_get(CTX_data_active_object(C));
05223     bArmature *arm= ob->data;
05224     
05225     bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone_cb);
05226     
05227     /* note, notifier might evolve */
05228     WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
05229 
05230     return OPERATOR_FINISHED;
05231 }
05232 
05233 void POSE_OT_reveal(wmOperatorType *ot)
05234 {
05235     /* identifiers */
05236     ot->name= "Reveal Selected";
05237     ot->idname= "POSE_OT_reveal";
05238     ot->description= "Unhide all bones that have been tagged to be hidden in Pose Mode";
05239     
05240     /* api callbacks */
05241     ot->exec= pose_reveal_exec;
05242     ot->poll= ED_operator_posemode;
05243     
05244     /* flags */
05245     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05246 }
05247 
05248 /* ************* RENAMING DISASTERS ************ */
05249 
05250 static int bone_unique_check(void *arg, const char *name)
05251 {
05252     return get_named_bone((bArmature *)arg, name) != NULL;
05253 }
05254 
05255 static void unique_bone_name(bArmature *arm, char *name)
05256 {
05257     BLI_uniquename_cb(bone_unique_check, (void *)arm, "Bone", '.', name, sizeof(((Bone *)NULL)->name));
05258 }
05259 
05260 /* helper call for armature_bone_rename */
05261 static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldname, char *newname)
05262 {
05263     bConstraint *curcon;
05264     bConstraintTarget *ct;
05265     
05266     for (curcon = conlist->first; curcon; curcon=curcon->next) {
05267         bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
05268         ListBase targets = {NULL, NULL};
05269         
05270         if (cti && cti->get_constraint_targets) {
05271             cti->get_constraint_targets(curcon, &targets);
05272             
05273             for (ct= targets.first; ct; ct= ct->next) {
05274                 if (ct->tar == ob) {
05275                     if (!strcmp(ct->subtarget, oldname) )
05276                         BLI_strncpy(ct->subtarget, newname, MAXBONENAME);
05277                 }
05278             }
05279             
05280             if (cti->flush_constraint_targets)
05281                 cti->flush_constraint_targets(curcon, &targets, 0);
05282         }   
05283     }
05284 }
05285 
05286 /* called by UI for renaming a bone */
05287 /* warning: make sure the original bone was not renamed yet! */
05288 /* seems messy, but thats what you get with not using pointers but channel names :) */
05289 void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *newnamep)
05290 {
05291     Object *ob;
05292     char newname[MAXBONENAME];
05293     char oldname[MAXBONENAME];
05294     
05295     /* names better differ! */
05296     if(strncmp(oldnamep, newnamep, MAXBONENAME)) {
05297         
05298         /* we alter newname string... so make copy */
05299         BLI_strncpy(newname, newnamep, MAXBONENAME);
05300         /* we use oldname for search... so make copy */
05301         BLI_strncpy(oldname, oldnamep, MAXBONENAME);
05302         
05303         /* now check if we're in editmode, we need to find the unique name */
05304         if (arm->edbo) {
05305             EditBone *eBone= editbone_name_exists(arm->edbo, oldname);
05306             
05307             if (eBone) {
05308                 unique_editbone_name(arm->edbo, newname, NULL);
05309                 BLI_strncpy(eBone->name, newname, MAXBONENAME);
05310             }
05311             else return;
05312         }
05313         else {
05314             Bone *bone= get_named_bone(arm, oldname);
05315             
05316             if (bone) {
05317                 unique_bone_name(arm, newname);
05318                 BLI_strncpy(bone->name, newname, MAXBONENAME);
05319             }
05320             else return;
05321         }
05322         
05323         /* do entire dbase - objects */
05324         for (ob= G.main->object.first; ob; ob= ob->id.next) {
05325             ModifierData *md;
05326             
05327             /* we have the object using the armature */
05328             if (arm==ob->data) {
05329                 Object *cob;
05330                 
05331                 /* Rename the pose channel, if it exists */
05332                 if (ob->pose) {
05333                     bPoseChannel *pchan = get_pose_channel(ob->pose, oldname);
05334                     if (pchan) {
05335                         BLI_strncpy(pchan->name, newname, MAXBONENAME);
05336                         
05337                         if (ob->pose->chanhash) {
05338                             GHash *gh = ob->pose->chanhash;
05339                             
05340                             /* remove the old hash entry, and replace with the new name */
05341                             BLI_ghash_remove(gh, oldname, NULL, NULL);
05342                             BLI_ghash_insert(gh, pchan->name, pchan);
05343                         }
05344                     }
05345                 }
05346                 
05347                 /* Update any object constraints to use the new bone name */
05348                 for (cob= G.main->object.first; cob; cob= cob->id.next) {
05349                     if (cob->constraints.first)
05350                         constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
05351                     if (cob->pose) {
05352                         bPoseChannel *pchan;
05353                         for (pchan = cob->pose->chanbase.first; pchan; pchan=pchan->next) {
05354                             constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
05355                         }
05356                     }
05357                 }
05358             }
05359                     
05360             /* See if an object is parented to this armature */
05361             if (ob->parent && (ob->parent->data == arm)) {
05362                 if (ob->partype==PARBONE) {
05363                     /* bone name in object */
05364                     if (!strcmp(ob->parsubstr, oldname))
05365                         BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
05366                 }
05367             }
05368             
05369             if (modifiers_usesArmature(ob, arm)) { 
05370                 bDeformGroup *dg= defgroup_find_name(ob, oldname);
05371                 if(dg) {
05372                     BLI_strncpy(dg->name, newname, MAXBONENAME);
05373                 }
05374             }
05375             
05376             /* fix modifiers that might be using this name */
05377             for (md= ob->modifiers.first; md; md= md->next) {
05378                 if (md->type == eModifierType_Hook) {
05379                     HookModifierData *hmd = (HookModifierData *)md;
05380                     
05381                     /* uses armature, so may use the affected bone name */
05382                     if (hmd->object && (hmd->object->data == arm)) {
05383                         if (!strcmp(hmd->subtarget, oldname))
05384                             BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
05385                     }
05386                 }
05387             }
05388             
05389             /* Fix animation data attached to this object */
05390             // TODO: should we be using the database wide version instead (since drivers may break)
05391             if (ob->adt) {
05392                 /* posechannels only... */
05393                 BKE_animdata_fix_paths_rename(&ob->id, ob->adt, "pose.bones", oldname, newname, 0, 0, 1);
05394             }
05395         }
05396 
05397         {
05398             /* correct view locking */
05399             bScreen *screen;
05400             for(screen= G.main->screen.first; screen; screen= screen->id.next) {
05401                 ScrArea *sa;
05402                 /* add regions */
05403                 for(sa= screen->areabase.first; sa; sa= sa->next) {
05404                     SpaceLink *sl;
05405                     for (sl= sa->spacedata.first; sl; sl= sl->next) {
05406                         if(sl->spacetype==SPACE_VIEW3D) {
05407                             View3D *v3d= (View3D *)sl;
05408                             if(v3d->ob_centre && v3d->ob_centre->data == arm) {
05409                                 if (!strcmp(v3d->ob_centre_bone, oldname)) {
05410                                     BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
05411                                 }
05412                             }
05413                         }
05414                     }
05415                 }
05416             }
05417         }
05418     }
05419 }
05420 
05421 
05422 static int armature_flip_names_exec (bContext *C, wmOperator *UNUSED(op))
05423 {
05424     Object *ob= CTX_data_edit_object(C);
05425     bArmature *arm;
05426     char newname[MAXBONENAME];
05427     
05428     /* paranoia checks */
05429     if (ELEM(NULL, ob, ob->pose)) 
05430         return OPERATOR_CANCELLED;
05431     arm= ob->data;
05432     
05433     /* loop through selected bones, auto-naming them */
05434     CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
05435     {
05436         flip_side_name(newname, ebone->name, TRUE); // 1 = do strip off number extensions
05437         ED_armature_bone_rename(arm, ebone->name, newname);
05438     }
05439     CTX_DATA_END;
05440     
05441     /* since we renamed stuff... */
05442     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
05443 
05444     /* note, notifier might evolve */
05445     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
05446     
05447     return OPERATOR_FINISHED;
05448 }
05449 
05450 void ARMATURE_OT_flip_names (wmOperatorType *ot)
05451 {
05452     /* identifiers */
05453     ot->name= "Flip Names";
05454     ot->idname= "ARMATURE_OT_flip_names";
05455     ot->description= "Flips (and corrects) the axis suffixes of the names of selected bones";
05456     
05457     /* api callbacks */
05458     ot->exec= armature_flip_names_exec;
05459     ot->poll= ED_operator_editarmature;
05460     
05461     /* flags */
05462     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05463 }
05464 
05465 
05466 static int armature_autoside_names_exec (bContext *C, wmOperator *op)
05467 {
05468     Object *ob= CTX_data_edit_object(C);
05469     bArmature *arm;
05470     char newname[MAXBONENAME];
05471     short axis= RNA_enum_get(op->ptr, "type");
05472     
05473     /* paranoia checks */
05474     if (ELEM(NULL, ob, ob->pose)) 
05475         return OPERATOR_CANCELLED;
05476     arm= ob->data;
05477     
05478     /* loop through selected bones, auto-naming them */
05479     CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
05480     {
05481         BLI_strncpy(newname, ebone->name, sizeof(newname));
05482         if(bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]))
05483             ED_armature_bone_rename(arm, ebone->name, newname);
05484     }
05485     CTX_DATA_END;
05486     
05487     /* since we renamed stuff... */
05488     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
05489 
05490     /* note, notifier might evolve */
05491     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
05492     
05493     return OPERATOR_FINISHED;
05494 }
05495 
05496 void ARMATURE_OT_autoside_names (wmOperatorType *ot)
05497 {
05498     static EnumPropertyItem axis_items[]= {
05499          {0, "XAXIS", 0, "X-Axis", "Left/Right"},
05500         {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
05501         {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
05502         {0, NULL, 0, NULL, NULL}};
05503     
05504     /* identifiers */
05505     ot->name= "AutoName by Axis";
05506     ot->idname= "ARMATURE_OT_autoside_names";
05507     ot->description= "Automatically renames the selected bones according to which side of the target axis they fall on";
05508     
05509     /* api callbacks */
05510     ot->invoke= WM_menu_invoke;
05511     ot->exec= armature_autoside_names_exec;
05512     ot->poll= ED_operator_editarmature;
05513     
05514     /* flags */
05515     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05516     
05517     /* settings */
05518     ot->prop= RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with");
05519 }
05520 
05521 
05522 
05523 /* if editbone (partial) selected, copy data */
05524 /* context; editmode armature, with mirror editing enabled */
05525 void transform_armature_mirror_update(Object *obedit)
05526 {
05527     bArmature *arm= obedit->data;
05528     EditBone *ebo, *eboflip;
05529     
05530     for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
05531         /* no layer check, correct mirror is more important */
05532         if (ebo->flag & (BONE_TIPSEL|BONE_ROOTSEL)) {
05533             eboflip= ED_armature_bone_get_mirrored(arm->edbo, ebo);
05534             
05535             if (eboflip) {
05536                 /* we assume X-axis flipping for now */
05537                 if (ebo->flag & BONE_TIPSEL) {
05538                     EditBone *children;
05539                     
05540                     eboflip->tail[0]= -ebo->tail[0];
05541                     eboflip->tail[1]= ebo->tail[1];
05542                     eboflip->tail[2]= ebo->tail[2];
05543                     eboflip->rad_tail= ebo->rad_tail;
05544                     eboflip->roll= -ebo->roll;
05545 
05546                     /* Also move connected children, in case children's name aren't mirrored properly */
05547                     for (children=arm->edbo->first; children; children=children->next) {
05548                         if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
05549                             copy_v3_v3(children->head, eboflip->tail);
05550                             children->rad_head = ebo->rad_tail;
05551                         }
05552                     }
05553                 }
05554                 if (ebo->flag & BONE_ROOTSEL) {
05555                     eboflip->head[0]= -ebo->head[0];
05556                     eboflip->head[1]= ebo->head[1];
05557                     eboflip->head[2]= ebo->head[2];
05558                     eboflip->rad_head= ebo->rad_head;
05559                     eboflip->roll= -ebo->roll;
05560                     
05561                     /* Also move connected parent, in case parent's name isn't mirrored properly */
05562                     if (eboflip->parent && eboflip->flag & BONE_CONNECTED)
05563                     {
05564                         EditBone *parent = eboflip->parent;
05565                         copy_v3_v3(parent->tail, eboflip->head);
05566                         parent->rad_tail = ebo->rad_head;
05567                     }
05568                 }
05569                 if (ebo->flag & BONE_SELECTED) {
05570                     eboflip->dist= ebo->dist;
05571                     eboflip->roll= -ebo->roll;
05572                     eboflip->xwidth= ebo->xwidth;
05573                     eboflip->zwidth= ebo->zwidth;
05574                 }
05575             }
05576         }
05577     }
05578 }
05579 
05580 
05581 /*****************************************************************************************************/
05582 /*************************************** SKELETON GENERATOR ******************************************/
05583 /*****************************************************************************************************/
05584 
05585 #if 0
05586 
05587 /**************************************** SUBDIVISION ALGOS ******************************************/
05588 
05589 EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
05590 {
05591     bArmature *arm= obedit->data;
05592     EditBone *lastBone = NULL;
05593     
05594     if (scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE)
05595     {
05596         ReebArcIterator arc_iter;
05597         BArcIterator *iter = (BArcIterator*)&arc_iter;
05598         float *previous = NULL, *current = NULL;
05599         EditBone *child = NULL;
05600         EditBone *parent = NULL;
05601         EditBone *root = NULL;
05602         float angleLimit = (float)cos(scene->toolsettings->skgen_angle_limit * M_PI / 180.0f);
05603         
05604         parent = ED_armature_edit_bone_add(arm, "Bone");
05605         parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
05606         copy_v3_v3(parent->head, head->p);
05607         
05608         root = parent;
05609         
05610         initArcIterator(iter, arc, head);
05611         IT_next(iter);
05612         previous = iter->p;
05613         
05614         for (IT_next(iter);
05615             IT_stopped(iter) == 0;
05616             previous = iter->p, IT_next(iter))
05617         {
05618             float vec1[3], vec2[3];
05619             float len1, len2;
05620             
05621             current = iter->p;
05622 
05623             sub_v3_v3v3(vec1, previous, parent->head);
05624             sub_v3_v3v3(vec2, current, previous);
05625 
05626             len1 = normalize_v3(vec1);
05627             len2 = normalize_v3(vec2);
05628 
05629             if (len1 > 0.0f && len2 > 0.0f && dot_v3v3(vec1, vec2) < angleLimit)
05630             {
05631                 copy_v3_v3(parent->tail, previous);
05632 
05633                 child = ED_armature_edit_bone_add(arm, "Bone");
05634                 copy_v3_v3(child->head, parent->tail);
05635                 child->parent = parent;
05636                 child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
05637                 
05638                 parent = child; /* new child is next parent */
05639             }
05640         }
05641         copy_v3_v3(parent->tail, tail->p);
05642         
05643         /* If the bone wasn't subdivided, delete it and return NULL
05644          * to let subsequent subdivision methods do their thing. 
05645          * */
05646         if (parent == root)
05647         {
05648             if(parent==arm->act_edbone) arm->act_edbone= NULL;
05649             ED_armature_edit_bone_remove(arm, parent);
05650             parent = NULL;
05651         }
05652         
05653         lastBone = parent; /* set last bone in the chain */
05654     }
05655     
05656     return lastBone;
05657 }
05658 
05659 EditBone * test_subdivideByCorrelation(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
05660 {
05661     EditBone *lastBone = NULL;
05662 
05663     if (scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
05664     {
05665         float invmat[4][4]= MAT4_UNITY;
05666         float tmat[3][3]= MAT3_UNITY;
05667         ReebArcIterator arc_iter;
05668         BArcIterator *iter = (BArcIterator*)&arc_iter;
05669         bArmature *arm= obedit->data;
05670         
05671         initArcIterator(iter, arc, head);
05672         
05673         lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
05674     }
05675     
05676     return lastBone;
05677 }
05678 
05679 float arcLengthRatio(ReebArc *arc)
05680 {
05681     float arcLength = 0.0f;
05682     float embedLength = 0.0f;
05683     int i;
05684     
05685     arcLength = len_v3v3(arc->head->p, arc->tail->p);
05686     
05687     if (arc->bcount > 0)
05688     {
05689         /* Add the embedding */
05690         for ( i = 1; i < arc->bcount; i++)
05691         {
05692             embedLength += len_v3v3(arc->buckets[i - 1].p, arc->buckets[i].p);
05693         }
05694         /* Add head and tail -> embedding vectors */
05695         embedLength += len_v3v3(arc->head->p, arc->buckets[0].p);
05696         embedLength += len_v3v3(arc->tail->p, arc->buckets[arc->bcount - 1].p);
05697     }
05698     else
05699     {
05700         embedLength = arcLength;
05701     }
05702     
05703     return embedLength / arcLength; 
05704 }
05705 
05706 EditBone * test_subdivideByLength(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
05707 {
05708     EditBone *lastBone = NULL;
05709     if ((scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) &&
05710         arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio)
05711     {
05712         float invmat[4][4]= MAT4_UNITY;
05713         float tmat[3][3]= MAT3_UNITY;
05714         ReebArcIterator arc_iter;
05715         BArcIterator *iter = (BArcIterator*)&arc_iter;
05716         bArmature *arm= obedit->data;
05717         
05718         initArcIterator(iter, arc, head);
05719         
05720         lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
05721     }
05722     
05723     return lastBone;
05724 }
05725 
05726 /***************************************** MAIN ALGORITHM ********************************************/
05727 
05728 void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
05729 {
05730     Object *obedit= scene->obedit; // XXX get from context
05731     GHash *arcBoneMap = NULL;
05732     ReebArc *arc = NULL;
05733     ReebNode *node = NULL;
05734     Object *src = NULL;
05735     Object *dst = NULL;
05736     
05737     src = scene->basact->object;
05738     
05739     if (obedit != NULL)
05740     {
05741         ED_armature_from_edit(obedit);
05742         ED_armature_edit_free(obedit);
05743     }
05744     
05745     dst = add_object(scene, OB_ARMATURE);
05746     ED_object_base_init_transform(NULL, scene->basact, NULL, NULL);     // XXX NULL is C, loc, rot
05747     obedit= scene->basact->object;
05748     
05749     /* Copy orientation from source */
05750     copy_v3_v3(dst->loc, src->obmat[3]);
05751     mat4_to_eul( dst->rot,src->obmat);
05752     mat4_to_size( dst->size,src->obmat);
05753     
05754     where_is_object(scene, obedit);
05755     
05756     ED_armature_to_edit(obedit);
05757 
05758     arcBoneMap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "SkeletonFromReebGraph gh");
05759     
05760     BLI_markdownSymmetry((BGraph*)rg, rg->nodes.first, scene->toolsettings->skgen_symmetry_limit);
05761     
05762     for (arc = rg->arcs.first; arc; arc = arc->next) 
05763     {
05764         EditBone *lastBone = NULL;
05765         ReebNode *head, *tail;
05766         int i;
05767 
05768         /* Find out the direction of the arc through simple heuristics (in order of priority) :
05769          * 
05770          * 1- Arcs on primary symmetry axis (symmetry == 1) point up (head: high weight -> tail: low weight)
05771          * 2- Arcs starting on a primary axis point away from it (head: node on primary axis)
05772          * 3- Arcs point down (head: low weight -> tail: high weight)
05773          *
05774          * Finally, the arc direction is stored in its flag: 1 (low -> high), -1 (high -> low)
05775          */
05776 
05777         /* if arc is a symmetry axis, internal bones go up the tree */      
05778         if (arc->symmetry_level == 1 && arc->tail->degree != 1)
05779         {
05780             head = arc->tail;
05781             tail = arc->head;
05782             
05783             arc->flag = -1; /* mark arc direction */
05784         }
05785         /* Bones point AWAY from the symmetry axis */
05786         else if (arc->head->symmetry_level == 1)
05787         {
05788             head = arc->head;
05789             tail = arc->tail;
05790             
05791             arc->flag = 1; /* mark arc direction */
05792         }
05793         else if (arc->tail->symmetry_level == 1)
05794         {
05795             head = arc->tail;
05796             tail = arc->head;
05797             
05798             arc->flag = -1; /* mark arc direction */
05799         }
05800         /* otherwise, always go from low weight to high weight */
05801         else
05802         {
05803             head = arc->head;
05804             tail = arc->tail;
05805             
05806             arc->flag = 1; /* mark arc direction */
05807         }
05808         
05809         /* Loop over subdivision methods */ 
05810         for (i = 0; lastBone == NULL && i < SKGEN_SUB_TOTAL; i++)
05811         {
05812             switch(scene->toolsettings->skgen_subdivisions[i])
05813             {
05814                 case SKGEN_SUB_LENGTH:
05815                     lastBone = test_subdivideByLength(scene, obedit, arc, head, tail);
05816                     break;
05817                 case SKGEN_SUB_ANGLE:
05818                     lastBone = subdivideByAngle(scene, obedit, arc, head, tail);
05819                     break;
05820                 case SKGEN_SUB_CORRELATION:
05821                     lastBone = test_subdivideByCorrelation(scene, obedit, arc, head, tail);
05822                     break;
05823             }
05824         }
05825     
05826         if (lastBone == NULL)
05827         {
05828             EditBone    *bone;
05829             bone = ED_armature_edit_bone_add(obedit->data, "Bone");
05830             bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
05831             
05832             copy_v3_v3(bone->head, head->p);
05833             copy_v3_v3(bone->tail, tail->p);
05834             
05835             /* set first and last bone, since there's only one */
05836             lastBone = bone;
05837         }
05838         
05839         BLI_ghash_insert(arcBoneMap, arc, lastBone);
05840     }
05841 
05842     /* Second pass, setup parent relationship between arcs */
05843     for (node = rg->nodes.first; node; node = node->next)
05844     {
05845         ReebArc *incomingArc = NULL;
05846         int i;
05847 
05848         for (i = 0; i < node->degree; i++)
05849         {
05850             arc = (ReebArc*)node->arcs[i];
05851 
05852             /* if arc is incoming into the node */
05853             if ((arc->head == node && arc->flag == -1) || (arc->tail == node && arc->flag == 1))
05854             {
05855                 if (incomingArc == NULL)
05856                 {
05857                     incomingArc = arc;
05858                     /* loop further to make sure there's only one incoming arc */
05859                 }
05860                 else
05861                 {
05862                     /* skip this node if more than one incomingArc */
05863                     incomingArc = NULL;
05864                     break; /* No need to look further, we are skipping already */
05865                 }
05866             }
05867         }
05868 
05869         if (incomingArc != NULL)
05870         {
05871             EditBone *parentBone = BLI_ghash_lookup(arcBoneMap, incomingArc);
05872 
05873             /* Look for outgoing arcs and parent their bones */
05874             for (i = 0; i < node->degree; i++)
05875             {
05876                 arc = node->arcs[i];
05877 
05878                 /* if arc is outgoing from the node */
05879                 if ((arc->head == node && arc->flag == 1) || (arc->tail == node && arc->flag == -1))
05880                 {
05881                     EditBone *childBone = BLI_ghash_lookup(arcBoneMap, arc);
05882 
05883                     /* find the root bone */
05884                     while(childBone->parent != NULL)
05885                     {
05886                         childBone = childBone->parent;
05887                     }
05888 
05889                     childBone->parent = parentBone;
05890                     childBone->flag |= BONE_CONNECTED;
05891                 }
05892             }
05893         }
05894     }
05895     
05896     BLI_ghash_free(arcBoneMap, NULL, NULL);
05897 }
05898 
05899 void generateSkeleton(Scene *scene)
05900 {
05901     ReebGraph *reebg;
05902     
05903 //  setcursor_space(SPACE_VIEW3D, CURSOR_WAIT);
05904     
05905     reebg = BIF_ReebGraphFromEditMesh();
05906 
05907     generateSkeletonFromReebGraph(scene, reebg);
05908 
05909     REEB_freeGraph(reebg);
05910 
05911     //setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
05912 }
05913 
05914 #endif