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