Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / animation / keyframes_general.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edanimation
22  */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <math.h>
27 #include <float.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "BLI_blenlib.h"
32 #include "BLI_utildefines.h"
33 #include "BLI_string_utils.h"
34
35 #include "DNA_anim_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_scene_types.h"
38
39 #include "BKE_action.h"
40 #include "BKE_fcurve.h"
41 #include "BKE_report.h"
42 #include "BKE_main.h"
43 #include "BKE_deform.h"
44
45 #include "RNA_access.h"
46 #include "RNA_enum_types.h"
47
48 #include "ED_anim_api.h"
49 #include "ED_keyframing.h"
50 #include "ED_keyframes_edit.h"
51
52 /* This file contains code for various keyframe-editing tools which are 'destructive'
53  * (i.e. they will modify the order of the keyframes, and change the size of the array).
54  * While some of these tools may eventually be moved out into blenkernel, for now, it is
55  * fine to have these calls here.
56  *
57  * There are also a few tools here which cannot be easily coded for in the other system (yet).
58  * These may also be moved around at some point, but for now, they are best added here.
59  *
60  * - Joshua Leung, Dec 2008
61  */
62
63 /* **************************************************** */
64
65 /**
66  * Only delete the nominated keyframe from provided F-Curve.
67  * Not recommended to be used many times successively. For that
68  * there is #delete_fcurve_keys().
69  */
70 void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
71 {
72   /* sanity check */
73   if (fcu == NULL) {
74     return;
75   }
76
77   /* verify the index:
78    * 1) cannot be greater than the number of available keyframes
79    * 2) negative indices are for specifying a value from the end of the array
80    */
81   if (abs(index) >= fcu->totvert) {
82     return;
83   }
84   else if (index < 0) {
85     index += fcu->totvert;
86   }
87
88   /* Delete this keyframe */
89   memmove(
90       &fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1));
91   fcu->totvert--;
92
93   if (fcu->totvert == 0) {
94     if (fcu->bezt) {
95       MEM_freeN(fcu->bezt);
96     }
97     fcu->bezt = NULL;
98   }
99
100   /* recalc handles - only if it won't cause problems */
101   if (do_recalc) {
102     calchandles_fcurve(fcu);
103   }
104 }
105
106 /* Delete selected keyframes in given F-Curve */
107 bool delete_fcurve_keys(FCurve *fcu)
108 {
109   int i;
110   bool changed = false;
111
112   if (fcu->bezt == NULL) { /* ignore baked curves */
113     return false;
114   }
115
116   /* Delete selected BezTriples */
117   for (i = 0; i < fcu->totvert; i++) {
118     if (fcu->bezt[i].f2 & SELECT) {
119       memmove(&fcu->bezt[i], &fcu->bezt[i + 1], sizeof(BezTriple) * (fcu->totvert - i - 1));
120       fcu->totvert--;
121       i--;
122       changed = true;
123     }
124   }
125
126   /* Free the array of BezTriples if there are not keyframes */
127   if (fcu->totvert == 0) {
128     clear_fcurve_keys(fcu);
129   }
130
131   return changed;
132 }
133
134 void clear_fcurve_keys(FCurve *fcu)
135 {
136   if (fcu->bezt) {
137     MEM_freeN(fcu->bezt);
138   }
139   fcu->bezt = NULL;
140
141   fcu->totvert = 0;
142 }
143
144 /* ---------------- */
145
146 /* duplicate selected keyframes for the given F-Curve */
147 void duplicate_fcurve_keys(FCurve *fcu)
148 {
149   BezTriple *newbezt;
150   int i;
151
152   /* this can only work when there is an F-Curve, and also when there are some BezTriples */
153   if (ELEM(NULL, fcu, fcu->bezt)) {
154     return;
155   }
156
157   for (i = 0; i < fcu->totvert; i++) {
158     /* If a key is selected */
159     if (fcu->bezt[i].f2 & SELECT) {
160       /* Expand the list */
161       newbezt = MEM_callocN(sizeof(BezTriple) * (fcu->totvert + 1), "beztriple");
162
163       memcpy(newbezt, fcu->bezt, sizeof(BezTriple) * (i + 1));
164       memcpy(newbezt + i + 1, fcu->bezt + i, sizeof(BezTriple));
165       memcpy(newbezt + i + 2, fcu->bezt + i + 1, sizeof(BezTriple) * (fcu->totvert - (i + 1)));
166       fcu->totvert++;
167
168       /* reassign pointers... (free old, and add new) */
169       MEM_freeN(fcu->bezt);
170       fcu->bezt = newbezt;
171
172       /* Unselect the current key */
173       BEZT_DESEL_ALL(&fcu->bezt[i]);
174       i++;
175
176       /* Select the copied key */
177       BEZT_SEL_ALL(&fcu->bezt[i]);
178     }
179   }
180 }
181
182 /* **************************************************** */
183 /* Various Tools */
184
185 /**
186  * Basic F-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on
187  * linear-segments only optionally clears up curve if one keyframe with default value remains.
188  */
189 void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
190 {
191   FCurve *fcu = (FCurve *)ale->key_data;
192   BezTriple *old_bezts, *bezt, *beztn;
193   BezTriple *lastb;
194   int totCount, i;
195
196   /* check if any points  */
197   if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) ||
198       (!cleardefault && fcu->totvert == 1)) {
199     return;
200   }
201
202   /* make a copy of the old BezTriples, and clear F-Curve */
203   old_bezts = fcu->bezt;
204   totCount = fcu->totvert;
205   fcu->bezt = NULL;
206   fcu->totvert = 0;
207
208   /* now insert first keyframe, as it should be ok */
209   bezt = old_bezts;
210   insert_bezt_fcurve(fcu, bezt, 0);
211   if (!(bezt->f2 & SELECT)) {
212     lastb = fcu->bezt;
213     lastb->f1 = lastb->f2 = lastb->f3 = 0;
214   }
215
216   /* Loop through BezTriples, comparing them. Skip any that do
217    * not fit the criteria for "ok" points.
218    */
219   for (i = 1; i < totCount; i++) {
220     float prev[2], cur[2], next[2];
221
222     /* get BezTriples and their values */
223     if (i < (totCount - 1)) {
224       beztn = (old_bezts + (i + 1));
225       next[0] = beztn->vec[1][0];
226       next[1] = beztn->vec[1][1];
227     }
228     else {
229       beztn = NULL;
230       next[0] = next[1] = 0.0f;
231     }
232     lastb = (fcu->bezt + (fcu->totvert - 1));
233     bezt = (old_bezts + i);
234
235     /* get references for quicker access */
236     prev[0] = lastb->vec[1][0];
237     prev[1] = lastb->vec[1][1];
238     cur[0] = bezt->vec[1][0];
239     cur[1] = bezt->vec[1][1];
240
241     if (!(bezt->f2 & SELECT)) {
242       insert_bezt_fcurve(fcu, bezt, 0);
243       lastb = (fcu->bezt + (fcu->totvert - 1));
244       lastb->f1 = lastb->f2 = lastb->f3 = 0;
245       continue;
246     }
247
248     /* check if current bezt occurs at same time as last ok */
249     if (IS_EQT(cur[0], prev[0], thresh)) {
250       /* If there is a next beztriple, and if occurs at the same time, only insert
251        * if there is a considerable distance between the points, and also if the
252        * current is further away than the next one is to the previous.
253        */
254       if (beztn && (IS_EQT(cur[0], next[0], thresh)) && (IS_EQT(next[1], prev[1], thresh) == 0)) {
255         /* only add if current is further away from previous */
256         if (cur[1] > next[1]) {
257           if (IS_EQT(cur[1], prev[1], thresh) == 0) {
258             /* add new keyframe */
259             insert_bezt_fcurve(fcu, bezt, 0);
260           }
261         }
262       }
263       else {
264         /* only add if values are a considerable distance apart */
265         if (IS_EQT(cur[1], prev[1], thresh) == 0) {
266           /* add new keyframe */
267           insert_bezt_fcurve(fcu, bezt, 0);
268         }
269       }
270     }
271     else {
272       /* checks required are dependent on whether this is last keyframe or not */
273       if (beztn) {
274         /* does current have same value as previous and next? */
275         if (IS_EQT(cur[1], prev[1], thresh) == 0) {
276           /* add new keyframe */
277           insert_bezt_fcurve(fcu, bezt, 0);
278         }
279         else if (IS_EQT(cur[1], next[1], thresh) == 0) {
280           /* add new keyframe */
281           insert_bezt_fcurve(fcu, bezt, 0);
282         }
283       }
284       else {
285         /* add if value doesn't equal that of previous */
286         if (IS_EQT(cur[1], prev[1], thresh) == 0) {
287           /* add new keyframe */
288           insert_bezt_fcurve(fcu, bezt, 0);
289         }
290       }
291     }
292   }
293
294   /* now free the memory used by the old BezTriples */
295   if (old_bezts) {
296     MEM_freeN(old_bezts);
297   }
298
299   /* final step, if there is just one key in fcurve, check if it's
300    * the default value and if is, remove fcurve completely. */
301   if (cleardefault && fcu->totvert == 1) {
302     float default_value = 0.0f;
303     PointerRNA id_ptr, ptr;
304     PropertyRNA *prop;
305     RNA_id_pointer_create(ale->id, &id_ptr);
306
307     /* get property to read from, and get value as appropriate */
308     if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
309       if (RNA_property_type(prop) == PROP_FLOAT) {
310         default_value = RNA_property_float_get_default_index(&ptr, prop, fcu->array_index);
311       }
312     }
313
314     if (fcu->bezt->vec[1][1] == default_value) {
315       clear_fcurve_keys(fcu);
316
317       /* check if curve is really unused and if it is, return signal for deletion */
318       if ((list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
319           (fcu->driver == NULL)) {
320         AnimData *adt = ale->adt;
321         ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
322         ale->key_data = NULL;
323       }
324     }
325   }
326 }
327
328 /* ---------------- */
329
330 /* temp struct used for smooth_fcurve */
331 typedef struct tSmooth_Bezt {
332   float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */
333   float y1, y2, y3;    /* averaged before/new/after y-values */
334 } tSmooth_Bezt;
335
336 /* Use a weighted moving-means method to reduce intensity of fluctuations */
337 // TODO: introduce scaling factor for weighting falloff
338 void smooth_fcurve(FCurve *fcu)
339 {
340   BezTriple *bezt;
341   int i, x, totSel = 0;
342
343   if (fcu->bezt == NULL) {
344     return;
345   }
346
347   /* first loop through - count how many verts are selected */
348   bezt = fcu->bezt;
349   for (i = 0; i < fcu->totvert; i++, bezt++) {
350     if (BEZT_ISSEL_ANY(bezt)) {
351       totSel++;
352     }
353   }
354
355   /* if any points were selected, allocate tSmooth_Bezt points to work on */
356   if (totSel >= 3) {
357     tSmooth_Bezt *tarray, *tsb;
358
359     /* allocate memory in one go */
360     tsb = tarray = MEM_callocN(totSel * sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
361
362     /* populate tarray with data of selected points */
363     bezt = fcu->bezt;
364     for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
365       if (BEZT_ISSEL_ANY(bezt)) {
366         /* tsb simply needs pointer to vec, and index */
367         tsb->h1 = &bezt->vec[0][1];
368         tsb->h2 = &bezt->vec[1][1];
369         tsb->h3 = &bezt->vec[2][1];
370
371         /* advance to the next tsb to populate */
372         if (x < totSel - 1) {
373           tsb++;
374         }
375         else {
376           break;
377         }
378       }
379     }
380
381     /* calculate the new smoothed F-Curve's with weighted averages:
382      * - this is done with two passes to avoid progressive corruption errors
383      * - uses 5 points for each operation (which stores in the relevant handles)
384      * -   previous: w/a ratio = 3:5:2:1:1
385      * -   next: w/a ratio = 1:1:2:5:3
386      */
387
388     /* round 1: calculate smoothing deltas and new values */
389     tsb = tarray;
390     for (i = 0; i < totSel; i++, tsb++) {
391       /* Don't touch end points (otherwise, curves slowly explode,
392        * as we don't have enough data there). */
393       if (ELEM(i, 0, (totSel - 1)) == 0) {
394         const tSmooth_Bezt *tP1 = tsb - 1;
395         const tSmooth_Bezt *tP2 = (i - 2 > 0) ? (tsb - 2) : (NULL);
396         const tSmooth_Bezt *tN1 = tsb + 1;
397         const tSmooth_Bezt *tN2 = (i + 2 < totSel) ? (tsb + 2) : (NULL);
398
399         const float p1 = *tP1->h2;
400         const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
401         const float c1 = *tsb->h2;
402         const float n1 = *tN1->h2;
403         const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
404
405         /* calculate previous and next, then new position by averaging these */
406         tsb->y1 = (3 * p2 + 5 * p1 + 2 * c1 + n1 + n2) / 12;
407         tsb->y3 = (p2 + p1 + 2 * c1 + 5 * n1 + 3 * n2) / 12;
408
409         tsb->y2 = (tsb->y1 + tsb->y3) / 2;
410       }
411     }
412
413     /* round 2: apply new values */
414     tsb = tarray;
415     for (i = 0; i < totSel; i++, tsb++) {
416       /* don't touch end points, as their values weren't touched above */
417       if (ELEM(i, 0, (totSel - 1)) == 0) {
418         /* y2 takes the average of the 2 points */
419         *tsb->h2 = tsb->y2;
420
421         /* handles are weighted between their original values and the averaged values */
422         *tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f);
423         *tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f);
424       }
425     }
426
427     /* free memory required for tarray */
428     MEM_freeN(tarray);
429   }
430
431   /* recalculate handles */
432   calchandles_fcurve(fcu);
433 }
434
435 /* ---------------- */
436
437 /* little cache for values... */
438 typedef struct TempFrameValCache {
439   float frame, val;
440 } TempFrameValCache;
441
442 /* Evaluates the curves between each selected keyframe on each frame, and keys the value  */
443 void sample_fcurve(FCurve *fcu)
444 {
445   BezTriple *bezt, *start = NULL, *end = NULL;
446   TempFrameValCache *value_cache, *fp;
447   int sfra, range;
448   int i, n;
449
450   if (fcu->bezt == NULL) { /* ignore baked */
451     return;
452   }
453
454   /* find selected keyframes... once pair has been found, add keyframes  */
455   for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
456     /* check if selected, and which end this is */
457     if (BEZT_ISSEL_ANY(bezt)) {
458       if (start) {
459         /* If next bezt is also selected, don't start sampling yet,
460          * but instead wait for that one to reconsider, to avoid
461          * changing the curve when sampling consecutive segments
462          * (T53229)
463          */
464         if (i < fcu->totvert - 1) {
465           BezTriple *next = &fcu->bezt[i + 1];
466           if (BEZT_ISSEL_ANY(next)) {
467             continue;
468           }
469         }
470
471         /* set end */
472         end = bezt;
473
474         /* cache values then add keyframes using these values, as adding
475          * keyframes while sampling will affect the outcome...
476          * - only start sampling+adding from index=1, so that we don't overwrite original keyframe
477          */
478         range = (int)(ceil(end->vec[1][0] - start->vec[1][0]));
479         sfra = (int)(floor(start->vec[1][0]));
480
481         if (range) {
482           value_cache = MEM_callocN(sizeof(TempFrameValCache) * range, "IcuFrameValCache");
483
484           /* sample values */
485           for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
486             fp->frame = (float)(sfra + n);
487             fp->val = evaluate_fcurve(fcu, fp->frame);
488           }
489
490           /* add keyframes with these, tagging as 'breakdowns' */
491           for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
492             insert_vert_fcurve(fcu, fp->frame, fp->val, BEZT_KEYTYPE_BREAKDOWN, 1);
493           }
494
495           /* free temp cache */
496           MEM_freeN(value_cache);
497
498           /* as we added keyframes, we need to compensate so that bezt is at the right place */
499           bezt = fcu->bezt + i + range - 1;
500           i += (range - 1);
501         }
502
503         /* the current selection island has ended, so start again from scratch */
504         start = NULL;
505         end = NULL;
506       }
507       else {
508         /* just set start keyframe */
509         start = bezt;
510         end = NULL;
511       }
512     }
513   }
514
515   /* recalculate channel's handles? */
516   calchandles_fcurve(fcu);
517 }
518
519 /* **************************************************** */
520 /* Copy/Paste Tools:
521  * - The copy/paste buffer currently stores a set of temporary F-Curves containing only the
522  *   keyframes that were selected in each of the original F-Curves.
523  * - All pasted frames are offset by the same amount.
524  *   This is calculated as the difference in the times of the current frame and the
525  *   'first keyframe' (i.e. the earliest one in all channels).
526  * - The earliest frame is calculated per copy operation.
527  */
528
529 /* globals for copy/paste data (like for other copy/paste buffers) */
530 static ListBase animcopybuf = {NULL, NULL};
531 static float animcopy_firstframe = 999999999.0f;
532 static float animcopy_lastframe = -999999999.0f;
533 static float animcopy_cfra = 0.0;
534
535 /* datatype for use in copy/paste buffer */
536 typedef struct tAnimCopybufItem {
537   struct tAnimCopybufItem *next, *prev;
538
539   ID *id;            /* ID which owns the curve */
540   bActionGroup *grp; /* Action Group */
541   char *rna_path;    /* RNA-Path */
542   int array_index;   /* array index */
543
544   int totvert;     /* number of keyframes stored for this channel */
545   BezTriple *bezt; /* keyframes in buffer */
546
547   short id_type; /* Result of GS(id->name)*/
548   bool is_bone;  /* special flag for armature bones */
549 } tAnimCopybufItem;
550
551 /* This function frees any MEM_calloc'ed copy/paste buffer data */
552 void ANIM_fcurves_copybuf_free(void)
553 {
554   tAnimCopybufItem *aci, *acn;
555
556   /* free each buffer element */
557   for (aci = animcopybuf.first; aci; aci = acn) {
558     acn = aci->next;
559
560     /* free keyframes */
561     if (aci->bezt) {
562       MEM_freeN(aci->bezt);
563     }
564
565     /* free RNA-path */
566     if (aci->rna_path) {
567       MEM_freeN(aci->rna_path);
568     }
569
570     /* free ourself */
571     BLI_freelinkN(&animcopybuf, aci);
572   }
573
574   /* restore initial state */
575   BLI_listbase_clear(&animcopybuf);
576   animcopy_firstframe = 999999999.0f;
577   animcopy_lastframe = -999999999.0f;
578 }
579
580 /* ------------------- */
581
582 /* This function adds data to the keyframes copy/paste buffer, freeing existing data first */
583 short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
584 {
585   bAnimListElem *ale;
586   Scene *scene = ac->scene;
587
588   /* clear buffer first */
589   ANIM_fcurves_copybuf_free();
590
591   /* assume that each of these is an F-Curve */
592   for (ale = anim_data->first; ale; ale = ale->next) {
593     FCurve *fcu = (FCurve *)ale->key_data;
594     tAnimCopybufItem *aci;
595     BezTriple *bezt, *nbezt, *newbuf;
596     int i;
597
598     /* firstly, check if F-Curve has any selected keyframes
599      * - skip if no selected keyframes found (so no need to create unnecessary copy-buffer data)
600      * - this check should also eliminate any problems associated with using sample-data
601      */
602     if (ANIM_fcurve_keyframes_loop(
603             NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0) {
604       continue;
605     }
606
607     /* init copybuf item info */
608     aci = MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem");
609     aci->id = ale->id;
610     aci->id_type = GS(ale->id->name);
611     aci->grp = fcu->grp;
612     aci->rna_path = MEM_dupallocN(fcu->rna_path);
613     aci->array_index = fcu->array_index;
614
615     /* Detect if this is a bone. We do that here rather than during pasting because ID pointers
616      * will get invalidated if we undo.
617      * Storing the relevant information here helps avoiding crashes if we undo-repaste. */
618     if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) {
619       Object *ob = (Object *)aci->id;
620       bPoseChannel *pchan;
621       char *bone_name;
622
623       bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones[");
624       pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
625       if (pchan) {
626         aci->is_bone = true;
627       }
628       if (bone_name) {
629         MEM_freeN(bone_name);
630       }
631     }
632
633     BLI_addtail(&animcopybuf, aci);
634
635     /* add selected keyframes to buffer */
636     /* TODO: currently, we resize array every time we add a new vert -
637      * this works ok as long as it is assumed only a few keys are copied */
638     for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
639       if (BEZT_ISSEL_ANY(bezt)) {
640         /* add to buffer */
641         newbuf = MEM_callocN(sizeof(BezTriple) * (aci->totvert + 1), "copybuf beztriple");
642
643         /* assume that since we are just re-sizing the array, just copy all existing data across */
644         if (aci->bezt) {
645           memcpy(newbuf, aci->bezt, sizeof(BezTriple) * (aci->totvert));
646         }
647
648         /* copy current beztriple across too */
649         nbezt = &newbuf[aci->totvert];
650         *nbezt = *bezt;
651
652         /* ensure copy buffer is selected so pasted keys are selected */
653         BEZT_SEL_ALL(nbezt);
654
655         /* free old array and set the new */
656         if (aci->bezt) {
657           MEM_freeN(aci->bezt);
658         }
659         aci->bezt = newbuf;
660         aci->totvert++;
661
662         /* check if this is the earliest frame encountered so far */
663         if (bezt->vec[1][0] < animcopy_firstframe) {
664           animcopy_firstframe = bezt->vec[1][0];
665         }
666         if (bezt->vec[1][0] > animcopy_lastframe) {
667           animcopy_lastframe = bezt->vec[1][0];
668         }
669       }
670     }
671   }
672
673   /* check if anything ended up in the buffer */
674   if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) {
675     return -1;
676   }
677
678   /* in case 'relative' paste method is used */
679   animcopy_cfra = CFRA;
680
681   /* everything went fine */
682   return 0;
683 }
684
685 static void flip_names(tAnimCopybufItem *aci, char **name)
686 {
687   if (aci->is_bone) {
688     char *str_start;
689     if ((str_start = strstr(aci->rna_path, "pose.bones["))) {
690       /* ninja coding, try to change the name */
691       char bname_new[MAX_VGROUP_NAME];
692       char *str_iter, *str_end;
693       int length, prefix_l, postfix_l;
694
695       str_start += 12;
696       prefix_l = str_start - aci->rna_path;
697
698       str_end = strchr(str_start, '\"');
699
700       length = str_end - str_start;
701       postfix_l = strlen(str_end);
702
703       /* more ninja stuff, temporary substitute with NULL terminator */
704       str_start[length] = 0;
705       BLI_string_flip_side_name(bname_new, str_start, false, sizeof(bname_new));
706       str_start[length] = '\"';
707
708       str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1),
709                                      "flipped_path");
710
711       BLI_strncpy(str_iter, aci->rna_path, prefix_l + 1);
712       str_iter += prefix_l;
713       BLI_strncpy(str_iter, bname_new, length + 1);
714       str_iter += length;
715       BLI_strncpy(str_iter, str_end, postfix_l + 1);
716       str_iter[postfix_l] = '\0';
717     }
718   }
719 }
720
721 /* ------------------- */
722
723 /* most strict method: exact matches only */
724 static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu,
725                                                   const short from_single,
726                                                   const short to_simple,
727                                                   bool flip)
728 {
729   tAnimCopybufItem *aci;
730
731   for (aci = animcopybuf.first; aci; aci = aci->next) {
732     if (to_simple || (aci->rna_path && fcu->rna_path)) {
733       if (!to_simple && flip && aci->is_bone && fcu->rna_path) {
734         if ((from_single) || (aci->array_index == fcu->array_index)) {
735           char *name = NULL;
736           flip_names(aci, &name);
737           if (STREQ(name, fcu->rna_path)) {
738             MEM_freeN(name);
739             break;
740           }
741           MEM_freeN(name);
742         }
743       }
744       else if (to_simple || STREQ(aci->rna_path, fcu->rna_path)) {
745         if ((from_single) || (aci->array_index == fcu->array_index)) {
746           break;
747         }
748       }
749     }
750   }
751
752   return aci;
753 }
754
755 /* medium match strictness: path match only (i.e. ignore ID) */
756 static tAnimCopybufItem *pastebuf_match_path_property(Main *bmain,
757                                                       FCurve *fcu,
758                                                       const short from_single,
759                                                       const short UNUSED(to_simple))
760 {
761   tAnimCopybufItem *aci;
762
763   for (aci = animcopybuf.first; aci; aci = aci->next) {
764     /* check that paths exist */
765     if (aci->rna_path && fcu->rna_path) {
766       /* find the property of the fcurve and compare against the end of the tAnimCopybufItem
767        * more involved since it needs to do path lookups.
768        * This is not 100% reliable since the user could be editing the curves on a path that wont
769        * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste
770        * this should work out ok.
771        */
772       if (BLI_findindex(which_libbase(bmain, aci->id_type), aci->id) == -1) {
773         /* pedantic but the ID could have been removed, and beats crashing! */
774         printf("paste_animedit_keys: error ID has been removed!\n");
775       }
776       else {
777         PointerRNA id_ptr, rptr;
778         PropertyRNA *prop;
779
780         RNA_id_pointer_create(aci->id, &id_ptr);
781
782         if (RNA_path_resolve_property(&id_ptr, aci->rna_path, &rptr, &prop)) {
783           const char *identifier = RNA_property_identifier(prop);
784           int len_id = strlen(identifier);
785           int len_path = strlen(fcu->rna_path);
786           if (len_id <= len_path) {
787             /* note, paths which end with "] will fail with this test - Animated ID Props */
788             if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) {
789               if ((from_single) || (aci->array_index == fcu->array_index)) {
790                 break;
791               }
792             }
793           }
794         }
795         else {
796           printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n",
797                  aci->id->name,
798                  aci->rna_path);
799         }
800       }
801     }
802   }
803
804   return aci;
805 }
806
807 /* least strict matching heuristic: indices only */
808 static tAnimCopybufItem *pastebuf_match_index_only(FCurve *fcu,
809                                                    const short from_single,
810                                                    const short UNUSED(to_simple))
811 {
812   tAnimCopybufItem *aci;
813
814   for (aci = animcopybuf.first; aci; aci = aci->next) {
815     /* check that paths exist */
816     if ((from_single) || (aci->array_index == fcu->array_index)) {
817       break;
818     }
819   }
820
821   return aci;
822 }
823
824 /* ................ */
825
826 static void do_curve_mirror_flippping(tAnimCopybufItem *aci, BezTriple *bezt)
827 {
828   if (aci->is_bone) {
829     const size_t slength = strlen(aci->rna_path);
830     bool flip = false;
831     if (BLI_strn_endswith(aci->rna_path, "location", slength) && aci->array_index == 0) {
832       flip = true;
833     }
834     else if (BLI_strn_endswith(aci->rna_path, "rotation_quaternion", slength) &&
835              ELEM(aci->array_index, 2, 3)) {
836       flip = true;
837     }
838     else if (BLI_strn_endswith(aci->rna_path, "rotation_euler", slength) &&
839              ELEM(aci->array_index, 1, 2)) {
840       flip = true;
841     }
842     else if (BLI_strn_endswith(aci->rna_path, "rotation_axis_angle", slength) &&
843              ELEM(aci->array_index, 2, 3)) {
844       flip = true;
845     }
846
847     if (flip) {
848       bezt->vec[0][1] = -bezt->vec[0][1];
849       bezt->vec[1][1] = -bezt->vec[1][1];
850       bezt->vec[2][1] = -bezt->vec[2][1];
851     }
852   }
853 }
854
855 /* helper for paste_animedit_keys() - performs the actual pasting */
856 static void paste_animedit_keys_fcurve(
857     FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode, bool flip)
858 {
859   BezTriple *bezt;
860   int i;
861
862   /* First de-select existing FCurve's keyframes */
863   for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
864     BEZT_DESEL_ALL(bezt);
865   }
866
867   /* mix mode with existing data */
868   switch (merge_mode) {
869     case KEYFRAME_PASTE_MERGE_MIX:
870       /* do-nothing */
871       break;
872
873     case KEYFRAME_PASTE_MERGE_OVER:
874       /* remove all keys */
875       clear_fcurve_keys(fcu);
876       break;
877
878     case KEYFRAME_PASTE_MERGE_OVER_RANGE:
879     case KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL: {
880       float f_min;
881       float f_max;
882
883       if (merge_mode == KEYFRAME_PASTE_MERGE_OVER_RANGE) {
884         f_min = aci->bezt[0].vec[1][0] + offset;
885         f_max = aci->bezt[aci->totvert - 1].vec[1][0] + offset;
886       }
887       else { /* Entire Range */
888         f_min = animcopy_firstframe + offset;
889         f_max = animcopy_lastframe + offset;
890       }
891
892       /* remove keys in range */
893       if (f_min < f_max) {
894         /* select verts in range for removal */
895         for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
896           if ((f_min < bezt[0].vec[1][0]) && (bezt[0].vec[1][0] < f_max)) {
897             bezt->f2 |= SELECT;
898           }
899         }
900
901         /* remove frames in the range */
902         delete_fcurve_keys(fcu);
903       }
904       break;
905     }
906   }
907
908   /* just start pasting, with the first keyframe on the current frame, and so on */
909   for (i = 0, bezt = aci->bezt; i < aci->totvert; i++, bezt++) {
910     /* temporarily apply offset to src beztriple while copying */
911     if (flip) {
912       do_curve_mirror_flippping(aci, bezt);
913     }
914
915     bezt->vec[0][0] += offset;
916     bezt->vec[1][0] += offset;
917     bezt->vec[2][0] += offset;
918
919     /* insert the keyframe
920      * NOTE: we do not want to inherit handles from existing keyframes in this case!
921      */
922
923     insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
924
925     /* un-apply offset from src beztriple after copying */
926     bezt->vec[0][0] -= offset;
927     bezt->vec[1][0] -= offset;
928     bezt->vec[2][0] -= offset;
929
930     if (flip) {
931       do_curve_mirror_flippping(aci, bezt);
932     }
933   }
934
935   /* recalculate F-Curve's handles? */
936   calchandles_fcurve(fcu);
937 }
938
939 /* ------------------- */
940
941 const EnumPropertyItem rna_enum_keyframe_paste_offset_items[] = {
942     {KEYFRAME_PASTE_OFFSET_CFRA_START,
943      "START",
944      0,
945      "Frame Start",
946      "Paste keys starting at current frame"},
947     {KEYFRAME_PASTE_OFFSET_CFRA_END, "END", 0, "Frame End", "Paste keys ending at current frame"},
948     {KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE,
949      "RELATIVE",
950      0,
951      "Frame Relative",
952      "Paste keys relative to the current frame when copying"},
953     {KEYFRAME_PASTE_OFFSET_NONE, "NONE", 0, "No Offset", "Paste keys from original time"},
954     {0, NULL, 0, NULL, NULL},
955 };
956
957 const EnumPropertyItem rna_enum_keyframe_paste_merge_items[] = {
958     {KEYFRAME_PASTE_MERGE_MIX, "MIX", 0, "Mix", "Overlay existing with new keys"},
959     {KEYFRAME_PASTE_MERGE_OVER, "OVER_ALL", 0, "Overwrite All", "Replace all keys"},
960     {KEYFRAME_PASTE_MERGE_OVER_RANGE,
961      "OVER_RANGE",
962      0,
963      "Overwrite Range",
964      "Overwrite keys in pasted range"},
965     {KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL,
966      "OVER_RANGE_ALL",
967      0,
968      "Overwrite Entire Range",
969      "Overwrite keys in pasted range, using the range of all copied keys"},
970     {0, NULL, 0, NULL, NULL},
971 };
972
973 /**
974  * This function pastes data from the keyframes copy/paste buffer
975  *
976  * \return Status code is whether the method FAILED to do anything
977  */
978 short paste_animedit_keys(bAnimContext *ac,
979                           ListBase *anim_data,
980                           const eKeyPasteOffset offset_mode,
981                           const eKeyMergeMode merge_mode,
982                           bool flip)
983 {
984   bAnimListElem *ale;
985
986   const Scene *scene = (ac->scene);
987
988   const bool from_single = BLI_listbase_is_single(&animcopybuf);
989   const bool to_simple = BLI_listbase_is_single(anim_data);
990
991   float offset = 0.0f;
992   int pass;
993
994   /* check if buffer is empty */
995   if (BLI_listbase_is_empty(&animcopybuf)) {
996     BKE_report(ac->reports, RPT_ERROR, "No animation data in buffer to paste");
997     return -1;
998   }
999
1000   if (BLI_listbase_is_empty(anim_data)) {
1001     BKE_report(ac->reports, RPT_ERROR, "No selected F-Curves to paste into");
1002     return -1;
1003   }
1004
1005   /* methods of offset */
1006   switch (offset_mode) {
1007     case KEYFRAME_PASTE_OFFSET_CFRA_START:
1008       offset = (float)(CFRA - animcopy_firstframe);
1009       break;
1010     case KEYFRAME_PASTE_OFFSET_CFRA_END:
1011       offset = (float)(CFRA - animcopy_lastframe);
1012       break;
1013     case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
1014       offset = (float)(CFRA - animcopy_cfra);
1015       break;
1016     case KEYFRAME_PASTE_OFFSET_NONE:
1017       offset = 0.0f;
1018       break;
1019   }
1020
1021   if (from_single && to_simple) {
1022     /* 1:1 match, no tricky checking, just paste */
1023     FCurve *fcu;
1024     tAnimCopybufItem *aci;
1025
1026     ale = anim_data->first;
1027     fcu = (FCurve *)ale->data; /* destination F-Curve */
1028     aci = animcopybuf.first;
1029
1030     paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false);
1031     ale->update |= ANIM_UPDATE_DEFAULT;
1032   }
1033   else {
1034     /* from selected channels
1035      * This "passes" system aims to try to find "matching" channels to paste keyframes
1036      * into with increasingly loose matching heuristics. The process finishes when at least
1037      * one F-Curve has been pasted into.
1038      */
1039     for (pass = 0; pass < 3; pass++) {
1040       unsigned int totmatch = 0;
1041
1042       for (ale = anim_data->first; ale; ale = ale->next) {
1043         /* Find buffer item to paste from:
1044          * - If names don't matter (i.e. only 1 channel in buffer), don't check id/group
1045          * - If names do matter, only check if id-type is ok for now
1046          *   (group check is not that important).
1047          * - Most importantly, rna-paths should match (array indices are unimportant for now)
1048          */
1049         AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1050         FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */
1051         tAnimCopybufItem *aci = NULL;
1052
1053         switch (pass) {
1054           case 0:
1055             /* most strict, must be exact path match data_path & index */
1056             aci = pastebuf_match_path_full(fcu, from_single, to_simple, flip);
1057             break;
1058
1059           case 1:
1060             /* less strict, just compare property names */
1061             aci = pastebuf_match_path_property(ac->bmain, fcu, from_single, to_simple);
1062             break;
1063
1064           case 2:
1065             /* Comparing properties gave no results, so just do index comparisons */
1066             aci = pastebuf_match_index_only(fcu, from_single, to_simple);
1067             break;
1068         }
1069
1070         /* copy the relevant data from the matching buffer curve */
1071         if (aci) {
1072           totmatch++;
1073
1074           if (adt) {
1075             ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
1076             paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
1077             ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
1078           }
1079           else {
1080             paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
1081           }
1082         }
1083
1084         ale->update |= ANIM_UPDATE_DEFAULT;
1085       }
1086
1087       /* don't continue if some fcurves were pasted */
1088       if (totmatch) {
1089         break;
1090       }
1091     }
1092   }
1093
1094   ANIM_animdata_update(ac, anim_data);
1095
1096   return 0;
1097 }
1098
1099 /* **************************************************** */