|
Blender
V2.59
|
00001 /* 00002 * $Id: action_edit.c 36220 2011-04-19 10:35:24Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): Joshua Leung 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include <math.h> 00036 #include <stdlib.h> 00037 #include <string.h> 00038 #include <float.h> 00039 00040 00041 #include "BLI_blenlib.h" 00042 #include "BLI_math.h" 00043 #include "BLI_utildefines.h" 00044 00045 #include "DNA_anim_types.h" 00046 #include "DNA_gpencil_types.h" 00047 #include "DNA_object_types.h" 00048 #include "DNA_scene_types.h" 00049 00050 #include "RNA_access.h" 00051 #include "RNA_define.h" 00052 #include "RNA_enum_types.h" 00053 00054 #include "BKE_action.h" 00055 #include "BKE_fcurve.h" 00056 #include "BKE_nla.h" 00057 #include "BKE_context.h" 00058 #include "BKE_report.h" 00059 00060 #include "UI_view2d.h" 00061 00062 #include "ED_anim_api.h" 00063 #include "ED_gpencil.h" 00064 #include "ED_keyframing.h" 00065 #include "ED_keyframes_edit.h" 00066 #include "ED_screen.h" 00067 #include "ED_transform.h" 00068 #include "ED_markers.h" 00069 00070 #include "WM_api.h" 00071 #include "WM_types.h" 00072 00073 #include "UI_interface.h" 00074 00075 #include "action_intern.h" 00076 00077 /* ************************************************************************** */ 00078 /* ACTION MANAGEMENT */ 00079 00080 /* ******************** New Action Operator *********************** */ 00081 00082 static int act_new_exec(bContext *C, wmOperator *UNUSED(op)) 00083 { 00084 PointerRNA ptr, idptr; 00085 PropertyRNA *prop; 00086 00087 /* hook into UI */ 00088 uiIDContextProperty(C, &ptr, &prop); 00089 00090 if (prop) { 00091 bAction *action=NULL, *oldact=NULL; 00092 PointerRNA oldptr; 00093 00094 /* create action - the way to do this depends on whether we've got an 00095 * existing one there already, in which case we make a copy of it 00096 * (which is useful for "versioning" actions within the same file) 00097 */ 00098 oldptr = RNA_property_pointer_get(&ptr, prop); 00099 oldact = (bAction *)oldptr.id.data; 00100 00101 if (oldact && GS(oldact->id.name)==ID_AC) { 00102 /* make a copy of the existing action */ 00103 action= copy_action(oldact); 00104 } 00105 else { 00106 /* just make a new (empty) action */ 00107 action= add_empty_action("Action"); 00108 } 00109 00110 /* when creating new ID blocks, use is already 1 (fake user), 00111 * but RNA pointer use also increases user, so this compensates it 00112 */ 00113 action->id.us--; 00114 00115 RNA_id_pointer_create(&action->id, &idptr); 00116 RNA_property_pointer_set(&ptr, prop, idptr); 00117 RNA_property_update(C, &ptr, prop); 00118 } 00119 00120 /* set notifier that keyframes have changed */ 00121 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 00122 00123 return OPERATOR_FINISHED; 00124 } 00125 00126 void ACTION_OT_new (wmOperatorType *ot) 00127 { 00128 /* identifiers */ 00129 ot->name= "New Action"; 00130 ot->idname= "ACTION_OT_new"; 00131 ot->description= "Create new action"; 00132 00133 /* api callbacks */ 00134 ot->exec= act_new_exec; 00135 // NOTE: this is used in the NLA too... 00136 //ot->poll= ED_operator_action_active; 00137 00138 /* flags */ 00139 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00140 } 00141 00142 /* ************************************************************************** */ 00143 /* POSE MARKERS STUFF */ 00144 00145 /* *************************** Localise Markers ***************************** */ 00146 00147 /* ensure that there is: 00148 * 1) an active action editor 00149 * 2) that the mode will have an active action available 00150 * 3) that the set of markers being shown are the scene markers, not the list we're merging 00151 * 4) that there are some selected markers 00152 */ 00153 static int act_markers_make_local_poll(bContext *C) 00154 { 00155 SpaceAction *sact = CTX_wm_space_action(C); 00156 00157 /* 1) */ 00158 if (sact == NULL) 00159 return 0; 00160 00161 /* 2) */ 00162 if (ELEM(sact->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) == 0) 00163 return 0; 00164 if (sact->action == NULL) 00165 return 0; 00166 00167 /* 3) */ 00168 if (sact->flag & SACTION_POSEMARKERS_SHOW) 00169 return 0; 00170 00171 /* 4) */ 00172 return ED_markers_get_first_selected(ED_context_get_markers(C)) != NULL; 00173 } 00174 00175 static int act_markers_make_local_exec (bContext *C, wmOperator *UNUSED(op)) 00176 { 00177 ListBase *markers = ED_context_get_markers(C); 00178 00179 SpaceAction *sact = CTX_wm_space_action(C); 00180 bAction *act = (sact)? sact->action : NULL; 00181 00182 TimeMarker *marker, *markern=NULL; 00183 00184 /* sanity checks */ 00185 if (ELEM(NULL, markers, act)) 00186 return OPERATOR_CANCELLED; 00187 00188 /* migrate markers */ 00189 for (marker = markers->first; marker; marker = markern) { 00190 markern = marker->next; 00191 00192 /* move if marker is selected */ 00193 if (marker->flag & SELECT) { 00194 BLI_remlink(markers, marker); 00195 BLI_addtail(&act->markers, marker); 00196 } 00197 } 00198 00199 /* now enable the "show posemarkers only" setting, so that we can see that something did happen */ 00200 sact->flag |= SACTION_POSEMARKERS_SHOW; 00201 00202 /* notifiers - both sets, as this change affects both */ 00203 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); 00204 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); 00205 00206 return OPERATOR_FINISHED; 00207 } 00208 00209 void ACTION_OT_markers_make_local (wmOperatorType *ot) 00210 { 00211 /* identifiers */ 00212 ot->name= "Make Markers Local"; 00213 ot->idname= "ACTION_OT_markers_make_local"; 00214 ot->description= "Move selected scene markers to the active Action as local 'pose' markers"; 00215 00216 /* callbacks */ 00217 ot->exec = act_markers_make_local_exec; 00218 ot->poll = act_markers_make_local_poll; 00219 00220 /* flags */ 00221 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00222 } 00223 00224 /* ************************************************************************** */ 00225 /* KEYFRAME-RANGE STUFF */ 00226 00227 /* *************************** Calculate Range ************************** */ 00228 00229 /* Get the min/max keyframes*/ 00230 static void get_keyframe_extents (bAnimContext *ac, float *min, float *max, const short onlySel) 00231 { 00232 ListBase anim_data = {NULL, NULL}; 00233 bAnimListElem *ale; 00234 int filter; 00235 00236 /* get data to filter, from Action or Dopesheet */ 00237 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00238 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00239 00240 /* set large values to try to override */ 00241 *min= 999999999.0f; 00242 *max= -999999999.0f; 00243 00244 /* check if any channels to set range with */ 00245 if (anim_data.first) { 00246 /* go through channels, finding max extents */ 00247 for (ale= anim_data.first; ale; ale= ale->next) { 00248 AnimData *adt= ANIM_nla_mapping_get(ac, ale); 00249 FCurve *fcu= (FCurve *)ale->key_data; 00250 float tmin, tmax; 00251 00252 /* get range and apply necessary scaling before processing */ 00253 calc_fcurve_range(fcu, &tmin, &tmax, onlySel); 00254 00255 if (adt) { 00256 tmin= BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP); 00257 tmax= BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP); 00258 } 00259 00260 /* try to set cur using these values, if they're more extreme than previously set values */ 00261 *min= MIN2(*min, tmin); 00262 *max= MAX2(*max, tmax); 00263 } 00264 00265 /* free memory */ 00266 BLI_freelistN(&anim_data); 00267 } 00268 else { 00269 /* set default range */ 00270 if (ac->scene) { 00271 *min= (float)ac->scene->r.sfra; 00272 *max= (float)ac->scene->r.efra; 00273 } 00274 else { 00275 *min= -5; 00276 *max= 100; 00277 } 00278 } 00279 } 00280 00281 /* ****************** Automatic Preview-Range Operator ****************** */ 00282 00283 static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op)) 00284 { 00285 bAnimContext ac; 00286 Scene *scene; 00287 float min, max; 00288 00289 /* get editor data */ 00290 if (ANIM_animdata_get_context(C, &ac) == 0) 00291 return OPERATOR_CANCELLED; 00292 if (ac.scene == NULL) 00293 return OPERATOR_CANCELLED; 00294 else 00295 scene= ac.scene; 00296 00297 /* set the range directly */ 00298 get_keyframe_extents(&ac, &min, &max, FALSE); 00299 scene->r.flag |= SCER_PRV_RANGE; 00300 scene->r.psfra= (int)floor(min + 0.5f); 00301 scene->r.pefra= (int)floor(max + 0.5f); 00302 00303 /* set notifier that things have changed */ 00304 // XXX err... there's nothing for frame ranges yet, but this should do fine too 00305 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene); 00306 00307 return OPERATOR_FINISHED; 00308 } 00309 00310 void ACTION_OT_previewrange_set (wmOperatorType *ot) 00311 { 00312 /* identifiers */ 00313 ot->name= "Auto-Set Preview Range"; 00314 ot->idname= "ACTION_OT_previewrange_set"; 00315 ot->description= "Set Preview Range based on extents of selected Keyframes"; 00316 00317 /* api callbacks */ 00318 ot->exec= actkeys_previewrange_exec; 00319 ot->poll= ED_operator_action_active; 00320 00321 /* flags */ 00322 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00323 } 00324 00325 /* ****************** View-All Operator ****************** */ 00326 00327 static int actkeys_viewall(bContext *C, const short onlySel) 00328 { 00329 bAnimContext ac; 00330 View2D *v2d; 00331 float extra; 00332 00333 /* get editor data */ 00334 if (ANIM_animdata_get_context(C, &ac) == 0) 00335 return OPERATOR_CANCELLED; 00336 v2d= &ac.ar->v2d; 00337 00338 /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ 00339 get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, onlySel); 00340 00341 extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin); 00342 v2d->cur.xmin -= extra; 00343 v2d->cur.xmax += extra; 00344 00345 /* set vertical range */ 00346 v2d->cur.ymax= 0.0f; 00347 v2d->cur.ymin= (float)-(v2d->mask.ymax - v2d->mask.ymin); 00348 00349 /* do View2D syncing */ 00350 UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); 00351 00352 /* just redraw this view */ 00353 ED_area_tag_redraw(CTX_wm_area(C)); 00354 00355 return OPERATOR_FINISHED; 00356 } 00357 00358 /* ......... */ 00359 00360 static int actkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op)) 00361 { 00362 /* whole range */ 00363 return actkeys_viewall(C, FALSE); 00364 } 00365 00366 static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) 00367 { 00368 /* only selected */ 00369 return actkeys_viewall(C, TRUE); 00370 } 00371 00372 void ACTION_OT_view_all (wmOperatorType *ot) 00373 { 00374 /* identifiers */ 00375 ot->name= "View All"; 00376 ot->idname= "ACTION_OT_view_all"; 00377 ot->description= "Reset viewable area to show full keyframe range"; 00378 00379 /* api callbacks */ 00380 ot->exec= actkeys_viewall_exec; 00381 ot->poll= ED_operator_action_active; 00382 00383 /* flags */ 00384 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00385 } 00386 00387 void ACTION_OT_view_selected (wmOperatorType *ot) 00388 { 00389 /* identifiers */ 00390 ot->name= "View Selected"; 00391 ot->idname= "ACTION_OT_view_selected"; 00392 ot->description= "Reset viewable area to show selected keyframes range"; 00393 00394 /* api callbacks */ 00395 ot->exec= actkeys_viewsel_exec; 00396 ot->poll= ED_operator_action_active; 00397 00398 /* flags */ 00399 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00400 } 00401 00402 /* ************************************************************************** */ 00403 /* GENERAL STUFF */ 00404 00405 /* ******************** Copy/Paste Keyframes Operator ************************* */ 00406 /* NOTE: the backend code for this is shared with the graph editor */ 00407 00408 static short copy_action_keys (bAnimContext *ac) 00409 { 00410 ListBase anim_data = {NULL, NULL}; 00411 int filter, ok=0; 00412 00413 /* clear buffer first */ 00414 free_anim_copybuf(); 00415 00416 /* filter data */ 00417 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00418 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00419 00420 /* copy keyframes */ 00421 ok= copy_animedit_keys(ac, &anim_data); 00422 00423 /* clean up */ 00424 BLI_freelistN(&anim_data); 00425 00426 return ok; 00427 } 00428 00429 00430 static short paste_action_keys (bAnimContext *ac, 00431 const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode) 00432 { 00433 ListBase anim_data = {NULL, NULL}; 00434 int filter, ok=0; 00435 00436 /* filter data */ 00437 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00438 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00439 00440 /* paste keyframes */ 00441 ok= paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode); 00442 00443 /* clean up */ 00444 BLI_freelistN(&anim_data); 00445 00446 return ok; 00447 } 00448 00449 /* ------------------- */ 00450 00451 static int actkeys_copy_exec(bContext *C, wmOperator *op) 00452 { 00453 bAnimContext ac; 00454 00455 /* get editor data */ 00456 if (ANIM_animdata_get_context(C, &ac) == 0) 00457 return OPERATOR_CANCELLED; 00458 00459 /* copy keyframes */ 00460 if (ac.datatype == ANIMCONT_GPENCIL) { 00461 // FIXME... 00462 } 00463 else { 00464 if (copy_action_keys(&ac)) { 00465 BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); 00466 return OPERATOR_CANCELLED; 00467 } 00468 } 00469 00470 return OPERATOR_FINISHED; 00471 } 00472 00473 void ACTION_OT_copy (wmOperatorType *ot) 00474 { 00475 /* identifiers */ 00476 ot->name= "Copy Keyframes"; 00477 ot->idname= "ACTION_OT_copy"; 00478 ot->description= "Copy selected keyframes to the copy/paste buffer"; 00479 00480 /* api callbacks */ 00481 // ot->invoke= WM_operator_props_popup; // better wait for graph redo panel 00482 ot->exec= actkeys_copy_exec; 00483 ot->poll= ED_operator_action_active; 00484 00485 /* flags */ 00486 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00487 } 00488 00489 static int actkeys_paste_exec(bContext *C, wmOperator *op) 00490 { 00491 bAnimContext ac; 00492 00493 const eKeyPasteOffset offset_mode= RNA_enum_get(op->ptr, "offset"); 00494 const eKeyMergeMode merge_mode= RNA_enum_get(op->ptr, "merge"); 00495 00496 /* get editor data */ 00497 if (ANIM_animdata_get_context(C, &ac) == 0) 00498 return OPERATOR_CANCELLED; 00499 00500 if(ac.reports==NULL) { 00501 ac.reports= op->reports; 00502 } 00503 00504 /* paste keyframes */ 00505 if (ac.datatype == ANIMCONT_GPENCIL) { 00506 // FIXME... 00507 } 00508 else { 00509 if (paste_action_keys(&ac, offset_mode, merge_mode)) { 00510 BKE_report(op->reports, RPT_ERROR, "No keyframes to paste"); 00511 return OPERATOR_CANCELLED; 00512 } 00513 } 00514 00515 /* validate keyframes after editing */ 00516 ANIM_editkeyframes_refresh(&ac); 00517 00518 /* set notifier that keyframes have changed */ 00519 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 00520 00521 return OPERATOR_FINISHED; 00522 } 00523 00524 void ACTION_OT_paste (wmOperatorType *ot) 00525 { 00526 /* identifiers */ 00527 ot->name= "Paste Keyframes"; 00528 ot->idname= "ACTION_OT_paste"; 00529 ot->description= "Paste keyframes from copy/paste buffer for the selected channels, starting on the current frame"; 00530 00531 /* api callbacks */ 00532 ot->exec= actkeys_paste_exec; 00533 ot->poll= ED_operator_action_active; 00534 00535 /* flags */ 00536 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00537 00538 RNA_def_enum(ot->srna, "offset", keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys"); 00539 RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merking pasted keys and existing"); 00540 } 00541 00542 /* ******************** Insert Keyframes Operator ************************* */ 00543 00544 /* defines for insert keyframes tool */ 00545 static EnumPropertyItem prop_actkeys_insertkey_types[] = { 00546 {1, "ALL", 0, "All Channels", ""}, 00547 {2, "SEL", 0, "Only Selected Channels", ""}, 00548 {3, "GROUP", 0, "In Active Group", ""}, // xxx not in all cases 00549 {0, NULL, 0, NULL, NULL} 00550 }; 00551 00552 /* this function is responsible for snapping keyframes to frame-times */ 00553 static void insert_action_keys(bAnimContext *ac, short mode) 00554 { 00555 ListBase anim_data = {NULL, NULL}; 00556 bAnimListElem *ale; 00557 int filter; 00558 00559 ReportList *reports = ac->reports; 00560 Scene *scene= ac->scene; 00561 short flag = 0; 00562 00563 /* filter data */ 00564 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00565 if (mode == 2) filter |= ANIMFILTER_SEL; 00566 else if (mode == 3) filter |= ANIMFILTER_ACTGROUPED; 00567 00568 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00569 00570 /* init keyframing flag */ 00571 flag = ANIM_get_keyframing_flags(scene, 1); 00572 00573 /* insert keyframes */ 00574 for (ale= anim_data.first; ale; ale= ale->next) { 00575 AnimData *adt= ANIM_nla_mapping_get(ac, ale); 00576 FCurve *fcu= (FCurve *)ale->key_data; 00577 float cfra; 00578 00579 /* adjust current frame for NLA-scaling */ 00580 if (adt) 00581 cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); 00582 else 00583 cfra= (float)CFRA; 00584 00585 /* if there's an id */ 00586 if (ale->id) 00587 insert_keyframe(reports, ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); 00588 else 00589 insert_vert_fcurve(fcu, cfra, fcu->curval, 0); 00590 } 00591 00592 BLI_freelistN(&anim_data); 00593 } 00594 00595 /* ------------------- */ 00596 00597 static int actkeys_insertkey_exec(bContext *C, wmOperator *op) 00598 { 00599 bAnimContext ac; 00600 short mode; 00601 00602 /* get editor data */ 00603 if (ANIM_animdata_get_context(C, &ac) == 0) 00604 return OPERATOR_CANCELLED; 00605 if (ac.datatype == ANIMCONT_GPENCIL) 00606 return OPERATOR_CANCELLED; 00607 00608 /* what channels to affect? */ 00609 mode= RNA_enum_get(op->ptr, "type"); 00610 00611 /* insert keyframes */ 00612 insert_action_keys(&ac, mode); 00613 00614 /* validate keyframes after editing */ 00615 ANIM_editkeyframes_refresh(&ac); 00616 00617 /* set notifier that keyframes have changed */ 00618 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 00619 00620 return OPERATOR_FINISHED; 00621 } 00622 00623 void ACTION_OT_keyframe_insert (wmOperatorType *ot) 00624 { 00625 /* identifiers */ 00626 ot->name= "Insert Keyframes"; 00627 ot->idname= "ACTION_OT_keyframe_insert"; 00628 ot->description= "Insert keyframes for the specified channels"; 00629 00630 /* api callbacks */ 00631 ot->invoke= WM_menu_invoke; 00632 ot->exec= actkeys_insertkey_exec; 00633 ot->poll= ED_operator_action_active; 00634 00635 /* flags */ 00636 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00637 00638 /* id-props */ 00639 ot->prop= RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", ""); 00640 } 00641 00642 /* ******************** Duplicate Keyframes Operator ************************* */ 00643 00644 static void duplicate_action_keys (bAnimContext *ac) 00645 { 00646 ListBase anim_data = {NULL, NULL}; 00647 bAnimListElem *ale; 00648 int filter; 00649 00650 /* filter data */ 00651 if (ac->datatype == ANIMCONT_GPENCIL) 00652 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); 00653 else 00654 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00655 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00656 00657 /* loop through filtered data and delete selected keys */ 00658 for (ale= anim_data.first; ale; ale= ale->next) { 00659 if (ale->type == ANIMTYPE_FCURVE) 00660 duplicate_fcurve_keys((FCurve *)ale->key_data); 00661 else 00662 duplicate_gplayer_frames((bGPDlayer *)ale->data); 00663 } 00664 00665 /* free filtered list */ 00666 BLI_freelistN(&anim_data); 00667 } 00668 00669 /* ------------------- */ 00670 00671 static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) 00672 { 00673 bAnimContext ac; 00674 00675 /* get editor data */ 00676 if (ANIM_animdata_get_context(C, &ac) == 0) 00677 return OPERATOR_CANCELLED; 00678 00679 /* duplicate keyframes */ 00680 duplicate_action_keys(&ac); 00681 00682 /* validate keyframes after editing */ 00683 ANIM_editkeyframes_refresh(&ac); 00684 00685 /* set notifier that keyframes have changed */ 00686 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 00687 00688 return OPERATOR_FINISHED; // xxx - start transform 00689 } 00690 00691 static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00692 { 00693 actkeys_duplicate_exec(C, op); 00694 00695 return OPERATOR_FINISHED; 00696 } 00697 00698 void ACTION_OT_duplicate (wmOperatorType *ot) 00699 { 00700 /* identifiers */ 00701 ot->name= "Duplicate Keyframes"; 00702 ot->idname= "ACTION_OT_duplicate"; 00703 ot->description= "Make a copy of all selected keyframes"; 00704 00705 /* api callbacks */ 00706 ot->invoke= actkeys_duplicate_invoke; 00707 ot->exec= actkeys_duplicate_exec; 00708 ot->poll= ED_operator_action_active; 00709 00710 /* flags */ 00711 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00712 00713 /* to give to transform */ 00714 RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", ""); 00715 } 00716 00717 /* ******************** Delete Keyframes Operator ************************* */ 00718 00719 static void delete_action_keys (bAnimContext *ac) 00720 { 00721 ListBase anim_data = {NULL, NULL}; 00722 bAnimListElem *ale; 00723 int filter; 00724 00725 /* filter data */ 00726 if (ac->datatype == ANIMCONT_GPENCIL) 00727 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); 00728 else 00729 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00730 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00731 00732 /* loop through filtered data and delete selected keys */ 00733 for (ale= anim_data.first; ale; ale= ale->next) { 00734 if (ale->type != ANIMTYPE_GPLAYER) { 00735 FCurve *fcu= (FCurve *)ale->key_data; 00736 AnimData *adt= ale->adt; 00737 00738 /* delete selected keyframes only */ 00739 delete_fcurve_keys(fcu); 00740 00741 /* Only delete curve too if it won't be doing anything anymore */ 00742 if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) 00743 ANIM_fcurve_delete_from_animdata(ac, adt, fcu); 00744 } 00745 else 00746 delete_gplayer_frames((bGPDlayer *)ale->data); 00747 } 00748 00749 /* free filtered list */ 00750 BLI_freelistN(&anim_data); 00751 } 00752 00753 /* ------------------- */ 00754 00755 static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op)) 00756 { 00757 bAnimContext ac; 00758 00759 /* get editor data */ 00760 if (ANIM_animdata_get_context(C, &ac) == 0) 00761 return OPERATOR_CANCELLED; 00762 00763 /* delete keyframes */ 00764 delete_action_keys(&ac); 00765 00766 /* validate keyframes after editing */ 00767 ANIM_editkeyframes_refresh(&ac); 00768 00769 /* set notifier that keyframes have changed */ 00770 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 00771 00772 return OPERATOR_FINISHED; 00773 } 00774 00775 void ACTION_OT_delete (wmOperatorType *ot) 00776 { 00777 /* identifiers */ 00778 ot->name= "Delete Keyframes"; 00779 ot->idname= "ACTION_OT_delete"; 00780 ot->description= "Remove all selected keyframes"; 00781 00782 /* api callbacks */ 00783 ot->invoke= WM_operator_confirm; 00784 ot->exec= actkeys_delete_exec; 00785 ot->poll= ED_operator_action_active; 00786 00787 /* flags */ 00788 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00789 } 00790 00791 /* ******************** Clean Keyframes Operator ************************* */ 00792 00793 static void clean_action_keys (bAnimContext *ac, float thresh) 00794 { 00795 ListBase anim_data = {NULL, NULL}; 00796 bAnimListElem *ale; 00797 int filter; 00798 00799 /* filter data */ 00800 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00801 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00802 00803 /* loop through filtered data and clean curves */ 00804 for (ale= anim_data.first; ale; ale= ale->next) 00805 clean_fcurve((FCurve *)ale->key_data, thresh); 00806 00807 /* free temp data */ 00808 BLI_freelistN(&anim_data); 00809 } 00810 00811 /* ------------------- */ 00812 00813 static int actkeys_clean_exec(bContext *C, wmOperator *op) 00814 { 00815 bAnimContext ac; 00816 float thresh; 00817 00818 /* get editor data */ 00819 if (ANIM_animdata_get_context(C, &ac) == 0) 00820 return OPERATOR_CANCELLED; 00821 if (ac.datatype == ANIMCONT_GPENCIL) 00822 return OPERATOR_PASS_THROUGH; 00823 00824 /* get cleaning threshold */ 00825 thresh= RNA_float_get(op->ptr, "threshold"); 00826 00827 /* clean keyframes */ 00828 clean_action_keys(&ac, thresh); 00829 00830 /* validate keyframes after editing */ 00831 ANIM_editkeyframes_refresh(&ac); 00832 00833 /* set notifier that keyframes have changed */ 00834 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 00835 00836 return OPERATOR_FINISHED; 00837 } 00838 00839 void ACTION_OT_clean (wmOperatorType *ot) 00840 { 00841 /* identifiers */ 00842 ot->name= "Clean Keyframes"; 00843 ot->idname= "ACTION_OT_clean"; 00844 ot->description= "Simplify F-Curves by removing closely spaced keyframes"; 00845 00846 /* api callbacks */ 00847 //ot->invoke= // XXX we need that number popup for this! 00848 ot->exec= actkeys_clean_exec; 00849 ot->poll= ED_operator_action_active; 00850 00851 /* flags */ 00852 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00853 00854 /* properties */ 00855 ot->prop= RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f); 00856 } 00857 00858 /* ******************** Sample Keyframes Operator *********************** */ 00859 00860 /* Evaluates the curves between each selected keyframe on each frame, and keys the value */ 00861 static void sample_action_keys (bAnimContext *ac) 00862 { 00863 ListBase anim_data = {NULL, NULL}; 00864 bAnimListElem *ale; 00865 int filter; 00866 00867 /* filter data */ 00868 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00869 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00870 00871 /* loop through filtered data and add keys between selected keyframes on every frame */ 00872 for (ale= anim_data.first; ale; ale= ale->next) 00873 sample_fcurve((FCurve *)ale->key_data); 00874 00875 /* admin and redraws */ 00876 BLI_freelistN(&anim_data); 00877 } 00878 00879 /* ------------------- */ 00880 00881 static int actkeys_sample_exec(bContext *C, wmOperator *UNUSED(op)) 00882 { 00883 bAnimContext ac; 00884 00885 /* get editor data */ 00886 if (ANIM_animdata_get_context(C, &ac) == 0) 00887 return OPERATOR_CANCELLED; 00888 if (ac.datatype == ANIMCONT_GPENCIL) 00889 return OPERATOR_PASS_THROUGH; 00890 00891 /* sample keyframes */ 00892 sample_action_keys(&ac); 00893 00894 /* validate keyframes after editing */ 00895 ANIM_editkeyframes_refresh(&ac); 00896 00897 /* set notifier that keyframes have changed */ 00898 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 00899 00900 return OPERATOR_FINISHED; 00901 } 00902 00903 void ACTION_OT_sample (wmOperatorType *ot) 00904 { 00905 /* identifiers */ 00906 ot->name= "Sample Keyframes"; 00907 ot->idname= "ACTION_OT_sample"; 00908 ot->description= "Add keyframes on every frame between the selected keyframes"; 00909 00910 /* api callbacks */ 00911 ot->exec= actkeys_sample_exec; 00912 ot->poll= ED_operator_action_active; 00913 00914 /* flags */ 00915 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00916 } 00917 00918 /* ************************************************************************** */ 00919 /* SETTINGS STUFF */ 00920 00921 /* ******************** Set Extrapolation-Type Operator *********************** */ 00922 00923 /* defines for set extrapolation-type for selected keyframes tool */ 00924 static EnumPropertyItem prop_actkeys_expo_types[] = { 00925 {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", ""}, 00926 {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", ""}, 00927 {0, NULL, 0, NULL, NULL} 00928 }; 00929 00930 /* this function is responsible for setting extrapolation mode for keyframes */ 00931 static void setexpo_action_keys(bAnimContext *ac, short mode) 00932 { 00933 ListBase anim_data = {NULL, NULL}; 00934 bAnimListElem *ale; 00935 int filter; 00936 00937 /* filter data */ 00938 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 00939 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00940 00941 /* loop through setting mode per F-Curve */ 00942 for (ale= anim_data.first; ale; ale= ale->next) { 00943 FCurve *fcu= (FCurve *)ale->data; 00944 fcu->extend= mode; 00945 } 00946 00947 /* cleanup */ 00948 BLI_freelistN(&anim_data); 00949 } 00950 00951 /* ------------------- */ 00952 00953 static int actkeys_expo_exec(bContext *C, wmOperator *op) 00954 { 00955 bAnimContext ac; 00956 short mode; 00957 00958 /* get editor data */ 00959 if (ANIM_animdata_get_context(C, &ac) == 0) 00960 return OPERATOR_CANCELLED; 00961 if (ac.datatype == ANIMCONT_GPENCIL) 00962 return OPERATOR_PASS_THROUGH; 00963 00964 /* get handle setting mode */ 00965 mode= RNA_enum_get(op->ptr, "type"); 00966 00967 /* set handle type */ 00968 setexpo_action_keys(&ac, mode); 00969 00970 /* validate keyframes after editing */ 00971 ANIM_editkeyframes_refresh(&ac); 00972 00973 /* set notifier that keyframe properties have changed */ 00974 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); 00975 00976 return OPERATOR_FINISHED; 00977 } 00978 00979 void ACTION_OT_extrapolation_type (wmOperatorType *ot) 00980 { 00981 /* identifiers */ 00982 ot->name= "Set Keyframe Extrapolation"; 00983 ot->idname= "ACTION_OT_extrapolation_type"; 00984 ot->description= "Set extrapolation mode for selected F-Curves"; 00985 00986 /* api callbacks */ 00987 ot->invoke= WM_menu_invoke; 00988 ot->exec= actkeys_expo_exec; 00989 ot->poll= ED_operator_action_active; 00990 00991 /* flags */ 00992 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00993 00994 /* id-props */ 00995 ot->prop= RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", ""); 00996 } 00997 00998 /* ******************** Set Interpolation-Type Operator *********************** */ 00999 01000 /* this function is responsible for setting interpolation mode for keyframes */ 01001 static void setipo_action_keys(bAnimContext *ac, short mode) 01002 { 01003 ListBase anim_data = {NULL, NULL}; 01004 bAnimListElem *ale; 01005 int filter; 01006 KeyframeEditFunc set_cb= ANIM_editkeyframes_ipo(mode); 01007 01008 /* filter data */ 01009 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 01010 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 01011 01012 /* loop through setting BezTriple interpolation 01013 * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... 01014 */ 01015 for (ale= anim_data.first; ale; ale= ale->next) 01016 ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve); 01017 01018 /* cleanup */ 01019 BLI_freelistN(&anim_data); 01020 } 01021 01022 /* ------------------- */ 01023 01024 static int actkeys_ipo_exec(bContext *C, wmOperator *op) 01025 { 01026 bAnimContext ac; 01027 short mode; 01028 01029 /* get editor data */ 01030 if (ANIM_animdata_get_context(C, &ac) == 0) 01031 return OPERATOR_CANCELLED; 01032 if (ac.datatype == ANIMCONT_GPENCIL) 01033 return OPERATOR_PASS_THROUGH; 01034 01035 /* get handle setting mode */ 01036 mode= RNA_enum_get(op->ptr, "type"); 01037 01038 /* set handle type */ 01039 setipo_action_keys(&ac, mode); 01040 01041 /* validate keyframes after editing */ 01042 ANIM_editkeyframes_refresh(&ac); 01043 01044 /* set notifier that keyframe properties have changed */ 01045 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); 01046 01047 return OPERATOR_FINISHED; 01048 } 01049 01050 void ACTION_OT_interpolation_type (wmOperatorType *ot) 01051 { 01052 /* identifiers */ 01053 ot->name= "Set Keyframe Interpolation"; 01054 ot->idname= "ACTION_OT_interpolation_type"; 01055 ot->description= "Set interpolation mode for the F-Curve segments starting from the selected keyframes"; 01056 01057 /* api callbacks */ 01058 ot->invoke= WM_menu_invoke; 01059 ot->exec= actkeys_ipo_exec; 01060 ot->poll= ED_operator_action_active; 01061 01062 /* flags */ 01063 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01064 01065 /* id-props */ 01066 ot->prop= RNA_def_enum(ot->srna, "type", beztriple_interpolation_mode_items, 0, "Type", ""); 01067 } 01068 01069 /* ******************** Set Handle-Type Operator *********************** */ 01070 01071 static EnumPropertyItem actkeys_handle_type_items[] = { 01072 {HD_FREE, "FREE", 0, "Free", ""}, 01073 {HD_VECT, "VECTOR", 0, "Vector", ""}, 01074 {HD_ALIGN, "ALIGNED", 0, "Aligned", ""}, 01075 {0, "", 0, "", ""}, 01076 {HD_AUTO, "AUTO", 0, "Auto", "Handles that are automatically adjusted upon moving the keyframe"}, 01077 {HD_AUTO_ANIM, "ANIM_CLAMPED", 0, "Auto Clamped", "Auto handles clamped to not overshoot"}, 01078 {0, NULL, 0, NULL, NULL}}; 01079 01080 /* ------------------- */ 01081 01082 /* this function is responsible for setting handle-type of selected keyframes */ 01083 static void sethandles_action_keys(bAnimContext *ac, short mode) 01084 { 01085 ListBase anim_data = {NULL, NULL}; 01086 bAnimListElem *ale; 01087 int filter; 01088 01089 KeyframeEditFunc edit_cb= ANIM_editkeyframes_handles(mode); 01090 KeyframeEditFunc sel_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED); 01091 01092 /* filter data */ 01093 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 01094 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 01095 01096 /* loop through setting flags for handles 01097 * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... 01098 */ 01099 for (ale= anim_data.first; ale; ale= ale->next) { 01100 FCurve *fcu= (FCurve *)ale->key_data; 01101 01102 /* any selected keyframes for editing? */ 01103 if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) { 01104 /* for auto/auto-clamped, toggle the auto-handles flag on the F-Curve */ 01105 if (mode == HD_AUTO_ANIM) 01106 fcu->flag |= FCURVE_AUTO_HANDLES; 01107 else if (mode == HD_AUTO) 01108 fcu->flag &= ~FCURVE_AUTO_HANDLES; 01109 01110 /* change type of selected handles */ 01111 ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, edit_cb, calchandles_fcurve); 01112 } 01113 } 01114 01115 /* cleanup */ 01116 BLI_freelistN(&anim_data); 01117 } 01118 01119 /* ------------------- */ 01120 01121 static int actkeys_handletype_exec(bContext *C, wmOperator *op) 01122 { 01123 bAnimContext ac; 01124 short mode; 01125 01126 /* get editor data */ 01127 if (ANIM_animdata_get_context(C, &ac) == 0) 01128 return OPERATOR_CANCELLED; 01129 if (ac.datatype == ANIMCONT_GPENCIL) 01130 return OPERATOR_PASS_THROUGH; 01131 01132 /* get handle setting mode */ 01133 mode= RNA_enum_get(op->ptr, "type"); 01134 01135 /* set handle type */ 01136 sethandles_action_keys(&ac, mode); 01137 01138 /* validate keyframes after editing */ 01139 ANIM_editkeyframes_refresh(&ac); 01140 01141 /* set notifier that keyframe properties have changed */ 01142 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); 01143 01144 return OPERATOR_FINISHED; 01145 } 01146 01147 void ACTION_OT_handle_type (wmOperatorType *ot) 01148 { 01149 /* identifiers */ 01150 ot->name= "Set Keyframe Handle Type"; 01151 ot->idname= "ACTION_OT_handle_type"; 01152 ot->description= "Set type of handle for selected keyframes"; 01153 01154 /* api callbacks */ 01155 ot->invoke= WM_menu_invoke; 01156 ot->exec= actkeys_handletype_exec; 01157 ot->poll= ED_operator_action_active; 01158 01159 /* flags */ 01160 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01161 01162 /* id-props */ 01163 ot->prop= RNA_def_enum(ot->srna, "type", actkeys_handle_type_items, 0, "Type", ""); 01164 } 01165 01166 /* ******************** Set Keyframe-Type Operator *********************** */ 01167 01168 /* this function is responsible for setting interpolation mode for keyframes */ 01169 static void setkeytype_action_keys(bAnimContext *ac, short mode) 01170 { 01171 ListBase anim_data = {NULL, NULL}; 01172 bAnimListElem *ale; 01173 int filter; 01174 KeyframeEditFunc set_cb= ANIM_editkeyframes_keytype(mode); 01175 01176 /* filter data */ 01177 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 01178 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 01179 01180 /* loop through setting BezTriple interpolation 01181 * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... 01182 */ 01183 for (ale= anim_data.first; ale; ale= ale->next) 01184 ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, NULL); 01185 01186 /* cleanup */ 01187 BLI_freelistN(&anim_data); 01188 } 01189 01190 /* ------------------- */ 01191 01192 static int actkeys_keytype_exec(bContext *C, wmOperator *op) 01193 { 01194 bAnimContext ac; 01195 short mode; 01196 01197 /* get editor data */ 01198 if (ANIM_animdata_get_context(C, &ac) == 0) 01199 return OPERATOR_CANCELLED; 01200 if (ac.datatype == ANIMCONT_GPENCIL) 01201 return OPERATOR_PASS_THROUGH; 01202 01203 /* get handle setting mode */ 01204 mode= RNA_enum_get(op->ptr, "type"); 01205 01206 /* set handle type */ 01207 setkeytype_action_keys(&ac, mode); 01208 01209 /* validate keyframes after editing */ 01210 ANIM_editkeyframes_refresh(&ac); 01211 01212 /* set notifier that keyframe properties have changed */ 01213 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); 01214 01215 return OPERATOR_FINISHED; 01216 } 01217 01218 void ACTION_OT_keyframe_type (wmOperatorType *ot) 01219 { 01220 /* identifiers */ 01221 ot->name= "Set Keyframe Type"; 01222 ot->idname= "ACTION_OT_keyframe_type"; 01223 ot->description= "Set type of keyframe for the selected keyframes"; 01224 01225 /* api callbacks */ 01226 ot->invoke= WM_menu_invoke; 01227 ot->exec= actkeys_keytype_exec; 01228 ot->poll= ED_operator_action_active; 01229 01230 /* flags */ 01231 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01232 01233 /* id-props */ 01234 ot->prop= RNA_def_enum(ot->srna, "type", beztriple_keyframe_type_items, 0, "Type", ""); 01235 } 01236 01237 /* ************************************************************************** */ 01238 /* TRANSFORM STUFF */ 01239 01240 /* ***************** Jump to Selected Frames Operator *********************** */ 01241 01242 /* snap current-frame indicator to 'average time' of selected keyframe */ 01243 static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) 01244 { 01245 bAnimContext ac; 01246 ListBase anim_data= {NULL, NULL}; 01247 bAnimListElem *ale; 01248 int filter; 01249 KeyframeEditData ked= {{NULL}}; 01250 01251 /* get editor data */ 01252 if (ANIM_animdata_get_context(C, &ac) == 0) 01253 return OPERATOR_CANCELLED; 01254 01255 /* init edit data */ 01256 /* loop over action data, averaging values */ 01257 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 01258 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 01259 01260 for (ale= anim_data.first; ale; ale= ale->next) { 01261 AnimData *adt= ANIM_nla_mapping_get(&ac, ale); 01262 if (adt) { 01263 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 01264 ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL); 01265 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); 01266 } 01267 else 01268 ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL); 01269 } 01270 01271 BLI_freelistN(&anim_data); 01272 01273 /* set the new current frame value, based on the average time */ 01274 if (ked.i1) { 01275 Scene *scene= ac.scene; 01276 CFRA= (int)floor((ked.f1 / ked.i1) + 0.5f); 01277 SUBFRA= 0.f; 01278 } 01279 01280 /* set notifier that things have changed */ 01281 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene); 01282 01283 return OPERATOR_FINISHED; 01284 } 01285 01286 void ACTION_OT_frame_jump (wmOperatorType *ot) 01287 { 01288 /* identifiers */ 01289 ot->name= "Jump to Frame"; 01290 ot->idname= "ACTION_OT_frame_jump"; 01291 ot->description= "Set the current frame to the average frame of the selected keyframes"; 01292 01293 /* api callbacks */ 01294 ot->exec= actkeys_framejump_exec; 01295 ot->poll= ED_operator_action_active; 01296 01297 /* flags */ 01298 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01299 } 01300 01301 /* ******************** Snap Keyframes Operator *********************** */ 01302 01303 /* defines for snap keyframes tool */ 01304 static EnumPropertyItem prop_actkeys_snap_types[] = { 01305 {ACTKEYS_SNAP_CFRA, "CFRA", 0, "Current frame", ""}, 01306 {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry? 01307 {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry? 01308 {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""}, 01309 {0, NULL, 0, NULL, NULL} 01310 }; 01311 01312 /* this function is responsible for snapping keyframes to frame-times */ 01313 static void snap_action_keys(bAnimContext *ac, short mode) 01314 { 01315 ListBase anim_data = {NULL, NULL}; 01316 bAnimListElem *ale; 01317 int filter; 01318 01319 KeyframeEditData ked= {{NULL}}; 01320 KeyframeEditFunc edit_cb; 01321 01322 /* filter data */ 01323 if (ac->datatype == ANIMCONT_GPENCIL) 01324 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT); 01325 else 01326 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 01327 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 01328 01329 /* get beztriple editing callbacks */ 01330 edit_cb= ANIM_editkeyframes_snap(mode); 01331 01332 ked.scene= ac->scene; 01333 if (mode == ACTKEYS_SNAP_NEAREST_MARKER) { 01334 ked.list.first= (ac->markers) ? ac->markers->first : NULL; 01335 ked.list.last= (ac->markers) ? ac->markers->last : NULL; 01336 } 01337 01338 /* snap keyframes */ 01339 for (ale= anim_data.first; ale; ale= ale->next) { 01340 AnimData *adt= ANIM_nla_mapping_get(ac, ale); 01341 01342 if (adt) { 01343 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 01344 ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); 01345 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); 01346 } 01347 //else if (ale->type == ACTTYPE_GPLAYER) 01348 // snap_gplayer_frames(ale->data, mode); 01349 else 01350 ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); 01351 } 01352 01353 BLI_freelistN(&anim_data); 01354 } 01355 01356 /* ------------------- */ 01357 01358 static int actkeys_snap_exec(bContext *C, wmOperator *op) 01359 { 01360 bAnimContext ac; 01361 short mode; 01362 01363 /* get editor data */ 01364 if (ANIM_animdata_get_context(C, &ac) == 0) 01365 return OPERATOR_CANCELLED; 01366 01367 /* get snapping mode */ 01368 mode= RNA_enum_get(op->ptr, "type"); 01369 01370 /* snap keyframes */ 01371 snap_action_keys(&ac, mode); 01372 01373 /* validate keyframes after editing */ 01374 ANIM_editkeyframes_refresh(&ac); 01375 01376 /* set notifier that keyframes have changed */ 01377 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 01378 01379 return OPERATOR_FINISHED; 01380 } 01381 01382 void ACTION_OT_snap (wmOperatorType *ot) 01383 { 01384 /* identifiers */ 01385 ot->name= "Snap Keys"; 01386 ot->idname= "ACTION_OT_snap"; 01387 ot->description= "Snap selected keyframes to the times specified"; 01388 01389 /* api callbacks */ 01390 ot->invoke= WM_menu_invoke; 01391 ot->exec= actkeys_snap_exec; 01392 ot->poll= ED_operator_action_active; 01393 01394 /* flags */ 01395 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01396 01397 /* id-props */ 01398 ot->prop= RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", ""); 01399 } 01400 01401 /* ******************** Mirror Keyframes Operator *********************** */ 01402 01403 /* defines for mirror keyframes tool */ 01404 static EnumPropertyItem prop_actkeys_mirror_types[] = { 01405 {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame", ""}, 01406 {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", ""}, 01407 {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", ""}, 01408 {0, NULL, 0, NULL, NULL} 01409 }; 01410 01411 /* this function is responsible for mirroring keyframes */ 01412 static void mirror_action_keys(bAnimContext *ac, short mode) 01413 { 01414 ListBase anim_data = {NULL, NULL}; 01415 bAnimListElem *ale; 01416 int filter; 01417 01418 KeyframeEditData ked= {{NULL}}; 01419 KeyframeEditFunc edit_cb; 01420 01421 /* get beztriple editing callbacks */ 01422 edit_cb= ANIM_editkeyframes_mirror(mode); 01423 01424 ked.scene= ac->scene; 01425 01426 /* for 'first selected marker' mode, need to find first selected marker first! */ 01427 // XXX should this be made into a helper func in the API? 01428 if (mode == ACTKEYS_MIRROR_MARKER) { 01429 TimeMarker *marker= NULL; 01430 01431 /* find first selected marker */ 01432 marker= ED_markers_get_first_selected(ac->markers); 01433 01434 /* store marker's time (if available) */ 01435 if (marker) 01436 ked.f1= (float)marker->frame; 01437 else 01438 return; 01439 } 01440 01441 /* filter data */ 01442 if (ac->datatype == ANIMCONT_GPENCIL) 01443 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); 01444 else 01445 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); 01446 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 01447 01448 /* mirror keyframes */ 01449 for (ale= anim_data.first; ale; ale= ale->next) { 01450 AnimData *adt= ANIM_nla_mapping_get(ac, ale); 01451 01452 if (adt) { 01453 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 01454 ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); 01455 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); 01456 } 01457 //else if (ale->type == ACTTYPE_GPLAYER) 01458 // snap_gplayer_frames(ale->data, mode); 01459 else 01460 ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); 01461 } 01462 01463 BLI_freelistN(&anim_data); 01464 } 01465 01466 /* ------------------- */ 01467 01468 static int actkeys_mirror_exec(bContext *C, wmOperator *op) 01469 { 01470 bAnimContext ac; 01471 short mode; 01472 01473 /* get editor data */ 01474 if (ANIM_animdata_get_context(C, &ac) == 0) 01475 return OPERATOR_CANCELLED; 01476 01477 /* get mirroring mode */ 01478 mode= RNA_enum_get(op->ptr, "type"); 01479 01480 /* mirror keyframes */ 01481 mirror_action_keys(&ac, mode); 01482 01483 /* validate keyframes after editing */ 01484 ANIM_editkeyframes_refresh(&ac); 01485 01486 /* set notifier that keyframes have changed */ 01487 WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 01488 01489 return OPERATOR_FINISHED; 01490 } 01491 01492 void ACTION_OT_mirror (wmOperatorType *ot) 01493 { 01494 /* identifiers */ 01495 ot->name= "Mirror Keys"; 01496 ot->idname= "ACTION_OT_mirror"; 01497 ot->description= "Flip selected keyframes over the selected mirror line"; 01498 01499 /* api callbacks */ 01500 ot->invoke= WM_menu_invoke; 01501 ot->exec= actkeys_mirror_exec; 01502 ot->poll= ED_operator_action_active; 01503 01504 /* flags */ 01505 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01506 01507 /* id-props */ 01508 ot->prop= RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", ""); 01509 } 01510 01511 /* ************************************************************************** */