Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Joshua Leung (full recode) 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdio.h> 00034 #include <stddef.h> 00035 #include <string.h> 00036 #include <math.h> 00037 #include <float.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "BLI_blenlib.h" 00042 #include "BLI_math.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_key_types.h" 00050 #include "DNA_material_types.h" 00051 #include "DNA_scene_types.h" 00052 #include "DNA_object_types.h" 00053 00054 #include "BKE_animsys.h" 00055 #include "BKE_action.h" 00056 #include "BKE_armature.h" 00057 #include "BKE_constraint.h" 00058 #include "BKE_depsgraph.h" 00059 #include "BKE_fcurve.h" 00060 #include "BKE_main.h" 00061 #include "BKE_nla.h" 00062 #include "BKE_global.h" 00063 #include "BKE_context.h" 00064 #include "BKE_report.h" 00065 #include "BKE_key.h" 00066 #include "BKE_material.h" 00067 00068 #include "ED_anim_api.h" 00069 #include "ED_keyframing.h" 00070 #include "ED_keyframes_edit.h" 00071 #include "ED_screen.h" 00072 00073 #include "UI_interface.h" 00074 00075 #include "WM_api.h" 00076 #include "WM_types.h" 00077 00078 #include "RNA_access.h" 00079 #include "RNA_define.h" 00080 #include "RNA_enum_types.h" 00081 00082 #include "anim_intern.h" 00083 00084 /* ************************************************** */ 00085 /* Keyframing Setting Wrangling */ 00086 00087 /* Get the active settings for keyframing settings from context (specifically the given scene) */ 00088 short ANIM_get_keyframing_flags (Scene *scene, short incl_mode) 00089 { 00090 short flag = 0; 00091 00092 /* standard flags */ 00093 { 00094 /* visual keying */ 00095 if (IS_AUTOKEY_FLAG(scene, AUTOMATKEY)) 00096 flag |= INSERTKEY_MATRIX; 00097 00098 /* only needed */ 00099 if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) 00100 flag |= INSERTKEY_NEEDED; 00101 00102 /* default F-Curve color mode - RGB from XYZ indices */ 00103 if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) 00104 flag |= INSERTKEY_XYZ2RGB; 00105 } 00106 00107 /* only if including settings from the autokeying mode... */ 00108 if (incl_mode) 00109 { 00110 /* keyframing mode - only replace existing keyframes */ 00111 if (IS_AUTOKEY_MODE(scene, EDITKEYS)) 00112 flag |= INSERTKEY_REPLACE; 00113 } 00114 00115 return flag; 00116 } 00117 00118 /* ******************************************* */ 00119 /* Animation Data Validation */ 00120 00121 /* Get (or add relevant data to be able to do so) the Active Action for the given 00122 * Animation Data block, given an ID block where the Animation Data should reside. 00123 */ 00124 bAction *verify_adt_action (ID *id, short add) 00125 { 00126 AnimData *adt; 00127 00128 /* init animdata if none available yet */ 00129 adt= BKE_animdata_from_id(id); 00130 if ((adt == NULL) && (add)) 00131 adt= BKE_id_add_animdata(id); 00132 if (adt == NULL) { 00133 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ 00134 printf("ERROR: Couldn't add AnimData (ID = %s) \n", (id) ? (id->name) : "<None>"); 00135 return NULL; 00136 } 00137 00138 /* init action if none available yet */ 00139 // TODO: need some wizardry to handle NLA stuff correct 00140 if ((adt->action == NULL) && (add)) { 00141 char actname[sizeof(id->name)-2]; 00142 BLI_snprintf(actname, sizeof(actname), "%sAction", id->name+2); 00143 adt->action= add_empty_action(actname); 00144 } 00145 00146 /* return the action */ 00147 return adt->action; 00148 } 00149 00150 /* Get (or add relevant data to be able to do so) F-Curve from the Active Action, 00151 * for the given Animation Data block. This assumes that all the destinations are valid. 00152 */ 00153 FCurve *verify_fcurve (bAction *act, const char group[], const char rna_path[], const int array_index, short add) 00154 { 00155 bActionGroup *grp; 00156 FCurve *fcu; 00157 00158 /* sanity checks */ 00159 if ELEM(NULL, act, rna_path) 00160 return NULL; 00161 00162 /* try to find f-curve matching for this setting 00163 * - add if not found and allowed to add one 00164 * TODO: add auto-grouping support? how this works will need to be resolved 00165 */ 00166 if (act) 00167 fcu= list_find_fcurve(&act->curves, rna_path, array_index); 00168 else 00169 fcu= NULL; 00170 00171 if ((fcu == NULL) && (add)) { 00172 /* use default settings to make a F-Curve */ 00173 fcu= MEM_callocN(sizeof(FCurve), "FCurve"); 00174 00175 fcu->flag = (FCURVE_VISIBLE|FCURVE_SELECTED); 00176 if (act->curves.first==NULL) 00177 fcu->flag |= FCURVE_ACTIVE; /* first one added active */ 00178 00179 /* store path - make copy, and store that */ 00180 fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path)); 00181 fcu->array_index= array_index; 00182 00183 /* if a group name has been provided, try to add or find a group, then add F-Curve to it */ 00184 if (group) { 00185 /* try to find group */ 00186 grp= action_groups_find_named(act, group); 00187 00188 /* no matching groups, so add one */ 00189 if (grp == NULL) 00190 grp= action_groups_add_new(act, group); 00191 00192 /* add F-Curve to group */ 00193 action_groups_add_channel(act, grp, fcu); 00194 } 00195 else { 00196 /* just add F-Curve to end of Action's list */ 00197 BLI_addtail(&act->curves, fcu); 00198 } 00199 } 00200 00201 /* return the F-Curve */ 00202 return fcu; 00203 } 00204 00205 /* ************************************************** */ 00206 /* KEYFRAME INSERTION */ 00207 00208 /* -------------- BezTriple Insertion -------------------- */ 00209 00210 /* This function adds a given BezTriple to an F-Curve. It will allocate 00211 * memory for the array if needed, and will insert the BezTriple into a 00212 * suitable place in chronological order. 00213 * 00214 * NOTE: any recalculate of the F-Curve that needs to be done will need to 00215 * be done by the caller. 00216 */ 00217 int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag) 00218 { 00219 int i= 0; 00220 00221 /* are there already keyframes? */ 00222 if (fcu->bezt) { 00223 short replace = -1; 00224 i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace); 00225 00226 /* replace an existing keyframe? */ 00227 if (replace) { 00228 /* sanity check: 'i' may in rare cases exceed arraylen */ 00229 if ((i >= 0) && (i < fcu->totvert)) { 00230 /* just change the values when replacing, so as to not overwrite handles */ 00231 BezTriple *dst= (fcu->bezt + i); 00232 float dy= bezt->vec[1][1] - dst->vec[1][1]; 00233 00234 /* just apply delta value change to the handle values */ 00235 dst->vec[0][1] += dy; 00236 dst->vec[1][1] += dy; 00237 dst->vec[2][1] += dy; 00238 00239 dst->f1= bezt->f1; 00240 dst->f2= bezt->f2; 00241 dst->f3= bezt->f3; 00242 00243 // TODO: perform some other operations? 00244 } 00245 } 00246 /* keyframing modes allow to not replace keyframe */ 00247 else if ((flag & INSERTKEY_REPLACE) == 0) { 00248 /* insert new - if we're not restricted to replacing keyframes only */ 00249 BezTriple *newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple"); 00250 00251 /* add the beztriples that should occur before the beztriple to be pasted (originally in fcu) */ 00252 if (i > 0) 00253 memcpy(newb, fcu->bezt, i*sizeof(BezTriple)); 00254 00255 /* add beztriple to paste at index i */ 00256 *(newb + i)= *bezt; 00257 00258 /* add the beztriples that occur after the beztriple to be pasted (originally in fcu) */ 00259 if (i < fcu->totvert) 00260 memcpy(newb+i+1, fcu->bezt+i, (fcu->totvert-i)*sizeof(BezTriple)); 00261 00262 /* replace (+ free) old with new, only if necessary to do so */ 00263 MEM_freeN(fcu->bezt); 00264 fcu->bezt= newb; 00265 00266 fcu->totvert++; 00267 } 00268 } 00269 /* no keyframes already, but can only add if... 00270 * 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know 00271 * 2) there are no samples on the curve 00272 * // NOTE: maybe we may want to allow this later when doing samples -> bezt conversions, 00273 * // but for now, having both is asking for trouble 00274 */ 00275 else if ((flag & INSERTKEY_REPLACE)==0 && (fcu->fpt==NULL)) { 00276 /* create new keyframes array */ 00277 fcu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); 00278 *(fcu->bezt)= *bezt; 00279 fcu->totvert= 1; 00280 } 00281 /* cannot add anything */ 00282 else { 00283 /* return error code -1 to prevent any misunderstandings */ 00284 return -1; 00285 } 00286 00287 00288 /* we need to return the index, so that some tools which do post-processing can 00289 * detect where we added the BezTriple in the array 00290 */ 00291 return i; 00292 } 00293 00294 /* This function is a wrapper for insert_bezt_fcurve_internal(), and should be used when 00295 * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet. 00296 * It returns the index at which the keyframe was added. 00297 */ 00298 int insert_vert_fcurve (FCurve *fcu, float x, float y, short flag) 00299 { 00300 BezTriple beztr= {{{0}}}; 00301 unsigned int oldTot = fcu->totvert; 00302 int a; 00303 00304 /* set all three points, for nicer start position 00305 * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok... 00306 */ 00307 beztr.vec[0][0]= x-1.0f; 00308 beztr.vec[0][1]= y; 00309 beztr.vec[1][0]= x; 00310 beztr.vec[1][1]= y; 00311 beztr.vec[2][0]= x+1.0f; 00312 beztr.vec[2][1]= y; 00313 beztr.f1= beztr.f2= beztr.f3= SELECT; 00314 beztr.h1= beztr.h2= U.keyhandles_new; /* use default handle type here */ 00315 //BEZKEYTYPE(&beztr)= scene->keytype; /* default keyframe type */ 00316 00317 /* use default interpolation mode, with exceptions for int/discrete values */ 00318 beztr.ipo= U.ipo_new; 00319 00320 if(fcu->flag & FCURVE_DISCRETE_VALUES) 00321 beztr.ipo = BEZT_IPO_CONST; 00322 else if(beztr.ipo == BEZT_IPO_BEZ && (fcu->flag & FCURVE_INT_VALUES)) 00323 beztr.ipo = BEZT_IPO_LIN; 00324 00325 /* add temp beztriple to keyframes */ 00326 a= insert_bezt_fcurve(fcu, &beztr, flag); 00327 00328 /* what if 'a' is a negative index? 00329 * for now, just exit to prevent any segfaults 00330 */ 00331 if (a < 0) return -1; 00332 00333 /* don't recalculate handles if fast is set 00334 * - this is a hack to make importers faster 00335 * - we may calculate twice (due to autohandle needing to be calculated twice) 00336 */ 00337 if ((flag & INSERTKEY_FAST) == 0) 00338 calchandles_fcurve(fcu); 00339 00340 /* set handletype and interpolation */ 00341 if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE)==0) { 00342 BezTriple *bezt= (fcu->bezt + a); 00343 00344 /* set interpolation from previous (if available), but only if we didn't just replace some keyframe 00345 * - replacement is indicated by no-change in number of verts 00346 * - when replacing, the user may have specified some interpolation that should be kept 00347 */ 00348 if (fcu->totvert > oldTot) { 00349 if (a > 0) 00350 bezt->ipo= (bezt-1)->ipo; 00351 else if (a < fcu->totvert-1) 00352 bezt->ipo= (bezt+1)->ipo; 00353 } 00354 00355 /* don't recalculate handles if fast is set 00356 * - this is a hack to make importers faster 00357 * - we may calculate twice (due to autohandle needing to be calculated twice) 00358 */ 00359 if ((flag & INSERTKEY_FAST) == 0) 00360 calchandles_fcurve(fcu); 00361 } 00362 00363 /* return the index at which the keyframe was added */ 00364 return a; 00365 } 00366 00367 /* -------------- 'Smarter' Keyframing Functions -------------------- */ 00368 /* return codes for new_key_needed */ 00369 enum { 00370 KEYNEEDED_DONTADD = 0, 00371 KEYNEEDED_JUSTADD, 00372 KEYNEEDED_DELPREV, 00373 KEYNEEDED_DELNEXT 00374 } /*eKeyNeededStatus*/; 00375 00376 /* This helper function determines whether a new keyframe is needed */ 00377 /* Cases where keyframes should not be added: 00378 * 1. Keyframe to be added bewteen two keyframes with similar values 00379 * 2. Keyframe to be added on frame where two keyframes are already situated 00380 * 3. Keyframe lies at point that intersects the linear line between two keyframes 00381 */ 00382 static short new_key_needed (FCurve *fcu, float cFrame, float nValue) 00383 { 00384 BezTriple *bezt=NULL, *prev=NULL; 00385 int totCount, i; 00386 float valA = 0.0f, valB = 0.0f; 00387 00388 /* safety checking */ 00389 if (fcu == NULL) return KEYNEEDED_JUSTADD; 00390 totCount= fcu->totvert; 00391 if (totCount == 0) return KEYNEEDED_JUSTADD; 00392 00393 /* loop through checking if any are the same */ 00394 bezt= fcu->bezt; 00395 for (i=0; i<totCount; i++) { 00396 float prevPosi=0.0f, prevVal=0.0f; 00397 float beztPosi=0.0f, beztVal=0.0f; 00398 00399 /* get current time+value */ 00400 beztPosi= bezt->vec[1][0]; 00401 beztVal= bezt->vec[1][1]; 00402 00403 if (prev) { 00404 /* there is a keyframe before the one currently being examined */ 00405 00406 /* get previous time+value */ 00407 prevPosi= prev->vec[1][0]; 00408 prevVal= prev->vec[1][1]; 00409 00410 /* keyframe to be added at point where there are already two similar points? */ 00411 if (IS_EQF(prevPosi, cFrame) && IS_EQF(beztPosi, cFrame) && IS_EQF(beztPosi, prevPosi)) { 00412 return KEYNEEDED_DONTADD; 00413 } 00414 00415 /* keyframe between prev+current points ? */ 00416 if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { 00417 /* is the value of keyframe to be added the same as keyframes on either side ? */ 00418 if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal)) { 00419 return KEYNEEDED_DONTADD; 00420 } 00421 else { 00422 float realVal; 00423 00424 /* get real value of curve at that point */ 00425 realVal= evaluate_fcurve(fcu, cFrame); 00426 00427 /* compare whether it's the same as proposed */ 00428 if (IS_EQF(realVal, nValue)) 00429 return KEYNEEDED_DONTADD; 00430 else 00431 return KEYNEEDED_JUSTADD; 00432 } 00433 } 00434 00435 /* new keyframe before prev beztriple? */ 00436 if (cFrame < prevPosi) { 00437 /* A new keyframe will be added. However, whether the previous beztriple 00438 * stays around or not depends on whether the values of previous/current 00439 * beztriples and new keyframe are the same. 00440 */ 00441 if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal)) 00442 return KEYNEEDED_DELNEXT; 00443 else 00444 return KEYNEEDED_JUSTADD; 00445 } 00446 } 00447 else { 00448 /* just add a keyframe if there's only one keyframe 00449 * and the new one occurs before the exisiting one does. 00450 */ 00451 if ((cFrame < beztPosi) && (totCount==1)) 00452 return KEYNEEDED_JUSTADD; 00453 } 00454 00455 /* continue. frame to do not yet passed (or other conditions not met) */ 00456 if (i < (totCount-1)) { 00457 prev= bezt; 00458 bezt++; 00459 } 00460 else 00461 break; 00462 } 00463 00464 /* Frame in which to add a new-keyframe occurs after all other keys 00465 * -> If there are at least two existing keyframes, then if the values of the 00466 * last two keyframes and the new-keyframe match, the last existing keyframe 00467 * gets deleted as it is no longer required. 00468 * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last 00469 * keyframe is not equal to last keyframe. 00470 */ 00471 bezt= (fcu->bezt + (fcu->totvert - 1)); 00472 valA= bezt->vec[1][1]; 00473 00474 if (prev) 00475 valB= prev->vec[1][1]; 00476 else 00477 valB= bezt->vec[1][1] + 1.0f; 00478 00479 if (IS_EQF(valA, nValue) && IS_EQF(valA, valB)) 00480 return KEYNEEDED_DELPREV; 00481 else 00482 return KEYNEEDED_JUSTADD; 00483 } 00484 00485 /* ------------------ RNA Data-Access Functions ------------------ */ 00486 00487 /* Try to read value using RNA-properties obtained already */ 00488 static float setting_get_rna_value (PointerRNA *ptr, PropertyRNA *prop, int index) 00489 { 00490 float value= 0.0f; 00491 00492 switch (RNA_property_type(prop)) { 00493 case PROP_BOOLEAN: 00494 if (RNA_property_array_length(ptr, prop)) 00495 value= (float)RNA_property_boolean_get_index(ptr, prop, index); 00496 else 00497 value= (float)RNA_property_boolean_get(ptr, prop); 00498 break; 00499 case PROP_INT: 00500 if (RNA_property_array_length(ptr, prop)) 00501 value= (float)RNA_property_int_get_index(ptr, prop, index); 00502 else 00503 value= (float)RNA_property_int_get(ptr, prop); 00504 break; 00505 case PROP_FLOAT: 00506 if (RNA_property_array_length(ptr, prop)) 00507 value= RNA_property_float_get_index(ptr, prop, index); 00508 else 00509 value= RNA_property_float_get(ptr, prop); 00510 break; 00511 case PROP_ENUM: 00512 value= (float)RNA_property_enum_get(ptr, prop); 00513 break; 00514 default: 00515 break; 00516 } 00517 00518 return value; 00519 } 00520 00521 /* ------------------ 'Visual' Keyframing Functions ------------------ */ 00522 00523 /* internal status codes for visualkey_can_use */ 00524 enum { 00525 VISUALKEY_NONE = 0, 00526 VISUALKEY_LOC, 00527 VISUALKEY_ROT 00528 /* VISUALKEY_SCA */ /* TODO - looks like support can be added now */ 00529 }; 00530 00531 /* This helper function determines if visual-keyframing should be used when 00532 * inserting keyframes for the given channel. As visual-keyframing only works 00533 * on Object and Pose-Channel blocks, this should only get called for those 00534 * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying 00535 * settings is on. 00536 */ 00537 static short visualkey_can_use (PointerRNA *ptr, PropertyRNA *prop) 00538 { 00539 bConstraint *con= NULL; 00540 short searchtype= VISUALKEY_NONE; 00541 short has_parent = FALSE; 00542 const char *identifier= NULL; 00543 00544 /* validate data */ 00545 // TODO: this check is probably not needed, but it won't hurt 00546 if (ELEM3(NULL, ptr, ptr->data, prop)) 00547 return 0; 00548 00549 /* get first constraint and determine type of keyframe constraints to check for 00550 * - constraints can be on either Objects or PoseChannels, so we only check if the 00551 * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for 00552 * those structs, allowing us to identify the owner of the data 00553 */ 00554 if (ptr->type == &RNA_Object) { 00555 /* Object */ 00556 Object *ob= (Object *)ptr->data; 00557 00558 con= ob->constraints.first; 00559 identifier= RNA_property_identifier(prop); 00560 has_parent= (ob->parent != NULL); 00561 } 00562 else if (ptr->type == &RNA_PoseBone) { 00563 /* Pose Channel */ 00564 bPoseChannel *pchan= (bPoseChannel *)ptr->data; 00565 00566 con= pchan->constraints.first; 00567 identifier= RNA_property_identifier(prop); 00568 has_parent= (pchan->parent != NULL); 00569 } 00570 00571 /* check if any data to search using */ 00572 if (ELEM(NULL, con, identifier) && (has_parent == FALSE)) 00573 return 0; 00574 00575 /* location or rotation identifiers only... */ 00576 if(identifier == NULL) { 00577 printf("%s failed: NULL identifier\n", __func__); 00578 return 0; 00579 } 00580 else if (strstr(identifier, "location")) { 00581 searchtype= VISUALKEY_LOC; 00582 } 00583 else if (strstr(identifier, "rotation")) { 00584 searchtype= VISUALKEY_ROT; 00585 } 00586 else { 00587 printf("%s failed: identifier - '%s' \n", __func__, identifier); 00588 return 0; 00589 } 00590 00591 00592 /* only search if a searchtype and initial constraint are available */ 00593 if (searchtype) { 00594 /* parent is always matching */ 00595 if (has_parent) 00596 return 1; 00597 00598 /* constraints */ 00599 for (; con; con= con->next) { 00600 /* only consider constraint if it is not disabled, and has influence */ 00601 if (con->flag & CONSTRAINT_DISABLE) continue; 00602 if (con->enforce == 0.0f) continue; 00603 00604 /* some constraints may alter these transforms */ 00605 switch (con->type) { 00606 /* multi-transform constraints */ 00607 case CONSTRAINT_TYPE_CHILDOF: 00608 return 1; 00609 case CONSTRAINT_TYPE_TRANSFORM: 00610 case CONSTRAINT_TYPE_TRANSLIKE: 00611 return 1; 00612 case CONSTRAINT_TYPE_FOLLOWPATH: 00613 return 1; 00614 case CONSTRAINT_TYPE_KINEMATIC: 00615 return 1; 00616 00617 /* single-transform constraits */ 00618 case CONSTRAINT_TYPE_TRACKTO: 00619 if (searchtype==VISUALKEY_ROT) return 1; 00620 break; 00621 case CONSTRAINT_TYPE_ROTLIMIT: 00622 if (searchtype==VISUALKEY_ROT) return 1; 00623 break; 00624 case CONSTRAINT_TYPE_LOCLIMIT: 00625 if (searchtype==VISUALKEY_LOC) return 1; 00626 break; 00627 case CONSTRAINT_TYPE_ROTLIKE: 00628 if (searchtype==VISUALKEY_ROT) return 1; 00629 break; 00630 case CONSTRAINT_TYPE_DISTLIMIT: 00631 if (searchtype==VISUALKEY_LOC) return 1; 00632 break; 00633 case CONSTRAINT_TYPE_LOCLIKE: 00634 if (searchtype==VISUALKEY_LOC) return 1; 00635 break; 00636 case CONSTRAINT_TYPE_LOCKTRACK: 00637 if (searchtype==VISUALKEY_ROT) return 1; 00638 break; 00639 case CONSTRAINT_TYPE_MINMAX: 00640 if (searchtype==VISUALKEY_LOC) return 1; 00641 break; 00642 00643 default: 00644 break; 00645 } 00646 } 00647 } 00648 00649 /* when some condition is met, this function returns, so here it can be 0 */ 00650 return 0; 00651 } 00652 00653 /* This helper function extracts the value to use for visual-keyframing 00654 * In the event that it is not possible to perform visual keying, try to fall-back 00655 * to using the default method. Assumes that all data it has been passed is valid. 00656 */ 00657 static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_index) 00658 { 00659 const char *identifier= RNA_property_identifier(prop); 00660 00661 /* handle for Objects or PoseChannels only 00662 * - constraints can be on either Objects or PoseChannels, so we only check if the 00663 * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for 00664 * those structs, allowing us to identify the owner of the data 00665 * - assume that array_index will be sane 00666 */ 00667 if (ptr->type == &RNA_Object) { 00668 Object *ob= (Object *)ptr->data; 00669 00670 /* only Location or Rotation keyframes are supported now */ 00671 if (strstr(identifier, "location")) { 00672 return ob->obmat[3][array_index]; 00673 } 00674 else if (strstr(identifier, "rotation_euler")) { 00675 float eul[3]; 00676 00677 mat4_to_eulO(eul, ob->rotmode, ob->obmat); 00678 return eul[array_index]; 00679 } 00680 else if (strstr(identifier, "rotation_quaternion")) { 00681 float trimat[3][3], quat[4]; 00682 00683 copy_m3_m4(trimat, ob->obmat); 00684 mat3_to_quat_is_ok(quat, trimat); 00685 00686 return quat[array_index]; 00687 } 00688 else if (strstr(identifier, "rotation_axis_angle")) { 00689 float axis[3], angle; 00690 00691 mat4_to_axis_angle(axis, &angle, ob->obmat); 00692 00693 /* w = 0, x,y,z = 1,2,3 */ 00694 if (array_index == 0) 00695 return angle; 00696 else 00697 return axis[array_index - 1]; 00698 } 00699 } 00700 else if (ptr->type == &RNA_PoseBone) { 00701 Object *ob = (Object *)ptr->id.data; /* we assume that this is always set, and is an object */ 00702 bPoseChannel *pchan= (bPoseChannel *)ptr->data; 00703 float tmat[4][4]; 00704 00705 /* Although it is not strictly required for this particular space conversion, 00706 * arg1 must not be null, as there is a null check for the other conversions to 00707 * be safe. Therefore, the active object is passed here, and in many cases, this 00708 * will be what owns the pose-channel that is getting this anyway. 00709 */ 00710 copy_m4_m4(tmat, pchan->pose_mat); 00711 constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); 00712 00713 /* Loc, Rot/Quat keyframes are supported... */ 00714 if (strstr(identifier, "location")) { 00715 /* only use for non-connected bones */ 00716 if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED)) 00717 return tmat[3][array_index]; 00718 else if (pchan->bone->parent == NULL) 00719 return tmat[3][array_index]; 00720 } 00721 else if (strstr(identifier, "rotation_euler")) { 00722 float eul[3]; 00723 00724 mat4_to_eulO(eul, pchan->rotmode, tmat); 00725 return eul[array_index]; 00726 } 00727 else if (strstr(identifier, "rotation_quaternion")) { 00728 float trimat[3][3], quat[4]; 00729 00730 copy_m3_m4(trimat, tmat); 00731 mat3_to_quat_is_ok(quat, trimat); 00732 00733 return quat[array_index]; 00734 } 00735 else if (strstr(identifier, "rotation_axis_angle")) { 00736 float axis[3], angle; 00737 00738 mat4_to_axis_angle(axis, &angle, tmat); 00739 00740 /* w = 0, x,y,z = 1,2,3 */ 00741 if (array_index == 0) 00742 return angle; 00743 else 00744 return axis[array_index - 1]; 00745 } 00746 } 00747 00748 /* as the function hasn't returned yet, read value from system in the default way */ 00749 return setting_get_rna_value(ptr, prop, array_index); 00750 } 00751 00752 /* ------------------------- Insert Key API ------------------------- */ 00753 00754 /* Secondary Keyframing API call: 00755 * Use this when validation of necessary animation data is not necessary, since an RNA-pointer to the necessary 00756 * data being keyframed, and a pointer to the F-Curve to use have both been provided. 00757 * 00758 * The flag argument is used for special settings that alter the behaviour of 00759 * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, 00760 * and extra keyframe filtering. 00761 */ 00762 short insert_keyframe_direct (ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, short flag) 00763 { 00764 float curval= 0.0f; 00765 00766 /* no F-Curve to add keyframe to? */ 00767 if (fcu == NULL) { 00768 BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to"); 00769 return 0; 00770 } 00771 /* F-Curve not editable? */ 00772 if (fcurve_is_keyframable(fcu) == 0) { 00773 BKE_reportf(reports, RPT_ERROR, 00774 "F-Curve with path = '%s' [%d] cannot be keyframed. Ensure that it is not locked or sampled. Also, try removing F-Modifiers", 00775 fcu->rna_path, fcu->array_index); 00776 return 0; 00777 } 00778 00779 /* if no property given yet, try to validate from F-Curve info */ 00780 if ((ptr.id.data == NULL) && (ptr.data==NULL)) { 00781 BKE_report(reports, RPT_ERROR, "No RNA-pointer available to retrieve values for keyframing from"); 00782 return 0; 00783 } 00784 if (prop == NULL) { 00785 PointerRNA tmp_ptr; 00786 00787 /* try to get property we should be affecting */ 00788 if ((RNA_path_resolve(&ptr, fcu->rna_path, &tmp_ptr, &prop) == 0) || (prop == NULL)) { 00789 /* property not found... */ 00790 const char *idname= (ptr.id.data) ? ((ID *)ptr.id.data)->name : "<No ID-Pointer>"; 00791 00792 BKE_reportf(reports, RPT_ERROR, 00793 "Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", 00794 idname, fcu->rna_path); 00795 return 0; 00796 } 00797 else { 00798 /* property found, so overwrite 'ptr' to make later code easier */ 00799 ptr= tmp_ptr; 00800 } 00801 } 00802 00803 /* set additional flags for the F-Curve (i.e. only integer values) */ 00804 fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES); 00805 switch (RNA_property_type(prop)) { 00806 case PROP_FLOAT: 00807 /* do nothing */ 00808 break; 00809 case PROP_INT: 00810 /* do integer (only 'whole' numbers) interpolation between all points */ 00811 fcu->flag |= FCURVE_INT_VALUES; 00812 break; 00813 default: 00814 /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate 00815 * values at all) interpolation between all points 00816 * - however, we must also ensure that evaluated values are only integers still 00817 */ 00818 fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES); 00819 break; 00820 } 00821 00822 /* obtain value to give keyframe */ 00823 if ( (flag & INSERTKEY_MATRIX) && 00824 (visualkey_can_use(&ptr, prop)) ) 00825 { 00826 /* visual-keying is only available for object and pchan datablocks, as 00827 * it works by keyframing using a value extracted from the final matrix 00828 * instead of using the kt system to extract a value. 00829 */ 00830 curval= visualkey_get_value(&ptr, prop, fcu->array_index); 00831 } 00832 else { 00833 /* read value from system */ 00834 curval= setting_get_rna_value(&ptr, prop, fcu->array_index); 00835 } 00836 00837 /* only insert keyframes where they are needed */ 00838 if (flag & INSERTKEY_NEEDED) { 00839 short insert_mode; 00840 00841 /* check whether this curve really needs a new keyframe */ 00842 insert_mode= new_key_needed(fcu, cfra, curval); 00843 00844 /* insert new keyframe at current frame */ 00845 if (insert_mode) 00846 insert_vert_fcurve(fcu, cfra, curval, flag); 00847 00848 /* delete keyframe immediately before/after newly added */ 00849 switch (insert_mode) { 00850 case KEYNEEDED_DELPREV: 00851 delete_fcurve_key(fcu, fcu->totvert-2, 1); 00852 break; 00853 case KEYNEEDED_DELNEXT: 00854 delete_fcurve_key(fcu, 1, 1); 00855 break; 00856 } 00857 00858 /* only return success if keyframe added */ 00859 if (insert_mode) 00860 return 1; 00861 } 00862 else { 00863 /* just insert keyframe */ 00864 insert_vert_fcurve(fcu, cfra, curval, flag); 00865 00866 /* return success */ 00867 return 1; 00868 } 00869 00870 /* failed */ 00871 return 0; 00872 } 00873 00874 /* Main Keyframing API call: 00875 * Use this when validation of necessary animation data is necessary, since it may not exist yet. 00876 * 00877 * The flag argument is used for special settings that alter the behaviour of 00878 * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, 00879 * and extra keyframe filtering. 00880 * 00881 * index of -1 keys all array indices 00882 */ 00883 short insert_keyframe (ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) 00884 { 00885 PointerRNA id_ptr, ptr; 00886 PropertyRNA *prop = NULL; 00887 FCurve *fcu; 00888 int array_index_max= array_index+1; 00889 int ret= 0; 00890 00891 /* validate pointer first - exit if failure */ 00892 if (id == NULL) { 00893 BKE_reportf(reports, RPT_ERROR, "No ID-block to insert keyframe in (Path = %s)", rna_path); 00894 return 0; 00895 } 00896 00897 RNA_id_pointer_create(id, &id_ptr); 00898 if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { 00899 BKE_reportf(reports, RPT_ERROR, 00900 "Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", 00901 (id)? id->name : "<Missing ID-Block>", rna_path); 00902 return 0; 00903 } 00904 00905 /* if no action is provided, keyframe to the default one attached to this ID-block */ 00906 if (act == NULL) { 00907 AnimData *adt= BKE_animdata_from_id(id); 00908 00909 /* get action to add F-Curve+keyframe to */ 00910 act= verify_adt_action(id, 1); 00911 00912 if (act == NULL) { 00913 BKE_reportf(reports, RPT_ERROR, 00914 "Could not insert keyframe, as this type does not support animation data (ID = %s, Path = %s)", 00915 id->name, rna_path); 00916 return 0; 00917 } 00918 00919 /* apply NLA-mapping to frame to use (if applicable) */ 00920 cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); 00921 } 00922 00923 /* key entire array convenience method */ 00924 if (array_index == -1) { 00925 array_index= 0; 00926 array_index_max= RNA_property_array_length(&ptr, prop); 00927 00928 /* for single properties, increase max_index so that the property itself gets included, 00929 * but don't do this for standard arrays since that can cause corruption issues 00930 * (extra unused curves) 00931 */ 00932 if (array_index_max == array_index) 00933 array_index_max++; 00934 } 00935 00936 /* will only loop once unless the array index was -1 */ 00937 for (; array_index < array_index_max; array_index++) { 00938 /* make sure the F-Curve exists 00939 * - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet 00940 * but still try to get the F-Curve if it exists... 00941 */ 00942 fcu= verify_fcurve(act, group, rna_path, array_index, (flag & INSERTKEY_REPLACE)==0); 00943 00944 /* we may not have a F-Curve when we're replacing only... */ 00945 if (fcu) { 00946 /* set color mode if the F-Curve is new (i.e. without any keyframes) */ 00947 if ((fcu->totvert == 0) && (flag & INSERTKEY_XYZ2RGB)) { 00948 /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor, 00949 * is determined by the array index for the F-Curve 00950 */ 00951 if (ELEM5(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) { 00952 fcu->color_mode= FCURVE_COLOR_AUTO_RGB; 00953 } 00954 } 00955 00956 /* insert keyframe */ 00957 ret += insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag); 00958 } 00959 } 00960 00961 return ret; 00962 } 00963 00964 /* ************************************************** */ 00965 /* KEYFRAME DELETION */ 00966 00967 /* Main Keyframing API call: 00968 * Use this when validation of necessary animation data isn't necessary as it 00969 * already exists. It will delete a keyframe at the current frame. 00970 * 00971 * The flag argument is used for special settings that alter the behaviour of 00972 * the keyframe deletion. These include the quick refresh options. 00973 */ 00974 short delete_keyframe (ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag)) 00975 { 00976 AnimData *adt= BKE_animdata_from_id(id); 00977 PointerRNA id_ptr, ptr; 00978 PropertyRNA *prop; 00979 int array_index_max= array_index+1; 00980 int ret= 0; 00981 00982 /* sanity checks */ 00983 if ELEM(NULL, id, adt) { 00984 BKE_report(reports, RPT_ERROR, "No ID-Block and/Or AnimData to delete keyframe from"); 00985 return 0; 00986 } 00987 00988 /* validate pointer first - exit if failure */ 00989 RNA_id_pointer_create(id, &id_ptr); 00990 if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { 00991 BKE_reportf(reports, RPT_ERROR, "Could not delete keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", id->name, rna_path); 00992 return 0; 00993 } 00994 00995 /* get F-Curve 00996 * Note: here is one of the places where we don't want new Action + F-Curve added! 00997 * so 'add' var must be 0 00998 */ 00999 if (act == NULL) { 01000 /* if no action is provided, use the default one attached to this ID-block 01001 * - if it doesn't exist, then we're out of options... 01002 */ 01003 if (adt->action) { 01004 act= adt->action; 01005 01006 /* apply NLA-mapping to frame to use (if applicable) */ 01007 cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); 01008 } 01009 else { 01010 BKE_reportf(reports, RPT_ERROR, "No Action to delete keyframes from for ID = %s \n", id->name); 01011 return 0; 01012 } 01013 } 01014 01015 /* key entire array convenience method */ 01016 if (array_index == -1) { 01017 array_index= 0; 01018 array_index_max= RNA_property_array_length(&ptr, prop); 01019 01020 /* for single properties, increase max_index so that the property itself gets included, 01021 * but don't do this for standard arrays since that can cause corruption issues 01022 * (extra unused curves) 01023 */ 01024 if (array_index_max == array_index) 01025 array_index_max++; 01026 } 01027 01028 /* will only loop once unless the array index was -1 */ 01029 for (; array_index < array_index_max; array_index++) { 01030 FCurve *fcu= verify_fcurve(act, group, rna_path, array_index, 0); 01031 short found = -1; 01032 int i; 01033 01034 /* check if F-Curve exists and/or whether it can be edited */ 01035 if (fcu == NULL) 01036 continue; 01037 01038 if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) { 01039 if (G.f & G_DEBUG) 01040 printf("WARNING: not deleting keyframe for locked F-Curve \n"); 01041 continue; 01042 } 01043 01044 /* try to find index of beztriple to get rid of */ 01045 i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found); 01046 if (found) { 01047 /* delete the key at the index (will sanity check + do recalc afterwards) */ 01048 delete_fcurve_key(fcu, i, 1); 01049 01050 /* Only delete curve too if it won't be doing anything anymore */ 01051 if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) 01052 ANIM_fcurve_delete_from_animdata(NULL, adt, fcu); 01053 01054 /* return success */ 01055 ret++; 01056 } 01057 } 01058 01059 /* return success/failure */ 01060 return ret; 01061 } 01062 01063 /* ******************************************* */ 01064 /* KEYFRAME MODIFICATION */ 01065 01066 /* mode for commonkey_modifykey */ 01067 enum { 01068 COMMONKEY_MODE_INSERT = 0, 01069 COMMONKEY_MODE_DELETE, 01070 } /*eCommonModifyKey_Modes*/; 01071 01072 /* Polling callback for use with ANIM_*_keyframe() operators 01073 * This is based on the standard ED_operator_areaactive callback, 01074 * except that it does special checks for a few spacetypes too... 01075 */ 01076 static int modify_key_op_poll(bContext *C) 01077 { 01078 ScrArea *sa= CTX_wm_area(C); 01079 Scene *scene= CTX_data_scene(C); 01080 SpaceOops *so= CTX_wm_space_outliner(C); 01081 01082 /* if no area or active scene */ 01083 if (ELEM(NULL, sa, scene)) 01084 return 0; 01085 01086 /* if Outliner, don't allow in some views */ 01087 if (so) { 01088 if (ELEM4(so->outlinevis, SO_GROUPS, SO_LIBRARIES, SO_VERSE_SESSION, SO_VERSE_SESSION)) 01089 return 0; 01090 if (ELEM3(so->outlinevis, SO_SEQUENCE, SO_USERDEF, SO_KEYMAP)) 01091 return 0; 01092 } 01093 01094 /* TODO: checks for other space types can be added here */ 01095 01096 /* should be fine */ 01097 return 1; 01098 } 01099 01100 /* Insert Key Operator ------------------------ */ 01101 01102 static int insert_key_exec (bContext *C, wmOperator *op) 01103 { 01104 Main *bmain= CTX_data_main(C); 01105 Scene *scene= CTX_data_scene(C); 01106 KeyingSet *ks= NULL; 01107 int type= RNA_enum_get(op->ptr, "type"); 01108 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap 01109 short success; 01110 01111 /* type is the Keying Set the user specified to use when calling the operator: 01112 * - type == 0: use scene's active Keying Set 01113 * - type > 0: use a user-defined Keying Set from the active scene 01114 * - type < 0: use a builtin Keying Set 01115 */ 01116 if (type == 0) 01117 type= scene->active_keyingset; 01118 if (type > 0) 01119 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 01120 else 01121 ks= BLI_findlink(&builtin_keyingsets, -type-1); 01122 01123 /* report failures */ 01124 if (ks == NULL) { 01125 BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); 01126 return OPERATOR_CANCELLED; 01127 } 01128 01129 /* try to insert keyframes for the channels specified by KeyingSet */ 01130 success= ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 01131 if (G.f & G_DEBUG) 01132 BKE_reportf(op->reports, RPT_INFO, "KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success); 01133 01134 /* report failure or do updates? */ 01135 if (success == MODIFYKEY_INVALID_CONTEXT) { 01136 BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set"); 01137 return OPERATOR_CANCELLED; 01138 } 01139 else if (success) { 01140 /* if the appropriate properties have been set, make a note that we've inserted something */ 01141 if (RNA_boolean_get(op->ptr, "confirm_success")) 01142 BKE_reportf(op->reports, RPT_INFO, "Successfully added %d Keyframes for KeyingSet '%s'", success, ks->name); 01143 01144 /* send notifiers that keyframes have been changed */ 01145 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 01146 } 01147 else 01148 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes"); 01149 01150 /* send updates */ 01151 DAG_ids_flush_update(bmain, 0); 01152 01153 return OPERATOR_FINISHED; 01154 } 01155 01156 void ANIM_OT_keyframe_insert (wmOperatorType *ot) 01157 { 01158 PropertyRNA *prop; 01159 01160 /* identifiers */ 01161 ot->name= "Insert Keyframe"; 01162 ot->idname= "ANIM_OT_keyframe_insert"; 01163 ot->description= "Insert keyframes on the current frame for all properties in the specified Keying Set"; 01164 01165 /* callbacks */ 01166 ot->exec= insert_key_exec; 01167 ot->poll= modify_key_op_poll; 01168 01169 /* flags */ 01170 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01171 01172 /* keyingset to use (dynamic enum) */ 01173 prop= RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use"); 01174 RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf); 01175 RNA_def_property_flag(prop, PROP_HIDDEN); 01176 ot->prop= prop; 01177 01178 /* confirm whether a keyframe was added by showing a popup 01179 * - by default, this is enabled, since this operator is assumed to be called independently 01180 */ 01181 prop= RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Insert", "Show a popup when the keyframes get successfully added"); 01182 RNA_def_property_flag(prop, PROP_HIDDEN); 01183 } 01184 01185 /* Insert Key Operator (With Menu) ------------------------ */ 01186 /* This operator checks if a menu should be shown for choosing the KeyingSet to use, 01187 * then calls the menu if necessary before 01188 */ 01189 01190 static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 01191 { 01192 Scene *scene= CTX_data_scene(C); 01193 01194 /* if prompting or no active Keying Set, show the menu */ 01195 if ((scene->active_keyingset == 0) || RNA_boolean_get(op->ptr, "always_prompt")) { 01196 /* call the menu, which will call this operator again, hence the cancelled */ 01197 ANIM_keying_sets_menu_setup(C, op->type->name, "ANIM_OT_keyframe_insert_menu"); 01198 return OPERATOR_CANCELLED; 01199 } 01200 else { 01201 /* just call the exec() on the active keyingset */ 01202 RNA_enum_set(op->ptr, "type", 0); 01203 RNA_boolean_set(op->ptr, "confirm_success", TRUE); 01204 01205 return op->type->exec(C, op); 01206 } 01207 } 01208 01209 void ANIM_OT_keyframe_insert_menu (wmOperatorType *ot) 01210 { 01211 PropertyRNA *prop; 01212 01213 /* identifiers */ 01214 ot->name= "Insert Keyframe Menu"; 01215 ot->idname= "ANIM_OT_keyframe_insert_menu"; 01216 ot->description= "Insert Keyframes for specified Keying Set, with menu of available Keying Sets if undefined"; 01217 01218 /* callbacks */ 01219 ot->invoke= insert_key_menu_invoke; 01220 ot->exec= insert_key_exec; 01221 ot->poll= ED_operator_areaactive; 01222 01223 /* flags */ 01224 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01225 01226 /* keyingset to use (dynamic enum) */ 01227 prop= RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use"); 01228 RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf); 01229 RNA_def_property_flag(prop, PROP_HIDDEN); 01230 ot->prop= prop; 01231 01232 /* confirm whether a keyframe was added by showing a popup 01233 * - by default, this is disabled so that if a menu is shown, this doesn't come up too 01234 */ 01235 // XXX should this just be always on? 01236 prop= RNA_def_boolean(ot->srna, "confirm_success", 0, "Confirm Successful Insert", "Show a popup when the keyframes get successfully added"); 01237 RNA_def_property_flag(prop, PROP_HIDDEN); 01238 01239 /* whether the menu should always be shown 01240 * - by default, the menu should only be shown when there is no active Keying Set (2.5 behaviour), 01241 * although in some cases it might be useful to always shown (pre 2.5 behaviour) 01242 */ 01243 prop= RNA_def_boolean(ot->srna, "always_prompt", 0, "Always Show Menu", ""); 01244 RNA_def_property_flag(prop, PROP_HIDDEN); 01245 } 01246 01247 /* Delete Key Operator ------------------------ */ 01248 01249 static int delete_key_exec (bContext *C, wmOperator *op) 01250 { 01251 Main *bmain= CTX_data_main(C); 01252 Scene *scene= CTX_data_scene(C); 01253 KeyingSet *ks= NULL; 01254 int type= RNA_enum_get(op->ptr, "type"); 01255 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap 01256 short success; 01257 01258 /* type is the Keying Set the user specified to use when calling the operator: 01259 * - type == 0: use scene's active Keying Set 01260 * - type > 0: use a user-defined Keying Set from the active scene 01261 * - type < 0: use a builtin Keying Set 01262 */ 01263 if (type == 0) 01264 type= scene->active_keyingset; 01265 if (type > 0) 01266 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 01267 else 01268 ks= BLI_findlink(&builtin_keyingsets, -type-1); 01269 01270 /* report failure */ 01271 if (ks == NULL) { 01272 BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); 01273 return OPERATOR_CANCELLED; 01274 } 01275 01276 /* try to insert keyframes for the channels specified by KeyingSet */ 01277 success= ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra); 01278 if (G.f & G_DEBUG) 01279 printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success); 01280 01281 /* report failure or do updates? */ 01282 if (success == MODIFYKEY_INVALID_CONTEXT) { 01283 BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set"); 01284 return OPERATOR_CANCELLED; 01285 } 01286 else if (success) { 01287 /* if the appropriate properties have been set, make a note that we've inserted something */ 01288 if (RNA_boolean_get(op->ptr, "confirm_success")) 01289 BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d Keyframes for KeyingSet '%s'", success, ks->name); 01290 01291 /* send notifiers that keyframes have been changed */ 01292 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 01293 } 01294 else 01295 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes"); 01296 01297 /* send updates */ 01298 DAG_ids_flush_update(bmain, 0); 01299 01300 return OPERATOR_FINISHED; 01301 } 01302 01303 void ANIM_OT_keyframe_delete (wmOperatorType *ot) 01304 { 01305 PropertyRNA *prop; 01306 01307 /* identifiers */ 01308 ot->name= "Delete Keying-Set Keyframe"; 01309 ot->idname= "ANIM_OT_keyframe_delete"; 01310 ot->description= "Delete keyframes on the current frame for all properties in the specified Keying Set"; 01311 01312 /* callbacks */ 01313 ot->exec= delete_key_exec; 01314 ot->poll= modify_key_op_poll; 01315 01316 /* flags */ 01317 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01318 01319 /* keyingset to use (dynamic enum) */ 01320 prop= RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use"); 01321 RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf); 01322 RNA_def_property_flag(prop, PROP_HIDDEN); 01323 ot->prop= prop; 01324 01325 /* confirm whether a keyframe was added by showing a popup 01326 * - by default, this is enabled, since this operator is assumed to be called independently 01327 */ 01328 RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Insert", "Show a popup when the keyframes get successfully added"); 01329 } 01330 01331 /* Delete Key Operator ------------------------ */ 01332 01333 /* XXX WARNING: 01334 * This is currently just a basic operator, which work in 3d-view context on objects only. 01335 * Should this be kept? It does have advantages over a version which requires selecting a keyingset to use... 01336 * -- Joshua Leung, Jan 2009 01337 */ 01338 01339 static int delete_key_v3d_exec (bContext *C, wmOperator *op) 01340 { 01341 Main *bmain= CTX_data_main(C); 01342 Scene *scene= CTX_data_scene(C); 01343 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap 01344 01345 // XXX more comprehensive tests will be needed 01346 CTX_DATA_BEGIN(C, Object*, ob, selected_objects) 01347 { 01348 ID *id= (ID *)ob; 01349 FCurve *fcu, *fcn; 01350 short success= 0; 01351 01352 /* loop through all curves in animdata and delete keys on this frame */ 01353 if ((ob->adt) && (ob->adt->action)) { 01354 AnimData *adt= ob->adt; 01355 bAction *act= adt->action; 01356 01357 for (fcu= act->curves.first; fcu; fcu= fcn) { 01358 fcn= fcu->next; 01359 success+= delete_keyframe(op->reports, id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0); 01360 } 01361 } 01362 01363 BKE_reportf(op->reports, RPT_INFO, "Ob '%s' - Successfully had %d keyframes removed", id->name+2, success); 01364 01365 ob->recalc |= OB_RECALC_OB; 01366 } 01367 CTX_DATA_END; 01368 01369 /* send updates */ 01370 DAG_ids_flush_update(bmain, 0); 01371 01372 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL); 01373 01374 return OPERATOR_FINISHED; 01375 } 01376 01377 void ANIM_OT_keyframe_delete_v3d (wmOperatorType *ot) 01378 { 01379 /* identifiers */ 01380 ot->name= "Delete Keyframe"; 01381 ot->description= "Remove keyframes on current frame for selected object"; 01382 ot->idname= "ANIM_OT_keyframe_delete_v3d"; 01383 01384 /* callbacks */ 01385 ot->invoke= WM_operator_confirm; 01386 ot->exec= delete_key_v3d_exec; 01387 01388 ot->poll= ED_operator_areaactive; 01389 01390 /* flags */ 01391 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01392 } 01393 01394 01395 /* Insert Key Button Operator ------------------------ */ 01396 01397 static int insert_key_button_exec (bContext *C, wmOperator *op) 01398 { 01399 Main *bmain= CTX_data_main(C); 01400 Scene *scene= CTX_data_scene(C); 01401 PointerRNA ptr= {{NULL}}; 01402 PropertyRNA *prop= NULL; 01403 char *path; 01404 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap 01405 short success= 0; 01406 int a, index, length, all= RNA_boolean_get(op->ptr, "all"); 01407 short flag = 0; 01408 01409 /* flags for inserting keyframes */ 01410 flag = ANIM_get_keyframing_flags(scene, 1); 01411 01412 /* try to insert keyframe using property retrieved from UI */ 01413 uiContextActiveProperty(C, &ptr, &prop, &index); 01414 01415 if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) { 01416 path= RNA_path_from_ID_to_property(&ptr, prop); 01417 01418 if (path) { 01419 if (all) { 01420 length= RNA_property_array_length(&ptr, prop); 01421 01422 if(length) index= 0; 01423 else length= 1; 01424 } 01425 else 01426 length= 1; 01427 01428 for (a=0; a<length; a++) 01429 success+= insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index+a, cfra, flag); 01430 01431 MEM_freeN(path); 01432 } 01433 else if (ptr.type == &RNA_NlaStrip) { 01434 /* handle special vars for NLA-strips */ 01435 NlaStrip *strip= (NlaStrip *)ptr.data; 01436 FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag); 01437 01438 success+= insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); 01439 } 01440 else { 01441 if (G.f & G_DEBUG) 01442 printf("Button Insert-Key: no path to property \n"); 01443 BKE_report(op->reports, RPT_WARNING, "Failed to resolve path to property. Try using a Keying Set instead"); 01444 } 01445 } 01446 else if (G.f & G_DEBUG) { 01447 printf("ptr.data = %p, prop = %p,", (void *)ptr.data, (void *)prop); 01448 if (prop) 01449 printf("animateable = %d \n", RNA_property_animateable(&ptr, prop)); 01450 else 01451 printf("animateable = NULL \n"); 01452 } 01453 01454 if (success) { 01455 /* send updates */ 01456 uiContextAnimUpdate(C); 01457 01458 DAG_ids_flush_update(bmain, 0); 01459 01460 /* send notifiers that keyframes have been changed */ 01461 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 01462 } 01463 01464 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; 01465 } 01466 01467 void ANIM_OT_keyframe_insert_button (wmOperatorType *ot) 01468 { 01469 /* identifiers */ 01470 ot->name= "Insert Keyframe (Buttons)"; 01471 ot->idname= "ANIM_OT_keyframe_insert_button"; 01472 01473 /* callbacks */ 01474 ot->exec= insert_key_button_exec; 01475 ot->poll= modify_key_op_poll; 01476 01477 /* flags */ 01478 ot->flag= OPTYPE_UNDO; 01479 01480 /* properties */ 01481 RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array"); 01482 } 01483 01484 /* Delete Key Button Operator ------------------------ */ 01485 01486 static int delete_key_button_exec (bContext *C, wmOperator *op) 01487 { 01488 Main *bmain= CTX_data_main(C); 01489 Scene *scene= CTX_data_scene(C); 01490 PointerRNA ptr= {{NULL}}; 01491 PropertyRNA *prop= NULL; 01492 char *path; 01493 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap 01494 short success= 0; 01495 int a, index, length, all= RNA_boolean_get(op->ptr, "all"); 01496 01497 /* try to insert keyframe using property retrieved from UI */ 01498 uiContextActiveProperty(C, &ptr, &prop, &index); 01499 01500 if (ptr.id.data && ptr.data && prop) { 01501 path= RNA_path_from_ID_to_property(&ptr, prop); 01502 01503 if (path) { 01504 if (all) { 01505 length= RNA_property_array_length(&ptr, prop); 01506 01507 if (length) index= 0; 01508 else length= 1; 01509 } 01510 else 01511 length= 1; 01512 01513 for (a=0; a<length; a++) 01514 success+= delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index+a, cfra, 0); 01515 01516 MEM_freeN(path); 01517 } 01518 else if (G.f & G_DEBUG) 01519 printf("Button Delete-Key: no path to property \n"); 01520 } 01521 else if (G.f & G_DEBUG) { 01522 printf("ptr.data = %p, prop = %p \n", (void *)ptr.data, (void *)prop); 01523 } 01524 01525 01526 if (success) { 01527 /* send updates */ 01528 uiContextAnimUpdate(C); 01529 01530 DAG_ids_flush_update(bmain, 0); 01531 01532 /* send notifiers that keyframes have been changed */ 01533 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 01534 } 01535 01536 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; 01537 } 01538 01539 void ANIM_OT_keyframe_delete_button (wmOperatorType *ot) 01540 { 01541 /* identifiers */ 01542 ot->name= "Delete Keyframe (Buttons)"; 01543 ot->idname= "ANIM_OT_keyframe_delete_button"; 01544 01545 /* callbacks */ 01546 ot->exec= delete_key_button_exec; 01547 ot->poll= modify_key_op_poll; 01548 01549 /* flags */ 01550 ot->flag= OPTYPE_UNDO; 01551 01552 /* properties */ 01553 RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyfames from all elements of the array"); 01554 } 01555 01556 /* ******************************************* */ 01557 /* AUTO KEYFRAME */ 01558 01559 int autokeyframe_cfra_can_key(Scene *scene, ID *id) 01560 { 01561 float cfra= (float)CFRA; // XXX for now, this will do 01562 01563 /* only filter if auto-key mode requires this */ 01564 if (IS_AUTOKEY_ON(scene) == 0) 01565 return 0; 01566 01567 if (IS_AUTOKEY_MODE(scene, NORMAL)) { 01568 /* can insert anytime we like... */ 01569 return 1; 01570 } 01571 else /* REPLACE */ { 01572 /* for whole block - only key if there's a keyframe on that frame already 01573 * this is a valid assumption when we're blocking + tweaking 01574 */ 01575 return id_frame_has_keyframe(id, cfra, ANIMFILTER_KEYS_LOCAL); 01576 } 01577 } 01578 01579 /* ******************************************* */ 01580 /* KEYFRAME DETECTION */ 01581 01582 /* --------------- API/Per-Datablock Handling ------------------- */ 01583 01584 /* Checks if some F-Curve has a keyframe for a given frame */ 01585 short fcurve_frame_has_keyframe (FCurve *fcu, float frame, short filter) 01586 { 01587 /* quick sanity check */ 01588 if (ELEM(NULL, fcu, fcu->bezt)) 01589 return 0; 01590 01591 /* we either include all regardless of muting, or only non-muted */ 01592 if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) { 01593 short replace = -1; 01594 int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace); 01595 01596 /* binarysearch_bezt_index will set replace to be 0 or 1 01597 * - obviously, 1 represents a match 01598 */ 01599 if (replace) { 01600 /* sanity check: 'i' may in rare cases exceed arraylen */ 01601 if ((i >= 0) && (i < fcu->totvert)) 01602 return 1; 01603 } 01604 } 01605 01606 return 0; 01607 } 01608 01609 /* Checks whether an Action has a keyframe for a given frame 01610 * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found... 01611 */ 01612 static short action_frame_has_keyframe (bAction *act, float frame, short filter) 01613 { 01614 FCurve *fcu; 01615 01616 /* can only find if there is data */ 01617 if (act == NULL) 01618 return 0; 01619 01620 /* if only check non-muted, check if muted */ 01621 if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED)) 01622 return 0; 01623 01624 /* loop over F-Curves, using binary-search to try to find matches 01625 * - this assumes that keyframes are only beztriples 01626 */ 01627 for (fcu= act->curves.first; fcu; fcu= fcu->next) { 01628 /* only check if there are keyframes (currently only of type BezTriple) */ 01629 if (fcu->bezt && fcu->totvert) { 01630 if (fcurve_frame_has_keyframe(fcu, frame, filter)) 01631 return 1; 01632 } 01633 } 01634 01635 /* nothing found */ 01636 return 0; 01637 } 01638 01639 /* Checks whether an Object has a keyframe for a given frame */ 01640 static short object_frame_has_keyframe (Object *ob, float frame, short filter) 01641 { 01642 /* error checking */ 01643 if (ob == NULL) 01644 return 0; 01645 01646 /* check own animation data - specifically, the action it contains */ 01647 if ((ob->adt) && (ob->adt->action)) { 01648 if (action_frame_has_keyframe(ob->adt->action, frame, filter)) 01649 return 1; 01650 } 01651 01652 /* try shapekey keyframes (if available, and allowed by filter) */ 01653 if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) { 01654 Key *key= ob_get_key(ob); 01655 01656 /* shapekeys can have keyframes ('Relative Shape Keys') 01657 * or depend on time (old 'Absolute Shape Keys') 01658 */ 01659 01660 /* 1. test for relative (with keyframes) */ 01661 if (id_frame_has_keyframe((ID *)key, frame, filter)) 01662 return 1; 01663 01664 /* 2. test for time */ 01665 // TODO... yet to be implemented (this feature may evolve before then anyway) 01666 } 01667 01668 /* try materials */ 01669 if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT) ) { 01670 /* if only active, then we can skip a lot of looping */ 01671 if (filter & ANIMFILTER_KEYS_ACTIVE) { 01672 Material *ma= give_current_material(ob, (ob->actcol + 1)); 01673 01674 /* we only retrieve the active material... */ 01675 if (id_frame_has_keyframe((ID *)ma, frame, filter)) 01676 return 1; 01677 } 01678 else { 01679 int a; 01680 01681 /* loop over materials */ 01682 for (a=0; a<ob->totcol; a++) { 01683 Material *ma= give_current_material(ob, a+1); 01684 01685 if (id_frame_has_keyframe((ID *)ma, frame, filter)) 01686 return 1; 01687 } 01688 } 01689 } 01690 01691 /* nothing found */ 01692 return 0; 01693 } 01694 01695 /* --------------- API ------------------- */ 01696 01697 /* Checks whether a keyframe exists for the given ID-block one the given frame */ 01698 short id_frame_has_keyframe (ID *id, float frame, short filter) 01699 { 01700 /* sanity checks */ 01701 if (id == NULL) 01702 return 0; 01703 01704 /* perform special checks for 'macro' types */ 01705 switch (GS(id->name)) { 01706 case ID_OB: /* object */ 01707 return object_frame_has_keyframe((Object *)id, frame, filter); 01708 break; 01709 01710 case ID_SCE: /* scene */ 01711 // XXX TODO... for now, just use 'normal' behaviour 01712 // break; 01713 01714 default: /* 'normal type' */ 01715 { 01716 AnimData *adt= BKE_animdata_from_id(id); 01717 01718 /* only check keyframes in active action */ 01719 if (adt) 01720 return action_frame_has_keyframe(adt->action, frame, filter); 01721 } 01722 break; 01723 } 01724 01725 01726 /* no keyframe found */ 01727 return 0; 01728 } 01729 01730 /* ************************************************** */ 01731 01732 int ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks) 01733 { 01734 /* auto keyframing */ 01735 if (autokeyframe_cfra_can_key(scene, &ob->id)) { 01736 ListBase dsources = {NULL, NULL}; 01737 01738 /* now insert the keyframe(s) using the Keying Set 01739 * 1) add datasource override for the Object 01740 * 2) insert keyframes 01741 * 3) free the extra info 01742 */ 01743 ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL); 01744 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); 01745 BLI_freelistN(&dsources); 01746 01747 return TRUE; 01748 } 01749 else { 01750 return FALSE; 01751 } 01752 } 01753 01754 int ED_autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks) 01755 { 01756 if (autokeyframe_cfra_can_key(scene, &ob->id)) { 01757 ListBase dsources = {NULL, NULL}; 01758 01759 /* now insert the keyframe(s) using the Keying Set 01760 * 1) add datasource override for the PoseChannel 01761 * 2) insert keyframes 01762 * 3) free the extra info 01763 */ 01764 ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 01765 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); 01766 BLI_freelistN(&dsources); 01767 01768 /* clear any unkeyed tags */ 01769 if (pchan->bone) { 01770 pchan->bone->flag &= ~BONE_UNKEYED; 01771 } 01772 01773 return TRUE; 01774 } 01775 else { 01776 /* add unkeyed tags */ 01777 if (pchan->bone) { 01778 pchan->bone->flag |= BONE_UNKEYED; 01779 } 01780 01781 return FALSE; 01782 } 01783 }