Blender V2.61 - r43446
|
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