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