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