1 /* Testing code for 2.5 animation system
2 * Copyright 2009, Joshua Leung
11 #include "MEM_guardedalloc.h"
13 #include "BLI_blenlib.h"
14 #include "BLI_arithb.h"
15 #include "BLI_dynstr.h"
17 #include "DNA_anim_types.h"
18 #include "DNA_action_types.h"
19 #include "DNA_armature_types.h"
20 #include "DNA_constraint_types.h"
21 #include "DNA_key_types.h"
22 #include "DNA_object_types.h"
23 #include "DNA_material_types.h"
24 #include "DNA_scene_types.h"
25 #include "DNA_userdef_types.h"
26 #include "DNA_windowmanager_types.h"
28 #include "BKE_animsys.h"
29 #include "BKE_action.h"
30 #include "BKE_constraint.h"
31 #include "BKE_fcurve.h"
32 #include "BKE_global.h"
33 #include "BKE_utildefines.h"
34 #include "BKE_context.h"
35 #include "BKE_report.h"
37 #include "BKE_material.h"
39 #include "ED_anim_api.h"
40 #include "ED_keyframing.h"
41 #include "ED_keyframes_edit.h"
42 #include "ED_screen.h"
45 #include "UI_interface.h"
50 #include "RNA_access.h"
51 #include "RNA_define.h"
52 #include "RNA_types.h"
54 #include "anim_intern.h"
56 /* ******************************************* */
57 /* Animation Data Validation */
59 /* Get (or add relevant data to be able to do so) the Active Action for the given
60 * Animation Data block, given an ID block where the Animation Data should reside.
62 bAction *verify_adt_action (ID *id, short add)
66 /* init animdata if none available yet */
67 adt= BKE_animdata_from_id(id);
68 if ((adt == NULL) && (add))
69 adt= BKE_id_add_animdata(id);
71 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
72 printf("ERROR: Couldn't add AnimData (ID = %s) \n", (id) ? (id->name) : "<None>");
76 /* init action if none available yet */
77 // TODO: need some wizardry to handle NLA stuff correct
78 if ((adt->action == NULL) && (add))
79 adt->action= add_empty_action("Action");
81 /* return the action */
85 /* Get (or add relevant data to be able to do so) F-Curve from the Active Action,
86 * for the given Animation Data block. This assumes that all the destinations are valid.
88 FCurve *verify_fcurve (bAction *act, const char group[], const char rna_path[], const int array_index, short add)
94 if ELEM(NULL, act, rna_path)
97 /* try to find f-curve matching for this setting
98 * - add if not found and allowed to add one
99 * TODO: add auto-grouping support? how this works will need to be resolved
102 fcu= list_find_fcurve(&act->curves, rna_path, array_index);
106 if ((fcu == NULL) && (add)) {
107 /* use default settings to make a F-Curve */
108 fcu= MEM_callocN(sizeof(FCurve), "FCurve");
110 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
111 if (act->curves.first==NULL)
112 fcu->flag |= FCURVE_ACTIVE; /* first one added active */
114 /* store path - make copy, and store that */
115 fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
116 fcu->array_index= array_index;
118 /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
120 /* try to find group */
121 grp= action_groups_find_named(act, group);
123 /* no matching groups, so add one */
125 /* Add a new group, and make it active */
126 grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
128 grp->flag = AGRP_SELECTED;
129 BLI_snprintf(grp->name, 64, group);
131 BLI_addtail(&act->groups, grp);
132 BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64);
135 /* add F-Curve to group */
136 action_groups_add_channel(act, grp, fcu);
139 /* just add F-Curve to end of Action's list */
140 BLI_addtail(&act->curves, fcu);
144 /* return the F-Curve */
148 /* ************************************************** */
149 /* KEYFRAME INSERTION */
151 /* -------------- BezTriple Insertion -------------------- */
153 /* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */
154 #define BEZT_INSERT_THRESH 0.00001f
156 /* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu)
157 * Returns the index to insert at (data already at that index will be offset if replace is 0)
159 static int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace)
161 int start=0, end=arraylen;
162 int loopbreaker= 0, maxloop= arraylen * 2;
164 /* initialise replace-flag first */
167 /* sneaky optimisations (don't go through searching process if...):
168 * - keyframe to be added is to be added out of current bounds
169 * - keyframe to be added would replace one of the existing ones on bounds
171 if ((arraylen <= 0) || (array == NULL)) {
172 printf("Warning: binarysearch_bezt_index() encountered invalid array \n");
176 /* check whether to add before/after/on */
179 /* 'First' Keyframe (when only one keyframe, this case is used) */
180 framenum= array[0].vec[1][0];
181 if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
185 else if (frame < framenum)
188 /* 'Last' Keyframe */
189 framenum= array[(arraylen-1)].vec[1][0];
190 if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
192 return (arraylen - 1);
194 else if (frame > framenum)
199 /* most of the time, this loop is just to find where to put it
200 * 'loopbreaker' is just here to prevent infinite loops
202 for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
203 /* compute and get midpoint */
204 int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
205 float midfra= array[mid].vec[1][0];
207 /* check if exactly equal to midpoint */
208 if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) {
213 /* repeat in upper/lower half */
216 else if (frame < midfra)
220 /* print error if loop-limit exceeded */
221 if (loopbreaker == (maxloop-1)) {
222 printf("Error: binarysearch_bezt_index() was taking too long \n");
224 // include debug info
225 printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
228 /* not found, so return where to place it */
232 /* This function adds a given BezTriple to an F-Curve. It will allocate
233 * memory for the array if needed, and will insert the BezTriple into a
234 * suitable place in chronological order.
236 * NOTE: any recalculate of the F-Curve that needs to be done will need to
237 * be done by the caller.
239 int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt)
246 i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
249 /* sanity check: 'i' may in rare cases exceed arraylen */
250 // FIXME: do not overwrite handletype if just replacing...?
251 if ((i >= 0) && (i < fcu->totvert))
252 *(fcu->bezt + i) = *bezt;
256 newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple");
258 /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
260 memcpy(newb, fcu->bezt, i*sizeof(BezTriple));
262 /* add beztriple to paste at index i */
265 /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */
266 if (i < fcu->totvert)
267 memcpy(newb+i+1, fcu->bezt+i, (fcu->totvert-i)*sizeof(BezTriple));
269 /* replace (+ free) old with new */
270 MEM_freeN(fcu->bezt);
277 // TODO: need to check for old sample-data now...
278 fcu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
284 /* we need to return the index, so that some tools which do post-processing can
285 * detect where we added the BezTriple in the array
290 /* This function is a wrapper for insert_bezt_icu, and should be used when
291 * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere
294 * 'fast' - is only for the python API where importing BVH's would take an extreamly long time.
296 void insert_vert_fcurve (FCurve *fcu, float x, float y, short fast)
301 /* set all three points, for nicer start position */
302 memset(&beztr, 0, sizeof(BezTriple));
309 beztr.ipo= U.ipo_new; /* use default interpolation mode here... */
310 beztr.f1= beztr.f2= beztr.f3= SELECT;
311 beztr.h1= beztr.h2= HD_AUTO; // XXX what about when we replace an old one?
313 /* add temp beztriple to keyframes */
314 a= insert_bezt_fcurve(fcu, &beztr);
316 /* what if 'a' is a negative index?
317 * for now, just exit to prevent any segfaults
321 /* don't recalculate handles if fast is set
322 * - this is a hack to make importers faster
323 * - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
325 if (!fast) calchandles_fcurve(fcu);
327 /* set handletype and interpolation */
328 if (fcu->totvert > 2) {
329 BezTriple *bezt= (fcu->bezt + a);
332 /* set handles (autohandles by default) */
335 if (a > 0) h1= (bezt-1)->h2;
336 if (a < fcu->totvert-1) h2= (bezt+1)->h1;
341 /* set interpolation from previous (if available) */
342 if (a > 0) bezt->ipo= (bezt-1)->ipo;
343 else if (a < fcu->totvert-1) bezt->ipo= (bezt+1)->ipo;
345 /* don't recalculate handles if fast is set
346 * - this is a hack to make importers faster
347 * - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
349 if (!fast) calchandles_fcurve(fcu);
353 /* -------------- 'Smarter' Keyframing Functions -------------------- */
354 /* return codes for new_key_needed */
356 KEYNEEDED_DONTADD = 0,
362 /* This helper function determines whether a new keyframe is needed */
363 /* Cases where keyframes should not be added:
364 * 1. Keyframe to be added bewteen two keyframes with similar values
365 * 2. Keyframe to be added on frame where two keyframes are already situated
366 * 3. Keyframe lies at point that intersects the linear line between two keyframes
368 static short new_key_needed (FCurve *fcu, float cFrame, float nValue)
370 BezTriple *bezt=NULL, *prev=NULL;
372 float valA = 0.0f, valB = 0.0f;
374 /* safety checking */
375 if (fcu == NULL) return KEYNEEDED_JUSTADD;
376 totCount= fcu->totvert;
377 if (totCount == 0) return KEYNEEDED_JUSTADD;
379 /* loop through checking if any are the same */
381 for (i=0; i<totCount; i++) {
382 float prevPosi=0.0f, prevVal=0.0f;
383 float beztPosi=0.0f, beztVal=0.0f;
385 /* get current time+value */
386 beztPosi= bezt->vec[1][0];
387 beztVal= bezt->vec[1][1];
390 /* there is a keyframe before the one currently being examined */
392 /* get previous time+value */
393 prevPosi= prev->vec[1][0];
394 prevVal= prev->vec[1][1];
396 /* keyframe to be added at point where there are already two similar points? */
397 if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) {
398 return KEYNEEDED_DONTADD;
401 /* keyframe between prev+current points ? */
402 if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
403 /* is the value of keyframe to be added the same as keyframes on either side ? */
404 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) {
405 return KEYNEEDED_DONTADD;
410 /* get real value of curve at that point */
411 realVal= evaluate_fcurve(fcu, cFrame);
413 /* compare whether it's the same as proposed */
414 if (IS_EQ(realVal, nValue))
415 return KEYNEEDED_DONTADD;
417 return KEYNEEDED_JUSTADD;
421 /* new keyframe before prev beztriple? */
422 if (cFrame < prevPosi) {
423 /* A new keyframe will be added. However, whether the previous beztriple
424 * stays around or not depends on whether the values of previous/current
425 * beztriples and new keyframe are the same.
427 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
428 return KEYNEEDED_DELNEXT;
430 return KEYNEEDED_JUSTADD;
434 /* just add a keyframe if there's only one keyframe
435 * and the new one occurs before the exisiting one does.
437 if ((cFrame < beztPosi) && (totCount==1))
438 return KEYNEEDED_JUSTADD;
441 /* continue. frame to do not yet passed (or other conditions not met) */
442 if (i < (totCount-1)) {
450 /* Frame in which to add a new-keyframe occurs after all other keys
451 * -> If there are at least two existing keyframes, then if the values of the
452 * last two keyframes and the new-keyframe match, the last existing keyframe
453 * gets deleted as it is no longer required.
454 * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
455 * keyframe is not equal to last keyframe.
457 bezt= (fcu->bezt + (fcu->totvert - 1));
458 valA= bezt->vec[1][1];
461 valB= prev->vec[1][1];
463 valB= bezt->vec[1][1] + 1.0f;
465 if (IS_EQ(valA, nValue) && IS_EQ(valA, valB))
466 return KEYNEEDED_DELPREV;
468 return KEYNEEDED_JUSTADD;
471 /* ------------------ RNA Data-Access Functions ------------------ */
473 /* Try to read value using RNA-properties obtained already */
474 static float setting_get_rna_value (PointerRNA *ptr, PropertyRNA *prop, int index)
478 switch (RNA_property_type(prop)) {
480 if (RNA_property_array_length(prop))
481 value= (float)RNA_property_boolean_get_index(ptr, prop, index);
483 value= (float)RNA_property_boolean_get(ptr, prop);
486 if (RNA_property_array_length(prop))
487 value= (float)RNA_property_int_get_index(ptr, prop, index);
489 value= (float)RNA_property_int_get(ptr, prop);
492 if (RNA_property_array_length(prop))
493 value= RNA_property_float_get_index(ptr, prop, index);
495 value= RNA_property_float_get(ptr, prop);
498 value= (float)RNA_property_enum_get(ptr, prop);
507 /* ------------------ 'Visual' Keyframing Functions ------------------ */
509 /* internal status codes for visualkey_can_use */
516 /* This helper function determines if visual-keyframing should be used when
517 * inserting keyframes for the given channel. As visual-keyframing only works
518 * on Object and Pose-Channel blocks, this should only get called for those
519 * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying
522 static short visualkey_can_use (PointerRNA *ptr, PropertyRNA *prop)
524 bConstraint *con= NULL;
525 short searchtype= VISUALKEY_NONE;
526 char *identifier= NULL;
529 // TODO: this check is probably not needed, but it won't hurt
530 if (ELEM3(NULL, ptr, ptr->data, prop))
533 /* get first constraint and determine type of keyframe constraints to check for
534 * - constraints can be on either Objects or PoseChannels, so we only check if the
535 * ptr->type is RNA_Object or RNA_PoseChannel, which are the RNA wrapping-info for
536 * those structs, allowing us to identify the owner of the data
538 if (ptr->type == &RNA_Object) {
540 Object *ob= (Object *)ptr->data;
542 con= ob->constraints.first;
543 identifier= (char *)RNA_property_identifier(prop);
545 else if (ptr->type == &RNA_PoseChannel) {
547 bPoseChannel *pchan= (bPoseChannel *)ptr->data;
549 con= pchan->constraints.first;
550 identifier= (char *)RNA_property_identifier(prop);
553 /* check if any data to search using */
554 if (ELEM(NULL, con, identifier))
557 /* location or rotation identifiers only... */
558 if (strstr(identifier, "location"))
559 searchtype= VISUALKEY_LOC;
560 else if (strstr(identifier, "rotation"))
561 searchtype= VISUALKEY_ROT;
563 printf("visualkey_can_use() failed: identifier - '%s' \n", identifier);
568 /* only search if a searchtype and initial constraint are available */
569 if (searchtype && con) {
570 for (; con; con= con->next) {
571 /* only consider constraint if it is not disabled, and has influence */
572 if (con->flag & CONSTRAINT_DISABLE) continue;
573 if (con->enforce == 0.0f) continue;
575 /* some constraints may alter these transforms */
577 /* multi-transform constraints */
578 case CONSTRAINT_TYPE_CHILDOF:
580 case CONSTRAINT_TYPE_TRANSFORM:
582 case CONSTRAINT_TYPE_FOLLOWPATH:
584 case CONSTRAINT_TYPE_KINEMATIC:
587 /* single-transform constraits */
588 case CONSTRAINT_TYPE_TRACKTO:
589 if (searchtype==VISUALKEY_ROT) return 1;
591 case CONSTRAINT_TYPE_ROTLIMIT:
592 if (searchtype==VISUALKEY_ROT) return 1;
594 case CONSTRAINT_TYPE_LOCLIMIT:
595 if (searchtype==VISUALKEY_LOC) return 1;
597 case CONSTRAINT_TYPE_ROTLIKE:
598 if (searchtype==VISUALKEY_ROT) return 1;
600 case CONSTRAINT_TYPE_DISTLIMIT:
601 if (searchtype==VISUALKEY_LOC) return 1;
603 case CONSTRAINT_TYPE_LOCLIKE:
604 if (searchtype==VISUALKEY_LOC) return 1;
606 case CONSTRAINT_TYPE_LOCKTRACK:
607 if (searchtype==VISUALKEY_ROT) return 1;
609 case CONSTRAINT_TYPE_MINMAX:
610 if (searchtype==VISUALKEY_LOC) return 1;
619 /* when some condition is met, this function returns, so here it can be 0 */
623 /* This helper function extracts the value to use for visual-keyframing
624 * In the event that it is not possible to perform visual keying, try to fall-back
625 * to using the default method. Assumes that all data it has been passed is valid.
627 static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_index)
629 char *identifier= (char *)RNA_property_identifier(prop);
631 /* handle for Objects or PoseChannels only
632 * - constraints can be on either Objects or PoseChannels, so we only check if the
633 * ptr->type is RNA_Object or RNA_PoseChannel, which are the RNA wrapping-info for
634 * those structs, allowing us to identify the owner of the data
635 * - assume that array_index will be sane
637 if (ptr->type == &RNA_Object) {
638 Object *ob= (Object *)ptr->data;
640 /* parented objects are not supported, as the effects of the parent
641 * are included in the matrix, which kindof beats the point
643 if (ob->parent == NULL) {
644 /* only Location or Rotation keyframes are supported now */
645 if (strstr(identifier, "location")) {
646 return ob->obmat[3][array_index];
648 else if (strstr(identifier, "rotation")) {
651 Mat4ToEul(ob->obmat, eul);
652 return eul[array_index];
656 else if (ptr->type == &RNA_PoseChannel) {
657 Object *ob= (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
658 bPoseChannel *pchan= (bPoseChannel *)ptr->data;
661 /* Although it is not strictly required for this particular space conversion,
662 * arg1 must not be null, as there is a null check for the other conversions to
663 * be safe. Therefore, the active object is passed here, and in many cases, this
664 * will be what owns the pose-channel that is getting this anyway.
666 Mat4CpyMat4(tmat, pchan->pose_mat);
667 constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
669 /* Loc, Rot/Quat keyframes are supported... */
670 if (strstr(identifier, "location")) {
671 /* only use for non-connected bones */
672 if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
673 return tmat[3][array_index];
674 else if (pchan->bone->parent == NULL)
675 return tmat[3][array_index];
677 else if (strstr(identifier, "euler_rotation")) {
680 /* euler-rotation test before standard rotation, as standard rotation does quats */
681 Mat4ToEul(tmat, eul);
682 return eul[array_index];
684 else if (strstr(identifier, "rotation")) {
685 float trimat[3][3], quat[4];
687 Mat3CpyMat4(trimat, tmat);
688 Mat3ToQuat_is_ok(trimat, quat);
690 return quat[array_index];
694 /* as the function hasn't returned yet, read value from system in the default way */
695 return setting_get_rna_value(ptr, prop, array_index);
698 /* ------------------------- Insert Key API ------------------------- */
700 /* Main Keyframing API call:
701 * Use this when validation of necessary animation data isn't necessary as it
702 * already exists. It will insert a keyframe using the current value being keyframed.
704 * The flag argument is used for special settings that alter the behaviour of
705 * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
706 * and extra keyframe filtering.
708 short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
710 PointerRNA id_ptr, ptr;
714 /* validate pointer first - exit if failure */
715 RNA_id_pointer_create(id, &id_ptr);
716 if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
717 printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
721 /* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */
723 act= verify_adt_action(id, 1);
724 fcu= verify_fcurve(act, group, rna_path, array_index, 1);
726 /* only continue if we have an F-Curve to add keyframe to */
730 /* set additional flags for the F-Curve (i.e. only integer values) */
731 fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES);
732 switch (RNA_property_type(prop)) {
737 /* do integer (only 'whole' numbers) interpolation between all points */
738 fcu->flag |= FCURVE_INT_VALUES;
741 /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
742 * values at all) interpolation between all points
743 * - however, we must also ensure that evaluated values are only integers still
745 fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES);
749 /* apply special time tweaking */
750 // XXX check on this stuff...
751 if (GS(id->name) == ID_OB) {
752 //Object *ob= (Object *)id;
754 /* apply NLA-scaling (if applicable) */
755 //cfra= get_action_frame(ob, cfra);
757 /* ancient time-offset cruft */
758 //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
759 // /* actually frametofloat calc again! */
760 // cfra-= give_timeoffset(ob)*scene->r.framelen;
764 /* obtain value to give keyframe */
765 if ( (flag & INSERTKEY_MATRIX) &&
766 (visualkey_can_use(&ptr, prop)) )
768 /* visual-keying is only available for object and pchan datablocks, as
769 * it works by keyframing using a value extracted from the final matrix
770 * instead of using the kt system to extract a value.
772 curval= visualkey_get_value(&ptr, prop, array_index);
775 /* read value from system */
776 curval= setting_get_rna_value(&ptr, prop, array_index);
779 /* only insert keyframes where they are needed */
780 if (flag & INSERTKEY_NEEDED) {
783 /* check whether this curve really needs a new keyframe */
784 insert_mode= new_key_needed(fcu, cfra, curval);
786 /* insert new keyframe at current frame */
788 insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
790 /* delete keyframe immediately before/after newly added */
791 switch (insert_mode) {
792 case KEYNEEDED_DELPREV:
793 delete_fcurve_key(fcu, fcu->totvert-2, 1);
795 case KEYNEEDED_DELNEXT:
796 delete_fcurve_key(fcu, 1, 1);
800 /* only return success if keyframe added */
805 /* just insert keyframe */
806 insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
813 /* no F-Curve to add keyframes to */
814 printf("ERROR: no F-Curve to add keyframes to \n");
820 /* ************************************************** */
821 /* KEYFRAME DELETION */
823 /* Main Keyframing API call:
824 * Use this when validation of necessary animation data isn't necessary as it
825 * already exists. It will delete a keyframe at the current frame.
827 * The flag argument is used for special settings that alter the behaviour of
828 * the keyframe deletion. These include the quick refresh options.
830 short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
835 * Note: here is one of the places where we don't want new Action + F-Curve added!
836 * so 'add' var must be 0
839 /* if no action is provided, use the default one attached to this ID-block */
840 AnimData *adt= BKE_animdata_from_id(id);
843 /* we don't check the validity of the path here yet, but it should be ok... */
844 fcu= verify_fcurve(act, group, rna_path, array_index, 0);
846 /* only continue if we have an F-Curve to remove keyframes from */
851 /* apply special time tweaking */
852 if (GS(id->name) == ID_OB) {
853 //Object *ob= (Object *)id;
855 /* apply NLA-scaling (if applicable) */
856 // cfra= get_action_frame(ob, cfra);
858 /* ancient time-offset cruft */
859 //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
860 // /* actually frametofloat calc again! */
861 // cfra-= give_timeoffset(ob)*scene->r.framelen;
865 /* try to find index of beztriple to get rid of */
866 i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
868 /* delete the key at the index (will sanity check + do recalc afterwards) */
869 delete_fcurve_key(fcu, i, 1);
871 /* Only delete curve too if there are no points (we don't need to check for drivers, as they're kept separate) */
872 if (fcu->totvert == 0) {
873 BLI_remlink(&act->curves, fcu);
886 /* ******************************************* */
887 /* KEYFRAME MODIFICATION */
889 /* mode for commonkey_modifykey */
891 COMMONKEY_MODE_INSERT = 0,
892 COMMONKEY_MODE_DELETE,
893 } eCommonModifyKey_Modes;
895 /* Polling callback for use with ANIM_*_keyframe() operators
896 * This is based on the standard ED_operator_areaactive callback,
897 * except that it does special checks for a few spacetypes too...
899 static int modify_key_op_poll(bContext *C)
901 ScrArea *sa= CTX_wm_area(C);
902 Scene *scene= CTX_data_scene(C);
904 /* if no area or active scene */
905 if (ELEM(NULL, sa, scene))
908 /* if Outliner, only allow in DataBlocks view */
909 if (sa->spacetype == SPACE_OUTLINER) {
910 SpaceOops *so= (SpaceOops *)CTX_wm_space_data(C);
912 if ((so->outlinevis != SO_DATABLOCKS))
916 /* TODO: checks for other space types can be added here */
922 /* Insert Key Operator ------------------------ */
924 static int insert_key_exec (bContext *C, wmOperator *op)
926 ListBase dsources = {NULL, NULL};
927 Scene *scene= CTX_data_scene(C);
929 int type= RNA_int_get(op->ptr, "type");
930 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
933 /* type is the Keying Set the user specified to use when calling the operator:
934 * - type == 0: use scene's active Keying Set
935 * - type > 0: use a user-defined Keying Set from the active scene
936 * - type < 0: use a builtin Keying Set
939 type= scene->active_keyingset;
941 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
943 ks= BLI_findlink(&builtin_keyingsets, -type-1);
945 /* report failures */
947 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
948 return OPERATOR_CANCELLED;
951 /* get context info for relative Keying Sets */
952 if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
953 /* exit if no suitable data obtained */
954 if (modifykey_get_context_data(C, &dsources, ks) == 0) {
955 BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set");
956 return OPERATOR_CANCELLED;
960 /* try to insert keyframes for the channels specified by KeyingSet */
961 success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
962 printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
964 /* report failure? */
966 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
968 /* free temp context-data if available */
969 if (dsources.first) {
970 /* we assume that there is no extra data that needs to be freed from here... */
971 BLI_freelistN(&dsources);
975 ED_anim_dag_flush_update(C);
977 /* for now, only send ND_KEYS for KeyingSets */
978 WM_event_add_notifier(C, ND_KEYS, NULL);
980 return OPERATOR_FINISHED;
983 void ANIM_OT_insert_keyframe (wmOperatorType *ot)
986 ot->name= "Insert Keyframe";
987 ot->idname= "ANIM_OT_insert_keyframe";
990 ot->exec= insert_key_exec;
991 ot->poll= modify_key_op_poll;
994 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
997 RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
1000 /* Insert Key Operator (With Menu) ------------------------ */
1003 * This operator pops up a menu which sets gets the index of the keyingset to use,
1004 * setting the global settings, and calling the insert-keyframe operator using these
1008 static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *event)
1010 Scene *scene= CTX_data_scene(C);
1016 pup= uiPupMenuBegin(C, "Insert Keyframe", 0);
1017 layout= uiPupMenuLayout(pup);
1019 /* active Keying Set */
1020 uiItemIntO(layout, "Active Keying Set", 0, "ANIM_OT_insert_keyframe_menu", "type", i++);
1023 /* user-defined Keying Sets
1024 * - these are listed in the order in which they were defined for the active scene
1026 if (scene->keyingsets.first) {
1027 for (ks= scene->keyingsets.first; ks; ks= ks->next)
1028 uiItemIntO(layout, ks->name, 0, "ANIM_OT_insert_keyframe_menu", "type", i++);
1032 /* builtin Keying Sets */
1033 // XXX polling the entire list may lag
1035 for (ks= builtin_keyingsets.first; ks; ks= ks->next) {
1036 /* only show KeyingSet if context is suitable */
1037 if (keyingset_context_ok_poll(C, ks)) {
1038 uiItemIntO(layout, ks->name, 0, "ANIM_OT_insert_keyframe_menu", "type", i--);
1042 uiPupMenuEnd(C, pup);
1044 return OPERATOR_CANCELLED;
1047 void ANIM_OT_insert_keyframe_menu (wmOperatorType *ot)
1050 ot->name= "Insert Keyframe";
1051 ot->idname= "ANIM_OT_insert_keyframe_menu";
1054 ot->invoke= insert_key_menu_invoke;
1055 ot->exec= insert_key_exec;
1056 ot->poll= ED_operator_areaactive;
1059 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1062 * - NOTE: here the type is int not enum, since many of the indicies here are determined dynamically
1064 RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
1067 /* Delete Key Operator ------------------------ */
1069 static int delete_key_exec (bContext *C, wmOperator *op)
1071 ListBase dsources = {NULL, NULL};
1072 Scene *scene= CTX_data_scene(C);
1073 KeyingSet *ks= NULL;
1074 int type= RNA_int_get(op->ptr, "type");
1075 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1078 /* type is the Keying Set the user specified to use when calling the operator:
1079 * - type == 0: use scene's active Keying Set
1080 * - type > 0: use a user-defined Keying Set from the active scene
1081 * - type < 0: use a builtin Keying Set
1084 type= scene->active_keyingset;
1086 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
1088 ks= BLI_findlink(&builtin_keyingsets, -type-1);
1090 /* report failure */
1092 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
1093 return OPERATOR_CANCELLED;
1096 /* get context info for relative Keying Sets */
1097 if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
1098 /* exit if no suitable data obtained */
1099 if (modifykey_get_context_data(C, &dsources, ks) == 0) {
1100 BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set");
1101 return OPERATOR_CANCELLED;
1105 /* try to insert keyframes for the channels specified by KeyingSet */
1106 success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
1107 printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success);
1109 /* report failure? */
1111 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes");
1113 /* free temp context-data if available */
1114 if (dsources.first) {
1115 /* we assume that there is no extra data that needs to be freed from here... */
1116 BLI_freelistN(&dsources);
1120 ED_anim_dag_flush_update(C);
1122 /* for now, only send ND_KEYS for KeyingSets */
1123 WM_event_add_notifier(C, ND_KEYS, NULL);
1125 return OPERATOR_FINISHED;
1128 void ANIM_OT_delete_keyframe (wmOperatorType *ot)
1131 ot->name= "Delete Keyframe";
1132 ot->idname= "ANIM_OT_delete_keyframe";
1135 ot->exec= delete_key_exec;
1136 ot->poll= modify_key_op_poll;
1139 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1142 * - NOTE: here the type is int not enum, since many of the indicies here are determined dynamically
1144 RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
1147 /* Delete Key Operator ------------------------ */
1150 * This is currently just a basic operator, which work in 3d-view context on objects only.
1151 * Should this be kept? It does have advantages over a version which requires selecting a keyingset to use...
1152 * -- Joshua Leung, Jan 2009
1155 static int delete_key_old_exec (bContext *C, wmOperator *op)
1157 Scene *scene= CTX_data_scene(C);
1158 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1160 // XXX more comprehensive tests will be needed
1161 CTX_DATA_BEGIN(C, Base*, base, selected_bases)
1163 Object *ob= base->object;
1168 /* loop through all curves in animdata and delete keys on this frame */
1170 AnimData *adt= ob->adt;
1171 bAction *act= adt->action;
1173 for (fcu= act->curves.first; fcu; fcu= fcn) {
1175 success+= delete_keyframe(id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
1179 printf("Ob '%s' - Successfully removed %d keyframes \n", id->name+2, success);
1181 ob->recalc |= OB_RECALC_OB;
1186 ED_anim_dag_flush_update(C);
1188 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
1190 return OPERATOR_FINISHED;
1193 void ANIM_OT_delete_keyframe_old (wmOperatorType *ot)
1196 ot->name= "Delete Keyframe";
1197 ot->idname= "ANIM_OT_delete_keyframe_old";
1200 ot->invoke= WM_operator_confirm;
1201 ot->exec= delete_key_old_exec;
1203 ot->poll= ED_operator_areaactive;
1206 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1210 /* Insert Key Button Operator ------------------------ */
1212 static int insert_key_button_exec (bContext *C, wmOperator *op)
1214 Scene *scene= CTX_data_scene(C);
1216 PropertyRNA *prop= NULL;
1218 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1220 int a, index, length, all= RNA_boolean_get(op->ptr, "all");
1222 /* try to insert keyframe using property retrieved from UI */
1223 memset(&ptr, 0, sizeof(PointerRNA));
1224 uiAnimContextProperty(C, &ptr, &prop, &index);
1226 if ((ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
1227 path= RNA_path_from_ID_to_property(&ptr, prop);
1231 length= RNA_property_array_length(prop);
1233 if(length) index= 0;
1239 for (a=0; a<length; a++)
1240 success+= insert_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0);
1246 printf("Button Insert-Key: no path to property \n");
1247 BKE_report(op->reports, RPT_WARNING, "Failed to resolve path to property. Try using a Keying Set instead.");
1250 else if (G.f & G_DEBUG) {
1251 printf("ptr.data = %p, prop = %p,", ptr.data, prop);
1253 printf("animateable = %d \n", RNA_property_animateable(&ptr, prop));
1255 printf("animateable = NULL \n");
1260 ED_anim_dag_flush_update(C);
1262 /* for now, only send ND_KEYS for KeyingSets */
1263 WM_event_add_notifier(C, ND_KEYS, NULL);
1266 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
1269 void ANIM_OT_insert_keyframe_button (wmOperatorType *ot)
1272 ot->name= "Insert Keyframe";
1273 ot->idname= "ANIM_OT_insert_keyframe_button";
1276 ot->exec= insert_key_button_exec;
1277 ot->poll= modify_key_op_poll;
1280 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1283 RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array.");
1286 /* Delete Key Button Operator ------------------------ */
1288 static int delete_key_button_exec (bContext *C, wmOperator *op)
1290 Scene *scene= CTX_data_scene(C);
1292 PropertyRNA *prop= NULL;
1294 float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1296 int a, index, length, all= RNA_boolean_get(op->ptr, "all");
1298 /* try to insert keyframe using property retrieved from UI */
1299 memset(&ptr, 0, sizeof(PointerRNA));
1300 uiAnimContextProperty(C, &ptr, &prop, &index);
1302 if (ptr.data && prop) {
1303 path= RNA_path_from_ID_to_property(&ptr, prop);
1307 length= RNA_property_array_length(prop);
1309 if(length) index= 0;
1315 for (a=0; a<length; a++)
1316 success+= delete_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0);
1320 else if (G.f & G_DEBUG)
1321 printf("Button Delete-Key: no path to property \n");
1323 else if (G.f & G_DEBUG) {
1324 printf("ptr.data = %p, prop = %p \n", ptr.data, prop);
1330 ED_anim_dag_flush_update(C);
1332 /* for now, only send ND_KEYS for KeyingSets */
1333 WM_event_add_notifier(C, ND_KEYS, NULL);
1336 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
1339 void ANIM_OT_delete_keyframe_button (wmOperatorType *ot)
1342 ot->name= "Delete Keyframe";
1343 ot->idname= "ANIM_OT_delete_keyframe_button";
1346 ot->exec= delete_key_button_exec;
1347 ot->poll= modify_key_op_poll;
1350 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1353 RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyfames from all elements of the array.");
1356 /* ******************************************* */
1357 /* KEYFRAME DETECTION */
1359 /* --------------- API/Per-Datablock Handling ------------------- */
1361 /* Checks whether an Action has a keyframe for a given frame
1362 * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
1364 short action_frame_has_keyframe (bAction *act, float frame, short filter)
1368 /* can only find if there is data */
1372 /* if only check non-muted, check if muted */
1373 if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
1376 /* loop over F-Curves, using binary-search to try to find matches
1377 * - this assumes that keyframes are only beztriples
1379 for (fcu= act->curves.first; fcu; fcu= fcu->next) {
1380 /* only check if there are keyframes (currently only of type BezTriple) */
1381 if (fcu->bezt && fcu->totvert) {
1382 /* we either include all regardless of muting, or only non-muted */
1383 if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) {
1385 int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
1387 /* binarysearch_bezt_index will set replace to be 0 or 1
1388 * - obviously, 1 represents a match
1391 /* sanity check: 'i' may in rare cases exceed arraylen */
1392 if ((i >= 0) && (i < fcu->totvert))
1403 /* Checks whether an Object has a keyframe for a given frame */
1404 short object_frame_has_keyframe (Object *ob, float frame, short filter)
1406 /* error checking */
1410 /* check own animation data - specifically, the action it contains */
1411 if ((ob->adt) && (ob->adt->action)) {
1412 if (action_frame_has_keyframe(ob->adt->action, frame, filter))
1416 /* try shapekey keyframes (if available, and allowed by filter) */
1417 if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) {
1418 Key *key= ob_get_key(ob);
1420 /* shapekeys can have keyframes ('Relative Shape Keys')
1421 * or depend on time (old 'Absolute Shape Keys')
1424 /* 1. test for relative (with keyframes) */
1425 if (id_frame_has_keyframe((ID *)key, frame, filter))
1428 /* 2. test for time */
1429 // TODO... yet to be implemented (this feature may evolve before then anyway)
1433 if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT) ) {
1434 /* if only active, then we can skip a lot of looping */
1435 if (filter & ANIMFILTER_KEYS_ACTIVE) {
1436 Material *ma= give_current_material(ob, (ob->actcol + 1));
1438 /* we only retrieve the active material... */
1439 if (id_frame_has_keyframe((ID *)ma, frame, filter))
1445 /* loop over materials */
1446 for (a=0; a<ob->totcol; a++) {
1447 Material *ma= give_current_material(ob, a+1);
1449 if (id_frame_has_keyframe((ID *)ma, frame, filter))
1459 /* --------------- API ------------------- */
1461 /* Checks whether a keyframe exists for the given ID-block one the given frame */
1462 short id_frame_has_keyframe (ID *id, float frame, short filter)
1468 /* perform special checks for 'macro' types */
1469 switch (GS(id->name)) {
1470 case ID_OB: /* object */
1471 return object_frame_has_keyframe((Object *)id, frame, filter);
1474 case ID_SCE: /* scene */
1475 // XXX TODO... for now, just use 'normal' behaviour
1478 default: /* 'normal type' */
1480 AnimData *adt= BKE_animdata_from_id(id);
1482 /* only check keyframes in active action */
1484 return action_frame_has_keyframe(adt->action, frame, filter);
1490 /* no keyframe found */
1494 /* ************************************************** */