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