Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2008 Blender Foundation 00019 * 00020 * Contributor(s): Joshua Leung 00021 * 00022 * ***** END GPL LICENSE BLOCK ***** 00023 */ 00024 00030 #include <stdlib.h> 00031 #include <string.h> 00032 #include <math.h> 00033 #include <float.h> 00034 00035 #include "MEM_guardedalloc.h" 00036 00037 #include "BLI_blenlib.h" 00038 #include "BLI_math.h" 00039 #include "BLI_utildefines.h" 00040 00041 #include "DNA_anim_types.h" 00042 #include "DNA_armature_types.h" 00043 #include "DNA_camera_types.h" 00044 #include "DNA_key_types.h" 00045 #include "DNA_lamp_types.h" 00046 #include "DNA_lattice_types.h" 00047 #include "DNA_mesh_types.h" 00048 #include "DNA_material_types.h" 00049 #include "DNA_object_types.h" 00050 #include "DNA_meta_types.h" 00051 #include "DNA_node_types.h" 00052 #include "DNA_particle_types.h" 00053 #include "DNA_scene_types.h" 00054 #include "DNA_space_types.h" 00055 #include "DNA_world_types.h" 00056 00057 #include "BKE_fcurve.h" 00058 #include "BKE_key.h" 00059 #include "BKE_material.h" 00060 00061 00062 #include "ED_anim_api.h" 00063 #include "ED_keyframes_edit.h" 00064 #include "ED_markers.h" 00065 00066 /* This file defines an API and set of callback-operators for non-destructive editing of keyframe data. 00067 * 00068 * Two API functions are defined for actually performing the operations on the data: 00069 * ANIM_fcurve_keyframes_loop() 00070 * which take the data they operate on, a few callbacks defining what operations to perform. 00071 * 00072 * As operators which work on keyframes usually apply the same operation on all BezTriples in 00073 * every channel, the code has been optimised providing a set of functions which will get the 00074 * appropriate bezier-modify function to set. These functions (ANIM_editkeyframes_*) will need 00075 * to be called before getting any channels. 00076 * 00077 * A set of 'validation' callbacks are provided for checking if a BezTriple should be operated on. 00078 * These should only be used when using a 'general' BezTriple editor (i.e. selection setters which 00079 * don't check existing selection status). 00080 * 00081 * - Joshua Leung, Dec 2008 00082 */ 00083 00084 /* ************************************************************************** */ 00085 /* Keyframe Editing Loops - Exposed API */ 00086 00087 /* --------------------------- Base Functions ------------------------------------ */ 00088 00089 /* This function is used to loop over BezTriples in the given F-Curve, applying a given 00090 * operation on them, and optionally applies an F-Curve validation function afterwards. 00091 */ 00092 // TODO: make this function work on samples too... 00093 short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 00094 { 00095 BezTriple *bezt; 00096 short ok = 0; 00097 unsigned int i; 00098 00099 /* sanity check */ 00100 if (ELEM(NULL, fcu, fcu->bezt)) 00101 return 0; 00102 00103 /* set the F-Curve into the editdata so that it can be accessed */ 00104 if (ked) { 00105 ked->fcu= fcu; 00106 ked->curIndex= 0; 00107 ked->curflags= ok; 00108 } 00109 00110 /* if function to apply to bezier curves is set, then loop through executing it on beztriples */ 00111 if (key_cb) { 00112 /* if there's a validation func, include that check in the loop 00113 * (this is should be more efficient than checking for it in every loop) 00114 */ 00115 if (key_ok) { 00116 for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) { 00117 if (ked) { 00118 /* advance the index, and reset the ok flags (to not influence the result) */ 00119 ked->curIndex= i; 00120 ked->curflags= 0; 00121 } 00122 00123 /* Only operate on this BezTriple if it fullfills the criteria of the validation func */ 00124 if ( (ok = key_ok(ked, bezt)) ) { 00125 if (ked) ked->curflags= ok; 00126 00127 /* Exit with return-code '1' if function returns positive 00128 * This is useful if finding if some BezTriple satisfies a condition. 00129 */ 00130 if (key_cb(ked, bezt)) return 1; 00131 } 00132 } 00133 } 00134 else { 00135 for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) { 00136 if (ked) ked->curIndex= i; 00137 00138 /* Exit with return-code '1' if function returns positive 00139 * This is useful if finding if some BezTriple satisfies a condition. 00140 */ 00141 if (key_cb(ked, bezt)) return 1; 00142 } 00143 } 00144 } 00145 00146 /* unset the F-Curve from the editdata now that it's done */ 00147 if (ked) { 00148 ked->fcu= NULL; 00149 ked->curIndex= 0; 00150 ked->curflags= 0; 00151 } 00152 00153 /* if fcu_cb (F-Curve post-editing callback) has been specified then execute it */ 00154 if (fcu_cb) 00155 fcu_cb(fcu); 00156 00157 /* done */ 00158 return 0; 00159 } 00160 00161 /* -------------------------------- Further Abstracted (Not Exposed Directly) ----------------------------- */ 00162 00163 /* This function is used to loop over the keyframe data in an Action Group */ 00164 static short agrp_keyframes_loop(KeyframeEditData *ked, bActionGroup *agrp, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 00165 { 00166 FCurve *fcu; 00167 00168 /* sanity check */ 00169 if (agrp == NULL) 00170 return 0; 00171 00172 /* only iterate over the F-Curves that are in this group */ 00173 for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) { 00174 if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb)) 00175 return 1; 00176 } 00177 00178 return 0; 00179 } 00180 00181 /* This function is used to loop over the keyframe data in an Action */ 00182 static short act_keyframes_loop(KeyframeEditData *ked, bAction *act, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 00183 { 00184 FCurve *fcu; 00185 00186 /* sanity check */ 00187 if (act == NULL) 00188 return 0; 00189 00190 /* just loop through all F-Curves */ 00191 for (fcu= act->curves.first; fcu; fcu= fcu->next) { 00192 if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb)) 00193 return 1; 00194 } 00195 00196 return 0; 00197 } 00198 00199 /* This function is used to loop over the keyframe data in an Object */ 00200 static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *ob, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 00201 { 00202 bAnimContext ac = {NULL}; 00203 ListBase anim_data = {NULL, NULL}; 00204 bAnimListElem *ale; 00205 int filter; 00206 int ret=0; 00207 00208 bAnimListElem dummychan = {NULL}; 00209 Base dummybase = {NULL}; 00210 00211 if (ob == NULL) 00212 return 0; 00213 00214 /* create a dummy wrapper data to work with */ 00215 dummybase.object = ob; 00216 00217 dummychan.type = ANIMTYPE_OBJECT; 00218 dummychan.data = &dummybase; 00219 dummychan.id = &ob->id; 00220 dummychan.adt = ob->adt; 00221 00222 ac.ads = ads; 00223 ac.data = &dummychan; 00224 ac.datatype = ANIMCONT_CHANNEL; 00225 00226 /* get F-Curves to take keyframes from */ 00227 filter= ANIMFILTER_DATA_VISIBLE; // curves only 00228 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 00229 00230 /* loop through each F-Curve, applying the operation as required, but stopping on the first one */ 00231 for (ale= anim_data.first; ale; ale= ale->next) { 00232 if (ANIM_fcurve_keyframes_loop(ked, (FCurve*)ale->data, key_ok, key_cb, fcu_cb)) { 00233 ret = 1; 00234 break; 00235 } 00236 } 00237 00238 BLI_freelistN(&anim_data); 00239 00240 /* return return code - defaults to zero if nothing happened */ 00241 return ret; 00242 } 00243 00244 /* This function is used to loop over the keyframe data in a Scene */ 00245 static short scene_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Scene *sce, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 00246 { 00247 bAnimContext ac = {NULL}; 00248 ListBase anim_data = {NULL, NULL}; 00249 bAnimListElem *ale; 00250 int filter; 00251 int ret=0; 00252 00253 bAnimListElem dummychan = {NULL}; 00254 00255 if (sce == NULL) 00256 return 0; 00257 00258 /* create a dummy wrapper data to work with */ 00259 dummychan.type = ANIMTYPE_SCENE; 00260 dummychan.data = sce; 00261 dummychan.id = &sce->id; 00262 dummychan.adt = sce->adt; 00263 00264 ac.ads = ads; 00265 ac.data = &dummychan; 00266 ac.datatype = ANIMCONT_CHANNEL; 00267 00268 /* get F-Curves to take keyframes from */ 00269 filter= ANIMFILTER_DATA_VISIBLE; // curves only 00270 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 00271 00272 /* loop through each F-Curve, applying the operation as required, but stopping on the first one */ 00273 for (ale= anim_data.first; ale; ale= ale->next) { 00274 if (ANIM_fcurve_keyframes_loop(ked, (FCurve*)ale->data, key_ok, key_cb, fcu_cb)) { 00275 ret = 1; 00276 break; 00277 } 00278 } 00279 00280 BLI_freelistN(&anim_data); 00281 00282 /* return return code - defaults to zero if nothing happened */ 00283 return ret; 00284 } 00285 00286 /* This function is used to loop over the keyframe data in a DopeSheet summary */ 00287 static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 00288 { 00289 ListBase anim_data = {NULL, NULL}; 00290 bAnimListElem *ale; 00291 int filter, ret_code=0; 00292 00293 /* sanity check */ 00294 if (ac == NULL) 00295 return 0; 00296 00297 /* get F-Curves to take keyframes from */ 00298 filter= ANIMFILTER_DATA_VISIBLE; 00299 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00300 00301 /* loop through each F-Curve, working on the keyframes until the first curve aborts */ 00302 for (ale= anim_data.first; ale; ale= ale->next) { 00303 ret_code= ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb); 00304 00305 if (ret_code) 00306 break; 00307 } 00308 00309 BLI_freelistN(&anim_data); 00310 00311 return ret_code; 00312 } 00313 00314 /* --- */ 00315 00316 /* This function is used to apply operation to all keyframes, regardless of the type */ 00317 short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, bAnimListElem *ale, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 00318 { 00319 /* sanity checks */ 00320 if (ale == NULL) 00321 return 0; 00322 00323 /* method to use depends on the type of keyframe data */ 00324 switch (ale->datatype) { 00325 /* direct keyframe data (these loops are exposed) */ 00326 case ALE_FCURVE: /* F-Curve */ 00327 return ANIM_fcurve_keyframes_loop(ked, ale->key_data, key_ok, key_cb, fcu_cb); 00328 00329 /* indirect 'summaries' (these are not exposed directly) 00330 * NOTE: must keep this code in sync with the drawing code and also the filtering code! 00331 */ 00332 case ALE_GROUP: /* action group */ 00333 return agrp_keyframes_loop(ked, (bActionGroup *)ale->data, key_ok, key_cb, fcu_cb); 00334 case ALE_ACT: /* action */ 00335 return act_keyframes_loop(ked, (bAction *)ale->key_data, key_ok, key_cb, fcu_cb); 00336 00337 case ALE_OB: /* object */ 00338 return ob_keyframes_loop(ked, ads, (Object *)ale->key_data, key_ok, key_cb, fcu_cb); 00339 case ALE_SCE: /* scene */ 00340 return scene_keyframes_loop(ked, ads, (Scene *)ale->data, key_ok, key_cb, fcu_cb); 00341 case ALE_ALL: /* 'all' (DopeSheet summary) */ 00342 return summary_keyframes_loop(ked, (bAnimContext *)ale->data, key_ok, key_cb, fcu_cb); 00343 } 00344 00345 return 0; 00346 } 00347 00348 /* This function is used to apply operation to all keyframes, regardless of the type without needed an AnimListElem wrapper */ 00349 short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, void *data, int keytype, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) 00350 { 00351 /* sanity checks */ 00352 if (data == NULL) 00353 return 0; 00354 00355 /* method to use depends on the type of keyframe data */ 00356 switch (keytype) { 00357 /* direct keyframe data (these loops are exposed) */ 00358 case ALE_FCURVE: /* F-Curve */ 00359 return ANIM_fcurve_keyframes_loop(ked, data, key_ok, key_cb, fcu_cb); 00360 00361 /* indirect 'summaries' (these are not exposed directly) 00362 * NOTE: must keep this code in sync with the drawing code and also the filtering code! 00363 */ 00364 case ALE_GROUP: /* action group */ 00365 return agrp_keyframes_loop(ked, (bActionGroup *)data, key_ok, key_cb, fcu_cb); 00366 case ALE_ACT: /* action */ 00367 return act_keyframes_loop(ked, (bAction *)data, key_ok, key_cb, fcu_cb); 00368 00369 case ALE_OB: /* object */ 00370 return ob_keyframes_loop(ked, ads, (Object *)data, key_ok, key_cb, fcu_cb); 00371 case ALE_SCE: /* scene */ 00372 return scene_keyframes_loop(ked, ads, (Scene *)data, key_ok, key_cb, fcu_cb); 00373 case ALE_ALL: /* 'all' (DopeSheet summary) */ 00374 return summary_keyframes_loop(ked, (bAnimContext *)data, key_ok, key_cb, fcu_cb); 00375 } 00376 00377 return 0; 00378 } 00379 00380 /* ************************************************************************** */ 00381 /* Keyframe Integrity Tools */ 00382 00383 /* Rearrange keyframes if some are out of order */ 00384 // used to be recalc_*_ipos() where * was object or action 00385 void ANIM_editkeyframes_refresh(bAnimContext *ac) 00386 { 00387 ListBase anim_data = {NULL, NULL}; 00388 bAnimListElem *ale; 00389 int filter; 00390 /* when not in graph view, don't use handles */ 00391 SpaceIpo *sipo= (ac->spacetype == SPACE_IPO) ? (SpaceIpo *)ac->sl : NULL; 00392 const short use_handle = sipo ? !(sipo->flag & SIPO_NOHANDLES) : FALSE; 00393 00394 /* filter animation data */ 00395 filter= ANIMFILTER_DATA_VISIBLE; 00396 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00397 00398 /* loop over F-Curves that are likely to have been edited, and check them */ 00399 for (ale= anim_data.first; ale; ale= ale->next) { 00400 FCurve *fcu= ale->key_data; 00401 00402 /* make sure keyframes in F-Curve are all in order, and handles are in valid positions */ 00403 sort_time_fcurve(fcu); 00404 testhandles_fcurve(fcu, use_handle); 00405 } 00406 00407 /* free temp data */ 00408 BLI_freelistN(&anim_data); 00409 } 00410 00411 /* ************************************************************************** */ 00412 /* BezTriple Validation Callbacks */ 00413 00414 /* ------------------------ */ 00415 /* Some macros to make this easier... */ 00416 00417 /* run the given check on the 3 handles 00418 * - check should be a macro, which takes the handle index as its single arg, which it substitutes later 00419 * - requires that a var, of type short, is named 'ok', and has been initialized to 0 00420 */ 00421 #define KEYFRAME_OK_CHECKS(check) \ 00422 { \ 00423 if (check(1)) \ 00424 ok |= KEYFRAME_OK_KEY; \ 00425 \ 00426 if (ked && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { \ 00427 if (check(0)) \ 00428 ok |= KEYFRAME_OK_H1; \ 00429 if (check(2)) \ 00430 ok |= KEYFRAME_OK_H2; \ 00431 } \ 00432 } 00433 00434 /* ------------------------ */ 00435 00436 static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt) 00437 { 00438 short ok = 0; 00439 00440 /* frame is stored in f1 property (this float accuracy check may need to be dropped?) */ 00441 #define KEY_CHECK_OK(_index) IS_EQF(bezt->vec[_index][0], ked->f1) 00442 KEYFRAME_OK_CHECKS(KEY_CHECK_OK); 00443 #undef KEY_CHECK_OK 00444 00445 /* return ok flags */ 00446 return ok; 00447 } 00448 00449 static short ok_bezier_framerange(KeyframeEditData *ked, BezTriple *bezt) 00450 { 00451 short ok = 0; 00452 00453 /* frame range is stored in float properties */ 00454 #define KEY_CHECK_OK(_index) ((bezt->vec[_index][0] > ked->f1) && (bezt->vec[_index][0] < ked->f2)) 00455 KEYFRAME_OK_CHECKS(KEY_CHECK_OK); 00456 #undef KEY_CHECK_OK 00457 00458 /* return ok flags */ 00459 return ok; 00460 } 00461 00462 static short ok_bezier_selected(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00463 { 00464 /* this macro checks all beztriple handles for selection... 00465 * only one of the verts has to be selected for this to be ok... 00466 */ 00467 if (BEZSELECTED(bezt)) 00468 return KEYFRAME_OK_ALL; 00469 else 00470 return 0; 00471 } 00472 00473 static short ok_bezier_value(KeyframeEditData *ked, BezTriple *bezt) 00474 { 00475 short ok = 0; 00476 00477 /* value is stored in f1 property 00478 * - this float accuracy check may need to be dropped? 00479 * - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too? 00480 */ 00481 #define KEY_CHECK_OK(_index) IS_EQF(bezt->vec[_index][1], ked->f1) 00482 KEYFRAME_OK_CHECKS(KEY_CHECK_OK); 00483 #undef KEY_CHECK_OK 00484 00485 /* return ok flags */ 00486 return ok; 00487 } 00488 00489 static short ok_bezier_valuerange(KeyframeEditData *ked, BezTriple *bezt) 00490 { 00491 short ok = 0; 00492 00493 /* value range is stored in float properties */ 00494 #define KEY_CHECK_OK(_index) ((bezt->vec[_index][1] > ked->f1) && (bezt->vec[_index][1] < ked->f2)) 00495 KEYFRAME_OK_CHECKS(KEY_CHECK_OK); 00496 #undef KEY_CHECK_OK 00497 00498 /* return ok flags */ 00499 return ok; 00500 } 00501 00502 static short ok_bezier_region(KeyframeEditData *ked, BezTriple *bezt) 00503 { 00504 /* rect is stored in data property (it's of type rectf, but may not be set) */ 00505 if (ked->data) { 00506 short ok = 0; 00507 00508 #define KEY_CHECK_OK(_index) BLI_in_rctf(ked->data, bezt->vec[_index][0], bezt->vec[_index][1]) 00509 KEYFRAME_OK_CHECKS(KEY_CHECK_OK); 00510 #undef KEY_CHECK_OK 00511 00512 /* return ok flags */ 00513 return ok; 00514 } 00515 else 00516 return 0; 00517 } 00518 00519 00520 KeyframeEditFunc ANIM_editkeyframes_ok(short mode) 00521 { 00522 /* eEditKeyframes_Validate */ 00523 switch (mode) { 00524 case BEZT_OK_FRAME: /* only if bezt falls on the right frame (float) */ 00525 return ok_bezier_frame; 00526 case BEZT_OK_FRAMERANGE: /* only if bezt falls within the specified frame range (floats) */ 00527 return ok_bezier_framerange; 00528 case BEZT_OK_SELECTED: /* only if bezt is selected (self) */ 00529 return ok_bezier_selected; 00530 case BEZT_OK_VALUE: /* only if bezt value matches (float) */ 00531 return ok_bezier_value; 00532 case BEZT_OK_VALUERANGE: /* only if bezier falls within the specified value range (floats) */ 00533 return ok_bezier_valuerange; 00534 case BEZT_OK_REGION: /* only if bezier falls within the specified rect (data -> rectf) */ 00535 return ok_bezier_region; 00536 default: /* nothing was ok */ 00537 return NULL; 00538 } 00539 } 00540 00541 /* ******************************************* */ 00542 /* Assorted Utility Functions */ 00543 00544 /* helper callback for <animeditor>_cfrasnap_exec() -> used to help get the average time of all selected beztriples */ 00545 short bezt_calc_average(KeyframeEditData *ked, BezTriple *bezt) 00546 { 00547 /* only if selected */ 00548 if (bezt->f2 & SELECT) { 00549 /* store average time in float 1 (only do rounding at last step) */ 00550 ked->f1 += bezt->vec[1][0]; 00551 00552 /* store average value in float 2 (only do rounding at last step) 00553 * - this isn't always needed, but some operators may also require this 00554 */ 00555 ked->f2 += bezt->vec[1][1]; 00556 00557 /* increment number of items */ 00558 ked->i1++; 00559 } 00560 00561 return 0; 00562 } 00563 00564 /* helper callback for columnselect_<animeditor>_keys() -> populate list CfraElems with frame numbers from selected beztriples */ 00565 short bezt_to_cfraelem(KeyframeEditData *ked, BezTriple *bezt) 00566 { 00567 /* only if selected */ 00568 if (bezt->f2 & SELECT) { 00569 CfraElem *ce= MEM_callocN(sizeof(CfraElem), "cfraElem"); 00570 BLI_addtail(&ked->list, ce); 00571 00572 ce->cfra= bezt->vec[1][0]; 00573 } 00574 00575 return 0; 00576 } 00577 00578 /* used to remap times from one range to another 00579 * requires: ked->data = KeyframeEditCD_Remap 00580 */ 00581 void bezt_remap_times(KeyframeEditData *ked, BezTriple *bezt) 00582 { 00583 KeyframeEditCD_Remap *rmap= (KeyframeEditCD_Remap*)ked->data; 00584 const float scale = (rmap->newMax - rmap->newMin) / (rmap->oldMax - rmap->oldMin); 00585 00586 /* perform transform on all three handles unless indicated otherwise */ 00587 // TODO: need to include some checks for that 00588 00589 bezt->vec[0][0]= scale*(bezt->vec[0][0] - rmap->oldMin) + rmap->newMin; 00590 bezt->vec[1][0]= scale*(bezt->vec[1][0] - rmap->oldMin) + rmap->newMin; 00591 bezt->vec[2][0]= scale*(bezt->vec[2][0] - rmap->oldMin) + rmap->newMin; 00592 } 00593 00594 /* ******************************************* */ 00595 /* Transform */ 00596 00597 /* snaps the keyframe to the nearest frame */ 00598 static short snap_bezier_nearest(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00599 { 00600 if (bezt->f2 & SELECT) 00601 bezt->vec[1][0]= (float)(floorf(bezt->vec[1][0]+0.5f)); 00602 return 0; 00603 } 00604 00605 /* snaps the keyframe to the neares second */ 00606 static short snap_bezier_nearestsec(KeyframeEditData *ked, BezTriple *bezt) 00607 { 00608 const Scene *scene= ked->scene; 00609 const float secf = (float)FPS; 00610 00611 if (bezt->f2 & SELECT) 00612 bezt->vec[1][0]= ((float)floor(bezt->vec[1][0]/secf + 0.5f) * secf); 00613 return 0; 00614 } 00615 00616 /* snaps the keyframe to the current frame */ 00617 static short snap_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt) 00618 { 00619 const Scene *scene= ked->scene; 00620 if (bezt->f2 & SELECT) 00621 bezt->vec[1][0]= (float)CFRA; 00622 return 0; 00623 } 00624 00625 /* snaps the keyframe time to the nearest marker's frame */ 00626 static short snap_bezier_nearmarker(KeyframeEditData *ked, BezTriple *bezt) 00627 { 00628 if (bezt->f2 & SELECT) 00629 bezt->vec[1][0]= (float)ED_markers_find_nearest_marker_time(&ked->list, bezt->vec[1][0]); 00630 return 0; 00631 } 00632 00633 /* make the handles have the same value as the key */ 00634 static short snap_bezier_horizontal(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00635 { 00636 if (bezt->f2 & SELECT) { 00637 bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1]; 00638 00639 if (ELEM3(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h1= HD_ALIGN; 00640 if (ELEM3(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h2= HD_ALIGN; 00641 } 00642 return 0; 00643 } 00644 00645 /* value to snap to is stored in the custom data -> first float value slot */ 00646 static short snap_bezier_value(KeyframeEditData *ked, BezTriple *bezt) 00647 { 00648 if (bezt->f2 & SELECT) 00649 bezt->vec[1][1]= ked->f1; 00650 return 0; 00651 } 00652 00653 KeyframeEditFunc ANIM_editkeyframes_snap(short type) 00654 { 00655 /* eEditKeyframes_Snap */ 00656 switch (type) { 00657 case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */ 00658 return snap_bezier_nearest; 00659 case SNAP_KEYS_CURFRAME: /* snap to current frame */ 00660 return snap_bezier_cframe; 00661 case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */ 00662 return snap_bezier_nearmarker; 00663 case SNAP_KEYS_NEARSEC: /* snap to nearest second */ 00664 return snap_bezier_nearestsec; 00665 case SNAP_KEYS_HORIZONTAL: /* snap handles to same value */ 00666 return snap_bezier_horizontal; 00667 case SNAP_KEYS_VALUE: /* snap to given value */ 00668 return snap_bezier_value; 00669 default: /* just in case */ 00670 return snap_bezier_nearest; 00671 } 00672 } 00673 00674 /* --------- */ 00675 00676 static short mirror_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt) 00677 { 00678 const Scene *scene= ked->scene; 00679 float diff; 00680 00681 if (bezt->f2 & SELECT) { 00682 diff= ((float)CFRA - bezt->vec[1][0]); 00683 bezt->vec[1][0]= ((float)CFRA + diff); 00684 } 00685 00686 return 0; 00687 } 00688 00689 static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00690 { 00691 float diff; 00692 00693 if (bezt->f2 & SELECT) { 00694 diff= (0.0f - bezt->vec[1][0]); 00695 bezt->vec[1][0]= (0.0f + diff); 00696 } 00697 00698 return 0; 00699 } 00700 00701 static short mirror_bezier_xaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00702 { 00703 float diff; 00704 00705 if (bezt->f2 & SELECT) { 00706 diff= (0.0f - bezt->vec[1][1]); 00707 bezt->vec[1][1]= (0.0f + diff); 00708 } 00709 00710 return 0; 00711 } 00712 00713 static short mirror_bezier_marker(KeyframeEditData *ked, BezTriple *bezt) 00714 { 00715 /* mirroring time stored in f1 */ 00716 if (bezt->f2 & SELECT) { 00717 const float diff= (ked->f1 - bezt->vec[1][0]); 00718 bezt->vec[1][0]= (ked->f1 + diff); 00719 } 00720 00721 return 0; 00722 } 00723 00724 static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt) 00725 { 00726 float diff; 00727 00728 /* value to mirror over is stored in the custom data -> first float value slot */ 00729 if (bezt->f2 & SELECT) { 00730 diff= (ked->f1 - bezt->vec[1][1]); 00731 bezt->vec[1][1]= (ked->f1 + diff); 00732 } 00733 00734 return 0; 00735 } 00736 00737 /* Note: for markers and 'value', the values to use must be supplied as the first float value */ 00738 // calchandles_fcurve 00739 KeyframeEditFunc ANIM_editkeyframes_mirror(short type) 00740 { 00741 switch (type) { 00742 case MIRROR_KEYS_CURFRAME: /* mirror over current frame */ 00743 return mirror_bezier_cframe; 00744 case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */ 00745 return mirror_bezier_yaxis; 00746 case MIRROR_KEYS_XAXIS: /* mirror over value 0 */ 00747 return mirror_bezier_xaxis; 00748 case MIRROR_KEYS_MARKER: /* mirror over marker */ 00749 return mirror_bezier_marker; 00750 case MIRROR_KEYS_VALUE: /* mirror over given value */ 00751 return mirror_bezier_value; 00752 default: /* just in case */ 00753 return mirror_bezier_yaxis; 00754 break; 00755 } 00756 } 00757 00758 /* ******************************************* */ 00759 /* Settings */ 00760 00761 /* standard validation step for a few of these (implemented as macro for inlining without fn-call overhead): 00762 * "if the handles are not of the same type, set them to type free" 00763 */ 00764 #define ENSURE_HANDLES_MATCH(bezt) \ 00765 if (bezt->h1 != bezt->h2) { \ 00766 if ELEM3(bezt->h1, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM) bezt->h1= HD_FREE; \ 00767 if ELEM3(bezt->h2, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM) bezt->h2= HD_FREE; \ 00768 } 00769 00770 /* Sets the selected bezier handles to type 'auto' */ 00771 static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00772 { 00773 if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) { 00774 if (bezt->f1 & SELECT) bezt->h1= HD_AUTO; 00775 if (bezt->f3 & SELECT) bezt->h2= HD_AUTO; 00776 00777 ENSURE_HANDLES_MATCH(bezt); 00778 } 00779 return 0; 00780 } 00781 00782 /* Sets the selected bezier handles to type 'auto-clamped' 00783 * NOTE: this is like auto above, but they're handled a bit different 00784 */ 00785 static short set_bezier_auto_clamped(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00786 { 00787 if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) { 00788 if (bezt->f1 & SELECT) bezt->h1= HD_AUTO_ANIM; 00789 if (bezt->f3 & SELECT) bezt->h2= HD_AUTO_ANIM; 00790 00791 ENSURE_HANDLES_MATCH(bezt); 00792 } 00793 return 0; 00794 } 00795 00796 /* Sets the selected bezier handles to type 'vector' */ 00797 static short set_bezier_vector(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00798 { 00799 if (bezt->f1 & SELECT) bezt->h1= HD_VECT; 00800 if (bezt->f3 & SELECT) bezt->h2= HD_VECT; 00801 return 0; 00802 } 00803 00804 /* Queries if the handle should be set to 'free' or 'align' */ 00805 // NOTE: this was used for the 'toggle free/align' option 00806 // currently this isn't used, but may be restored later 00807 static short bezier_isfree(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00808 { 00809 if ((bezt->f1 & SELECT) && (bezt->h1)) return 1; 00810 if ((bezt->f3 & SELECT) && (bezt->h2)) return 1; 00811 return 0; 00812 } 00813 00814 /* Sets selected bezier handles to type 'align' */ 00815 static short set_bezier_align(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00816 { 00817 if (bezt->f1 & SELECT) bezt->h1= HD_ALIGN; 00818 if (bezt->f3 & SELECT) bezt->h2= HD_ALIGN; 00819 return 0; 00820 } 00821 00822 /* Sets selected bezier handles to type 'free' */ 00823 static short set_bezier_free(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00824 { 00825 if (bezt->f1 & SELECT) bezt->h1= HD_FREE; 00826 if (bezt->f3 & SELECT) bezt->h2= HD_FREE; 00827 return 0; 00828 } 00829 00830 /* Set all selected Bezier Handles to a single type */ 00831 // calchandles_fcurve 00832 KeyframeEditFunc ANIM_editkeyframes_handles(short code) 00833 { 00834 switch (code) { 00835 case HD_AUTO: /* auto */ 00836 return set_bezier_auto; 00837 case HD_AUTO_ANIM: /* auto clamped */ 00838 return set_bezier_auto_clamped; 00839 00840 case HD_VECT: /* vector */ 00841 return set_bezier_vector; 00842 case HD_FREE: /* free */ 00843 return set_bezier_free; 00844 case HD_ALIGN: /* align */ 00845 return set_bezier_align; 00846 00847 default: /* check for toggle free or align? */ 00848 return bezier_isfree; 00849 } 00850 } 00851 00852 /* ------- */ 00853 00854 static short set_bezt_constant(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00855 { 00856 if (bezt->f2 & SELECT) 00857 bezt->ipo= BEZT_IPO_CONST; 00858 return 0; 00859 } 00860 00861 static short set_bezt_linear(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00862 { 00863 if (bezt->f2 & SELECT) 00864 bezt->ipo= BEZT_IPO_LIN; 00865 return 0; 00866 } 00867 00868 static short set_bezt_bezier(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00869 { 00870 if (bezt->f2 & SELECT) 00871 bezt->ipo= BEZT_IPO_BEZ; 00872 return 0; 00873 } 00874 00875 /* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */ 00876 // ANIM_editkeyframes_ipocurve_ipotype() ! 00877 KeyframeEditFunc ANIM_editkeyframes_ipo(short code) 00878 { 00879 switch (code) { 00880 case BEZT_IPO_CONST: /* constant */ 00881 return set_bezt_constant; 00882 case BEZT_IPO_LIN: /* linear */ 00883 return set_bezt_linear; 00884 default: /* bezier */ 00885 return set_bezt_bezier; 00886 } 00887 } 00888 00889 /* ------- */ 00890 00891 static short set_keytype_keyframe(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00892 { 00893 if (bezt->f2 & SELECT) 00894 BEZKEYTYPE(bezt)= BEZT_KEYTYPE_KEYFRAME; 00895 return 0; 00896 } 00897 00898 static short set_keytype_breakdown(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00899 { 00900 if (bezt->f2 & SELECT) 00901 BEZKEYTYPE(bezt)= BEZT_KEYTYPE_BREAKDOWN; 00902 return 0; 00903 } 00904 00905 static short set_keytype_extreme(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00906 { 00907 if (bezt->f2 & SELECT) 00908 BEZKEYTYPE(bezt)= BEZT_KEYTYPE_EXTREME; 00909 return 0; 00910 } 00911 00912 static short set_keytype_jitter(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00913 { 00914 if (bezt->f2 & SELECT) 00915 BEZKEYTYPE(bezt)= BEZT_KEYTYPE_JITTER; 00916 return 0; 00917 } 00918 00919 /* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */ 00920 KeyframeEditFunc ANIM_editkeyframes_keytype(short code) 00921 { 00922 switch (code) { 00923 case BEZT_KEYTYPE_BREAKDOWN: /* breakdown */ 00924 return set_keytype_breakdown; 00925 00926 case BEZT_KEYTYPE_EXTREME: /* extreme keyframe */ 00927 return set_keytype_extreme; 00928 00929 case BEZT_KEYTYPE_JITTER: /* jitter keyframe */ 00930 return set_keytype_jitter; 00931 00932 case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */ 00933 default: 00934 return set_keytype_keyframe; 00935 } 00936 } 00937 00938 /* ******************************************* */ 00939 /* Selection */ 00940 00941 static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt) 00942 { 00943 /* if we've got info on what to select, use it, otherwise select all */ 00944 if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { 00945 if (ked->curflags & KEYFRAME_OK_KEY) 00946 bezt->f2 |= SELECT; 00947 if (ked->curflags & KEYFRAME_OK_H1) 00948 bezt->f1 |= SELECT; 00949 if (ked->curflags & KEYFRAME_OK_H2) 00950 bezt->f3 |= SELECT; 00951 } 00952 else { 00953 BEZ_SEL(bezt); 00954 } 00955 00956 return 0; 00957 } 00958 00959 static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt) 00960 { 00961 /* if we've got info on what to deselect, use it, otherwise deselect all */ 00962 if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { 00963 if (ked->curflags & KEYFRAME_OK_KEY) 00964 bezt->f2 &= ~SELECT; 00965 if (ked->curflags & KEYFRAME_OK_H1) 00966 bezt->f1 &= ~SELECT; 00967 if (ked->curflags & KEYFRAME_OK_H2) 00968 bezt->f3 &= ~SELECT; 00969 } 00970 else { 00971 BEZ_DESEL(bezt); 00972 } 00973 00974 return 0; 00975 } 00976 00977 static short select_bezier_invert(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 00978 { 00979 /* Invert the selection for the whole bezier triple */ 00980 bezt->f2 ^= SELECT; 00981 if (bezt->f2 & SELECT) { 00982 bezt->f1 |= SELECT; 00983 bezt->f3 |= SELECT; 00984 } 00985 else { 00986 bezt->f1 &= ~SELECT; 00987 bezt->f3 &= ~SELECT; 00988 } 00989 return 0; 00990 } 00991 00992 KeyframeEditFunc ANIM_editkeyframes_select(short selectmode) 00993 { 00994 switch (selectmode) { 00995 case SELECT_ADD: /* add */ 00996 return select_bezier_add; 00997 case SELECT_SUBTRACT: /* subtract */ 00998 return select_bezier_subtract; 00999 case SELECT_INVERT: /* invert */ 01000 return select_bezier_invert; 01001 default: /* replace (need to clear all, then add) */ 01002 return select_bezier_add; 01003 } 01004 } 01005 01006 /* ******************************************* */ 01007 /* Selection Maps */ 01008 01009 /* Selection maps are simply fancy names for char arrays that store on/off 01010 * info for whether the selection status. The main purpose for these is to 01011 * allow extra info to be tagged to the keyframes without influencing their 01012 * values or having to be removed later. 01013 */ 01014 01015 /* ----------- */ 01016 01017 static short selmap_build_bezier_more(KeyframeEditData *ked, BezTriple *bezt) 01018 { 01019 FCurve *fcu= ked->fcu; 01020 char *map= ked->data; 01021 int i= ked->curIndex; 01022 01023 /* if current is selected, just make sure it stays this way */ 01024 if (BEZSELECTED(bezt)) { 01025 map[i]= 1; 01026 return 0; 01027 } 01028 01029 /* if previous is selected, that means that selection should extend across */ 01030 if (i > 0) { 01031 BezTriple *prev= bezt - 1; 01032 01033 if (BEZSELECTED(prev)) { 01034 map[i]= 1; 01035 return 0; 01036 } 01037 } 01038 01039 /* if next is selected, that means that selection should extend across */ 01040 if (i < (fcu->totvert-1)) { 01041 BezTriple *next= bezt + 1; 01042 01043 if (BEZSELECTED(next)) { 01044 map[i]= 1; 01045 return 0; 01046 } 01047 } 01048 01049 return 0; 01050 } 01051 01052 static short selmap_build_bezier_less(KeyframeEditData *ked, BezTriple *bezt) 01053 { 01054 FCurve *fcu= ked->fcu; 01055 char *map= ked->data; 01056 int i= ked->curIndex; 01057 01058 /* if current is selected, check the left/right keyframes 01059 * since it might need to be deselected (but otherwise no) 01060 */ 01061 if (BEZSELECTED(bezt)) { 01062 /* if previous is not selected, we're on the tip of an iceberg */ 01063 if (i > 0) { 01064 BezTriple *prev= bezt - 1; 01065 01066 if (BEZSELECTED(prev) == 0) 01067 return 0; 01068 } 01069 else if (i == 0) { 01070 /* current keyframe is selected at an endpoint, so should get deselected */ 01071 return 0; 01072 } 01073 01074 /* if next is not selected, we're on the tip of an iceberg */ 01075 if (i < (fcu->totvert-1)) { 01076 BezTriple *next= bezt + 1; 01077 01078 if (BEZSELECTED(next) == 0) 01079 return 0; 01080 } 01081 else if (i == (fcu->totvert-1)) { 01082 /* current keyframe is selected at an endpoint, so should get deselected */ 01083 return 0; 01084 } 01085 01086 /* if we're still here, that means that keyframe should remain untouched */ 01087 map[i]= 1; 01088 } 01089 01090 return 0; 01091 } 01092 01093 /* Get callback for building selection map */ 01094 KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode) 01095 { 01096 switch (mode) { 01097 case SELMAP_LESS: /* less */ 01098 return selmap_build_bezier_less; 01099 01100 case SELMAP_MORE: /* more */ 01101 default: 01102 return selmap_build_bezier_more; 01103 } 01104 } 01105 01106 /* ----------- */ 01107 01108 /* flush selection map values to the given beztriple */ 01109 short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt) 01110 { 01111 char *map= ked->data; 01112 short on= map[ked->curIndex]; 01113 01114 /* select or deselect based on whether the map allows it or not */ 01115 if (on) { 01116 BEZ_SEL(bezt); 01117 } 01118 else { 01119 BEZ_DESEL(bezt); 01120 } 01121 01122 return 0; 01123 } 01124