|
Blender
V2.59
|
00001 /* 00002 * $Id: poseobject.c 36813 2011-05-21 23:44:36Z zanqdo $ 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): Ton Roosendaal, Blender Foundation '05, full recode. 00024 * Joshua Leung 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 * support for animation modes - Reevan McKay 00028 */ 00029 00035 #include <stdlib.h> 00036 #include <stddef.h> 00037 #include <string.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "BLI_math.h" 00042 #include "BLI_blenlib.h" 00043 #include "BLI_dynstr.h" 00044 #include "BLI_utildefines.h" 00045 00046 #include "DNA_anim_types.h" 00047 #include "DNA_armature_types.h" 00048 #include "DNA_constraint_types.h" 00049 #include "DNA_scene_types.h" 00050 #include "DNA_object_types.h" 00051 00052 #include "BKE_anim.h" 00053 #include "BKE_idprop.h" 00054 #include "BKE_action.h" 00055 #include "BKE_armature.h" 00056 #include "BKE_context.h" 00057 #include "BKE_constraint.h" 00058 #include "BKE_deform.h" 00059 #include "BKE_depsgraph.h" 00060 #include "BKE_fcurve.h" 00061 #include "BKE_modifier.h" 00062 #include "BKE_report.h" 00063 00064 00065 #include "RNA_access.h" 00066 #include "RNA_define.h" 00067 00068 #include "WM_api.h" 00069 #include "WM_types.h" 00070 00071 #include "ED_armature.h" 00072 #include "ED_keyframing.h" 00073 #include "ED_mesh.h" 00074 #include "ED_screen.h" 00075 00076 #include "UI_interface.h" 00077 #include "UI_resources.h" 00078 00079 #include "armature_intern.h" 00080 00081 static int object_pose_context(Object *ob) 00082 { 00083 if( (ob) && 00084 (ob->type == OB_ARMATURE) && 00085 (ob->pose) && 00086 (ob->mode & OB_MODE_POSE) 00087 ) { 00088 return 1; 00089 } 00090 else { 00091 return 0; 00092 } 00093 } 00094 00095 Object *ED_object_pose_armature(Object *ob) 00096 { 00097 if(ob==NULL) 00098 return NULL; 00099 00100 if(object_pose_context(ob)) 00101 return ob; 00102 00103 ob= modifiers_isDeformedByArmature(ob); 00104 00105 if(object_pose_context(ob)) 00106 return ob; 00107 00108 return NULL; 00109 } 00110 00111 00112 /* This function is used to indicate that a bone is selected and needs keyframes inserted */ 00113 static void set_pose_keys (Object *ob) 00114 { 00115 bArmature *arm= ob->data; 00116 bPoseChannel *chan; 00117 00118 if (ob->pose){ 00119 for (chan=ob->pose->chanbase.first; chan; chan=chan->next){ 00120 Bone *bone= chan->bone; 00121 if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer)) 00122 chan->flag |= POSE_KEY; 00123 else 00124 chan->flag &= ~POSE_KEY; 00125 } 00126 } 00127 } 00128 00129 /* This function is used to process the necessary updates for */ 00130 void ED_armature_enter_posemode(bContext *C, Base *base) 00131 { 00132 ReportList *reports= CTX_wm_reports(C); 00133 Object *ob= base->object; 00134 00135 if (ob->id.lib) { 00136 BKE_report(reports, RPT_WARNING, "Can't pose libdata"); 00137 return; 00138 } 00139 00140 switch (ob->type) { 00141 case OB_ARMATURE: 00142 ob->restore_mode = ob->mode; 00143 ob->mode |= OB_MODE_POSE; 00144 00145 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_POSE, NULL); 00146 00147 break; 00148 default: 00149 return; 00150 } 00151 00152 // XXX: disabled as this would otherwise cause a nasty loop... 00153 //ED_object_toggle_modes(C, ob->mode); 00154 } 00155 00156 void ED_armature_exit_posemode(bContext *C, Base *base) 00157 { 00158 if(base) { 00159 Object *ob= base->object; 00160 00161 ob->restore_mode = ob->mode; 00162 ob->mode &= ~OB_MODE_POSE; 00163 00164 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL); 00165 } 00166 } 00167 00168 /* if a selected or active bone is protected, throw error (oonly if warn==1) and return 1 */ 00169 /* only_selected==1 : the active bone is allowed to be protected */ 00170 #if 0 /* UNUSED 2.5 */ 00171 static short pose_has_protected_selected(Object *ob, short warn) 00172 { 00173 /* check protection */ 00174 if (ob->proxy) { 00175 bPoseChannel *pchan; 00176 bArmature *arm= ob->data; 00177 00178 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00179 if (pchan->bone && (pchan->bone->layer & arm->layer)) { 00180 if (pchan->bone->layer & arm->layer_protected) { 00181 if (pchan->bone->flag & BONE_SELECTED) 00182 break; 00183 } 00184 } 00185 } 00186 if (pchan) { 00187 if (warn) error("Cannot change Proxy protected bones"); 00188 return 1; 00189 } 00190 } 00191 return 0; 00192 } 00193 #endif 00194 00195 /* only for real IK, not for auto-IK */ 00196 static int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level) 00197 { 00198 bConstraint *con; 00199 Bone *bone; 00200 00201 /* No need to check if constraint is active (has influence), 00202 * since all constraints with CONSTRAINT_IK_AUTO are active */ 00203 for(con= pchan->constraints.first; con; con= con->next) { 00204 if(con->type==CONSTRAINT_TYPE_KINEMATIC) { 00205 bKinematicConstraint *data= con->data; 00206 if(data->rootbone == 0 || data->rootbone > level) { 00207 if((data->flag & CONSTRAINT_IK_AUTO)==0) 00208 return 1; 00209 } 00210 } 00211 } 00212 for(bone= pchan->bone->childbase.first; bone; bone= bone->next) { 00213 pchan= get_pose_channel(ob->pose, bone->name); 00214 if(pchan && pose_channel_in_IK_chain(ob, pchan, level + 1)) 00215 return 1; 00216 } 00217 return 0; 00218 } 00219 00220 int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan) 00221 { 00222 return pose_channel_in_IK_chain(ob, pchan, 0); 00223 } 00224 00225 /* ********************************************** */ 00226 /* Motion Paths */ 00227 00228 /* For the object with pose/action: update paths for those that have got them 00229 * This should selectively update paths that exist... 00230 * 00231 * To be called from various tools that do incremental updates 00232 */ 00233 void ED_pose_recalculate_paths(Scene *scene, Object *ob) 00234 { 00235 ListBase targets = {NULL, NULL}; 00236 00237 /* set flag to force recalc, then grab the relevant bones to target */ 00238 ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS; 00239 animviz_get_object_motionpaths(ob, &targets); 00240 00241 /* recalculate paths, then free */ 00242 animviz_calc_motionpaths(scene, &targets); 00243 BLI_freelistN(&targets); 00244 } 00245 00246 /* For the object with pose/action: create path curves for selected bones 00247 * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range 00248 */ 00249 static int pose_calculate_paths_exec (bContext *C, wmOperator *UNUSED(op)) 00250 { 00251 ScrArea *sa= CTX_wm_area(C); 00252 Scene *scene= CTX_data_scene(C); 00253 Object *ob; 00254 00255 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 00256 if (sa->spacetype == SPACE_BUTS) 00257 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00258 else 00259 ob= ED_object_pose_armature(CTX_data_active_object(C)); 00260 00261 if (ELEM(NULL, ob, ob->pose)) 00262 return OPERATOR_CANCELLED; 00263 00264 /* set up path data for bones being calculated */ 00265 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 00266 { 00267 /* verify makes sure that the selected bone has a bone with the appropriate settings */ 00268 animviz_verify_motionpaths(scene, ob, pchan); 00269 } 00270 CTX_DATA_END; 00271 00272 /* calculate the bones that now have motionpaths... */ 00273 // TODO: only make for the selected bones? 00274 ED_pose_recalculate_paths(scene, ob); 00275 00276 /* notifiers for updates */ 00277 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 00278 00279 return OPERATOR_FINISHED; 00280 } 00281 00282 void POSE_OT_paths_calculate (wmOperatorType *ot) 00283 { 00284 /* identifiers */ 00285 ot->name= "Calculate Bone Paths"; 00286 ot->idname= "POSE_OT_paths_calculate"; 00287 ot->description= "Calculate paths for the selected bones"; 00288 00289 /* api callbacks */ 00290 ot->exec= pose_calculate_paths_exec; 00291 ot->poll= ED_operator_posemode; 00292 00293 /* flags */ 00294 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00295 } 00296 00297 /* --------- */ 00298 00299 /* for the object with pose/action: clear path curves for selected bones only */ 00300 static void ED_pose_clear_paths(Object *ob) 00301 { 00302 bPoseChannel *pchan; 00303 short skipped = 0; 00304 00305 if ELEM(NULL, ob, ob->pose) 00306 return; 00307 00308 /* free the motionpath blocks, but also take note of whether we skipped some... */ 00309 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00310 if (pchan->mpath) { 00311 if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) { 00312 animviz_free_motionpath(pchan->mpath); 00313 pchan->mpath= NULL; 00314 } 00315 else 00316 skipped = 1; 00317 } 00318 } 00319 00320 /* if we didn't skip any, we shouldn't have any paths left */ 00321 if (skipped == 0) 00322 ob->pose->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS; 00323 } 00324 00325 /* operator callback for this */ 00326 static int pose_clear_paths_exec (bContext *C, wmOperator *UNUSED(op)) 00327 { 00328 ScrArea *sa= CTX_wm_area(C); 00329 Object *ob; 00330 00331 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 00332 if (sa->spacetype == SPACE_BUTS) 00333 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00334 else 00335 ob= ED_object_pose_armature(CTX_data_active_object(C)); 00336 00337 /* only continue if there's an object */ 00338 if ELEM(NULL, ob, ob->pose) 00339 return OPERATOR_CANCELLED; 00340 00341 /* use the backend function for this */ 00342 ED_pose_clear_paths(ob); 00343 00344 /* notifiers for updates */ 00345 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 00346 00347 return OPERATOR_FINISHED; 00348 } 00349 00350 void POSE_OT_paths_clear (wmOperatorType *ot) 00351 { 00352 /* identifiers */ 00353 ot->name= "Clear Bone Paths"; 00354 ot->idname= "POSE_OT_paths_clear"; 00355 ot->description= "Clear path caches for selected bones"; 00356 00357 /* api callbacks */ 00358 ot->exec= pose_clear_paths_exec; 00359 ot->poll= ED_operator_posemode; 00360 00361 /* flags */ 00362 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 00363 } 00364 00365 /* ******************* Select Constraint Target Operator ************* */ 00366 00367 static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op)) 00368 { 00369 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 00370 bConstraint *con; 00371 int found= 0; 00372 00373 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 00374 { 00375 if (pchan->bone->flag & BONE_SELECTED) { 00376 for (con= pchan->constraints.first; con; con= con->next) { 00377 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 00378 ListBase targets = {NULL, NULL}; 00379 bConstraintTarget *ct; 00380 00381 if (cti && cti->get_constraint_targets) { 00382 cti->get_constraint_targets(con, &targets); 00383 00384 for (ct= targets.first; ct; ct= ct->next) { 00385 if ((ct->tar == ob) && (ct->subtarget[0])) { 00386 bPoseChannel *pchanc= get_pose_channel(ob->pose, ct->subtarget); 00387 if((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) { 00388 pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; 00389 found= 1; 00390 } 00391 } 00392 } 00393 00394 if (cti->flush_constraint_targets) 00395 cti->flush_constraint_targets(con, &targets, 1); 00396 } 00397 } 00398 } 00399 } 00400 CTX_DATA_END; 00401 00402 if (!found) 00403 return OPERATOR_CANCELLED; 00404 00405 WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob); 00406 00407 return OPERATOR_FINISHED; 00408 } 00409 00410 void POSE_OT_select_constraint_target(wmOperatorType *ot) 00411 { 00412 /* identifiers */ 00413 ot->name= "Select Constraint Target"; 00414 ot->idname= "POSE_OT_select_constraint_target"; 00415 ot->description= "Select bones used as targets for the currently selected bones"; 00416 00417 /* api callbacks */ 00418 ot->exec= pose_select_constraint_target_exec; 00419 ot->poll= ED_operator_posemode; 00420 00421 /* flags */ 00422 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00423 } 00424 00425 /* ******************* select hierarchy operator ************* */ 00426 00427 static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) 00428 { 00429 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 00430 bArmature *arm= ob->data; 00431 Bone *curbone, *pabone, *chbone; 00432 int direction = RNA_enum_get(op->ptr, "direction"); 00433 int add_to_sel = RNA_boolean_get(op->ptr, "extend"); 00434 int found= 0; 00435 00436 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 00437 { 00438 curbone= pchan->bone; 00439 00440 if ((curbone->flag & BONE_UNSELECTABLE)==0) { 00441 if (curbone == arm->act_bone) { 00442 if (direction == BONE_SELECT_PARENT) { 00443 if (pchan->parent == NULL) continue; 00444 else pabone= pchan->parent->bone; 00445 00446 if (PBONE_VISIBLE(arm, pabone)) { 00447 if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; 00448 pabone->flag |= BONE_SELECTED; 00449 arm->act_bone= pabone; 00450 00451 found= 1; 00452 break; 00453 } 00454 } 00455 else { /* direction == BONE_SELECT_CHILD */ 00456 if (pchan->child == NULL) continue; 00457 else chbone = pchan->child->bone; 00458 00459 if (PBONE_VISIBLE(arm, chbone)) { 00460 if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; 00461 chbone->flag |= BONE_SELECTED; 00462 arm->act_bone= chbone; 00463 00464 found= 1; 00465 break; 00466 } 00467 } 00468 } 00469 } 00470 } 00471 CTX_DATA_END; 00472 00473 if (found == 0) 00474 return OPERATOR_CANCELLED; 00475 00476 WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob); 00477 00478 return OPERATOR_FINISHED; 00479 } 00480 00481 void POSE_OT_select_hierarchy(wmOperatorType *ot) 00482 { 00483 static EnumPropertyItem direction_items[]= { 00484 {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""}, 00485 {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""}, 00486 {0, NULL, 0, NULL, NULL} 00487 }; 00488 00489 /* identifiers */ 00490 ot->name= "Select Hierarchy"; 00491 ot->idname= "POSE_OT_select_hierarchy"; 00492 ot->description= "Select immediate parent/children of selected bones"; 00493 00494 /* api callbacks */ 00495 ot->exec= pose_select_hierarchy_exec; 00496 ot->poll= ED_operator_posemode; 00497 00498 /* flags */ 00499 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00500 00501 /* props */ 00502 ot->prop= RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", ""); 00503 RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", ""); 00504 00505 } 00506 00507 /* ******************* select grouped operator ************* */ 00508 00509 static short pose_select_same_group (bContext *C, Object *ob, short extend) 00510 { 00511 bArmature *arm= (ob)? ob->data : NULL; 00512 bPose *pose= (ob)? ob->pose : NULL; 00513 char *group_flags; 00514 int numGroups = 0; 00515 short changed=0, tagged=0; 00516 00517 /* sanity checks */ 00518 if (ELEM3(NULL, ob, pose, arm)) 00519 return 0; 00520 00521 /* count the number of groups */ 00522 numGroups= BLI_countlist(&pose->agroups); 00523 if (numGroups == 0) 00524 return 0; 00525 00526 /* alloc a small array to keep track of the groups to use 00527 * - each cell stores on/off state for whether group should be used 00528 * - size is numGroups + 1, since index=0 is used for no-group 00529 */ 00530 group_flags= MEM_callocN(numGroups+1, "pose_select_same_group"); 00531 00532 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 00533 { 00534 /* keep track of group as group to use later? */ 00535 if (pchan->bone->flag & BONE_SELECTED) { 00536 group_flags[pchan->agrp_index] = 1; 00537 tagged= 1; 00538 } 00539 00540 /* deselect all bones before selecting new ones? */ 00541 if ((extend == 0) && (pchan->bone->flag & BONE_UNSELECTABLE)==0) 00542 pchan->bone->flag &= ~BONE_SELECTED; 00543 } 00544 CTX_DATA_END; 00545 00546 /* small optimisation: only loop through bones a second time if there are any groups tagged */ 00547 if (tagged) { 00548 /* only if group matches (and is not selected or current bone) */ 00549 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 00550 { 00551 if ((pchan->bone->flag & BONE_UNSELECTABLE)==0) { 00552 /* check if the group used by this bone is counted */ 00553 if (group_flags[pchan->agrp_index]) { 00554 pchan->bone->flag |= BONE_SELECTED; 00555 changed= 1; 00556 } 00557 } 00558 } 00559 CTX_DATA_END; 00560 } 00561 00562 /* free temp info */ 00563 MEM_freeN(group_flags); 00564 00565 return changed; 00566 } 00567 00568 static short pose_select_same_layer (bContext *C, Object *ob, short extend) 00569 { 00570 bPose *pose= (ob)? ob->pose : NULL; 00571 bArmature *arm= (ob)? ob->data : NULL; 00572 short changed= 0; 00573 int layers= 0; 00574 00575 if (ELEM3(NULL, ob, pose, arm)) 00576 return 0; 00577 00578 /* figure out what bones are selected */ 00579 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 00580 { 00581 /* keep track of layers to use later? */ 00582 if (pchan->bone->flag & BONE_SELECTED) 00583 layers |= pchan->bone->layer; 00584 00585 /* deselect all bones before selecting new ones? */ 00586 if ((extend == 0) && (pchan->bone->flag & BONE_UNSELECTABLE)==0) 00587 pchan->bone->flag &= ~BONE_SELECTED; 00588 } 00589 CTX_DATA_END; 00590 if (layers == 0) 00591 return 0; 00592 00593 /* select bones that are on same layers as layers flag */ 00594 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 00595 { 00596 /* if bone is on a suitable layer, and the bone can have its selection changed, select it */ 00597 if ((layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE)==0) { 00598 pchan->bone->flag |= BONE_SELECTED; 00599 changed= 1; 00600 } 00601 } 00602 CTX_DATA_END; 00603 00604 return changed; 00605 } 00606 00607 00608 static int pose_select_grouped_exec (bContext *C, wmOperator *op) 00609 { 00610 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 00611 short extend= RNA_boolean_get(op->ptr, "extend"); 00612 short changed = 0; 00613 00614 /* sanity check */ 00615 if (ELEM(NULL, ob, ob->pose)) 00616 return OPERATOR_CANCELLED; 00617 00618 /* selection types 00619 * NOTE: for the order of these, see the enum in POSE_OT_select_grouped() 00620 */ 00621 switch (RNA_enum_get(op->ptr, "type")) { 00622 case 1: /* group */ 00623 changed= pose_select_same_group(C, ob, extend); 00624 break; 00625 default: /* layer */ 00626 changed= pose_select_same_layer(C, ob, extend); 00627 break; 00628 } 00629 00630 /* notifiers for updates */ 00631 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 00632 00633 /* report done status */ 00634 if (changed) 00635 return OPERATOR_FINISHED; 00636 else 00637 return OPERATOR_CANCELLED; 00638 } 00639 00640 void POSE_OT_select_grouped (wmOperatorType *ot) 00641 { 00642 static EnumPropertyItem prop_select_grouped_types[] = { 00643 {0, "LAYER", 0, "Layer", "Shared layers"}, 00644 {1, "GROUP", 0, "Group", "Shared group"}, 00645 {0, NULL, 0, NULL, NULL} 00646 }; 00647 00648 /* identifiers */ 00649 ot->name= "Select Grouped"; 00650 ot->description = "Select all visible bones grouped by similar properties"; 00651 ot->idname= "POSE_OT_select_grouped"; 00652 00653 /* api callbacks */ 00654 ot->invoke= WM_menu_invoke; 00655 ot->exec= pose_select_grouped_exec; 00656 ot->poll= ED_operator_posemode; 00657 00658 /* flags */ 00659 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00660 00661 /* properties */ 00662 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); 00663 ot->prop= RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", ""); 00664 } 00665 00666 00667 /* ********************************************** */ 00668 00669 /* context active object, or weightpainted object with armature in posemode */ 00670 static int pose_bone_flip_active_exec (bContext *C, wmOperator *UNUSED(op)) 00671 { 00672 Object *ob_act= CTX_data_active_object(C); 00673 Object *ob= ED_object_pose_armature(ob_act); 00674 00675 if(ob && (ob->mode & OB_MODE_POSE)) { 00676 bArmature *arm= ob->data; 00677 00678 if(arm->act_bone) { 00679 bPoseChannel *pchanf; 00680 char name[MAXBONENAME]; 00681 flip_side_name(name, arm->act_bone->name, TRUE); 00682 00683 pchanf= get_pose_channel(ob->pose, name); 00684 if(pchanf && pchanf->bone != arm->act_bone) { 00685 arm->act_bone->flag &= ~BONE_SELECTED; 00686 pchanf->bone->flag |= BONE_SELECTED; 00687 00688 arm->act_bone= pchanf->bone; 00689 00690 /* in weightpaint we select the associated vertex group too */ 00691 if(ob_act->mode & OB_MODE_WEIGHT_PAINT) { 00692 ED_vgroup_select_by_name(ob_act, name); 00693 DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA); 00694 } 00695 00696 WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob); 00697 00698 return OPERATOR_FINISHED; 00699 } 00700 } 00701 } 00702 00703 return OPERATOR_CANCELLED; 00704 } 00705 00706 void POSE_OT_select_flip_active(wmOperatorType *ot) 00707 { 00708 /* identifiers */ 00709 ot->name= "Flip Selected Active Bone"; 00710 ot->idname= "POSE_OT_select_flip_active"; 00711 ot->description= "Activate the bone with a flipped name."; 00712 00713 /* api callbacks */ 00714 ot->exec= pose_bone_flip_active_exec; 00715 ot->poll= ED_operator_posemode; 00716 00717 /* flags */ 00718 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 00719 } 00720 00721 00722 /* ********************************************** */ 00723 #if 0 /* UNUSED 2.5 */ 00724 static void pose_copy_menu(Scene *scene) 00725 { 00726 Object *obedit= scene->obedit; // XXX context 00727 Object *ob= OBACT; 00728 bArmature *arm; 00729 bPoseChannel *pchan, *pchanact; 00730 short nr=0; 00731 int i=0; 00732 00733 /* paranoia checks */ 00734 if (ELEM(NULL, ob, ob->pose)) return; 00735 if ((ob==obedit) || (ob->mode & OB_MODE_POSE)==0) return; 00736 00737 pchan= get_active_posechannel(ob); 00738 00739 if (pchan==NULL) return; 00740 pchanact= pchan; 00741 arm= ob->data; 00742 00743 /* if proxy-protected bones selected, some things (such as locks + displays) shouldn't be changable, 00744 * but for constraints (just add local constraints) 00745 */ 00746 if (pose_has_protected_selected(ob, 0)) { 00747 i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */ 00748 if (i < 25) 00749 nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5"); 00750 else 00751 nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4"); 00752 } 00753 else { 00754 i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */ 00755 if (i < 25) 00756 nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8"); 00757 else 00758 nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8"); 00759 } 00760 00761 if (nr <= 0) 00762 return; 00763 00764 if (nr != 5) { 00765 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00766 if ( (arm->layer & pchan->bone->layer) && 00767 (pchan->bone->flag & BONE_SELECTED) && 00768 (pchan != pchanact) ) 00769 { 00770 switch (nr) { 00771 case 1: /* Local Location */ 00772 VECCOPY(pchan->loc, pchanact->loc); 00773 break; 00774 case 2: /* Local Rotation */ 00775 QUATCOPY(pchan->quat, pchanact->quat); 00776 VECCOPY(pchan->eul, pchanact->eul); 00777 break; 00778 case 3: /* Local Size */ 00779 VECCOPY(pchan->size, pchanact->size); 00780 break; 00781 case 4: /* All Constraints */ 00782 { 00783 ListBase tmp_constraints = {NULL, NULL}; 00784 00785 /* copy constraints to tmpbase and apply 'local' tags before 00786 * appending to list of constraints for this channel 00787 */ 00788 copy_constraints(&tmp_constraints, &pchanact->constraints, TRUE); 00789 if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) { 00790 bConstraint *con; 00791 00792 /* add proxy-local tags */ 00793 for (con= tmp_constraints.first; con; con= con->next) 00794 con->flag |= CONSTRAINT_PROXY_LOCAL; 00795 } 00796 BLI_movelisttolist(&pchan->constraints, &tmp_constraints); 00797 00798 /* update flags (need to add here, not just copy) */ 00799 pchan->constflag |= pchanact->constflag; 00800 00801 if (ob->pose) 00802 ob->pose->flag |= POSE_RECALC; 00803 } 00804 break; 00805 case 6: /* Transform Locks */ 00806 pchan->protectflag = pchanact->protectflag; 00807 break; 00808 case 7: /* IK (DOF) settings */ 00809 { 00810 pchan->ikflag = pchanact->ikflag; 00811 VECCOPY(pchan->limitmin, pchanact->limitmin); 00812 VECCOPY(pchan->limitmax, pchanact->limitmax); 00813 VECCOPY(pchan->stiffness, pchanact->stiffness); 00814 pchan->ikstretch= pchanact->ikstretch; 00815 pchan->ikrotweight= pchanact->ikrotweight; 00816 pchan->iklinweight= pchanact->iklinweight; 00817 } 00818 break; 00819 case 8: /* Custom Bone Shape */ 00820 pchan->custom = pchanact->custom; 00821 break; 00822 case 9: /* Visual Location */ 00823 armature_loc_pose_to_bone(pchan, pchanact->pose_mat[3], pchan->loc); 00824 break; 00825 case 10: /* Visual Rotation */ 00826 { 00827 float delta_mat[4][4]; 00828 00829 armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat); 00830 00831 if (pchan->rotmode == ROT_MODE_AXISANGLE) { 00832 float tmp_quat[4]; 00833 00834 /* need to convert to quat first (in temp var)... */ 00835 mat4_to_quat( tmp_quat,delta_mat); 00836 quat_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,tmp_quat); 00837 } 00838 else if (pchan->rotmode == ROT_MODE_QUAT) 00839 mat4_to_quat( pchan->quat,delta_mat); 00840 else 00841 mat4_to_eulO( pchan->eul, pchan->rotmode,delta_mat); 00842 } 00843 break; 00844 case 11: /* Visual Size */ 00845 { 00846 float delta_mat[4][4], size[4]; 00847 00848 armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat); 00849 mat4_to_size( size,delta_mat); 00850 VECCOPY(pchan->size, size); 00851 } 00852 } 00853 } 00854 } 00855 } 00856 else { /* constraints, optional (note: max we can have is 24 constraints) */ 00857 bConstraint *con, *con_back; 00858 int const_toggle[24]= {0}; /* XXX, initialize as 0 to quiet errors */ 00859 ListBase const_copy = {NULL, NULL}; 00860 00861 BLI_duplicatelist(&const_copy, &(pchanact->constraints)); 00862 00863 /* build the puplist of constraints */ 00864 for (con = pchanact->constraints.first, i=0; con; con=con->next, i++){ 00865 const_toggle[i]= 1; 00866 // add_numbut(i, TOG|INT, con->name, 0, 0, &(const_toggle[i]), ""); 00867 } 00868 00869 // if (!do_clever_numbuts("Select Constraints", i, REDRAW)) { 00870 // BLI_freelistN(&const_copy); 00871 // return; 00872 // } 00873 00874 /* now build a new listbase from the options selected */ 00875 for (i=0, con=const_copy.first; con; i++) { 00876 /* if not selected, free/remove it from the list */ 00877 if (!const_toggle[i]) { 00878 con_back= con->next; 00879 BLI_freelinkN(&const_copy, con); 00880 con= con_back; 00881 } 00882 else 00883 con= con->next; 00884 } 00885 00886 /* Copy the temo listbase to the selected posebones */ 00887 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00888 if ( (arm->layer & pchan->bone->layer) && 00889 (pchan->bone->flag & BONE_SELECTED) && 00890 (pchan!=pchanact) ) 00891 { 00892 ListBase tmp_constraints = {NULL, NULL}; 00893 00894 /* copy constraints to tmpbase and apply 'local' tags before 00895 * appending to list of constraints for this channel 00896 */ 00897 copy_constraints(&tmp_constraints, &const_copy, TRUE); 00898 if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) { 00899 /* add proxy-local tags */ 00900 for (con= tmp_constraints.first; con; con= con->next) 00901 con->flag |= CONSTRAINT_PROXY_LOCAL; 00902 } 00903 BLI_movelisttolist(&pchan->constraints, &tmp_constraints); 00904 00905 /* update flags (need to add here, not just copy) */ 00906 pchan->constflag |= pchanact->constflag; 00907 } 00908 } 00909 BLI_freelistN(&const_copy); 00910 update_pose_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */ 00911 00912 if (ob->pose) 00913 ob->pose->flag |= POSE_RECALC; 00914 } 00915 00916 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations 00917 00918 BIF_undo_push("Copy Pose Attributes"); 00919 00920 } 00921 #endif 00922 00923 /* ******************** copy/paste pose ********************** */ 00924 00925 /* Global copy/paste buffer for pose - cleared on start/end session + before every copy operation */ 00926 static bPose *g_posebuf = NULL; 00927 00928 void free_posebuf(void) 00929 { 00930 if (g_posebuf) { 00931 bPoseChannel *pchan; 00932 00933 for (pchan= g_posebuf->chanbase.first; pchan; pchan= pchan->next) { 00934 if(pchan->prop) { 00935 IDP_FreeProperty(pchan->prop); 00936 MEM_freeN(pchan->prop); 00937 } 00938 } 00939 00940 /* was copied without constraints */ 00941 BLI_freelistN(&g_posebuf->chanbase); 00942 MEM_freeN(g_posebuf); 00943 } 00944 00945 g_posebuf=NULL; 00946 } 00947 00948 /* ---- */ 00949 00950 static int pose_copy_exec (bContext *C, wmOperator *op) 00951 { 00952 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 00953 00954 /* sanity checking */ 00955 if ELEM(NULL, ob, ob->pose) { 00956 BKE_report(op->reports, RPT_ERROR, "No Pose to Copy"); 00957 return OPERATOR_CANCELLED; 00958 } 00959 00960 /* free existing pose buffer */ 00961 free_posebuf(); 00962 00963 /* sets chan->flag to POSE_KEY if bone selected, then copy those bones to the buffer */ 00964 set_pose_keys(ob); 00965 copy_pose(&g_posebuf, ob->pose, 0); 00966 00967 00968 return OPERATOR_FINISHED; 00969 } 00970 00971 void POSE_OT_copy (wmOperatorType *ot) 00972 { 00973 /* identifiers */ 00974 ot->name= "Copy Pose"; 00975 ot->idname= "POSE_OT_copy"; 00976 ot->description= "Copies the current pose of the selected bones to copy/paste buffer"; 00977 00978 /* api callbacks */ 00979 ot->exec= pose_copy_exec; 00980 ot->poll= ED_operator_posemode; 00981 00982 /* flag */ 00983 ot->flag= OPTYPE_REGISTER; 00984 } 00985 00986 /* ---- */ 00987 00988 static int pose_paste_exec (bContext *C, wmOperator *op) 00989 { 00990 Scene *scene= CTX_data_scene(C); 00991 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 00992 bPoseChannel *chan, *pchan; 00993 int flip= RNA_boolean_get(op->ptr, "flipped"); 00994 int selOnly= RNA_boolean_get(op->ptr, "selected_mask"); 00995 00996 /* sanity checks */ 00997 if ELEM(NULL, ob, ob->pose) 00998 return OPERATOR_CANCELLED; 00999 01000 if (g_posebuf == NULL) { 01001 BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty"); 01002 return OPERATOR_CANCELLED; 01003 } 01004 01005 /* Safely merge all of the channels in the buffer pose into any existing pose */ 01006 for (chan= g_posebuf->chanbase.first; chan; chan=chan->next) { 01007 if (chan->flag & POSE_KEY) { 01008 char name[32]; 01009 short paste_ok; 01010 01011 /* get the name - if flipping, we must flip this first */ 01012 if (flip) 01013 flip_side_name(name, chan->name, 0); /* 0 = don't strip off number extensions */ 01014 else 01015 BLI_strncpy(name, chan->name, sizeof(name)); 01016 01017 /* only copy when: 01018 * 1) channel exists - poses are not meant to add random channels to anymore 01019 * 2) if selection-masking is on, channel is selected - only selected bones get pasted on, allowing making both sides symmetrical 01020 */ 01021 pchan= get_pose_channel(ob->pose, name); 01022 01023 if (selOnly) 01024 paste_ok= ((pchan) && (pchan->bone->flag & BONE_SELECTED)); 01025 else 01026 paste_ok= ((pchan != NULL)); 01027 01028 /* continue? */ 01029 if (paste_ok) { 01030 /* only loc rot size 01031 * - only copies transform info for the pose 01032 */ 01033 VECCOPY(pchan->loc, chan->loc); 01034 VECCOPY(pchan->size, chan->size); 01035 pchan->flag= chan->flag; 01036 01037 /* check if rotation modes are compatible (i.e. do they need any conversions) */ 01038 if (pchan->rotmode == chan->rotmode) { 01039 /* copy the type of rotation in use */ 01040 if (pchan->rotmode > 0) { 01041 VECCOPY(pchan->eul, chan->eul); 01042 } 01043 else if (pchan->rotmode == ROT_MODE_AXISANGLE) { 01044 VECCOPY(pchan->rotAxis, chan->rotAxis); 01045 pchan->rotAngle = chan->rotAngle; 01046 } 01047 else { 01048 QUATCOPY(pchan->quat, chan->quat); 01049 } 01050 } 01051 else if (pchan->rotmode > 0) { 01052 /* quat/axis-angle to euler */ 01053 if (chan->rotmode == ROT_MODE_AXISANGLE) 01054 axis_angle_to_eulO( pchan->eul, pchan->rotmode,chan->rotAxis, chan->rotAngle); 01055 else 01056 quat_to_eulO( pchan->eul, pchan->rotmode,chan->quat); 01057 } 01058 else if (pchan->rotmode == ROT_MODE_AXISANGLE) { 01059 /* quat/euler to axis angle */ 01060 if (chan->rotmode > 0) 01061 eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode); 01062 else 01063 quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat); 01064 } 01065 else { 01066 /* euler/axis-angle to quat */ 01067 if (chan->rotmode > 0) 01068 eulO_to_quat(pchan->quat, chan->eul, chan->rotmode); 01069 else 01070 axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle); 01071 } 01072 01073 /* paste flipped pose? */ 01074 if (flip) { 01075 pchan->loc[0]*= -1; 01076 01077 /* has to be done as eulers... */ 01078 if (pchan->rotmode > 0) { 01079 pchan->eul[1] *= -1; 01080 pchan->eul[2] *= -1; 01081 } 01082 else if (pchan->rotmode == ROT_MODE_AXISANGLE) { 01083 float eul[3]; 01084 01085 axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle); 01086 eul[1]*= -1; 01087 eul[2]*= -1; 01088 eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT); 01089 } 01090 else { 01091 float eul[3]; 01092 01093 normalize_qt(pchan->quat); 01094 quat_to_eul(eul, pchan->quat); 01095 eul[1]*= -1; 01096 eul[2]*= -1; 01097 eul_to_quat(pchan->quat, eul); 01098 } 01099 } 01100 01101 /* ID properties 01102 * - only free the existing properties if the channel we're copying from has them 01103 * NOTE: this means that if the pose depends on some pchan property, the pose may not be ok, 01104 * but this is better than loosing all the setting you've painstakingly added... 01105 */ 01106 if (chan->prop) { 01107 /* free the old properties since we want to replace them now */ 01108 if (pchan->prop) { 01109 IDP_FreeProperty(pchan->prop); 01110 MEM_freeN(pchan->prop); 01111 pchan->prop= NULL; 01112 } 01113 01114 /* now copy over the new copy of the properties */ 01115 pchan->prop= IDP_CopyProperty(chan->prop); 01116 } 01117 01118 /* keyframing tagging */ 01119 if (autokeyframe_cfra_can_key(scene, &ob->id)) { 01120 ListBase dsources = {NULL, NULL}; 01121 01122 /* get KeyingSet to use */ 01123 KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "LocRotScale"); 01124 01125 /* now insert the keyframe(s) using the Keying Set 01126 * 1) add datasource override for the PoseChannel 01127 * 2) insert keyframes 01128 * 3) free the extra info 01129 */ 01130 ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 01131 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); 01132 BLI_freelistN(&dsources); 01133 01134 /* clear any unkeyed tags */ 01135 if (chan->bone) 01136 chan->bone->flag &= ~BONE_UNKEYED; 01137 } 01138 else { 01139 /* add unkeyed tags */ 01140 if (chan->bone) 01141 chan->bone->flag |= BONE_UNKEYED; 01142 } 01143 } 01144 } 01145 } 01146 01147 /* Update event for pose and deformation children */ 01148 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01149 01150 /* notifiers for updates */ 01151 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01152 01153 return OPERATOR_FINISHED; 01154 } 01155 01156 void POSE_OT_paste (wmOperatorType *ot) 01157 { 01158 /* identifiers */ 01159 ot->name= "Paste Pose"; 01160 ot->idname= "POSE_OT_paste"; 01161 ot->description= "Pastes the stored pose on to the current pose"; 01162 01163 /* api callbacks */ 01164 ot->exec= pose_paste_exec; 01165 ot->poll= ED_operator_posemode; 01166 01167 /* flag */ 01168 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01169 01170 /* properties */ 01171 RNA_def_boolean(ot->srna, "flipped", 0, "Flipped on X-Axis", "Paste the stored pose flipped on to current pose"); 01172 RNA_def_boolean(ot->srna, "selected_mask", 0, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose"); 01173 } 01174 01175 /* ********************************************** */ 01176 01177 01178 static int pose_group_add_exec (bContext *C, wmOperator *UNUSED(op)) 01179 { 01180 ScrArea *sa= CTX_wm_area(C); 01181 Object *ob; 01182 01183 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 01184 if (sa->spacetype == SPACE_BUTS) 01185 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01186 else 01187 ob= ED_object_pose_armature(CTX_data_active_object(C)); 01188 01189 /* only continue if there's an object */ 01190 if (ob == NULL) 01191 return OPERATOR_CANCELLED; 01192 01193 /* for now, just call the API function for this */ 01194 pose_add_group(ob); 01195 01196 /* notifiers for updates */ 01197 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01198 01199 return OPERATOR_FINISHED; 01200 } 01201 01202 void POSE_OT_group_add (wmOperatorType *ot) 01203 { 01204 /* identifiers */ 01205 ot->name= "Add Bone Group"; 01206 ot->idname= "POSE_OT_group_add"; 01207 ot->description= "Add a new bone group"; 01208 01209 /* api callbacks */ 01210 ot->exec= pose_group_add_exec; 01211 ot->poll= ED_operator_posemode; 01212 01213 /* flags */ 01214 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 01215 } 01216 01217 01218 static int pose_group_remove_exec (bContext *C, wmOperator *UNUSED(op)) 01219 { 01220 ScrArea *sa= CTX_wm_area(C); 01221 Object *ob; 01222 01223 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 01224 if (sa->spacetype == SPACE_BUTS) 01225 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01226 else 01227 ob= ED_object_pose_armature(CTX_data_active_object(C)); 01228 01229 /* only continue if there's an object */ 01230 if (ob == NULL) 01231 return OPERATOR_CANCELLED; 01232 01233 /* for now, just call the API function for this */ 01234 pose_remove_group(ob); 01235 01236 /* notifiers for updates */ 01237 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01238 01239 return OPERATOR_FINISHED; 01240 } 01241 01242 void POSE_OT_group_remove (wmOperatorType *ot) 01243 { 01244 /* identifiers */ 01245 ot->name= "Remove Bone Group"; 01246 ot->idname= "POSE_OT_group_remove"; 01247 ot->description= "Removes the active bone group"; 01248 01249 /* api callbacks */ 01250 ot->exec= pose_group_remove_exec; 01251 ot->poll= ED_operator_posemode; 01252 01253 /* flags */ 01254 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 01255 } 01256 01257 /* ------------ */ 01258 01259 /* invoke callback which presents a list of bone-groups for the user to choose from */ 01260 static int pose_groups_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) 01261 { 01262 ScrArea *sa= CTX_wm_area(C); 01263 Object *ob; 01264 bPose *pose; 01265 01266 uiPopupMenu *pup; 01267 uiLayout *layout; 01268 bActionGroup *grp; 01269 int i; 01270 01271 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 01272 if (sa->spacetype == SPACE_BUTS) 01273 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01274 else 01275 ob= ED_object_pose_armature(CTX_data_active_object(C)); 01276 01277 /* only continue if there's an object, and a pose there too */ 01278 if (ELEM(NULL, ob, ob->pose)) 01279 return OPERATOR_CANCELLED; 01280 pose= ob->pose; 01281 01282 /* if there's no active group (or active is invalid), create a new menu to find it */ 01283 if (pose->active_group <= 0) { 01284 /* create a new menu, and start populating it with group names */ 01285 pup= uiPupMenuBegin(C, op->type->name, ICON_NONE); 01286 layout= uiPupMenuLayout(pup); 01287 01288 /* special entry - allow to create new group, then use that 01289 * (not to be used for removing though) 01290 */ 01291 if (strstr(op->idname, "assign")) { 01292 uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0); 01293 uiItemS(layout); 01294 } 01295 01296 /* add entries for each group */ 01297 for (grp= pose->agroups.first, i=1; grp; grp=grp->next, i++) 01298 uiItemIntO(layout, grp->name, ICON_NONE, op->idname, "type", i); 01299 01300 /* finish building the menu, and process it (should result in calling self again) */ 01301 uiPupMenuEnd(C, pup); 01302 01303 return OPERATOR_CANCELLED; 01304 } 01305 else { 01306 /* just use the active group index, and call the exec callback for the calling operator */ 01307 RNA_int_set(op->ptr, "type", pose->active_group); 01308 return op->type->exec(C, op); 01309 } 01310 } 01311 01312 /* Assign selected pchans to the bone group that the user selects */ 01313 static int pose_group_assign_exec (bContext *C, wmOperator *op) 01314 { 01315 ScrArea *sa= CTX_wm_area(C); 01316 Object *ob; 01317 bPose *pose; 01318 short done= 0; 01319 01320 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 01321 if (sa->spacetype == SPACE_BUTS) 01322 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01323 else 01324 ob= ED_object_pose_armature(CTX_data_active_object(C)); 01325 01326 /* only continue if there's an object, and a pose there too */ 01327 if (ELEM(NULL, ob, ob->pose)) 01328 return OPERATOR_CANCELLED; 01329 01330 pose= ob->pose; 01331 01332 /* set the active group number to the one from operator props 01333 * - if 0 after this, make a new group... 01334 */ 01335 pose->active_group= RNA_int_get(op->ptr, "type"); 01336 if (pose->active_group == 0) 01337 pose_add_group(ob); 01338 01339 /* add selected bones to group then */ 01340 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 01341 { 01342 pchan->agrp_index= pose->active_group; 01343 done= 1; 01344 } 01345 CTX_DATA_END; 01346 01347 /* notifiers for updates */ 01348 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01349 01350 /* report done status */ 01351 if (done) 01352 return OPERATOR_FINISHED; 01353 else 01354 return OPERATOR_CANCELLED; 01355 } 01356 01357 void POSE_OT_group_assign (wmOperatorType *ot) 01358 { 01359 /* identifiers */ 01360 ot->name= "Add Selected to Bone Group"; 01361 ot->idname= "POSE_OT_group_assign"; 01362 ot->description= "Add selected bones to the chosen bone group"; 01363 01364 /* api callbacks */ 01365 ot->invoke= pose_groups_menu_invoke; 01366 ot->exec= pose_group_assign_exec; 01367 ot->poll= ED_operator_posemode; 01368 01369 /* flags */ 01370 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 01371 01372 /* properties */ 01373 RNA_def_int(ot->srna, "type", 0, 0, 10, "Bone Group Index", "", 0, INT_MAX); 01374 } 01375 01376 01377 static int pose_group_unassign_exec (bContext *C, wmOperator *UNUSED(op)) 01378 { 01379 ScrArea *sa= CTX_wm_area(C); 01380 Object *ob; 01381 short done= 0; 01382 01383 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 01384 if (sa->spacetype == SPACE_BUTS) 01385 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01386 else 01387 ob= ED_object_pose_armature(CTX_data_active_object(C)); 01388 01389 /* only continue if there's an object, and a pose there too */ 01390 if (ELEM(NULL, ob, ob->pose)) 01391 return OPERATOR_CANCELLED; 01392 01393 /* find selected bones to remove from all bone groups */ 01394 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 01395 { 01396 if (pchan->agrp_index) { 01397 pchan->agrp_index= 0; 01398 done= 1; 01399 } 01400 } 01401 CTX_DATA_END; 01402 01403 /* notifiers for updates */ 01404 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01405 01406 /* report done status */ 01407 if (done) 01408 return OPERATOR_FINISHED; 01409 else 01410 return OPERATOR_CANCELLED; 01411 } 01412 01413 void POSE_OT_group_unassign (wmOperatorType *ot) 01414 { 01415 /* identifiers */ 01416 ot->name= "Remove Selected from Bone Groups"; 01417 ot->idname= "POSE_OT_group_unassign"; 01418 ot->description= "Remove selected bones from all bone groups"; 01419 01420 /* api callbacks */ 01421 ot->exec= pose_group_unassign_exec; 01422 ot->poll= ED_operator_posemode; 01423 01424 /* flags */ 01425 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 01426 } 01427 01428 static void pose_group_select(bContext *C, Object *ob, int select) 01429 { 01430 bPose *pose= ob->pose; 01431 01432 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, visible_pose_bones) 01433 { 01434 if ((pchan->bone->flag & BONE_UNSELECTABLE)==0) { 01435 if (select) { 01436 if (pchan->agrp_index == pose->active_group) 01437 pchan->bone->flag |= BONE_SELECTED; 01438 } 01439 else { 01440 if (pchan->agrp_index == pose->active_group) 01441 pchan->bone->flag &= ~BONE_SELECTED; 01442 } 01443 } 01444 } 01445 CTX_DATA_END; 01446 } 01447 01448 static int pose_group_select_exec (bContext *C, wmOperator *UNUSED(op)) 01449 { 01450 ScrArea *sa= CTX_wm_area(C); 01451 Object *ob; 01452 01453 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 01454 if (sa->spacetype == SPACE_BUTS) 01455 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01456 else 01457 ob= ED_object_pose_armature(CTX_data_active_object(C)); 01458 01459 /* only continue if there's an object, and a pose there too */ 01460 if (ELEM(NULL, ob, ob->pose)) 01461 return OPERATOR_CANCELLED; 01462 01463 pose_group_select(C, ob, 1); 01464 01465 /* notifiers for updates */ 01466 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01467 01468 return OPERATOR_FINISHED; 01469 } 01470 01471 void POSE_OT_group_select (wmOperatorType *ot) 01472 { 01473 /* identifiers */ 01474 ot->name= "Select Bones of Bone Group"; 01475 ot->idname= "POSE_OT_group_select"; 01476 ot->description= "Select bones in active Bone Group"; 01477 01478 /* api callbacks */ 01479 ot->exec= pose_group_select_exec; 01480 ot->poll= ED_operator_posemode; 01481 01482 /* flags */ 01483 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 01484 } 01485 01486 static int pose_group_deselect_exec (bContext *C, wmOperator *UNUSED(op)) 01487 { 01488 ScrArea *sa= CTX_wm_area(C); 01489 Object *ob; 01490 01491 /* since this call may also be used from the buttons window, we need to check for where to get the object */ 01492 if (sa->spacetype == SPACE_BUTS) 01493 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01494 else 01495 ob= ED_object_pose_armature(CTX_data_active_object(C)); 01496 01497 /* only continue if there's an object, and a pose there too */ 01498 if (ELEM(NULL, ob, ob->pose)) 01499 return OPERATOR_CANCELLED; 01500 01501 pose_group_select(C, ob, 0); 01502 01503 /* notifiers for updates */ 01504 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01505 01506 return OPERATOR_FINISHED; 01507 } 01508 01509 void POSE_OT_group_deselect (wmOperatorType *ot) 01510 { 01511 /* identifiers */ 01512 ot->name= "Deselect Bone Group"; 01513 ot->idname= "POSE_OT_group_deselect"; 01514 ot->description= "Deselect bones of active Bone Group"; 01515 01516 /* api callbacks */ 01517 ot->exec= pose_group_deselect_exec; 01518 ot->poll= ED_operator_posemode; 01519 01520 /* flags */ 01521 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 01522 } 01523 01524 /* ********************************************** */ 01525 01526 static int pose_flip_names_exec (bContext *C, wmOperator *UNUSED(op)) 01527 { 01528 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01529 bArmature *arm; 01530 01531 /* paranoia checks */ 01532 if (ELEM(NULL, ob, ob->pose)) 01533 return OPERATOR_CANCELLED; 01534 arm= ob->data; 01535 01536 /* loop through selected bones, auto-naming them */ 01537 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 01538 { 01539 char newname[32]; 01540 flip_side_name(newname, pchan->name, TRUE); 01541 ED_armature_bone_rename(arm, pchan->name, newname); 01542 } 01543 CTX_DATA_END; 01544 01545 /* since we renamed stuff... */ 01546 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01547 01548 /* note, notifier might evolve */ 01549 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01550 01551 return OPERATOR_FINISHED; 01552 } 01553 01554 void POSE_OT_flip_names (wmOperatorType *ot) 01555 { 01556 /* identifiers */ 01557 ot->name= "Flip Names"; 01558 ot->idname= "POSE_OT_flip_names"; 01559 ot->description= "Flips (and corrects) the axis suffixes of the the names of selected bones"; 01560 01561 /* api callbacks */ 01562 ot->exec= pose_flip_names_exec; 01563 ot->poll= ED_operator_posemode; 01564 01565 /* flags */ 01566 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01567 } 01568 01569 /* ------------------ */ 01570 01571 static int pose_autoside_names_exec (bContext *C, wmOperator *op) 01572 { 01573 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01574 bArmature *arm; 01575 char newname[32]; 01576 short axis= RNA_enum_get(op->ptr, "axis"); 01577 01578 /* paranoia checks */ 01579 if (ELEM(NULL, ob, ob->pose)) 01580 return OPERATOR_CANCELLED; 01581 arm= ob->data; 01582 01583 /* loop through selected bones, auto-naming them */ 01584 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 01585 { 01586 BLI_strncpy(newname, pchan->name, sizeof(newname)); 01587 if(bone_autoside_name(newname, 1, axis, pchan->bone->head[axis], pchan->bone->tail[axis])) 01588 ED_armature_bone_rename(arm, pchan->name, newname); 01589 } 01590 CTX_DATA_END; 01591 01592 /* since we renamed stuff... */ 01593 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01594 01595 /* note, notifier might evolve */ 01596 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01597 01598 return OPERATOR_FINISHED; 01599 } 01600 01601 void POSE_OT_autoside_names (wmOperatorType *ot) 01602 { 01603 static EnumPropertyItem axis_items[]= { 01604 {0, "XAXIS", 0, "X-Axis", "Left/Right"}, 01605 {1, "YAXIS", 0, "Y-Axis", "Front/Back"}, 01606 {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"}, 01607 {0, NULL, 0, NULL, NULL}}; 01608 01609 /* identifiers */ 01610 ot->name= "AutoName by Axis"; 01611 ot->idname= "POSE_OT_autoside_names"; 01612 ot->description= "Automatically renames the selected bones according to which side of the target axis they fall on"; 01613 01614 /* api callbacks */ 01615 ot->invoke= WM_menu_invoke; 01616 ot->exec= pose_autoside_names_exec; 01617 ot->poll= ED_operator_posemode; 01618 01619 /* flags */ 01620 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01621 01622 /* settings */ 01623 ot->prop= RNA_def_enum(ot->srna, "axis", axis_items, 0, "Axis", "Axis tag names with."); 01624 } 01625 01626 /* ********************************************** */ 01627 01628 /* Show all armature layers */ 01629 static int pose_armature_layers_showall_poll (bContext *C) 01630 { 01631 /* this single operator can be used in posemode OR editmode for armatures */ 01632 return ED_operator_posemode(C) || ED_operator_editarmature(C); 01633 } 01634 01635 static int pose_armature_layers_showall_exec (bContext *C, wmOperator *op) 01636 { 01637 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01638 bArmature *arm = (ob)? ob->data : NULL; 01639 PointerRNA ptr; 01640 int maxLayers = (RNA_boolean_get(op->ptr, "all"))? 32 : 16; 01641 int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ 01642 int i; 01643 01644 /* sanity checking */ 01645 if (arm == NULL) 01646 return OPERATOR_CANCELLED; 01647 01648 /* use RNA to set the layers 01649 * although it would be faster to just set directly using bitflags, we still 01650 * need to setup a RNA pointer so that we get the "update" callbacks for free... 01651 */ 01652 RNA_id_pointer_create(&arm->id, &ptr); 01653 01654 for (i = 0; i < maxLayers; i++) 01655 layers[i] = 1; 01656 01657 RNA_boolean_set_array(&ptr, "layers", layers); 01658 01659 /* note, notifier might evolve */ 01660 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01661 01662 /* done */ 01663 return OPERATOR_FINISHED; 01664 } 01665 01666 void ARMATURE_OT_layers_show_all (wmOperatorType *ot) 01667 { 01668 /* identifiers */ 01669 ot->name= "Show All Layers"; 01670 ot->idname= "ARMATURE_OT_layers_show_all"; 01671 ot->description= "Make all armature layers visible"; 01672 01673 /* callbacks */ 01674 ot->exec= pose_armature_layers_showall_exec; 01675 ot->poll= pose_armature_layers_showall_poll; 01676 01677 /* flags */ 01678 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01679 01680 /* properties */ 01681 ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All Layers", "Enable all layers or just the first 16 (top row)"); 01682 } 01683 01684 /* ------------------- */ 01685 01686 /* Present a popup to get the layers that should be used */ 01687 static int pose_armature_layers_invoke (bContext *C, wmOperator *op, wmEvent *evt) 01688 { 01689 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01690 bArmature *arm= (ob)? ob->data : NULL; 01691 PointerRNA ptr; 01692 int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ 01693 01694 /* sanity checking */ 01695 if (arm == NULL) 01696 return OPERATOR_CANCELLED; 01697 01698 /* get RNA pointer to armature data to use that to retrieve the layers as ints to init the operator */ 01699 RNA_id_pointer_create((ID *)arm, &ptr); 01700 RNA_boolean_get_array(&ptr, "layers", layers); 01701 RNA_boolean_set_array(op->ptr, "layers", layers); 01702 01703 /* part to sync with other similar operators... */ 01704 return WM_operator_props_popup(C, op, evt); 01705 } 01706 01707 /* Set the visible layers for the active armature (edit and pose modes) */ 01708 static int pose_armature_layers_exec (bContext *C, wmOperator *op) 01709 { 01710 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01711 PointerRNA ptr; 01712 int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ 01713 01714 if(ob==NULL || ob->data==NULL) { 01715 return OPERATOR_CANCELLED; 01716 } 01717 01718 /* get the values set in the operator properties */ 01719 RNA_boolean_get_array(op->ptr, "layers", layers); 01720 01721 /* get pointer for armature, and write data there... */ 01722 RNA_id_pointer_create((ID *)ob->data, &ptr); 01723 RNA_boolean_set_array(&ptr, "layers", layers); 01724 01725 /* note, notifier might evolve */ 01726 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01727 01728 return OPERATOR_FINISHED; 01729 } 01730 01731 01732 void POSE_OT_armature_layers (wmOperatorType *ot) 01733 { 01734 /* identifiers */ 01735 ot->name= "Change Armature Layers"; 01736 ot->idname= "POSE_OT_armature_layers"; 01737 ot->description= "Change the visible armature layers"; 01738 01739 /* callbacks */ 01740 ot->invoke= pose_armature_layers_invoke; 01741 ot->exec= pose_armature_layers_exec; 01742 ot->poll= ED_operator_posemode; 01743 01744 /* flags */ 01745 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01746 01747 /* properties */ 01748 RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible"); 01749 } 01750 01751 void ARMATURE_OT_armature_layers (wmOperatorType *ot) 01752 { 01753 /* identifiers */ 01754 ot->name= "Change Armature Layers"; 01755 ot->idname= "ARMATURE_OT_armature_layers"; 01756 ot->description= "Change the visible armature layers"; 01757 01758 /* callbacks */ 01759 ot->invoke= pose_armature_layers_invoke; 01760 ot->exec= pose_armature_layers_exec; 01761 ot->poll= ED_operator_editarmature; 01762 01763 /* flags */ 01764 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01765 01766 /* properties */ 01767 RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible"); 01768 } 01769 01770 /* ------------------- */ 01771 01772 /* Present a popup to get the layers that should be used */ 01773 static int pose_bone_layers_invoke (bContext *C, wmOperator *op, wmEvent *evt) 01774 { 01775 int layers[32]= {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ 01776 01777 /* get layers that are active already */ 01778 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones) 01779 { 01780 short bit; 01781 01782 /* loop over the bits for this pchan's layers, adding layers where they're needed */ 01783 for (bit= 0; bit < 32; bit++) { 01784 if (pchan->bone->layer & (1<<bit)) 01785 layers[bit]= 1; 01786 } 01787 } 01788 CTX_DATA_END; 01789 01790 /* copy layers to operator */ 01791 RNA_boolean_set_array(op->ptr, "layers", layers); 01792 01793 /* part to sync with other similar operators... */ 01794 return WM_operator_props_popup(C, op, evt); 01795 } 01796 01797 /* Set the visible layers for the active armature (edit and pose modes) */ 01798 static int pose_bone_layers_exec (bContext *C, wmOperator *op) 01799 { 01800 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01801 PointerRNA ptr; 01802 int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ 01803 01804 if(ob==NULL || ob->data==NULL) { 01805 return OPERATOR_CANCELLED; 01806 } 01807 01808 /* get the values set in the operator properties */ 01809 RNA_boolean_get_array(op->ptr, "layers", layers); 01810 01811 /* set layers of pchans based on the values set in the operator props */ 01812 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones) 01813 { 01814 /* get pointer for pchan, and write flags this way */ 01815 RNA_pointer_create((ID *)ob->data, &RNA_Bone, pchan->bone, &ptr); 01816 RNA_boolean_set_array(&ptr, "layers", layers); 01817 } 01818 CTX_DATA_END; 01819 01820 /* note, notifier might evolve */ 01821 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01822 01823 return OPERATOR_FINISHED; 01824 } 01825 01826 void POSE_OT_bone_layers (wmOperatorType *ot) 01827 { 01828 /* identifiers */ 01829 ot->name= "Change Bone Layers"; 01830 ot->idname= "POSE_OT_bone_layers"; 01831 ot->description= "Change the layers that the selected bones belong to"; 01832 01833 /* callbacks */ 01834 ot->invoke= pose_bone_layers_invoke; 01835 ot->exec= pose_bone_layers_exec; 01836 ot->poll= ED_operator_posemode; 01837 01838 /* flags */ 01839 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01840 01841 /* properties */ 01842 RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to"); 01843 } 01844 01845 /* ------------------- */ 01846 01847 /* Present a popup to get the layers that should be used */ 01848 static int armature_bone_layers_invoke (bContext *C, wmOperator *op, wmEvent *evt) 01849 { 01850 int layers[32]= {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ 01851 01852 /* get layers that are active already */ 01853 CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) 01854 { 01855 short bit; 01856 01857 /* loop over the bits for this pchan's layers, adding layers where they're needed */ 01858 for (bit= 0; bit < 32; bit++) { 01859 if (ebone->layer & (1<<bit)) 01860 layers[bit]= 1; 01861 } 01862 } 01863 CTX_DATA_END; 01864 01865 /* copy layers to operator */ 01866 RNA_boolean_set_array(op->ptr, "layers", layers); 01867 01868 /* part to sync with other similar operators... */ 01869 return WM_operator_props_popup(C, op, evt); 01870 } 01871 01872 /* Set the visible layers for the active armature (edit and pose modes) */ 01873 static int armature_bone_layers_exec (bContext *C, wmOperator *op) 01874 { 01875 Object *ob= CTX_data_edit_object(C); 01876 bArmature *arm= (ob)? ob->data : NULL; 01877 PointerRNA ptr; 01878 int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ 01879 01880 /* get the values set in the operator properties */ 01881 RNA_boolean_get_array(op->ptr, "layers", layers); 01882 01883 /* set layers of pchans based on the values set in the operator props */ 01884 CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) 01885 { 01886 /* get pointer for pchan, and write flags this way */ 01887 RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr); 01888 RNA_boolean_set_array(&ptr, "layers", layers); 01889 } 01890 CTX_DATA_END; 01891 01892 /* note, notifier might evolve */ 01893 WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); 01894 01895 return OPERATOR_FINISHED; 01896 } 01897 01898 void ARMATURE_OT_bone_layers (wmOperatorType *ot) 01899 { 01900 /* identifiers */ 01901 ot->name= "Change Bone Layers"; 01902 ot->idname= "ARMATURE_OT_bone_layers"; 01903 ot->description= "Change the layers that the selected bones belong to"; 01904 01905 /* callbacks */ 01906 ot->invoke= armature_bone_layers_invoke; 01907 ot->exec= armature_bone_layers_exec; 01908 ot->poll= ED_operator_editarmature; 01909 01910 /* flags */ 01911 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01912 01913 /* properties */ 01914 RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to"); 01915 } 01916 01917 /* ********************************************** */ 01918 01919 static int pose_flip_quats_exec (bContext *C, wmOperator *UNUSED(op)) 01920 { 01921 Scene *scene= CTX_data_scene(C); 01922 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01923 KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, "LocRotScale"); 01924 01925 /* loop through all selected pchans, flipping and keying (as needed) */ 01926 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 01927 { 01928 /* only if bone is using quaternion rotation */ 01929 if (pchan->rotmode == ROT_MODE_QUAT) { 01930 /* quaternions have 720 degree range */ 01931 negate_v4(pchan->quat); 01932 01933 /* tagging */ 01934 if (autokeyframe_cfra_can_key(scene, &ob->id)) { 01935 ListBase dsources = {NULL, NULL}; 01936 01937 /* now insert the keyframe(s) using the Keying Set 01938 * 1) add datasource override for the PoseChannel 01939 * 2) insert keyframes 01940 * 3) free the extra info 01941 */ 01942 ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 01943 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); 01944 BLI_freelistN(&dsources); 01945 01946 /* clear any unkeyed tags */ 01947 if (pchan->bone) 01948 pchan->bone->flag &= ~BONE_UNKEYED; 01949 } 01950 else { 01951 /* add unkeyed tags */ 01952 if (pchan->bone) 01953 pchan->bone->flag |= BONE_UNKEYED; 01954 } 01955 } 01956 } 01957 CTX_DATA_END; 01958 01959 /* notifiers and updates */ 01960 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01961 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); 01962 01963 return OPERATOR_FINISHED; 01964 } 01965 01966 void POSE_OT_quaternions_flip (wmOperatorType *ot) 01967 { 01968 /* identifiers */ 01969 ot->name = "Flip Quats"; 01970 ot->idname= "POSE_OT_quaternions_flip"; 01971 ot->description= "Flip quaternion values to achieve desired rotations, while maintaining the same orientations"; 01972 01973 /* callbacks */ 01974 ot->exec= pose_flip_quats_exec; 01975 ot->poll= ED_operator_posemode; 01976 01977 /* flags */ 01978 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01979 } 01980 01981 /* ********************************************** */ 01982 01983 /* context: active channel */ 01984 #if 0 01985 void pose_special_editmenu(Scene *scene) 01986 { 01987 Object *obedit= scene->obedit; // XXX context 01988 Object *ob= OBACT; 01989 short nr; 01990 01991 /* paranoia checks */ 01992 if(!ob && !ob->pose) return; 01993 if(ob==obedit || (ob->mode & OB_MODE_POSE)==0) return; 01994 01995 nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear Paths%x4|Clear User Transform %x5|Relax Pose %x6|%l|AutoName Left-Right%x7|AutoName Front-Back%x8|AutoName Top-Bottom%x9"); 01996 if(nr==1) { 01997 pose_select_constraint_target(scene); 01998 } 01999 else if(nr==2) { 02000 pose_flip_names(); 02001 } 02002 else if(nr==3) { 02003 pose_calculate_path(C, ob); 02004 } 02005 else if(nr==4) { 02006 pose_clear_paths(ob); 02007 } 02008 else if(nr==5) { 02009 pose_clear_user_transforms(ob); 02010 } 02011 else if(nr==6) { 02012 pose_relax(); 02013 } 02014 else if(ELEM3(nr, 7, 8, 9)) { 02015 pose_autoside_names(nr-7); 02016 } 02017 } 02018 02019 02020 /* Restore selected pose-bones to 'action'-defined pose */ 02021 static void pose_clear_user_transforms(Object *ob) 02022 { 02023 bArmature *arm= ob->data; 02024 bPoseChannel *pchan; 02025 02026 if (ob->pose == NULL) 02027 return; 02028 02029 /* if the object has an action, restore pose to the pose defined by the action by clearing pose on selected bones */ 02030 if (ob->action) { 02031 /* find selected bones */ 02032 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 02033 if (pchan->bone && (pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) { 02034 /* just clear the BONE_UNKEYED flag, allowing this bone to get overwritten by actions again */ 02035 pchan->bone->flag &= ~BONE_UNKEYED; 02036 } 02037 } 02038 02039 /* clear pose locking flag 02040 * - this will only clear the user-defined pose in the selected bones, where BONE_UNKEYED has been cleared 02041 */ 02042 ob->pose->flag |= POSE_DO_UNLOCK; 02043 } 02044 else { 02045 /* no action, so restore entire pose to rest pose (cannot restore only selected bones) */ 02046 rest_pose(ob->pose); 02047 } 02048 02049 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 02050 BIF_undo_push("Clear User Transform"); 02051 } 02052 02053 #endif