4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2008 Blender Foundation
22 * Contributor(s): Joshua Leung
24 * ***** END GPL LICENSE BLOCK *****
32 #include "MEM_guardedalloc.h"
34 #include "BLI_blenlib.h"
35 #include "BLI_arithb.h"
37 #include "DNA_action_types.h"
38 #include "DNA_curve_types.h"
39 #include "DNA_ipo_types.h"
40 #include "DNA_key_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_space_types.h"
43 #include "DNA_scene_types.h"
45 #include "BKE_action.h"
48 #include "BKE_utildefines.h"
50 #include "ED_anim_api.h"
51 #include "ED_keyframes_edit.h"
52 #include "ED_markers.h"
54 /* This file defines an API and set of callback-operators for non-destructive editing of keyframe data.
56 * Two API functions are defined for actually performing the operations on the data:
57 * ipo_keys_bezier_loop() and icu_keys_bezier_loop()
58 * which take the data they operate on, a few callbacks defining what operations to perform.
60 * As operators which work on keyframes usually apply the same operation on all BezTriples in
61 * every channel, the code has been optimised providing a set of functions which will get the
62 * appropriate bezier-modify function to set. These functions (ANIM_editkeyframes_*) will need
63 * to be called before getting any channels.
65 * A set of 'validation' callbacks are provided for checking if a BezTriple should be operated on.
66 * These should only be used when using a 'general' BezTriple editor (i.e. selection setters which
67 * don't check existing selection status).
69 * - Joshua Leung, Dec 2008
72 /* ************************************************************************** */
73 /* IPO Editing Loops - Exposed API */
75 /* --------------------------- Base Functions ------------------------------------ */
77 /* This function is used to loop over BezTriples in the given IpoCurve, applying a given
78 * operation on them, and optionally applies an IPO-curve validate function afterwards.
80 short icu_keys_bezier_loop(BeztEditData *bed, IpoCurve *icu, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, IcuEditFunc icu_cb)
85 /* if function to apply to bezier curves is set, then loop through executing it on beztriples */
87 /* if there's a validation func, include that check in the loop
88 * (this is should be more efficient than checking for it in every loop)
91 for (b=0, bezt=icu->bezt; b < icu->totvert; b++, bezt++) {
92 /* Only operate on this BezTriple if it fullfills the criteria of the validation func */
93 if (bezt_ok(bed, bezt)) {
94 /* Exit with return-code '1' if function returns positive
95 * This is useful if finding if some BezTriple satisfies a condition.
97 if (bezt_cb(bed, bezt)) return 1;
102 for (b=0, bezt=icu->bezt; b < icu->totvert; b++, bezt++) {
103 /* Exit with return-code '1' if function returns positive
104 * This is useful if finding if some BezTriple satisfies a condition.
106 if (bezt_cb(bed, bezt)) return 1;
111 /* if ipocurve_function has been specified then execute it */
119 /* This function is used to loop over the IPO curves (and subsequently the keyframes in them) */
120 short ipo_keys_bezier_loop(BeztEditData *bed, Ipo *ipo, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, IcuEditFunc icu_cb)
128 /* Loop through each curve in the Ipo */
129 for (icu= ipo->curve.first; icu; icu=icu->next) {
130 if (icu_keys_bezier_loop(bed, icu, bezt_ok, bezt_cb, icu_cb))
137 /* -------------------------------- Further Abstracted ----------------------------- */
139 /* This function is used to apply operation to all keyframes, regardless of the type */
140 short animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, IcuEditFunc icu_cb)
145 /* ************************************************************************** */
146 /* Keyframe Integrity Tools */
148 /* Rearrange keyframes if some are out of order */
149 // used to be recalc_*_ipos() where * was object or action
150 void ANIM_editkeyframes_refresh(bAnimContext *ac)
152 ListBase anim_data = {NULL, NULL};
156 /* filter animation data */
157 filter= ANIMFILTER_ONLYICU;
158 ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
160 /* loop over ipo-curves that are likely to have been edited, and check them */
161 for (ale= anim_data.first; ale; ale= ale->next) {
162 IpoCurve *icu= ale->key_data;
164 /* make sure keyframes in IPO-curve are all in order, and handles are in valid positions */
165 sort_time_ipocurve(icu);
166 testhandles_ipocurve(icu);
170 BLI_freelistN(&anim_data);
173 /* ************************************************************************** */
174 /* BezTriple Validation Callbacks */
176 static short ok_bezier_frame(BeztEditData *bed, BezTriple *bezt)
178 /* frame is stored in f1 property (this float accuracy check may need to be dropped?) */
179 return IS_EQ(bezt->vec[1][0], bed->f1);
182 static short ok_bezier_framerange(BeztEditData *bed, BezTriple *bezt)
184 /* frame range is stored in float properties */
185 return ((bezt->vec[1][0] > bed->f1) && (bezt->vec[1][0] < bed->f2));
188 static short ok_bezier_selected(BeztEditData *bed, BezTriple *bezt)
190 /* this macro checks all beztriple handles for selection... */
191 return BEZSELECTED(bezt);
194 static short ok_bezier_value(BeztEditData *bed, BezTriple *bezt)
196 /* value is stored in f1 property
197 * - this float accuracy check may need to be dropped?
198 * - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too?
200 return IS_EQ(bezt->vec[1][1], bed->f1);
204 BeztEditFunc ANIM_editkeyframes_ok(short mode)
206 /* eEditKeyframes_Validate */
208 case BEZT_OK_FRAME: /* only if bezt falls on the right frame (float) */
209 return ok_bezier_frame;
210 case BEZT_OK_FRAMERANGE: /* only if bezt falls within the specified frame range (floats) */
211 return ok_bezier_framerange;
212 case BEZT_OK_SELECTED: /* only if bezt is selected */
213 return ok_bezier_selected;
214 case BEZT_OK_VALUE: /* only if bezt value matches (float) */
215 return ok_bezier_value;
216 default: /* nothing was ok */
221 /* ******************************************* */
224 static short snap_bezier_nearest(BeztEditData *bed, BezTriple *bezt)
226 if (bezt->f2 & SELECT)
227 bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
231 static short snap_bezier_nearestsec(BeztEditData *bed, BezTriple *bezt)
233 const Scene *scene= bed->scene;
234 const float secf = FPS;
236 if (bezt->f2 & SELECT)
237 bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]/secf + 0.5f) * secf);
241 static short snap_bezier_cframe(BeztEditData *bed, BezTriple *bezt)
243 const Scene *scene= bed->scene;
244 if (bezt->f2 & SELECT)
245 bezt->vec[1][0]= (float)CFRA;
249 static short snap_bezier_nearmarker(BeztEditData *bed, BezTriple *bezt)
251 //if (bezt->f2 & SELECT)
252 // bezt->vec[1][0]= (float)find_nearest_marker_time(bezt->vec[1][0]); // XXX missing function!
256 // calchandles_ipocurve
257 BeztEditFunc ANIM_editkeyframes_snap(short type)
259 /* eEditKeyframes_Snap */
261 case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
262 return snap_bezier_nearest;
263 case SNAP_KEYS_CURFRAME: /* snap to current frame */
264 return snap_bezier_cframe;
265 case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
266 return snap_bezier_nearmarker;
267 case SNAP_KEYS_NEARSEC: /* snap to nearest second */
268 return snap_bezier_nearestsec;
269 default: /* just in case */
270 return snap_bezier_nearest;
276 static short mirror_bezier_cframe(BeztEditData *bed, BezTriple *bezt)
278 const Scene *scene= bed->scene;
281 if (bezt->f2 & SELECT) {
282 diff= ((float)CFRA - bezt->vec[1][0]);
283 bezt->vec[1][0]= ((float)CFRA + diff);
289 static short mirror_bezier_yaxis(BeztEditData *bed, BezTriple *bezt)
293 if (bezt->f2 & SELECT) {
294 diff= (0.0f - bezt->vec[1][0]);
295 bezt->vec[1][0]= (0.0f + diff);
301 static short mirror_bezier_xaxis(BeztEditData *bed, BezTriple *bezt)
305 if (bezt->f2 & SELECT) {
306 diff= (0.0f - bezt->vec[1][1]);
307 bezt->vec[1][1]= (0.0f + diff);
313 static short mirror_bezier_marker(BeztEditData *bed, BezTriple *bezt)
315 /* mirroring time stored in f1 */
316 if (bezt->f2 & SELECT) {
317 const float diff= (bed->f1 - bezt->vec[1][0]);
318 bezt->vec[1][0]= (bed->f1 + diff);
324 /* Note: for markers case, need to set global vars (eww...) */
325 // calchandles_ipocurve
326 BeztEditFunc ANIM_editkeyframes_mirror(short type)
329 case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
330 return mirror_bezier_cframe;
331 case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
332 return mirror_bezier_yaxis;
333 case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
334 return mirror_bezier_xaxis;
335 case MIRROR_KEYS_MARKER: /* mirror over marker */
336 return mirror_bezier_marker;
337 default: /* just in case */
338 return mirror_bezier_yaxis;
345 /* This function is called to calculate the average location of the
346 * selected keyframes, and place the current frame at that location.
348 * It must be called like so:
349 * snap_cfra_ipo_keys(scene, NULL, -1); // initialise the static vars first
350 * for (ipo...) snap_cfra_ipo_keys(scene, ipo, 0); // sum up keyframe times
351 * snap_cfra_ipo_keys(scene, NULL, 1); // set current frame after taking average
353 // XXX this thing needs to be refactored!
354 void snap_cfra_ipo_keys(BeztEditData *bed, Ipo *ipo, short mode)
359 Scene *scene= bed->scene;
366 /* initialise a new snap-operation */
370 else if (mode == 1) {
371 /* set current frame - using average frame */
376 /* loop through keys in ipo, summing the frame
377 * numbers of those that are selected
382 for (icu= ipo->curve.first; icu; icu= icu->next) {
383 for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
384 if (BEZSELECTED(bezt)) {
385 cfra += bezt->vec[1][0];
393 /* ******************************************* */
396 /* Sets the selected bezier handles to type 'auto' */
397 static short set_bezier_auto(BeztEditData *bed, BezTriple *bezt)
399 if((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
400 if (bezt->f1 & SELECT) bezt->h1= 1; /* the secret code for auto */
401 if (bezt->f3 & SELECT) bezt->h2= 1;
403 /* if the handles are not of the same type, set them
406 if (bezt->h1 != bezt->h2) {
407 if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
408 if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
414 /* Sets the selected bezier handles to type 'vector' */
415 static short set_bezier_vector(BeztEditData *bed, BezTriple *bezt)
417 if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
418 if (bezt->f1 & SELECT) bezt->h1= HD_VECT;
419 if (bezt->f3 & SELECT) bezt->h2= HD_VECT;
421 /* if the handles are not of the same type, set them
424 if (bezt->h1 != bezt->h2) {
425 if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
426 if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
432 /* Queries if the handle should be set to 'free' or 'align' */
433 static short bezier_isfree(BeztEditData *bed, BezTriple *bezt)
435 if ((bezt->f1 & SELECT) && (bezt->h1)) return 1;
436 if ((bezt->f3 & SELECT) && (bezt->h2)) return 1;
440 /* Sets selected bezier handles to type 'align' */
441 static short set_bezier_align(BeztEditData *bed, BezTriple *bezt)
443 if (bezt->f1 & SELECT) bezt->h1= HD_ALIGN;
444 if (bezt->f3 & SELECT) bezt->h2= HD_ALIGN;
448 /* Sets selected bezier handles to type 'free' */
449 static short set_bezier_free(BeztEditData *bed, BezTriple *bezt)
451 if (bezt->f1 & SELECT) bezt->h1= HD_FREE;
452 if (bezt->f3 & SELECT) bezt->h2= HD_FREE;
456 /* Set all Bezier Handles to a single type */
457 // calchandles_ipocurve
458 BeztEditFunc ANIM_editkeyframes_handles(short code)
461 case HD_AUTO: /* auto */
462 return set_bezier_auto;
463 case HD_VECT: /* vector */
464 return set_bezier_vector;
465 case HD_FREE: /* free */
466 return set_bezier_free;
467 case HD_ALIGN: /* align */
468 return set_bezier_align;
470 default: /* free or align? */
471 return bezier_isfree;
477 /* IPO-curve sanity callback - the name of this is a bit unwieldy, by is best to keep this in style... */
478 // was called set_ipocurve_mixed()
479 void ANIM_editkeyframes_ipocurve_ipotype(IpoCurve *icu)
481 /* Sets the type of the IPO curve to mixed, as some (selected)
482 * keyframes were set to other interpolation types
486 /* recalculate handles, as some changes may have occurred */
487 calchandles_ipocurve(icu);
490 static short set_bezt_constant(BeztEditData *bed, BezTriple *bezt)
492 if (bezt->f2 & SELECT)
493 bezt->ipo= IPO_CONST;
497 static short set_bezt_linear(BeztEditData *bed, BezTriple *bezt)
499 if (bezt->f2 & SELECT)
504 static short set_bezt_bezier(BeztEditData *bed, BezTriple *bezt)
506 if (bezt->f2 & SELECT)
511 /* Set the interpolation type of the selected BezTriples in each IPO curve to the specified one */
512 // ANIM_editkeyframes_ipocurve_ipotype() !
513 BeztEditFunc ANIM_editkeyframes_ipo(short code)
516 case IPO_CONST: /* constant */
517 return set_bezt_constant;
518 case IPO_LIN: /* linear */
519 return set_bezt_linear;
520 default: /* bezier */
521 return set_bezt_bezier;
525 // XXX will we keep this?
526 void setexprap_ipoloop(Ipo *ipo, short code)
530 /* Loop through each curve in the Ipo */
531 for (icu=ipo->curve.first; icu; icu=icu->next)
535 /* ******************************************* */
538 static short select_bezier_add(BeztEditData *bed, BezTriple *bezt)
540 /* Select the bezier triple */
545 static short select_bezier_subtract(BeztEditData *bed, BezTriple *bezt)
547 /* Deselect the bezier triple */
552 static short select_bezier_invert(BeztEditData *bed, BezTriple *bezt)
554 /* Invert the selection for the bezier triple */
556 if (bezt->f2 & SELECT) {
568 BeztEditFunc ANIM_editkeyframes_select(short selectmode)
570 switch (selectmode) {
571 case SELECT_ADD: /* add */
572 return select_bezier_add;
573 case SELECT_SUBTRACT: /* subtract */
574 return select_bezier_subtract;
575 case SELECT_INVERT: /* invert */
576 return select_bezier_invert;
577 default: /* replace (need to clear all, then add) */
578 return select_bezier_add;
583 short is_ipo_key_selected(Ipo *ipo)
592 for (icu=ipo->curve.first; icu; icu=icu->next) {
593 for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
594 if (BEZSELECTED(bezt))
602 // XXX although this is still needed, it should be removed!
603 void set_ipo_key_selection(Ipo *ipo, short sel)
612 for (icu=ipo->curve.first; icu; icu=icu->next) {
613 for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
627 // XXX port this over to the new system!
628 // err... this is this still used?
629 int fullselect_ipo_keys(Ipo *ipo)
638 for (icu=ipo->curve.first; icu; icu=icu->next) {
639 for (i=0; i<icu->totvert; i++) {
640 if (icu->bezt[i].f2 & SELECT) {
642 icu->bezt[i].f1 |= SELECT;
643 icu->bezt[i].f3 |= SELECT;