c3a393994d71d559e70501f35a0031d1f2ed3629
[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) 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_anim_types.h"
38 #include "DNA_action_types.h"
39 #include "DNA_constraint_types.h"
40 #include "DNA_curve_types.h"
41 #include "DNA_key_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_space_types.h"
44 #include "DNA_scene_types.h"
45
46 #include "BKE_action.h"
47 #include "BKE_fcurve.h"
48 #include "BKE_key.h"
49 #include "BKE_utildefines.h"
50
51 #include "ED_anim_api.h"
52 #include "ED_keyframes_edit.h"
53 #include "ED_markers.h"
54
55 /* This file defines an API and set of callback-operators for non-destructive editing of keyframe data.
56  *
57  * Two API functions are defined for actually performing the operations on the data:
58  *                      ANIM_fcurve_keys_bezier_loop()
59  * which take the data they operate on, a few callbacks defining what operations to perform.
60  *
61  * As operators which work on keyframes usually apply the same operation on all BezTriples in 
62  * every channel, the code has been optimised providing a set of functions which will get the 
63  * appropriate bezier-modify function to set. These functions (ANIM_editkeyframes_*) will need
64  * to be called before getting any channels.
65  * 
66  * A set of 'validation' callbacks are provided for checking if a BezTriple should be operated on.
67  * These should only be used when using a 'general' BezTriple editor (i.e. selection setters which 
68  * don't check existing selection status).
69  * 
70  * - Joshua Leung, Dec 2008
71  */
72
73 /* ************************************************************************** */
74 /* IPO Editing Loops - Exposed API */
75
76 /* --------------------------- Base Functions ------------------------------------ */
77
78 /* This function is used to loop over BezTriples in the given F-Curve, applying a given 
79  * operation on them, and optionally applies an F-Curve validation function afterwards.
80  */
81 short ANIM_fcurve_keys_bezier_loop(BeztEditData *bed, FCurve *fcu, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb) 
82 {
83     BezTriple *bezt;
84         int b;
85         
86         /* sanity check */
87         if (fcu == NULL)
88                 return 0;
89         
90         /* if function to apply to bezier curves is set, then loop through executing it on beztriples */
91     if (bezt_cb) {
92                 /* if there's a validation func, include that check in the loop 
93                  * (this is should be more efficient than checking for it in every loop)
94                  */
95                 if (bezt_ok) {
96                         for (b=0, bezt=fcu->bezt; b < fcu->totvert; b++, bezt++) {
97                                 /* Only operate on this BezTriple if it fullfills the criteria of the validation func */
98                                 if (bezt_ok(bed, bezt)) {
99                                         /* Exit with return-code '1' if function returns positive
100                                          * This is useful if finding if some BezTriple satisfies a condition.
101                                          */
102                                 if (bezt_cb(bed, bezt)) return 1;
103                                 }
104                         }
105                 }
106                 else {
107                         for (b=0, bezt=fcu->bezt; b < fcu->totvert; b++, bezt++) {
108                                 /* Exit with return-code '1' if function returns positive
109                                  * This is useful if finding if some BezTriple satisfies a condition.
110                                  */
111                         if (bezt_cb(bed, bezt)) return 1;
112                         }
113                 }
114     }
115
116     /* if fcu_cb (F-Curve post-editing callback) has been specified then execute it */
117     if (fcu_cb)
118         fcu_cb(fcu);
119         
120         /* done */      
121     return 0;
122 }
123
124 /* -------------------------------- Further Abstracted ----------------------------- */
125
126 /* This function is used to loop over the keyframe data in an Action Group */
127 static short agrp_keys_bezier_loop(BeztEditData *bed, bActionGroup *agrp, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb)
128 {
129         FCurve *fcu;
130         
131         /* only iterate over the action-channels and their sub-channels that are in this group */
132         for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
133                 if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
134                         return 1;
135         }
136         
137         return 0;
138 }
139
140 /* This function is used to loop over the keyframe data in an Action */
141 static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb)
142 {
143         FCurve *fcu;
144         
145         /* just loop through all F-Curves */
146         for (fcu= act->curves.first; fcu; fcu= fcu->next) {
147                 ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb);
148         }
149         
150         return 0;
151 }
152
153 /* --- */
154
155
156 /* This function is used to apply operation to all keyframes, regardless of the type */
157 short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb)
158 {
159         /* sanity checks */
160         if (ale == NULL)
161                 return 0;
162         
163         /* method to use depends on the type of keyframe data */
164         switch (ale->datatype) {
165                 /* direct keyframe data (these loops are exposed) */
166                 case ALE_FCURVE: /* F-Curve */
167                         return ANIM_fcurve_keys_bezier_loop(bed, ale->key_data, bezt_ok, bezt_cb, fcu_cb);
168                 
169                 /* indirect 'summaries' (these are not exposed directly) 
170                  * NOTE: must keep this code in sync with the drawing code and also the filtering code!
171                  */
172                 case ALE_GROUP: /* action group */
173                         return agrp_keys_bezier_loop(bed, (bActionGroup *)ale->data, bezt_ok, bezt_cb, fcu_cb);
174                 case ALE_ACT: /* action */
175                         return act_keys_bezier_loop(bed, (bAction *)ale->data, bezt_ok, bezt_cb, fcu_cb);
176         }
177         
178         return 0;
179 }
180
181 /* ************************************************************************** */
182 /* Keyframe Integrity Tools */
183
184 /* Rearrange keyframes if some are out of order */
185 // used to be recalc_*_ipos() where * was object or action
186 void ANIM_editkeyframes_refresh(bAnimContext *ac)
187 {
188         ListBase anim_data = {NULL, NULL};
189         bAnimListElem *ale;
190         int filter;
191         
192         /* filter animation data */
193         filter= ANIMFILTER_CURVESONLY; 
194         ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
195         
196         /* loop over ipo-curves that are likely to have been edited, and check them */
197         for (ale= anim_data.first; ale; ale= ale->next) {
198                 FCurve *fcu= ale->key_data;
199                 
200                 /* make sure keyframes in F-curve are all in order, and handles are in valid positions */
201                 sort_time_fcurve(fcu);
202                 testhandles_fcurve(fcu);
203         }
204         
205         /* free temp data */
206         BLI_freelistN(&anim_data);
207 }
208
209 /* ************************************************************************** */
210 /* BezTriple Validation Callbacks */
211
212 static short ok_bezier_frame(BeztEditData *bed, BezTriple *bezt)
213 {
214         /* frame is stored in f1 property (this float accuracy check may need to be dropped?) */
215         return IS_EQ(bezt->vec[1][0], bed->f1);
216 }
217
218 static short ok_bezier_framerange(BeztEditData *bed, BezTriple *bezt)
219 {
220         /* frame range is stored in float properties */
221         return ((bezt->vec[1][0] > bed->f1) && (bezt->vec[1][0] < bed->f2));
222 }
223
224 static short ok_bezier_selected(BeztEditData *bed, BezTriple *bezt)
225 {
226         /* this macro checks all beztriple handles for selection... */
227         return BEZSELECTED(bezt);
228 }
229
230 static short ok_bezier_value(BeztEditData *bed, BezTriple *bezt)
231 {
232         /* value is stored in f1 property 
233          *      - this float accuracy check may need to be dropped?
234          *      - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too?
235          */
236         return IS_EQ(bezt->vec[1][1], bed->f1);
237 }
238
239 static short ok_bezier_valuerange(BeztEditData *bed, BezTriple *bezt)
240 {
241         /* value range is stored in float properties */
242         return ((bezt->vec[1][1] > bed->f1) && (bezt->vec[1][1] < bed->f2));
243 }
244
245 static short ok_bezier_region(BeztEditData *bed, BezTriple *bezt)
246 {
247         /* rect is stored in data property (it's of type rectf, but may not be set) */
248         if (bed->data)
249                 return BLI_in_rctf(bed->data, bezt->vec[1][0], bezt->vec[1][1]);
250         else 
251                 return 0;
252 }
253
254
255 BeztEditFunc ANIM_editkeyframes_ok(short mode)
256 {
257         /* eEditKeyframes_Validate */
258         switch (mode) {
259                 case BEZT_OK_FRAME: /* only if bezt falls on the right frame (float) */
260                         return ok_bezier_frame;
261                 case BEZT_OK_FRAMERANGE: /* only if bezt falls within the specified frame range (floats) */
262                         return ok_bezier_framerange;
263                 case BEZT_OK_SELECTED:  /* only if bezt is selected (self) */
264                         return ok_bezier_selected;
265                 case BEZT_OK_VALUE: /* only if bezt value matches (float) */
266                         return ok_bezier_value;
267                 case BEZT_OK_VALUERANGE: /* only if bezier falls within the specified value range (floats) */
268                         return ok_bezier_valuerange;
269                 case BEZT_OK_REGION: /* only if bezier falls within the specified rect (data -> rectf) */
270                         return ok_bezier_region;
271                 default: /* nothing was ok */
272                         return NULL;
273         }
274 }
275
276 /* ******************************************* */
277 /* Transform */
278
279 static short snap_bezier_nearest(BeztEditData *bed, BezTriple *bezt)
280 {
281         if (bezt->f2 & SELECT)
282                 bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
283         return 0;
284 }
285
286 static short snap_bezier_nearestsec(BeztEditData *bed, BezTriple *bezt)
287 {
288         const Scene *scene= bed->scene;
289         const float secf = (float)FPS;
290         
291         if (bezt->f2 & SELECT)
292                 bezt->vec[1][0]= ((float)floor(bezt->vec[1][0]/secf + 0.5f) * secf);
293         return 0;
294 }
295
296 static short snap_bezier_cframe(BeztEditData *bed, BezTriple *bezt)
297 {
298         const Scene *scene= bed->scene;
299         if (bezt->f2 & SELECT)
300                 bezt->vec[1][0]= (float)CFRA;
301         return 0;
302 }
303
304 static short snap_bezier_nearmarker(BeztEditData *bed, BezTriple *bezt)
305 {
306         //if (bezt->f2 & SELECT)
307         //      bezt->vec[1][0]= (float)find_nearest_marker_time(bezt->vec[1][0]);  // XXX missing function!
308         return 0;
309 }
310
311 static short snap_bezier_horizontal(BeztEditData *bed, BezTriple *bezt)
312 {
313         if (bezt->f2 & SELECT) {
314                 bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
315                 if ((bezt->h1==HD_AUTO) || (bezt->h1==HD_VECT)) bezt->h1= HD_ALIGN;
316                 if ((bezt->h2==HD_AUTO) || (bezt->h2==HD_VECT)) bezt->h2= HD_ALIGN;
317         }
318         return 0;       
319 }
320
321 // calchandles_ipocurve
322 BeztEditFunc ANIM_editkeyframes_snap(short type)
323 {
324         /* eEditKeyframes_Snap */
325         switch (type) {
326                 case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
327                         return snap_bezier_nearest;
328                 case SNAP_KEYS_CURFRAME: /* snap to current frame */
329                         return snap_bezier_cframe;
330                 case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
331                         return snap_bezier_nearmarker;
332                 case SNAP_KEYS_NEARSEC: /* snap to nearest second */
333                         return snap_bezier_nearestsec;
334                 case SNAP_KEYS_HORIZONTAL: /* snap handles to same value */
335                         return snap_bezier_horizontal;
336                 default: /* just in case */
337                         return snap_bezier_nearest;
338         }
339 }
340
341 /* --------- */
342
343 static short mirror_bezier_cframe(BeztEditData *bed, BezTriple *bezt)
344 {
345         const Scene *scene= bed->scene;
346         float diff;
347         
348         if (bezt->f2 & SELECT) {
349                 diff= ((float)CFRA - bezt->vec[1][0]);
350                 bezt->vec[1][0]= ((float)CFRA + diff);
351         }
352         
353         return 0;
354 }
355
356 static short mirror_bezier_yaxis(BeztEditData *bed, BezTriple *bezt)
357 {
358         float diff;
359         
360         if (bezt->f2 & SELECT) {
361                 diff= (0.0f - bezt->vec[1][0]);
362                 bezt->vec[1][0]= (0.0f + diff);
363         }
364         
365         return 0;
366 }
367
368 static short mirror_bezier_xaxis(BeztEditData *bed, BezTriple *bezt)
369 {
370         float diff;
371         
372         if (bezt->f2 & SELECT) {
373                 diff= (0.0f - bezt->vec[1][1]);
374                 bezt->vec[1][1]= (0.0f + diff);
375         }
376         
377         return 0;
378 }
379
380 static short mirror_bezier_marker(BeztEditData *bed, BezTriple *bezt)
381 {
382         /* mirroring time stored in f1 */
383         if (bezt->f2 & SELECT) {
384                 const float diff= (bed->f1 - bezt->vec[1][0]);
385                 bezt->vec[1][0]= (bed->f1 + diff);
386         }
387         
388         return 0;
389 }
390
391 /* Note: for markers case, need to set global vars (eww...) */
392 // calchandles_fcurve
393 BeztEditFunc ANIM_editkeyframes_mirror(short type)
394 {
395         switch (type) {
396                 case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
397                         return mirror_bezier_cframe;
398                 case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
399                         return mirror_bezier_yaxis;
400                 case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
401                         return mirror_bezier_xaxis;
402                 case MIRROR_KEYS_MARKER: /* mirror over marker */
403                         return mirror_bezier_marker; 
404                 default: /* just in case */
405                         return mirror_bezier_yaxis;
406                         break;
407         }
408 }
409
410 /* ******************************************* */
411 /* Settings */
412
413 /* Sets the selected bezier handles to type 'auto' */
414 static short set_bezier_auto(BeztEditData *bed, BezTriple *bezt) 
415 {
416         if((bezt->f1  & SELECT) || (bezt->f3 & SELECT)) {
417                 if (bezt->f1 & SELECT) bezt->h1= 1; /* the secret code for auto */
418                 if (bezt->f3 & SELECT) bezt->h2= 1;
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 /* Sets the selected bezier handles to type 'vector'  */
432 static short set_bezier_vector(BeztEditData *bed, BezTriple *bezt) 
433 {
434         if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
435                 if (bezt->f1 & SELECT) bezt->h1= HD_VECT;
436                 if (bezt->f3 & SELECT) bezt->h2= HD_VECT;
437                 
438                 /* if the handles are not of the same type, set them
439                  * to type free
440                  */
441                 if (bezt->h1 != bezt->h2) {
442                         if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
443                         if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
444                 }
445         }
446         return 0;
447 }
448
449 /* Queries if the handle should be set to 'free' or 'align' */
450 static short bezier_isfree(BeztEditData *bed, BezTriple *bezt) 
451 {
452         if ((bezt->f1 & SELECT) && (bezt->h1)) return 1;
453         if ((bezt->f3 & SELECT) && (bezt->h2)) return 1;
454         return 0;
455 }
456
457 /* Sets selected bezier handles to type 'align' */
458 static short set_bezier_align(BeztEditData *bed, BezTriple *bezt) 
459 {       
460         if (bezt->f1 & SELECT) bezt->h1= HD_ALIGN;
461         if (bezt->f3 & SELECT) bezt->h2= HD_ALIGN;
462         return 0;
463 }
464
465 /* Sets selected bezier handles to type 'free'  */
466 static short set_bezier_free(BeztEditData *bed, BezTriple *bezt) 
467 {
468         if (bezt->f1 & SELECT) bezt->h1= HD_FREE;
469         if (bezt->f3 & SELECT) bezt->h2= HD_FREE;
470         return 0;
471 }
472
473 /* Set all Bezier Handles to a single type */
474 // calchandles_fcurve
475 BeztEditFunc ANIM_editkeyframes_handles(short code)
476 {
477         switch (code) {
478                 case HD_AUTO: /* auto */
479                         return set_bezier_auto;
480                 case HD_VECT: /* vector */
481                         return set_bezier_vector;
482                 case HD_FREE: /* free */
483                         return set_bezier_free;
484                 case HD_ALIGN: /* align */
485                         return set_bezier_align;
486                 
487                 default: /* free or align? */
488                         return bezier_isfree;
489         }
490 }
491
492 /* ------- */
493
494 static short set_bezt_constant(BeztEditData *bed, BezTriple *bezt) 
495 {
496         if (bezt->f2 & SELECT) 
497                 bezt->ipo= BEZT_IPO_CONST;
498         return 0;
499 }
500
501 static short set_bezt_linear(BeztEditData *bed, BezTriple *bezt) 
502 {
503         if (bezt->f2 & SELECT) 
504                 bezt->ipo= BEZT_IPO_LIN;
505         return 0;
506 }
507
508 static short set_bezt_bezier(BeztEditData *bed, BezTriple *bezt) 
509 {
510         if (bezt->f2 & SELECT) 
511                 bezt->ipo= BEZT_IPO_BEZ;
512         return 0;
513 }
514
515 /* Set the interpolation type of the selected BezTriples in each IPO curve to the specified one */
516 // ANIM_editkeyframes_ipocurve_ipotype() !
517 BeztEditFunc ANIM_editkeyframes_ipo(short code)
518 {
519         switch (code) {
520                 case BEZT_IPO_CONST: /* constant */
521                         return set_bezt_constant;
522                 case BEZT_IPO_LIN: /* linear */ 
523                         return set_bezt_linear;
524                 default: /* bezier */
525                         return set_bezt_bezier;
526         }
527 }
528
529 /* ******************************************* */
530 /* Selection */
531
532 static short select_bezier_add(BeztEditData *bed, BezTriple *bezt) 
533 {
534         /* Select the bezier triple */
535         BEZ_SEL(bezt);
536         return 0;
537 }
538
539 static short select_bezier_subtract(BeztEditData *bed, BezTriple *bezt) 
540 {
541         /* Deselect the bezier triple */
542         BEZ_DESEL(bezt);
543         return 0;
544 }
545
546 static short select_bezier_invert(BeztEditData *bed, BezTriple *bezt) 
547 {
548         /* Invert the selection for the bezier triple */
549         bezt->f2 ^= SELECT;
550         if (bezt->f2 & SELECT) {
551                 bezt->f1 |= SELECT;
552                 bezt->f3 |= SELECT;
553         }
554         else {
555                 bezt->f1 &= ~SELECT;
556                 bezt->f3 &= ~SELECT;
557         }
558         return 0;
559 }
560
561 // NULL
562 BeztEditFunc ANIM_editkeyframes_select(short selectmode)
563 {
564         switch (selectmode) {
565                 case SELECT_ADD: /* add */
566                         return select_bezier_add;
567                 case SELECT_SUBTRACT: /* subtract */
568                         return select_bezier_subtract;
569                 case SELECT_INVERT: /* invert */
570                         return select_bezier_invert;
571                 default: /* replace (need to clear all, then add) */
572                         return select_bezier_add;
573         }
574 }