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