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