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