b8a3b8acb1966bf6a86ed5f6e60ab07b7887bd74
[blender-staging.git] / source / blender / editors / animation / keyframes_edit.c
1 /**
2  * $Id: 
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <math.h>
31 #include <float.h>
32
33 #include "BLI_blenlib.h"
34 #include "BLI_arithb.h"
35
36 #include "DNA_action_types.h"
37 #include "DNA_curve_types.h"
38 #include "DNA_ipo_types.h"
39 #include "DNA_key_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_scene_types.h"
43
44 #include "BKE_action.h"
45 #include "BKE_ipo.h"
46 #include "BKE_key.h"
47 #include "BKE_utildefines.h"
48
49 #include "ED_anim_api.h"
50 #include "ED_keyframes_edit.h"
51 #include "ED_markers.h"
52
53 /* This file defines an API and set of callback-operators for non-destructive editing of keyframe data.
54  *
55  * Two API functions are defined for actually performing the operations on the data:
56  *                      ipo_keys_bezier_loop() and icu_keys_bezier_loop()
57  * which take the data they operate on, a few callbacks defining what operations to perform.
58  *
59  * As operators which work on keyframes usually apply the same operation on all BezTriples in 
60  * every channel, the code has been optimised providing a set of functions which will get the 
61  * appropriate bezier-modify function to set. These functions (ANIM_editkeyframes_*) will need
62  * to be called before getting any channels.
63  * 
64  * A set of 'validation' callbacks are provided for checking if a BezTriple should be operated on.
65  * These should only be used when using a 'general' BezTriple editor (i.e. selection setters which 
66  * don't check existing selection status).
67  * 
68  * - Joshua Leung, Dec 2008
69  */
70
71 /* ************************************************************************** */
72 /* IPO Editing Loops - Exposed API */
73
74 /* --------------------------- Base Functions ------------------------------------ */
75
76 /* This function is used to loop over BezTriples in the given IpoCurve, applying a given 
77  * operation on them, and optionally applies an IPO-curve validate function afterwards.
78  */
79 short icu_keys_bezier_loop(BeztEditData *bed, IpoCurve *icu, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, IcuEditFunc icu_cb) 
80 {
81     BezTriple *bezt;
82         int b;
83         
84         /* if function to apply to bezier curves is set, then loop through executing it on beztriples */
85     if (bezt_cb) {
86                 /* if there's a validation func, include that check in the loop 
87                  * (this is should be more efficient than checking for it in every loop)
88                  */
89                 if (bezt_ok) {
90                         for (b=0, bezt=icu->bezt; b < icu->totvert; b++, bezt++) {
91                                 /* Only operate on this BezTriple if it fullfills the criteria of the validation func */
92                                 if (bezt_ok(bed, bezt)) {
93                                         /* Exit with return-code '1' if function returns positive
94                                          * This is useful if finding if some BezTriple satisfies a condition.
95                                          */
96                                 if (bezt_cb(bed, bezt)) return 1;
97                                 }
98                         }
99                 }
100                 else {
101                         for (b=0, bezt=icu->bezt; b < icu->totvert; b++, bezt++) {
102                                 /* Exit with return-code '1' if function returns positive
103                                  * This is useful if finding if some BezTriple satisfies a condition.
104                                  */
105                         if (bezt_cb(bed, bezt)) return 1;
106                         }
107                 }
108     }
109
110     /* if ipocurve_function has been specified then execute it */
111     if (icu_cb)
112         icu_cb(icu);
113         
114         /* done */      
115     return 0;
116 }
117
118 /* This function is used to loop over the IPO curves (and subsequently the keyframes in them) */
119 short ipo_keys_bezier_loop(BeztEditData *bed, Ipo *ipo, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, IcuEditFunc icu_cb)
120 {
121     IpoCurve *icu;
122         
123         /* Sanity check */
124         if (ipo == NULL)
125                 return 0;
126         
127     /* Loop through each curve in the Ipo */
128     for (icu= ipo->curve.first; icu; icu=icu->next) {
129         if (icu_keys_bezier_loop(bed, icu, bezt_ok, bezt_cb, icu_cb))
130             return 1;
131     }
132
133     return 0;
134 }
135
136 /* -------------------------------- Further Abstracted ----------------------------- */
137
138 /* This function is used to apply operation to all keyframes, regardless of the type */
139 short animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, IcuEditFunc icu_cb)
140 {
141         return 0;
142 }
143
144 /* ************************************************************************** */
145 /* Keyframe Integrity Tools */
146
147 /* Rearrange keyframes if some are out of order */
148 // used to be recalc_*_ipos() where * was object or action
149 void ANIM_editkeyframes_refresh(bAnimContext *ac)
150 {
151         ListBase anim_data = {NULL, NULL};
152         bAnimListElem *ale;
153         int filter;
154         
155         /* filter animation data */
156         filter= ANIMFILTER_ONLYICU;
157         ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
158         
159         /* loop over ipo-curves that are likely to have been edited, and check them */
160         for (ale= anim_data.first; ale; ale= ale->next) {
161                 IpoCurve *icu= ale->key_data;
162                 
163                 /* make sure keyframes in IPO-curve are all in order, and handles are in valid positions */
164                 sort_time_ipocurve(icu);
165                 testhandles_ipocurve(icu);
166         }
167         
168         /* free temp data */
169         BLI_freelistN(&anim_data);
170 }
171
172 /* ************************************************************************** */
173 /* BezTriple Validation Callbacks */
174
175 static short ok_bezier_frame(BeztEditData *bed, BezTriple *bezt)
176 {
177         /* frame is stored in f1 property (this float accuracy check may need to be dropped?) */
178         return IS_EQ(bezt->vec[1][0], bed->f1);
179 }
180
181 static short ok_bezier_framerange(BeztEditData *bed, BezTriple *bezt)
182 {
183         /* frame range is stored in float properties */
184         return ((bezt->vec[1][0] > bed->f1) && (bezt->vec[1][0] < bed->f2));
185 }
186
187 static short ok_bezier_selected(BeztEditData *bed, BezTriple *bezt)
188 {
189         /* this macro checks all beztriple handles for selection... */
190         return BEZSELECTED(bezt);
191 }
192
193 static short ok_bezier_value(BeztEditData *bed, BezTriple *bezt)
194 {
195         /* value is stored in f1 property 
196          *      - this float accuracy check may need to be dropped?
197          *      - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too?
198          */
199         return IS_EQ(bezt->vec[1][1], bed->f1);
200 }
201
202
203 BeztEditFunc ANIM_editkeyframes_ok(short mode)
204 {
205         /* eEditKeyframes_Validate */
206         switch (mode) {
207                 case BEZT_OK_FRAME: /* only if bezt falls on the right frame (float) */
208                         return ok_bezier_frame;
209                 case BEZT_OK_FRAMERANGE: /* only if bezt falls within the specified frame range (floats) */
210                         return ok_bezier_framerange;
211                 case BEZT_OK_SELECTED:  /* only if bezt is selected */
212                         return ok_bezier_selected;
213                 case BEZT_OK_VALUE: /* only if bezt value matches (float) */
214                         return ok_bezier_value;
215                 default: /* nothing was ok */
216                         return NULL;
217         }
218 }
219
220 /* ******************************************* */
221 /* Transform */
222
223 static short snap_bezier_nearest(BeztEditData *bed, BezTriple *bezt)
224 {
225         if (bezt->f2 & SELECT)
226                 bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
227         return 0;
228 }
229
230 static short snap_bezier_nearestsec(BeztEditData *bed, BezTriple *bezt)
231 {
232         const Scene *scene= bed->scene;
233         const float secf = FPS;
234         
235         if (bezt->f2 & SELECT)
236                 bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]/secf + 0.5f) * secf);
237         return 0;
238 }
239
240 static short snap_bezier_cframe(BeztEditData *bed, BezTriple *bezt)
241 {
242         const Scene *scene= bed->scene;
243         if (bezt->f2 & SELECT)
244                 bezt->vec[1][0]= (float)CFRA;
245         return 0;
246 }
247
248 static short snap_bezier_nearmarker(BeztEditData *bed, BezTriple *bezt)
249 {
250         //if (bezt->f2 & SELECT)
251         //      bezt->vec[1][0]= (float)find_nearest_marker_time(bezt->vec[1][0]);  // XXX missing function!
252         return 0;
253 }
254
255 // calchandles_ipocurve
256 BeztEditFunc ANIM_editkeyframes_snap(short type)
257 {
258         /* eEditKeyframes_Snap */
259         switch (type) {
260                 case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
261                         return snap_bezier_nearest;
262                 case SNAP_KEYS_CURFRAME: /* snap to current frame */
263                         return snap_bezier_cframe;
264                 case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
265                         return snap_bezier_nearmarker;
266                 case SNAP_KEYS_NEARSEC: /* snap to nearest second */
267                         return snap_bezier_nearestsec;
268                 default: /* just in case */
269                         return snap_bezier_nearest;
270         }
271 }
272
273 /* --------- */
274
275 static short mirror_bezier_cframe(BeztEditData *bed, BezTriple *bezt)
276 {
277         const Scene *scene= bed->scene;
278         float diff;
279         
280         if (bezt->f2 & SELECT) {
281                 diff= ((float)CFRA - bezt->vec[1][0]);
282                 bezt->vec[1][0]= ((float)CFRA + diff);
283         }
284         
285         return 0;
286 }
287
288 static short mirror_bezier_yaxis(BeztEditData *bed, BezTriple *bezt)
289 {
290         float diff;
291         
292         if (bezt->f2 & SELECT) {
293                 diff= (0.0f - bezt->vec[1][0]);
294                 bezt->vec[1][0]= (0.0f + diff);
295         }
296         
297         return 0;
298 }
299
300 static short mirror_bezier_xaxis(BeztEditData *bed, BezTriple *bezt)
301 {
302         float diff;
303         
304         if (bezt->f2 & SELECT) {
305                 diff= (0.0f - bezt->vec[1][1]);
306                 bezt->vec[1][1]= (0.0f + diff);
307         }
308         
309         return 0;
310 }
311
312 static short mirror_bezier_marker(BeztEditData *bed, BezTriple *bezt)
313 {
314         /* mirroring time stored in f1 */
315         if (bezt->f2 & SELECT) {
316                 const float diff= (bed->f1 - bezt->vec[1][0]);
317                 bezt->vec[1][0]= (bed->f1 + diff);
318         }
319         
320         return 0;
321 }
322
323 /* Note: for markers case, need to set global vars (eww...) */
324 // calchandles_ipocurve
325 BeztEditFunc ANIM_editkeyframes_mirror(short type)
326 {
327         switch (type) {
328                 case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
329                         return mirror_bezier_cframe;
330                 case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
331                         return mirror_bezier_yaxis;
332                 case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
333                         return mirror_bezier_xaxis;
334                 case MIRROR_KEYS_MARKER: /* mirror over marker */
335                         return mirror_bezier_marker; 
336                 default: /* just in case */
337                         return mirror_bezier_yaxis;
338                         break;
339         }
340 }
341
342 /* --------- */
343
344 /* This function is called to calculate the average location of the
345  * selected keyframes, and place the current frame at that location.
346  *
347  * It must be called like so:
348  *      snap_cfra_ipo_keys(scene, NULL, -1); // initialise the static vars first
349  *      for (ipo...) snap_cfra_ipo_keys(scene, ipo, 0); // sum up keyframe times
350  *      snap_cfra_ipo_keys(scene, NULL, 1); // set current frame after taking average
351  */
352 // XXX this thing needs to be refactored!
353 void snap_cfra_ipo_keys(BeztEditData *bed, Ipo *ipo, short mode)
354 {
355         static int cfra;
356         static int tot;
357         
358         Scene *scene= bed->scene;
359         IpoCurve *icu;
360         BezTriple *bezt;
361         int a;
362         
363         
364         if (mode == -1) {
365                 /* initialise a new snap-operation */
366                 cfra= 0;
367                 tot= 0;
368         }
369         else if (mode == 1) {
370                 /* set current frame - using average frame */
371                 if (tot != 0)
372                         CFRA = cfra / tot;
373         }
374         else {
375                 /* loop through keys in ipo, summing the frame
376                  * numbers of those that are selected 
377                  */
378                 if (ipo == NULL) 
379                         return;
380                 
381                 for (icu= ipo->curve.first; icu; icu= icu->next) {
382                         for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
383                                 if (BEZSELECTED(bezt)) {
384                                         cfra += bezt->vec[1][0];
385                                         tot++;
386                                 }
387                         }
388                 }
389         }       
390 }
391
392 /* ******************************************* */
393 /* Settings */
394
395 /* Sets the selected bezier handles to type 'auto' */
396 static short set_bezier_auto(BeztEditData *bed, BezTriple *bezt) 
397 {
398         if((bezt->f1  & SELECT) || (bezt->f3 & SELECT)) {
399                 if (bezt->f1 & SELECT) bezt->h1= 1; /* the secret code for auto */
400                 if (bezt->f3 & SELECT) bezt->h2= 1;
401                 
402                 /* if the handles are not of the same type, set them
403                  * to type free
404                  */
405                 if (bezt->h1 != bezt->h2) {
406                         if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
407                         if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
408                 }
409         }
410         return 0;
411 }
412
413 /* Sets the selected bezier handles to type 'vector'  */
414 static short set_bezier_vector(BeztEditData *bed, BezTriple *bezt) 
415 {
416         if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
417                 if (bezt->f1 & SELECT) bezt->h1= HD_VECT;
418                 if (bezt->f3 & SELECT) bezt->h2= HD_VECT;
419                 
420                 /* if the handles are not of the same type, set them
421                  * to type free
422                  */
423                 if (bezt->h1 != bezt->h2) {
424                         if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
425                         if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
426                 }
427         }
428         return 0;
429 }
430
431 /* Queries if the handle should be set to 'free' or 'align' */
432 static short bezier_isfree(BeztEditData *bed, BezTriple *bezt) 
433 {
434         if ((bezt->f1 & SELECT) && (bezt->h1)) return 1;
435         if ((bezt->f3 & SELECT) && (bezt->h2)) return 1;
436         return 0;
437 }
438
439 /* Sets selected bezier handles to type 'align' */
440 static short set_bezier_align(BeztEditData *bed, BezTriple *bezt) 
441 {       
442         if (bezt->f1 & SELECT) bezt->h1= HD_ALIGN;
443         if (bezt->f3 & SELECT) bezt->h2= HD_ALIGN;
444         return 0;
445 }
446
447 /* Sets selected bezier handles to type 'free'  */
448 static short set_bezier_free(BeztEditData *bed, BezTriple *bezt) 
449 {
450         if (bezt->f1 & SELECT) bezt->h1= HD_FREE;
451         if (bezt->f3 & SELECT) bezt->h2= HD_FREE;
452         return 0;
453 }
454
455 /* Set all Bezier Handles to a single type */
456 // calchandles_ipocurve
457 BeztEditFunc ANIM_editkeyframes_handles(short code)
458 {
459         switch (code) {
460                 case HD_AUTO: /* auto */
461                         return set_bezier_auto;
462                 case HD_VECT: /* vector */
463                         return set_bezier_vector;
464                 case HD_FREE: /* free */
465                         return set_bezier_free;
466                 case HD_ALIGN: /* align */
467                         return set_bezier_align;
468                 
469                 default: /* free or align? */
470                         return bezier_isfree;
471         }
472 }
473
474 /* ------- */
475
476 /* IPO-curve sanity callback - the name of this is a bit unwieldy, by is best to keep this in style... */
477 // was called set_ipocurve_mixed()
478 void ANIM_editkeyframes_ipocurve_ipotype(IpoCurve *icu)
479 {
480         /* Sets the type of the IPO curve to mixed, as some (selected)
481          * keyframes were set to other interpolation types
482          */
483         icu->ipo= IPO_MIXED;
484         
485         /* recalculate handles, as some changes may have occurred */
486         calchandles_ipocurve(icu);
487 }
488
489 static short set_bezt_constant(BeztEditData *bed, BezTriple *bezt) 
490 {
491         if (bezt->f2 & SELECT) 
492                 bezt->ipo= IPO_CONST;
493         return 0;
494 }
495
496 static short set_bezt_linear(BeztEditData *bed, BezTriple *bezt) 
497 {
498         if (bezt->f2 & SELECT) 
499                 bezt->ipo= IPO_LIN;
500         return 0;
501 }
502
503 static short set_bezt_bezier(BeztEditData *bed, BezTriple *bezt) 
504 {
505         if (bezt->f2 & SELECT) 
506                 bezt->ipo= IPO_BEZ;
507         return 0;
508 }
509
510 /* Set the interpolation type of the selected BezTriples in each IPO curve to the specified one */
511 // ANIM_editkeyframes_ipocurve_ipotype() !
512 BeztEditFunc ANIM_editkeyframes_ipo(short code)
513 {
514         switch (code) {
515                 case IPO_CONST: /* constant */
516                         return set_bezt_constant;
517                 case IPO_LIN: /* linear */      
518                         return set_bezt_linear;
519                 default: /* bezier */
520                         return set_bezt_bezier;
521         }
522 }
523
524 // XXX will we keep this?
525 void setexprap_ipoloop(Ipo *ipo, short code)
526 {
527         IpoCurve *icu;
528         
529         /* Loop through each curve in the Ipo */
530         for (icu=ipo->curve.first; icu; icu=icu->next)
531                 icu->extrap= code;
532 }
533
534 /* ******************************************* */
535 /* Selection */
536
537 static short select_bezier_add(BeztEditData *bed, BezTriple *bezt) 
538 {
539         /* Select the bezier triple */
540         BEZ_SEL(bezt);
541         return 0;
542 }
543
544 static short select_bezier_subtract(BeztEditData *bed, BezTriple *bezt) 
545 {
546         /* Deselect the bezier triple */
547         BEZ_DESEL(bezt);
548         return 0;
549 }
550
551 static short select_bezier_invert(BeztEditData *bed, BezTriple *bezt) 
552 {
553         /* Invert the selection for the bezier triple */
554         bezt->f2 ^= SELECT;
555         if (bezt->f2 & SELECT) {
556                 bezt->f1 |= SELECT;
557                 bezt->f3 |= SELECT;
558         }
559         else {
560                 bezt->f1 &= ~SELECT;
561                 bezt->f3 &= ~SELECT;
562         }
563         return 0;
564 }
565
566 // NULL
567 BeztEditFunc ANIM_editkeyframes_select(short selectmode)
568 {
569         switch (selectmode) {
570                 case SELECT_ADD: /* add */
571                         return select_bezier_add;
572                 case SELECT_SUBTRACT: /* subtract */
573                         return select_bezier_subtract;
574                 case SELECT_INVERT: /* invert */
575                         return select_bezier_invert;
576                 default: /* replace (need to clear all, then add) */
577                         return select_bezier_add;
578         }
579 }
580
581
582 short is_ipo_key_selected(Ipo *ipo)
583 {
584         IpoCurve *icu;
585         BezTriple *bezt;
586         int i;
587         
588         if (ipo == NULL)
589                 return 0;
590         
591         for (icu=ipo->curve.first; icu; icu=icu->next) {
592                 for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
593                         if (BEZSELECTED(bezt))
594                                 return 1;
595                 }
596         }
597         
598         return 0;
599 }
600
601 // XXX although this is still needed, it should be removed!
602 void set_ipo_key_selection(Ipo *ipo, short sel)
603 {
604         IpoCurve *icu;
605         BezTriple *bezt;
606         int i;
607         
608         if (ipo == NULL)
609                 return;
610         
611         for (icu=ipo->curve.first; icu; icu=icu->next) {
612                 for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
613                         if (sel == 2) {
614                                 BEZ_INVSEL(bezt);
615                         }
616                         else if (sel == 1) {
617                                 BEZ_SEL(bezt);
618                         }
619                         else {
620                                 BEZ_DESEL(bezt);
621                         }
622                 }
623         }
624 }
625
626 // XXX port this over to the new system!
627 // err... this is this still used?
628 int fullselect_ipo_keys(Ipo *ipo)
629 {
630         IpoCurve *icu;
631         int tvtot = 0;
632         int i;
633         
634         if (!ipo)
635                 return tvtot;
636         
637         for (icu=ipo->curve.first; icu; icu=icu->next) {
638                 for (i=0; i<icu->totvert; i++) {
639                         if (icu->bezt[i].f2 & SELECT) {
640                                 tvtot+=3;
641                                 icu->bezt[i].f1 |= SELECT;
642                                 icu->bezt[i].f3 |= SELECT;
643                         }
644                 }
645         }
646         
647         return tvtot;
648 }
649