svn merge -r40197:40311 ^/trunk/blender
[blender.git] / source / blender / editors / animation / keyframes_edit.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation
19  *
20  * Contributor(s): Joshua Leung
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/editors/animation/keyframes_edit.c
26  *  \ingroup edanimation
27  */
28
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include <float.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_math.h"
39 #include "BLI_utildefines.h"
40
41 #include "DNA_anim_types.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_camera_types.h"
44 #include "DNA_key_types.h"
45 #include "DNA_lamp_types.h"
46 #include "DNA_lattice_types.h"
47 #include "DNA_mesh_types.h"
48 #include "DNA_material_types.h"
49 #include "DNA_object_types.h"
50 #include "DNA_meta_types.h"
51 #include "DNA_node_types.h"
52 #include "DNA_particle_types.h"
53 #include "DNA_scene_types.h"
54 #include "DNA_world_types.h"
55
56 #include "BKE_fcurve.h"
57 #include "BKE_key.h"
58 #include "BKE_material.h"
59
60
61 #include "ED_anim_api.h"
62 #include "ED_keyframes_edit.h"
63 #include "ED_markers.h"
64
65 /* This file defines an API and set of callback-operators for non-destructive editing of keyframe data.
66  *
67  * Two API functions are defined for actually performing the operations on the data:
68  *                      ANIM_fcurve_keyframes_loop()
69  * which take the data they operate on, a few callbacks defining what operations to perform.
70  *
71  * As operators which work on keyframes usually apply the same operation on all BezTriples in 
72  * every channel, the code has been optimised providing a set of functions which will get the 
73  * appropriate bezier-modify function to set. These functions (ANIM_editkeyframes_*) will need
74  * to be called before getting any channels.
75  * 
76  * A set of 'validation' callbacks are provided for checking if a BezTriple should be operated on.
77  * These should only be used when using a 'general' BezTriple editor (i.e. selection setters which 
78  * don't check existing selection status).
79  * 
80  * - Joshua Leung, Dec 2008
81  */
82
83 /* ************************************************************************** */
84 /* Keyframe Editing Loops - Exposed API */
85
86 /* --------------------------- Base Functions ------------------------------------ */
87
88 /* This function is used to loop over BezTriples in the given F-Curve, applying a given 
89  * operation on them, and optionally applies an F-Curve validation function afterwards.
90  */
91 // TODO: make this function work on samples too...
92 short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 
93 {
94         BezTriple *bezt;
95         short ok = 0;
96         unsigned int i;
97
98         /* sanity check */
99         if (ELEM(NULL, fcu, fcu->bezt))
100                 return 0;
101
102         /* set the F-Curve into the editdata so that it can be accessed */
103         if (ked) {
104                 ked->fcu= fcu;
105                 ked->curIndex= 0;
106                 ked->curflags= ok;
107         }
108
109         /* if function to apply to bezier curves is set, then loop through executing it on beztriples */
110         if (key_cb) {
111                 /* if there's a validation func, include that check in the loop 
112                  * (this is should be more efficient than checking for it in every loop)
113                  */
114                 if (key_ok) {
115                         for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) {
116                                 if (ked) {
117                                         /* advance the index, and reset the ok flags (to not influence the result) */
118                                         ked->curIndex= i;
119                                         ked->curflags= 0;
120                                 }
121                                 
122                                 /* Only operate on this BezTriple if it fullfills the criteria of the validation func */
123                                 if ( (ok = key_ok(ked, bezt)) ) {
124                                         if (ked) ked->curflags= ok;
125                                         
126                                         /* Exit with return-code '1' if function returns positive
127                                          * This is useful if finding if some BezTriple satisfies a condition.
128                                          */
129                                         if (key_cb(ked, bezt)) return 1;
130                                 }
131                         }
132                 }
133                 else {
134                         for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) {
135                                 if (ked) ked->curIndex= i;
136                                 
137                                 /* Exit with return-code '1' if function returns positive
138                                 * This is useful if finding if some BezTriple satisfies a condition.
139                                 */
140                                 if (key_cb(ked, bezt)) return 1;
141                         }
142                 }
143         }
144         
145         /* unset the F-Curve from the editdata now that it's done */
146         if (ked) {
147                 ked->fcu= NULL;
148                 ked->curIndex= 0;
149                 ked->curflags= 0;
150         }
151
152         /* if fcu_cb (F-Curve post-editing callback) has been specified then execute it */
153         if (fcu_cb)
154                 fcu_cb(fcu);
155         
156         /* done */      
157         return 0;
158 }
159
160 /* -------------------------------- Further Abstracted (Not Exposed Directly) ----------------------------- */
161
162 /* This function is used to loop over the keyframe data in an Action Group */
163 static short agrp_keyframes_loop(KeyframeEditData *ked, bActionGroup *agrp, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
164 {
165         FCurve *fcu;
166         
167         /* sanity check */
168         if (agrp == NULL)
169                 return 0;
170         
171         /* only iterate over the F-Curves that are in this group */
172         for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
173                 if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb))
174                         return 1;
175         }
176         
177         return 0;
178 }
179
180 /* This function is used to loop over the keyframe data in an Action */
181 static short act_keyframes_loop(KeyframeEditData *ked, bAction *act, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
182 {
183         FCurve *fcu;
184         
185         /* sanity check */
186         if (act == NULL)
187                 return 0;
188         
189         /* just loop through all F-Curves */
190         for (fcu= act->curves.first; fcu; fcu= fcu->next) {
191                 if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb))
192                         return 1;
193         }
194         
195         return 0;
196 }
197
198 /* This function is used to loop over the keyframe data in an Object */
199 static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *ob, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
200 {
201         bAnimContext ac = {NULL};
202         ListBase anim_data = {NULL, NULL};
203         bAnimListElem *ale;
204         int filter;
205         int ret=0;
206         
207         bAnimListElem dummychan = {NULL};
208         Base dummybase = {NULL};
209         
210         if (ob == NULL)
211                 return 0;
212         
213         /* create a dummy wrapper data to work with */
214         dummybase.object = ob;
215         
216         dummychan.type = ANIMTYPE_OBJECT;
217         dummychan.data = &dummybase;
218         dummychan.id = &ob->id;
219         dummychan.adt = ob->adt;
220         
221         ac.ads = ads;
222         ac.data = &dummychan;
223         ac.datatype = ANIMCONT_CHANNEL;
224         
225         /* get F-Curves to take keyframes from */
226         filter= ANIMFILTER_DATA_VISIBLE; // curves only
227         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
228         
229         /* loop through each F-Curve, applying the operation as required, but stopping on the first one */
230         for (ale= anim_data.first; ale; ale= ale->next) {
231                 if (ANIM_fcurve_keyframes_loop(ked, (FCurve*)ale->data, key_ok, key_cb, fcu_cb)) {
232                         ret = 1;
233                         break;
234                 }
235         }
236         
237         BLI_freelistN(&anim_data);
238         
239         /* return return code - defaults to zero if nothing happened */
240         return ret;
241 }
242
243 /* This function is used to loop over the keyframe data in a Scene */
244 static short scene_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Scene *sce, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
245 {
246         bAnimContext ac = {NULL};
247         ListBase anim_data = {NULL, NULL};
248         bAnimListElem *ale;
249         int filter;
250         int ret=0;
251         
252         bAnimListElem dummychan = {NULL};
253         
254         if (sce == NULL)
255                 return 0;
256         
257         /* create a dummy wrapper data to work with */
258         dummychan.type = ANIMTYPE_SCENE;
259         dummychan.data = sce;
260         dummychan.id = &sce->id;
261         dummychan.adt = sce->adt;
262         
263         ac.ads = ads;
264         ac.data = &dummychan;
265         ac.datatype = ANIMCONT_CHANNEL;
266         
267         /* get F-Curves to take keyframes from */
268         filter= ANIMFILTER_DATA_VISIBLE; // curves only
269         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
270         
271         /* loop through each F-Curve, applying the operation as required, but stopping on the first one */
272         for (ale= anim_data.first; ale; ale= ale->next) {
273                 if (ANIM_fcurve_keyframes_loop(ked, (FCurve*)ale->data, key_ok, key_cb, fcu_cb)) {
274                         ret = 1;
275                         break;
276                 }
277         }
278         
279         BLI_freelistN(&anim_data);
280         
281         /* return return code - defaults to zero if nothing happened */
282         return ret;
283 }
284
285 /* This function is used to loop over the keyframe data in a DopeSheet summary */
286 static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
287 {
288         ListBase anim_data = {NULL, NULL};
289         bAnimListElem *ale;
290         int filter, ret_code=0;
291         
292         /* sanity check */
293         if (ac == NULL)
294                 return 0;
295         
296         /* get F-Curves to take keyframes from */
297         filter= ANIMFILTER_DATA_VISIBLE;
298         ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
299         
300         /* loop through each F-Curve, working on the keyframes until the first curve aborts */
301         for (ale= anim_data.first; ale; ale= ale->next) {
302                 ret_code= ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
303                 
304                 if (ret_code)
305                         break;
306         }
307         
308         BLI_freelistN(&anim_data);
309         
310         return ret_code;
311 }
312
313 /* --- */
314
315 /* This function is used to apply operation to all keyframes, regardless of the type */
316 short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, bAnimListElem *ale, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
317 {
318         /* sanity checks */
319         if (ale == NULL)
320                 return 0;
321         
322         /* method to use depends on the type of keyframe data */
323         switch (ale->datatype) {
324                 /* direct keyframe data (these loops are exposed) */
325                 case ALE_FCURVE: /* F-Curve */
326                         return ANIM_fcurve_keyframes_loop(ked, ale->key_data, key_ok, key_cb, fcu_cb);
327                 
328                 /* indirect 'summaries' (these are not exposed directly) 
329                  * NOTE: must keep this code in sync with the drawing code and also the filtering code!
330                  */
331                 case ALE_GROUP: /* action group */
332                         return agrp_keyframes_loop(ked, (bActionGroup *)ale->data, key_ok, key_cb, fcu_cb);
333                 case ALE_ACT: /* action */
334                         return act_keyframes_loop(ked, (bAction *)ale->key_data, key_ok, key_cb, fcu_cb);
335                         
336                 case ALE_OB: /* object */
337                         return ob_keyframes_loop(ked, ads, (Object *)ale->key_data, key_ok, key_cb, fcu_cb);
338                 case ALE_SCE: /* scene */
339                         return scene_keyframes_loop(ked, ads, (Scene *)ale->data, key_ok, key_cb, fcu_cb);
340                 case ALE_ALL: /* 'all' (DopeSheet summary) */
341                         return summary_keyframes_loop(ked, (bAnimContext *)ale->data, key_ok, key_cb, fcu_cb);
342         }
343         
344         return 0;
345 }
346
347 /* This function is used to apply operation to all keyframes, regardless of the type without needed an AnimListElem wrapper */
348 short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, void *data, int keytype, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
349 {
350         /* sanity checks */
351         if (data == NULL)
352                 return 0;
353         
354         /* method to use depends on the type of keyframe data */
355         switch (keytype) {
356                 /* direct keyframe data (these loops are exposed) */
357                 case ALE_FCURVE: /* F-Curve */
358                         return ANIM_fcurve_keyframes_loop(ked, data, key_ok, key_cb, fcu_cb);
359                 
360                 /* indirect 'summaries' (these are not exposed directly) 
361                  * NOTE: must keep this code in sync with the drawing code and also the filtering code!
362                  */
363                 case ALE_GROUP: /* action group */
364                         return agrp_keyframes_loop(ked, (bActionGroup *)data, key_ok, key_cb, fcu_cb);
365                 case ALE_ACT: /* action */
366                         return act_keyframes_loop(ked, (bAction *)data, key_ok, key_cb, fcu_cb);
367                         
368                 case ALE_OB: /* object */
369                         return ob_keyframes_loop(ked, ads, (Object *)data, key_ok, key_cb, fcu_cb);
370                 case ALE_SCE: /* scene */
371                         return scene_keyframes_loop(ked, ads, (Scene *)data, key_ok, key_cb, fcu_cb);
372                 case ALE_ALL: /* 'all' (DopeSheet summary) */
373                         return summary_keyframes_loop(ked, (bAnimContext *)data, key_ok, key_cb, fcu_cb);
374         }
375         
376         return 0;
377 }
378
379 /* ************************************************************************** */
380 /* Keyframe Integrity Tools */
381
382 /* Rearrange keyframes if some are out of order */
383 // used to be recalc_*_ipos() where * was object or action
384 void ANIM_editkeyframes_refresh(bAnimContext *ac)
385 {
386         ListBase anim_data = {NULL, NULL};
387         bAnimListElem *ale;
388         int filter;
389         
390         /* filter animation data */
391         filter= ANIMFILTER_DATA_VISIBLE; 
392         ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
393         
394         /* loop over F-Curves that are likely to have been edited, and check them */
395         for (ale= anim_data.first; ale; ale= ale->next) {
396                 FCurve *fcu= ale->key_data;
397                 
398                 /* make sure keyframes in F-Curve are all in order, and handles are in valid positions */
399                 sort_time_fcurve(fcu);
400                 testhandles_fcurve(fcu);
401         }
402         
403         /* free temp data */
404         BLI_freelistN(&anim_data);
405 }
406
407 /* ************************************************************************** */
408 /* BezTriple Validation Callbacks */
409
410 /* ------------------------ */
411 /* Some macros to make this easier... */
412
413 /* run the given check on the 3 handles 
414  *      - check should be a macro, which takes the handle index as its single arg, which it substitutes later
415  *      - requires that a var, of type short, is named 'ok', and has been initialized to 0
416  */
417 #define KEYFRAME_OK_CHECKS(check) \
418         { \
419                 if (check(1)) \
420                         ok |= KEYFRAME_OK_KEY; \
421                  \
422                 if (ked && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { \
423                         if (check(0)) \
424                                 ok |= KEYFRAME_OK_H1; \
425                         if (check(2)) \
426                                 ok |= KEYFRAME_OK_H2; \
427                 } \
428         }       
429  
430 /* ------------------------ */
431  
432 static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt)
433 {
434         short ok = 0;
435         
436         /* frame is stored in f1 property (this float accuracy check may need to be dropped?) */
437         #define KEY_CHECK_OK(_index) IS_EQF(bezt->vec[_index][0], ked->f1)
438                 KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
439         #undef KEY_CHECK_OK
440         
441         /* return ok flags */
442         return ok;
443 }
444
445 static short ok_bezier_framerange(KeyframeEditData *ked, BezTriple *bezt)
446 {
447         short ok = 0;
448         
449         /* frame range is stored in float properties */
450         #define KEY_CHECK_OK(_index) ((bezt->vec[_index][0] > ked->f1) && (bezt->vec[_index][0] < ked->f2))
451                 KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
452         #undef KEY_CHECK_OK
453         
454         /* return ok flags */
455         return ok;
456 }
457
458 static short ok_bezier_selected(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
459 {
460         /* this macro checks all beztriple handles for selection... 
461          *      only one of the verts has to be selected for this to be ok...
462          */
463         if (BEZSELECTED(bezt))
464                 return KEYFRAME_OK_ALL;
465         else
466                 return 0;
467 }
468
469 static short ok_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
470 {       
471         short ok = 0;
472         
473         /* value is stored in f1 property 
474          *      - this float accuracy check may need to be dropped?
475          *      - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too?
476          */
477         #define KEY_CHECK_OK(_index) IS_EQF(bezt->vec[_index][1], ked->f1)
478                 KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
479         #undef KEY_CHECK_OK
480         
481         /* return ok flags */
482         return ok;
483 }
484
485 static short ok_bezier_valuerange(KeyframeEditData *ked, BezTriple *bezt)
486 {
487         short ok = 0;
488         
489         /* value range is stored in float properties */
490         #define KEY_CHECK_OK(_index) ((bezt->vec[_index][1] > ked->f1) && (bezt->vec[_index][1] < ked->f2))
491                 KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
492         #undef KEY_CHECK_OK
493         
494         /* return ok flags */
495         return ok;
496 }
497
498 static short ok_bezier_region(KeyframeEditData *ked, BezTriple *bezt)
499 {
500         /* rect is stored in data property (it's of type rectf, but may not be set) */
501         if (ked->data) {
502                 short ok = 0;
503                 
504                 #define KEY_CHECK_OK(_index) BLI_in_rctf(ked->data, bezt->vec[_index][0], bezt->vec[_index][1])
505                         KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
506                 #undef KEY_CHECK_OK
507                 
508                 /* return ok flags */
509                 return ok;
510         }
511         else 
512                 return 0;
513 }
514
515
516 KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
517 {
518         /* eEditKeyframes_Validate */
519         switch (mode) {
520                 case BEZT_OK_FRAME: /* only if bezt falls on the right frame (float) */
521                         return ok_bezier_frame;
522                 case BEZT_OK_FRAMERANGE: /* only if bezt falls within the specified frame range (floats) */
523                         return ok_bezier_framerange;
524                 case BEZT_OK_SELECTED:  /* only if bezt is selected (self) */
525                         return ok_bezier_selected;
526                 case BEZT_OK_VALUE: /* only if bezt value matches (float) */
527                         return ok_bezier_value;
528                 case BEZT_OK_VALUERANGE: /* only if bezier falls within the specified value range (floats) */
529                         return ok_bezier_valuerange;
530                 case BEZT_OK_REGION: /* only if bezier falls within the specified rect (data -> rectf) */
531                         return ok_bezier_region;
532                 default: /* nothing was ok */
533                         return NULL;
534         }
535 }
536
537 /* ******************************************* */
538 /* Assorted Utility Functions */
539
540 /* helper callback for <animeditor>_cfrasnap_exec() -> used to help get the average time of all selected beztriples */
541 short bezt_calc_average(KeyframeEditData *ked, BezTriple *bezt)
542 {
543         /* only if selected */
544         if (bezt->f2 & SELECT) {
545                 /* store average time in float 1 (only do rounding at last step) */
546                 ked->f1 += bezt->vec[1][0];
547                 
548                 /* store average value in float 2 (only do rounding at last step) 
549                  *      - this isn't always needed, but some operators may also require this
550                  */
551                 ked->f2 += bezt->vec[1][1];
552                 
553                 /* increment number of items */
554                 ked->i1++;
555         }
556         
557         return 0;
558 }
559
560 /* helper callback for columnselect_<animeditor>_keys() -> populate list CfraElems with frame numbers from selected beztriples */
561 short bezt_to_cfraelem(KeyframeEditData *ked, BezTriple *bezt)
562 {
563         /* only if selected */
564         if (bezt->f2 & SELECT) {
565                 CfraElem *ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
566                 BLI_addtail(&ked->list, ce);
567                 
568                 ce->cfra= bezt->vec[1][0];
569         }
570         
571         return 0;
572 }
573
574 /* used to remap times from one range to another
575  * requires:  ked->data = KeyframeEditCD_Remap  
576  */
577 void bezt_remap_times(KeyframeEditData *ked, BezTriple *bezt)
578 {
579         KeyframeEditCD_Remap *rmap= (KeyframeEditCD_Remap*)ked->data;
580         const float scale = (rmap->newMax - rmap->newMin) / (rmap->oldMax - rmap->oldMin);
581         
582         /* perform transform on all three handles unless indicated otherwise */
583         // TODO: need to include some checks for that
584         
585         bezt->vec[0][0]= scale*(bezt->vec[0][0] - rmap->oldMin) + rmap->newMin;
586         bezt->vec[1][0]= scale*(bezt->vec[1][0] - rmap->oldMin) + rmap->newMin;
587         bezt->vec[2][0]= scale*(bezt->vec[2][0] - rmap->oldMin) + rmap->newMin;
588 }
589
590 /* ******************************************* */
591 /* Transform */
592
593 /* snaps the keyframe to the nearest frame */
594 static short snap_bezier_nearest(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
595 {
596         if (bezt->f2 & SELECT)
597                 bezt->vec[1][0]= (float)(floorf(bezt->vec[1][0]+0.5f));
598         return 0;
599 }
600
601 /* snaps the keyframe to the neares second */
602 static short snap_bezier_nearestsec(KeyframeEditData *ked, BezTriple *bezt)
603 {
604         const Scene *scene= ked->scene;
605         const float secf = (float)FPS;
606         
607         if (bezt->f2 & SELECT)
608                 bezt->vec[1][0]= ((float)floor(bezt->vec[1][0]/secf + 0.5f) * secf);
609         return 0;
610 }
611
612 /* snaps the keyframe to the current frame */
613 static short snap_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt)
614 {
615         const Scene *scene= ked->scene;
616         if (bezt->f2 & SELECT)
617                 bezt->vec[1][0]= (float)CFRA;
618         return 0;
619 }
620
621 /* snaps the keyframe time to the nearest marker's frame */
622 static short snap_bezier_nearmarker(KeyframeEditData *ked, BezTriple *bezt)
623 {
624         if (bezt->f2 & SELECT)
625                 bezt->vec[1][0]= (float)ED_markers_find_nearest_marker_time(&ked->list, bezt->vec[1][0]);
626         return 0;
627 }
628
629 /* make the handles have the same value as the key */
630 static short snap_bezier_horizontal(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
631 {
632         if (bezt->f2 & SELECT) {
633                 bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
634                 
635                 if (ELEM3(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h1= HD_ALIGN;
636                 if (ELEM3(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h2= HD_ALIGN;
637         }
638         return 0;       
639 }
640
641 /* value to snap to is stored in the custom data -> first float value slot */
642 static short snap_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
643 {
644         if (bezt->f2 & SELECT)
645                 bezt->vec[1][1]= ked->f1;
646         return 0;
647 }
648
649 KeyframeEditFunc ANIM_editkeyframes_snap(short type)
650 {
651         /* eEditKeyframes_Snap */
652         switch (type) {
653                 case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
654                         return snap_bezier_nearest;
655                 case SNAP_KEYS_CURFRAME: /* snap to current frame */
656                         return snap_bezier_cframe;
657                 case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
658                         return snap_bezier_nearmarker;
659                 case SNAP_KEYS_NEARSEC: /* snap to nearest second */
660                         return snap_bezier_nearestsec;
661                 case SNAP_KEYS_HORIZONTAL: /* snap handles to same value */
662                         return snap_bezier_horizontal;
663                 case SNAP_KEYS_VALUE: /* snap to given value */
664                         return snap_bezier_value;
665                 default: /* just in case */
666                         return snap_bezier_nearest;
667         }
668 }
669
670 /* --------- */
671
672 static short mirror_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt)
673 {
674         const Scene *scene= ked->scene;
675         float diff;
676         
677         if (bezt->f2 & SELECT) {
678                 diff= ((float)CFRA - bezt->vec[1][0]);
679                 bezt->vec[1][0]= ((float)CFRA + diff);
680         }
681         
682         return 0;
683 }
684
685 static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
686 {
687         float diff;
688         
689         if (bezt->f2 & SELECT) {
690                 diff= (0.0f - bezt->vec[1][0]);
691                 bezt->vec[1][0]= (0.0f + diff);
692         }
693         
694         return 0;
695 }
696
697 static short mirror_bezier_xaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
698 {
699         float diff;
700         
701         if (bezt->f2 & SELECT) {
702                 diff= (0.0f - bezt->vec[1][1]);
703                 bezt->vec[1][1]= (0.0f + diff);
704         }
705         
706         return 0;
707 }
708
709 static short mirror_bezier_marker(KeyframeEditData *ked, BezTriple *bezt)
710 {
711         /* mirroring time stored in f1 */
712         if (bezt->f2 & SELECT) {
713                 const float diff= (ked->f1 - bezt->vec[1][0]);
714                 bezt->vec[1][0]= (ked->f1 + diff);
715         }
716         
717         return 0;
718 }
719
720 static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
721 {
722         float diff;
723         
724         /* value to mirror over is stored in the custom data -> first float value slot */
725         if (bezt->f2 & SELECT) {
726                 diff= (ked->f1 - bezt->vec[1][1]);
727                 bezt->vec[1][1]= (ked->f1 + diff);
728         }
729         
730         return 0;
731 }
732
733 /* Note: for markers and 'value', the values to use must be supplied as the first float value */
734 // calchandles_fcurve
735 KeyframeEditFunc ANIM_editkeyframes_mirror(short type)
736 {
737         switch (type) {
738                 case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
739                         return mirror_bezier_cframe;
740                 case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
741                         return mirror_bezier_yaxis;
742                 case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
743                         return mirror_bezier_xaxis;
744                 case MIRROR_KEYS_MARKER: /* mirror over marker */
745                         return mirror_bezier_marker; 
746                 case MIRROR_KEYS_VALUE: /* mirror over given value */
747                         return mirror_bezier_value;
748                 default: /* just in case */
749                         return mirror_bezier_yaxis;
750                         break;
751         }
752 }
753
754 /* ******************************************* */
755 /* Settings */
756
757 /* standard validation step for a few of these (implemented as macro for inlining without fn-call overhead):
758  *      "if the handles are not of the same type, set them to type free"
759  */
760 #define ENSURE_HANDLES_MATCH(bezt) \
761                 if (bezt->h1 != bezt->h2) { \
762                         if ELEM3(bezt->h1, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM) bezt->h1= HD_FREE; \
763                         if ELEM3(bezt->h2, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM) bezt->h2= HD_FREE; \
764                 }
765
766 /* Sets the selected bezier handles to type 'auto' */
767 static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
768 {
769         if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
770                 if (bezt->f1 & SELECT) bezt->h1= HD_AUTO;
771                 if (bezt->f3 & SELECT) bezt->h2= HD_AUTO;
772                 
773                 ENSURE_HANDLES_MATCH(bezt);
774         }
775         return 0;
776 }
777
778 /* Sets the selected bezier handles to type 'auto-clamped'
779  * NOTE: this is like auto above, but they're handled a bit different
780  */
781 static short set_bezier_auto_clamped(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
782 {
783         if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
784                 if (bezt->f1 & SELECT) bezt->h1= HD_AUTO_ANIM;
785                 if (bezt->f3 & SELECT) bezt->h2= HD_AUTO_ANIM;
786                 
787                 ENSURE_HANDLES_MATCH(bezt);
788         }
789         return 0;
790 }
791
792 /* Sets the selected bezier handles to type 'vector'  */
793 static short set_bezier_vector(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
794 {
795         if (bezt->f1 & SELECT) bezt->h1= HD_VECT;
796         if (bezt->f3 & SELECT) bezt->h2= HD_VECT;
797         return 0;
798 }
799
800 /* Queries if the handle should be set to 'free' or 'align' */
801 // NOTE: this was used for the 'toggle free/align' option
802 //              currently this isn't used, but may be restored later
803 static short bezier_isfree(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
804 {
805         if ((bezt->f1 & SELECT) && (bezt->h1)) return 1;
806         if ((bezt->f3 & SELECT) && (bezt->h2)) return 1;
807         return 0;
808 }
809
810 /* Sets selected bezier handles to type 'align' */
811 static short set_bezier_align(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
812 {       
813         if (bezt->f1 & SELECT) bezt->h1= HD_ALIGN;
814         if (bezt->f3 & SELECT) bezt->h2= HD_ALIGN;
815         return 0;
816 }
817
818 /* Sets selected bezier handles to type 'free'  */
819 static short set_bezier_free(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
820 {
821         if (bezt->f1 & SELECT) bezt->h1= HD_FREE;
822         if (bezt->f3 & SELECT) bezt->h2= HD_FREE;
823         return 0;
824 }
825
826 /* Set all selected Bezier Handles to a single type */
827 // calchandles_fcurve
828 KeyframeEditFunc ANIM_editkeyframes_handles(short code)
829 {
830         switch (code) {
831                 case HD_AUTO: /* auto */
832                         return set_bezier_auto;
833                 case HD_AUTO_ANIM: /* auto clamped */
834                         return set_bezier_auto_clamped;
835                         
836                 case HD_VECT: /* vector */
837                         return set_bezier_vector;
838                 case HD_FREE: /* free */
839                         return set_bezier_free;
840                 case HD_ALIGN: /* align */
841                         return set_bezier_align;
842                 
843                 default: /* check for toggle free or align? */
844                         return bezier_isfree;
845         }
846 }
847
848 /* ------- */
849
850 static short set_bezt_constant(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
851 {
852         if (bezt->f2 & SELECT) 
853                 bezt->ipo= BEZT_IPO_CONST;
854         return 0;
855 }
856
857 static short set_bezt_linear(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
858 {
859         if (bezt->f2 & SELECT) 
860                 bezt->ipo= BEZT_IPO_LIN;
861         return 0;
862 }
863
864 static short set_bezt_bezier(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
865 {
866         if (bezt->f2 & SELECT) 
867                 bezt->ipo= BEZT_IPO_BEZ;
868         return 0;
869 }
870
871 /* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */
872 // ANIM_editkeyframes_ipocurve_ipotype() !
873 KeyframeEditFunc ANIM_editkeyframes_ipo(short code)
874 {
875         switch (code) {
876                 case BEZT_IPO_CONST: /* constant */
877                         return set_bezt_constant;
878                 case BEZT_IPO_LIN: /* linear */ 
879                         return set_bezt_linear;
880                 default: /* bezier */
881                         return set_bezt_bezier;
882         }
883 }
884
885 /* ------- */
886
887 static short set_keytype_keyframe(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
888 {
889         if (bezt->f2 & SELECT) 
890                 BEZKEYTYPE(bezt)= BEZT_KEYTYPE_KEYFRAME;
891         return 0;
892 }
893
894 static short set_keytype_breakdown(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
895 {
896         if (bezt->f2 & SELECT) 
897                 BEZKEYTYPE(bezt)= BEZT_KEYTYPE_BREAKDOWN;
898         return 0;
899 }
900
901 static short set_keytype_extreme(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
902 {
903         if (bezt->f2 & SELECT) 
904                 BEZKEYTYPE(bezt)= BEZT_KEYTYPE_EXTREME;
905         return 0;
906 }
907
908 static short set_keytype_jitter(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
909 {
910         if (bezt->f2 & SELECT) 
911                 BEZKEYTYPE(bezt)= BEZT_KEYTYPE_JITTER;
912         return 0;
913 }
914
915 /* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */
916 KeyframeEditFunc ANIM_editkeyframes_keytype(short code)
917 {
918         switch (code) {
919                 case BEZT_KEYTYPE_BREAKDOWN: /* breakdown */
920                         return set_keytype_breakdown;
921                         
922                 case BEZT_KEYTYPE_EXTREME: /* extreme keyframe */
923                         return set_keytype_extreme;
924                         
925                 case BEZT_KEYTYPE_JITTER: /* jitter keyframe */
926                         return set_keytype_jitter;
927                         
928                 case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */       
929                 default:
930                         return set_keytype_keyframe;
931         }
932 }
933
934 /* ******************************************* */
935 /* Selection */
936
937 static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt) 
938 {
939         /* if we've got info on what to select, use it, otherwise select all */
940         if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) {
941                 if (ked->curflags & KEYFRAME_OK_KEY)
942                         bezt->f2 |= SELECT;
943                 if (ked->curflags & KEYFRAME_OK_H1)
944                         bezt->f1 |= SELECT;
945                 if (ked->curflags & KEYFRAME_OK_H2)
946                         bezt->f3 |= SELECT;
947         }
948         else {
949                 BEZ_SEL(bezt);
950         }
951         
952         return 0;
953 }
954
955 static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt) 
956 {
957         /* if we've got info on what to deselect, use it, otherwise deselect all */
958         if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) {
959                 if (ked->curflags & KEYFRAME_OK_KEY)
960                         bezt->f2 &= ~SELECT;
961                 if (ked->curflags & KEYFRAME_OK_H1)
962                         bezt->f1 &= ~SELECT;
963                 if (ked->curflags & KEYFRAME_OK_H2)
964                         bezt->f3 &= ~SELECT;
965         }
966         else {
967                 BEZ_DESEL(bezt);
968         }
969         
970         return 0;
971 }
972
973 static short select_bezier_invert(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
974 {
975         /* Invert the selection for the whole bezier triple */
976         bezt->f2 ^= SELECT;
977         if (bezt->f2 & SELECT) {
978                 bezt->f1 |= SELECT;
979                 bezt->f3 |= SELECT;
980         }
981         else {
982                 bezt->f1 &= ~SELECT;
983                 bezt->f3 &= ~SELECT;
984         }
985         return 0;
986 }
987
988 KeyframeEditFunc ANIM_editkeyframes_select(short selectmode)
989 {
990         switch (selectmode) {
991                 case SELECT_ADD: /* add */
992                         return select_bezier_add;
993                 case SELECT_SUBTRACT: /* subtract */
994                         return select_bezier_subtract;
995                 case SELECT_INVERT: /* invert */
996                         return select_bezier_invert;
997                 default: /* replace (need to clear all, then add) */
998                         return select_bezier_add;
999         }
1000 }
1001
1002 /* ******************************************* */
1003 /* Selection Maps */
1004
1005 /* Selection maps are simply fancy names for char arrays that store on/off
1006  * info for whether the selection status. The main purpose for these is to
1007  * allow extra info to be tagged to the keyframes without influencing their
1008  * values or having to be removed later.
1009  */
1010
1011 /* ----------- */
1012
1013 static short selmap_build_bezier_more(KeyframeEditData *ked, BezTriple *bezt)
1014 {
1015         FCurve *fcu= ked->fcu;
1016         char *map= ked->data;
1017         int i= ked->curIndex;
1018         
1019         /* if current is selected, just make sure it stays this way */
1020         if (BEZSELECTED(bezt)) {
1021                 map[i]= 1;
1022                 return 0;
1023         }
1024         
1025         /* if previous is selected, that means that selection should extend across */
1026         if (i > 0) {
1027                 BezTriple *prev= bezt - 1;
1028                 
1029                 if (BEZSELECTED(prev)) {
1030                         map[i]= 1;
1031                         return 0;
1032                 }
1033         }
1034         
1035         /* if next is selected, that means that selection should extend across */
1036         if (i < (fcu->totvert-1)) {
1037                 BezTriple *next= bezt + 1;
1038                 
1039                 if (BEZSELECTED(next)) {
1040                         map[i]= 1;
1041                         return 0;
1042                 }
1043         }
1044         
1045         return 0;
1046 }
1047
1048 static short selmap_build_bezier_less(KeyframeEditData *ked, BezTriple *bezt)
1049 {
1050         FCurve *fcu= ked->fcu;
1051         char *map= ked->data;
1052         int i= ked->curIndex;
1053         
1054         /* if current is selected, check the left/right keyframes
1055          * since it might need to be deselected (but otherwise no)
1056          */
1057         if (BEZSELECTED(bezt)) {
1058                 /* if previous is not selected, we're on the tip of an iceberg */
1059                 if (i > 0) {
1060                         BezTriple *prev= bezt - 1;
1061                         
1062                         if (BEZSELECTED(prev) == 0)
1063                                 return 0;
1064                 }
1065                 else if (i == 0) {
1066                         /* current keyframe is selected at an endpoint, so should get deselected */
1067                         return 0;
1068                 }
1069                 
1070                 /* if next is not selected, we're on the tip of an iceberg */
1071                 if (i < (fcu->totvert-1)) {
1072                         BezTriple *next= bezt + 1;
1073                         
1074                         if (BEZSELECTED(next) == 0)
1075                                 return 0;
1076                 }
1077                 else if (i == (fcu->totvert-1)) {
1078                         /* current keyframe is selected at an endpoint, so should get deselected */
1079                         return 0;
1080                 }
1081                 
1082                 /* if we're still here, that means that keyframe should remain untouched */
1083                 map[i]= 1;
1084         }
1085         
1086         return 0;
1087 }
1088
1089 /* Get callback for building selection map */
1090 KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode)
1091 {
1092         switch (mode) {
1093                 case SELMAP_LESS: /* less */
1094                         return selmap_build_bezier_less;
1095                 
1096                 case SELMAP_MORE: /* more */
1097                 default:
1098                         return selmap_build_bezier_more;
1099         }
1100 }
1101
1102 /* ----------- */
1103
1104 /* flush selection map values to the given beztriple */
1105 short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt)
1106 {
1107         char *map= ked->data;
1108         short on= map[ked->curIndex];
1109         
1110         /* select or deselect based on whether the map allows it or not */
1111         if (on) {
1112                 BEZ_SEL(bezt);
1113         }
1114         else {
1115                 BEZ_DESEL(bezt);
1116         }
1117         
1118         return 0;
1119 }
1120