2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2008 Blender Foundation
19 * All rights reserved.
21 * Contributor(s): Joshua Leung
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/animation/keyframes_general.c
27 * \ingroup edanimation
36 #include "MEM_guardedalloc.h"
38 #include "BLI_blenlib.h"
39 #include "BLI_utildefines.h"
41 #include "DNA_anim_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_scene_types.h"
46 #include "BKE_action.h"
47 #include "BKE_fcurve.h"
48 #include "BKE_report.h"
49 #include "BKE_library.h"
50 #include "BKE_global.h"
51 #include "BKE_deform.h"
53 #include "RNA_access.h"
55 #include "ED_anim_api.h"
56 #include "ED_keyframing.h"
57 #include "ED_keyframes_edit.h"
59 /* This file contains code for various keyframe-editing tools which are 'destructive'
60 * (i.e. they will modify the order of the keyframes, and change the size of the array).
61 * While some of these tools may eventually be moved out into blenkernel, for now, it is
62 * fine to have these calls here.
64 * There are also a few tools here which cannot be easily coded for in the other system (yet).
65 * These may also be moved around at some point, but for now, they are best added here.
67 * - Joshua Leung, Dec 2008
70 /* **************************************************** */
72 /* Only delete the nominated keyframe from provided F-Curve.
73 * Not recommended to be used many times successively. For that
74 * there is delete_fcurve_keys().
76 void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
83 * 1) cannot be greater than the number of available keyframes
84 * 2) negative indices are for specifying a value from the end of the array
86 if (abs(index) >= fcu->totvert)
89 index += fcu->totvert;
91 /* Delete this keyframe */
92 memmove(&fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1));
95 if (fcu->totvert == 0) {
101 /* recalc handles - only if it won't cause problems */
103 calchandles_fcurve(fcu);
106 /* Delete selected keyframes in given F-Curve */
107 bool delete_fcurve_keys(FCurve *fcu)
110 bool changed = false;
112 if (fcu->bezt == NULL) /* ignore baked curves */
115 /* Delete selected BezTriples */
116 for (i = 0; i < fcu->totvert; i++) {
117 if (fcu->bezt[i].f2 & SELECT) {
118 memmove(&fcu->bezt[i], &fcu->bezt[i + 1], sizeof(BezTriple) * (fcu->totvert - i - 1));
125 /* Free the array of BezTriples if there are not keyframes */
126 if (fcu->totvert == 0)
127 clear_fcurve_keys(fcu);
133 void clear_fcurve_keys(FCurve *fcu)
136 MEM_freeN(fcu->bezt);
142 /* ---------------- */
144 /* duplicate selected keyframes for the given F-Curve */
145 void duplicate_fcurve_keys(FCurve *fcu)
150 /* this can only work when there is an F-Curve, and also when there are some BezTriples */
151 if (ELEM(NULL, fcu, fcu->bezt))
154 for (i = 0; i < fcu->totvert; i++) {
155 /* If a key is selected */
156 if (fcu->bezt[i].f2 & SELECT) {
157 /* Expand the list */
158 newbezt = MEM_callocN(sizeof(BezTriple) * (fcu->totvert + 1), "beztriple");
160 memcpy(newbezt, fcu->bezt, sizeof(BezTriple) * (i + 1));
161 memcpy(newbezt + i + 1, fcu->bezt + i, sizeof(BezTriple));
162 memcpy(newbezt + i + 2, fcu->bezt + i + 1, sizeof(BezTriple) * (fcu->totvert - (i + 1)));
165 /* reassign pointers... (free old, and add new) */
166 MEM_freeN(fcu->bezt);
169 /* Unselect the current key */
170 BEZT_DESEL_ALL(&fcu->bezt[i]);
173 /* Select the copied key */
174 BEZT_SEL_ALL(&fcu->bezt[i]);
179 /* **************************************************** */
182 /* Basic F-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only
183 * optionally clears up curve if one keyframe with default value remains */
184 void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
186 FCurve *fcu = (FCurve *)ale->key_data;
187 BezTriple *old_bezts, *bezt, *beztn;
191 /* check if any points */
192 if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) ||
193 (!cleardefault && fcu->totvert == 1))
198 /* make a copy of the old BezTriples, and clear F-Curve */
199 old_bezts = fcu->bezt;
200 totCount = fcu->totvert;
204 /* now insert first keyframe, as it should be ok */
206 insert_vert_fcurve(fcu, bezt->vec[1][0], bezt->vec[1][1], BEZKEYTYPE(bezt), 0);
207 if (!(bezt->f2 & SELECT)) {
209 lastb->f1 = lastb->f2 = lastb->f3 = 0;
212 /* Loop through BezTriples, comparing them. Skip any that do
213 * not fit the criteria for "ok" points.
215 for (i = 1; i < totCount; i++) {
216 float prev[2], cur[2], next[2];
218 /* get BezTriples and their values */
219 if (i < (totCount - 1)) {
220 beztn = (old_bezts + (i + 1));
221 next[0] = beztn->vec[1][0]; next[1] = beztn->vec[1][1];
225 next[0] = next[1] = 0.0f;
227 lastb = (fcu->bezt + (fcu->totvert - 1));
228 bezt = (old_bezts + i);
230 /* get references for quicker access */
231 prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1];
232 cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1];
234 if (!(bezt->f2 & SELECT)) {
235 insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
236 lastb = (fcu->bezt + (fcu->totvert - 1));
237 lastb->f1 = lastb->f2 = lastb->f3 = 0;
241 /* check if current bezt occurs at same time as last ok */
242 if (IS_EQT(cur[0], prev[0], thresh)) {
243 /* If there is a next beztriple, and if occurs at the same time, only insert
244 * if there is a considerable distance between the points, and also if the
245 * current is further away than the next one is to the previous.
247 if (beztn && (IS_EQT(cur[0], next[0], thresh)) &&
248 (IS_EQT(next[1], prev[1], thresh) == 0))
250 /* only add if current is further away from previous */
251 if (cur[1] > next[1]) {
252 if (IS_EQT(cur[1], prev[1], thresh) == 0) {
253 /* add new keyframe */
254 insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
259 /* only add if values are a considerable distance apart */
260 if (IS_EQT(cur[1], prev[1], thresh) == 0) {
261 /* add new keyframe */
262 insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
267 /* checks required are dependent on whether this is last keyframe or not */
269 /* does current have same value as previous and next? */
270 if (IS_EQT(cur[1], prev[1], thresh) == 0) {
271 /* add new keyframe*/
272 insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
274 else if (IS_EQT(cur[1], next[1], thresh) == 0) {
275 /* add new keyframe */
276 insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
280 /* add if value doesn't equal that of previous */
281 if (IS_EQT(cur[1], prev[1], thresh) == 0) {
282 /* add new keyframe */
283 insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
289 /* now free the memory used by the old BezTriples */
291 MEM_freeN(old_bezts);
293 /* final step, if there is just one key in fcurve, check if it's
294 * the default value and if is, remove fcurve completely. */
295 if (cleardefault && fcu->totvert == 1) {
296 float default_value = 0.0f;
297 PointerRNA id_ptr, ptr;
299 RNA_id_pointer_create(ale->id, &id_ptr);
301 /* get property to read from, and get value as appropriate */
302 if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
303 if (RNA_property_type(prop) == PROP_FLOAT)
304 default_value = RNA_property_float_get_default_index(&ptr, prop, fcu->array_index);
307 if (fcu->bezt->vec[1][1] == default_value) {
308 clear_fcurve_keys(fcu);
310 /* check if curve is really unused and if it is, return signal for deletion */
311 if ((list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
312 (fcu->driver == NULL))
314 AnimData *adt = ale->adt;
315 ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
316 ale->key_data = NULL;
322 /* ---------------- */
324 /* temp struct used for smooth_fcurve */
325 typedef struct tSmooth_Bezt {
326 float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */
327 float y1, y2, y3; /* averaged before/new/after y-values */
330 /* Use a weighted moving-means method to reduce intensity of fluctuations */
331 // TODO: introduce scaling factor for weighting falloff
332 void smooth_fcurve(FCurve *fcu)
335 int i, x, totSel = 0;
337 if (fcu->bezt == NULL) {
341 /* first loop through - count how many verts are selected */
343 for (i = 0; i < fcu->totvert; i++, bezt++) {
344 if (BEZT_ISSEL_ANY(bezt))
348 /* if any points were selected, allocate tSmooth_Bezt points to work on */
350 tSmooth_Bezt *tarray, *tsb;
352 /* allocate memory in one go */
353 tsb = tarray = MEM_callocN(totSel * sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
355 /* populate tarray with data of selected points */
357 for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
358 if (BEZT_ISSEL_ANY(bezt)) {
359 /* tsb simply needs pointer to vec, and index */
360 tsb->h1 = &bezt->vec[0][1];
361 tsb->h2 = &bezt->vec[1][1];
362 tsb->h3 = &bezt->vec[2][1];
364 /* advance to the next tsb to populate */
372 /* calculate the new smoothed F-Curve's with weighted averages:
373 * - this is done with two passes to avoid progressive corruption errors
374 * - uses 5 points for each operation (which stores in the relevant handles)
375 * - previous: w/a ratio = 3:5:2:1:1
376 * - next: w/a ratio = 1:1:2:5:3
379 /* round 1: calculate smoothing deltas and new values */
381 for (i = 0; i < totSel; i++, tsb++) {
382 /* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */
383 if (ELEM(i, 0, (totSel - 1)) == 0) {
384 const tSmooth_Bezt *tP1 = tsb - 1;
385 const tSmooth_Bezt *tP2 = (i - 2 > 0) ? (tsb - 2) : (NULL);
386 const tSmooth_Bezt *tN1 = tsb + 1;
387 const tSmooth_Bezt *tN2 = (i + 2 < totSel) ? (tsb + 2) : (NULL);
389 const float p1 = *tP1->h2;
390 const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
391 const float c1 = *tsb->h2;
392 const float n1 = *tN1->h2;
393 const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
395 /* calculate previous and next, then new position by averaging these */
396 tsb->y1 = (3 * p2 + 5 * p1 + 2 * c1 + n1 + n2) / 12;
397 tsb->y3 = (p2 + p1 + 2 * c1 + 5 * n1 + 3 * n2) / 12;
399 tsb->y2 = (tsb->y1 + tsb->y3) / 2;
403 /* round 2: apply new values */
405 for (i = 0; i < totSel; i++, tsb++) {
406 /* don't touch end points, as their values weren't touched above */
407 if (ELEM(i, 0, (totSel - 1)) == 0) {
408 /* y2 takes the average of the 2 points */
411 /* handles are weighted between their original values and the averaged values */
412 *tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f);
413 *tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f);
417 /* free memory required for tarray */
421 /* recalculate handles */
422 calchandles_fcurve(fcu);
425 /* ---------------- */
427 /* little cache for values... */
428 typedef struct TempFrameValCache {
433 /* Evaluates the curves between each selected keyframe on each frame, and keys the value */
434 void sample_fcurve(FCurve *fcu)
436 BezTriple *bezt, *start = NULL, *end = NULL;
437 TempFrameValCache *value_cache, *fp;
441 if (fcu->bezt == NULL) /* ignore baked */
444 /* find selected keyframes... once pair has been found, add keyframes */
445 for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
446 /* check if selected, and which end this is */
447 if (BEZT_ISSEL_ANY(bezt)) {
452 /* cache values then add keyframes using these values, as adding
453 * keyframes while sampling will affect the outcome...
454 * - only start sampling+adding from index=1, so that we don't overwrite original keyframe
456 range = (int)(ceil(end->vec[1][0] - start->vec[1][0]));
457 sfra = (int)(floor(start->vec[1][0]));
460 value_cache = MEM_callocN(sizeof(TempFrameValCache) * range, "IcuFrameValCache");
463 for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
464 fp->frame = (float)(sfra + n);
465 fp->val = evaluate_fcurve(fcu, fp->frame);
468 /* add keyframes with these, tagging as 'breakdowns' */
469 for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
470 insert_vert_fcurve(fcu, fp->frame, fp->val, BEZT_KEYTYPE_BREAKDOWN, 1);
473 /* free temp cache */
474 MEM_freeN(value_cache);
476 /* as we added keyframes, we need to compensate so that bezt is at the right place */
477 bezt = fcu->bezt + i + range - 1;
481 /* bezt was selected, so it now marks the start of a whole new chain to search */
486 /* just set start keyframe */
493 /* recalculate channel's handles? */
494 calchandles_fcurve(fcu);
497 /* **************************************************** */
498 /* Copy/Paste Tools */
499 /* - The copy/paste buffer currently stores a set of temporary F-Curves containing only the keyframes
500 * that were selected in each of the original F-Curves
501 * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
502 * the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
503 * - The earliest frame is calculated per copy operation.
506 /* globals for copy/paste data (like for other copy/paste buffers) */
507 static ListBase animcopybuf = {NULL, NULL};
508 static float animcopy_firstframe = 999999999.0f;
509 static float animcopy_lastframe = -999999999.0f;
510 static float animcopy_cfra = 0.0;
512 /* datatype for use in copy/paste buffer */
513 typedef struct tAnimCopybufItem {
514 struct tAnimCopybufItem *next, *prev;
516 ID *id; /* ID which owns the curve */
517 bActionGroup *grp; /* Action Group */
518 char *rna_path; /* RNA-Path */
519 int array_index; /* array index */
521 int totvert; /* number of keyframes stored for this channel */
522 BezTriple *bezt; /* keyframes in buffer */
524 short id_type; /* Result of GS(id->name)*/
525 bool is_bone; /* special flag for armature bones */
529 /* This function frees any MEM_calloc'ed copy/paste buffer data */
530 void ANIM_fcurves_copybuf_free(void)
532 tAnimCopybufItem *aci, *acn;
534 /* free each buffer element */
535 for (aci = animcopybuf.first; aci; aci = acn) {
540 MEM_freeN(aci->bezt);
544 MEM_freeN(aci->rna_path);
547 BLI_freelinkN(&animcopybuf, aci);
550 /* restore initial state */
551 BLI_listbase_clear(&animcopybuf);
552 animcopy_firstframe = 999999999.0f;
553 animcopy_lastframe = -999999999.0f;
556 /* ------------------- */
558 /* This function adds data to the keyframes copy/paste buffer, freeing existing data first */
559 short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
562 Scene *scene = ac->scene;
564 /* clear buffer first */
565 ANIM_fcurves_copybuf_free();
567 /* assume that each of these is an F-Curve */
568 for (ale = anim_data->first; ale; ale = ale->next) {
569 FCurve *fcu = (FCurve *)ale->key_data;
570 tAnimCopybufItem *aci;
571 BezTriple *bezt, *nbezt, *newbuf;
574 /* firstly, check if F-Curve has any selected keyframes
575 * - skip if no selected keyframes found (so no need to create unnecessary copy-buffer data)
576 * - this check should also eliminate any problems associated with using sample-data
578 if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0)
581 /* init copybuf item info */
582 aci = MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem");
584 aci->id_type = GS(ale->id->name);
586 aci->rna_path = MEM_dupallocN(fcu->rna_path);
587 aci->array_index = fcu->array_index;
589 /* detect if this is a bone. We do that here rather than during pasting because ID pointers will get invalidated if we undo.
590 * storing the relevant information here helps avoiding crashes if we undo-repaste */
591 if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) {
592 Object *ob = (Object *)aci->id;
596 bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones[");
597 pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
601 if (bone_name) MEM_freeN(bone_name);
604 BLI_addtail(&animcopybuf, aci);
606 /* add selected keyframes to buffer */
607 /* TODO: currently, we resize array every time we add a new vert -
608 * this works ok as long as it is assumed only a few keys are copied */
609 for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
610 if (BEZT_ISSEL_ANY(bezt)) {
612 newbuf = MEM_callocN(sizeof(BezTriple) * (aci->totvert + 1), "copybuf beztriple");
614 /* assume that since we are just re-sizing the array, just copy all existing data across */
616 memcpy(newbuf, aci->bezt, sizeof(BezTriple) * (aci->totvert));
618 /* copy current beztriple across too */
619 nbezt = &newbuf[aci->totvert];
622 /* ensure copy buffer is selected so pasted keys are selected */
625 /* free old array and set the new */
626 if (aci->bezt) MEM_freeN(aci->bezt);
630 /* check if this is the earliest frame encountered so far */
631 if (bezt->vec[1][0] < animcopy_firstframe)
632 animcopy_firstframe = bezt->vec[1][0];
633 if (bezt->vec[1][0] > animcopy_lastframe)
634 animcopy_lastframe = bezt->vec[1][0];
640 /* check if anything ended up in the buffer */
641 if (ELEM(NULL, animcopybuf.first, animcopybuf.last))
644 /* in case 'relative' paste method is used */
645 animcopy_cfra = CFRA;
647 /* everything went fine */
651 static void flip_names(tAnimCopybufItem *aci, char **name)
655 if ((str_start = strstr(aci->rna_path, "pose.bones["))) {
656 /* ninja coding, try to change the name */
657 char bname_new[MAX_VGROUP_NAME];
658 char *str_iter, *str_end;
659 int length, prefix_l, postfix_l;
662 prefix_l = str_start - aci->rna_path;
664 str_end = strchr(str_start, '\"');
666 length = str_end - str_start;
667 postfix_l = strlen(str_end);
669 /* more ninja stuff, temporary substitute with NULL terminator */
670 str_start[length] = 0;
671 BKE_deform_flip_side_name(bname_new, str_start, false);
672 str_start[length] = '\"';
674 str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1), "flipped_path");
676 BLI_strncpy(str_iter, aci->rna_path, prefix_l + 1);
677 str_iter += prefix_l;
678 BLI_strncpy(str_iter, bname_new, length + 1);
680 BLI_strncpy(str_iter, str_end, postfix_l + 1);
681 str_iter[postfix_l] = '\0';
686 /* ------------------- */
688 /* most strict method: exact matches only */
689 static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_single, const short to_simple, bool flip)
691 tAnimCopybufItem *aci;
693 for (aci = animcopybuf.first; aci; aci = aci->next) {
694 if (to_simple || (aci->rna_path && fcu->rna_path)) {
695 if (!to_simple && flip && aci->is_bone && fcu->rna_path) {
696 if ((from_single) || (aci->array_index == fcu->array_index)) {
698 flip_names(aci, &name);
699 if (STREQ(name, fcu->rna_path)) {
706 else if (to_simple || STREQ(aci->rna_path, fcu->rna_path)) {
707 if ((from_single) || (aci->array_index == fcu->array_index)) {
717 /* medium match strictness: path match only (i.e. ignore ID) */
718 static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short from_single, const short UNUSED(to_simple))
720 tAnimCopybufItem *aci;
722 for (aci = animcopybuf.first; aci; aci = aci->next) {
723 /* check that paths exist */
724 if (aci->rna_path && fcu->rna_path) {
725 /* find the property of the fcurve and compare against the end of the tAnimCopybufItem
726 * more involved since it needs to to path lookups.
727 * This is not 100% reliable since the user could be editing the curves on a path that wont
728 * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste
729 * this should work out ok.
731 if (BLI_findindex(which_libbase(G.main, aci->id_type), aci->id) == -1) {
732 /* pedantic but the ID could have been removed, and beats crashing! */
733 printf("paste_animedit_keys: error ID has been removed!\n");
736 PointerRNA id_ptr, rptr;
739 RNA_id_pointer_create(aci->id, &id_ptr);
741 if (RNA_path_resolve_property(&id_ptr, aci->rna_path, &rptr, &prop)) {
742 const char *identifier = RNA_property_identifier(prop);
743 int len_id = strlen(identifier);
744 int len_path = strlen(fcu->rna_path);
745 if (len_id <= len_path) {
746 /* note, paths which end with "] will fail with this test - Animated ID Props */
747 if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) {
748 if ((from_single) || (aci->array_index == fcu->array_index))
754 printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n", aci->id->name, aci->rna_path);
763 /* least strict matching heuristic: indices only */
764 static tAnimCopybufItem *pastebuf_match_index_only(FCurve *fcu, const short from_single, const short UNUSED(to_simple))
766 tAnimCopybufItem *aci;
768 for (aci = animcopybuf.first; aci; aci = aci->next) {
769 /* check that paths exist */
770 if ((from_single) || (aci->array_index == fcu->array_index)) {
778 /* ................ */
780 static void do_curve_mirror_flippping(tAnimCopybufItem *aci, BezTriple *bezt)
783 const size_t slength = strlen(aci->rna_path);
785 if (BLI_strn_endswith(aci->rna_path, "location", slength) && aci->array_index == 0)
787 else if (BLI_strn_endswith(aci->rna_path, "rotation_quaternion", slength) && ELEM(aci->array_index, 2, 3))
789 else if (BLI_strn_endswith(aci->rna_path, "rotation_euler", slength) && ELEM(aci->array_index, 1, 2))
791 else if (BLI_strn_endswith(aci->rna_path, "rotation_axis_angle", slength) && ELEM(aci->array_index, 2, 3))
795 bezt->vec[0][1] = -bezt->vec[0][1];
796 bezt->vec[1][1] = -bezt->vec[1][1];
797 bezt->vec[2][1] = -bezt->vec[2][1];
802 /* helper for paste_animedit_keys() - performs the actual pasting */
803 static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode, bool flip)
808 /* First de-select existing FCurve's keyframes */
809 for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
810 BEZT_DESEL_ALL(bezt);
813 /* mix mode with existing data */
814 switch (merge_mode) {
815 case KEYFRAME_PASTE_MERGE_MIX:
819 case KEYFRAME_PASTE_MERGE_OVER:
820 /* remove all keys */
821 clear_fcurve_keys(fcu);
824 case KEYFRAME_PASTE_MERGE_OVER_RANGE:
825 case KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL:
830 if (merge_mode == KEYFRAME_PASTE_MERGE_OVER_RANGE) {
831 f_min = aci->bezt[0].vec[1][0] + offset;
832 f_max = aci->bezt[aci->totvert - 1].vec[1][0] + offset;
834 else { /* Entire Range */
835 f_min = animcopy_firstframe + offset;
836 f_max = animcopy_lastframe + offset;
839 /* remove keys in range */
841 /* select verts in range for removal */
842 for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
843 if ((f_min < bezt[0].vec[1][0]) && (bezt[0].vec[1][0] < f_max)) {
848 /* remove frames in the range */
849 delete_fcurve_keys(fcu);
855 /* just start pasting, with the first keyframe on the current frame, and so on */
856 for (i = 0, bezt = aci->bezt; i < aci->totvert; i++, bezt++) {
857 /* temporarily apply offset to src beztriple while copying */
859 do_curve_mirror_flippping(aci, bezt);
861 bezt->vec[0][0] += offset;
862 bezt->vec[1][0] += offset;
863 bezt->vec[2][0] += offset;
865 /* insert the keyframe
866 * NOTE: we do not want to inherit handles from existing keyframes in this case!
869 insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
871 /* un-apply offset from src beztriple after copying */
872 bezt->vec[0][0] -= offset;
873 bezt->vec[1][0] -= offset;
874 bezt->vec[2][0] -= offset;
877 do_curve_mirror_flippping(aci, bezt);
880 /* recalculate F-Curve's handles? */
881 calchandles_fcurve(fcu);
884 /* ------------------- */
886 EnumPropertyItem rna_enum_keyframe_paste_offset_items[] = {
887 {KEYFRAME_PASTE_OFFSET_CFRA_START, "START", 0, "Frame Start", "Paste keys starting at current frame"},
888 {KEYFRAME_PASTE_OFFSET_CFRA_END, "END", 0, "Frame End", "Paste keys ending at current frame"},
889 {KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE, "RELATIVE", 0, "Frame Relative", "Paste keys relative to the current frame when copying"},
890 {KEYFRAME_PASTE_OFFSET_NONE, "NONE", 0, "No Offset", "Paste keys from original time"},
891 {0, NULL, 0, NULL, NULL}};
893 EnumPropertyItem rna_enum_keyframe_paste_merge_items[] = {
894 {KEYFRAME_PASTE_MERGE_MIX, "MIX", 0, "Mix", "Overlay existing with new keys"},
895 {KEYFRAME_PASTE_MERGE_OVER, "OVER_ALL", 0, "Overwrite All", "Replace all keys"},
896 {KEYFRAME_PASTE_MERGE_OVER_RANGE, "OVER_RANGE", 0, "Overwrite Range", "Overwrite keys in pasted range"},
897 {KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL, "OVER_RANGE_ALL", 0, "Overwrite Entire Range", "Overwrite keys in pasted range, using the range of all copied keys"},
898 {0, NULL, 0, NULL, NULL}};
902 * This function pastes data from the keyframes copy/paste buffer
904 * \return Status code is whether the method FAILED to do anything
906 short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
907 const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
911 const Scene *scene = (ac->scene);
913 const bool from_single = BLI_listbase_is_single(&animcopybuf);
914 const bool to_simple = BLI_listbase_is_single(anim_data);
919 /* check if buffer is empty */
920 if (BLI_listbase_is_empty(&animcopybuf)) {
921 BKE_report(ac->reports, RPT_ERROR, "No animation data in buffer to paste");
925 if (BLI_listbase_is_empty(anim_data)) {
926 BKE_report(ac->reports, RPT_ERROR, "No selected F-Curves to paste into");
930 /* methods of offset */
931 switch (offset_mode) {
932 case KEYFRAME_PASTE_OFFSET_CFRA_START:
933 offset = (float)(CFRA - animcopy_firstframe);
935 case KEYFRAME_PASTE_OFFSET_CFRA_END:
936 offset = (float)(CFRA - animcopy_lastframe);
938 case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
939 offset = (float)(CFRA - animcopy_cfra);
941 case KEYFRAME_PASTE_OFFSET_NONE:
946 if (from_single && to_simple) {
947 /* 1:1 match, no tricky checking, just paste */
949 tAnimCopybufItem *aci;
951 ale = anim_data->first;
952 fcu = (FCurve *)ale->data; /* destination F-Curve */
953 aci = animcopybuf.first;
955 paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false);
956 ale->update |= ANIM_UPDATE_DEFAULT;
959 /* from selected channels
960 * This "passes" system aims to try to find "matching" channels to paste keyframes
961 * into with increasingly loose matching heuristics. The process finishes when at least
962 * one F-Curve has been pasted into.
964 for (pass = 0; pass < 3; pass++) {
965 unsigned int totmatch = 0;
967 for (ale = anim_data->first; ale; ale = ale->next) {
968 /* find buffer item to paste from
969 * - if names don't matter (i.e. only 1 channel in buffer), don't check id/group
970 * - if names do matter, only check if id-type is ok for now (group check is not that important)
971 * - most importantly, rna-paths should match (array indices are unimportant for now)
973 AnimData *adt = ANIM_nla_mapping_get(ac, ale);
974 FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */
975 tAnimCopybufItem *aci = NULL;
979 /* most strict, must be exact path match data_path & index */
980 aci = pastebuf_match_path_full(fcu, from_single, to_simple, flip);
984 /* less strict, just compare property names */
985 aci = pastebuf_match_path_property(fcu, from_single, to_simple);
989 /* Comparing properties gave no results, so just do index comparisons */
990 aci = pastebuf_match_index_only(fcu, from_single, to_simple);
994 /* copy the relevant data from the matching buffer curve */
999 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
1000 paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
1001 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
1004 paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
1008 ale->update |= ANIM_UPDATE_DEFAULT;
1011 /* don't continue if some fcurves were pasted */
1017 ANIM_animdata_update(ac, anim_data);
1022 /* **************************************************** */