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