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