/* Deselects keyframes in the action editor * - This is called by the deselect all operator, as well as other ones! * * - test: check if select or deselect all * - sel: how to select keyframes (SELECT_*) */ static void deselect_action_keys(bAnimContext *ac, short test, short sel) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; KeyframeEditData ked = {{NULL}}; KeyframeEditFunc test_cb, sel_cb; /* determine type-based settings */ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); /* filter data */ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* init BezTriple looping data */ test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED); /* See if we should be selecting or deselecting */ if (test) { for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { if (ED_gplayer_frame_select_check(ale->data)) { sel = SELECT_SUBTRACT; break; } } else if (ale->type == ANIMTYPE_MASKLAYER) { if (ED_masklayer_frame_select_check(ale->data)) { sel = SELECT_SUBTRACT; break; } } else { if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) { sel = SELECT_SUBTRACT; break; } } } } /* convert sel to selectmode, and use that to get editor */ sel_cb = ANIM_editkeyframes_select(sel); /* Now set the flags */ for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) ED_gplayer_frame_select_set(ale->data, sel); else if (ale->type == ANIMTYPE_MASKLAYER) ED_masklayer_frame_select_set(ale->data, sel); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); } /* Cleanup */ BLI_freelistN(&anim_data); }
/* option 1) select keyframe directly under mouse */ static void mouse_graph_keys (bAnimContext *ac, int mval[], short select_mode, short curves_only) { SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first; tNearestVertInfo *nvi; BezTriple *bezt= NULL; /* find the beztriple that we're selecting, and the handle that was clicked on */ nvi = find_nearest_fcurve_vert(ac, mval); /* check if anything to select */ if (nvi == NULL) return; /* deselect all other curves? */ if (select_mode == SELECT_REPLACE) { /* reset selection mode */ select_mode= SELECT_ADD; /* deselect all other keyframes */ deselect_graph_keys(ac, 0, SELECT_SUBTRACT); /* deselect other channels too, but only only do this if * selection of channel when the visibility of keyframes * doesn't depend on this */ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); } /* if points can be selected on this F-Curve */ // TODO: what about those with no keyframes? if ((curves_only == 0) && ((nvi->fcu->flag & FCURVE_PROTECTED)==0)) { /* only if there's keyframe */ if (nvi->bezt) { bezt= nvi->bezt; /* used to check bezt seletion is set */ /* depends on selection mode */ if (select_mode == SELECT_INVERT) { /* keyframe - invert select of all */ if (nvi->hpoint == NEAREST_HANDLE_KEY) { if (BEZSELECTED(bezt)) { BEZ_DESEL(bezt); } else { BEZ_SEL(bezt); } } /* handles - toggle selection of relevant handle */ else if (nvi->hpoint == NEAREST_HANDLE_LEFT) { /* toggle selection */ bezt->f1 ^= SELECT; } else { /* toggle selection */ bezt->f3 ^= SELECT; } } else { /* if the keyframe was clicked on, select all verts of given beztriple */ if (nvi->hpoint == NEAREST_HANDLE_KEY) { BEZ_SEL(bezt); } /* otherwise, select the handle that applied */ else if (nvi->hpoint == NEAREST_HANDLE_LEFT) bezt->f1 |= SELECT; else bezt->f3 |= SELECT; } } else if (nvi->fpt) { // TODO: need to handle sample points } } else { KeyframeEditFunc select_cb; KeyframeEditData ked; /* initialise keyframe editing data */ memset(&ked, 0, sizeof(KeyframeEditData)); /* set up BezTriple edit callbacks */ select_cb= ANIM_editkeyframes_select(select_mode); /* select all keyframes */ ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL); } /* only change selection of channel when the visibility of keyframes doesn't depend on this */ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { /* select or deselect curve? */ if (bezt) { /* take selection status from item that got hit, to prevent flip/flop on channel * selection status when shift-selecting (i.e. "SELECT_INVERT") points */ if (BEZSELECTED(bezt)) nvi->fcu->flag |= FCURVE_SELECTED; else nvi->fcu->flag &= ~FCURVE_SELECTED; } else { /* didn't hit any channel, so just apply that selection mode to the curve's selection status */ if (select_mode == SELECT_INVERT) nvi->fcu->flag ^= FCURVE_SELECTED; else if (select_mode == SELECT_ADD) nvi->fcu->flag |= FCURVE_SELECTED; } /* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */ if (nvi->fcu->flag & FCURVE_SELECTED) { int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, ANIMTYPE_FCURVE); } } /* free temp sample data for filtering */ MEM_freeN(nvi); }
/* Selects all visible keyframes in the same frames as the specified elements */ static void columnselect_action_keys(bAnimContext *ac, short mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; Scene *scene = ac->scene; CfraElem *ce; KeyframeEditFunc select_cb, ok_cb; KeyframeEditData ked = {{NULL}}; /* initialize keyframe editing data */ /* build list of columns */ switch (mode) { case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */ if (ac->datatype == ANIMCONT_GPENCIL) { filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) ED_gplayer_make_cfra_list(ale->data, &ked.list, 1); } else { filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL); } BLI_freelistN(&anim_data); break; case ACTKEYS_COLUMNSEL_CFRA: /* current frame */ /* make a single CfraElem for storing this */ ce = MEM_callocN(sizeof(CfraElem), "cfraElem"); BLI_addtail(&ked.list, ce); ce->cfra = (float)CFRA; break; case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */ ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT); break; default: /* invalid option */ return; } /* set up BezTriple edit callbacks */ select_cb = ANIM_editkeyframes_select(SELECT_ADD); ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME); /* loop through all of the keys and select additional keyframes * based on the keys found to be selected above */ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* loop over cfraelems (stored in the KeyframeEditData->list) * - we need to do this here, as we can apply fewer NLA-mapping conversions */ for (ce = ked.list.first; ce; ce = ce->next) { /* set frame for validation callback to refer to */ if (adt) ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP); else ked.f1 = ce->cfra; /* select elements with frame number matching cfraelem */ if (ale->type == ANIMTYPE_GPLAYER) ED_gpencil_select_frame(ale->data, ce->cfra, SELECT_ADD); else if (ale->type == ANIMTYPE_MASKLAYER) ED_mask_select_frame(ale->data, ce->cfra, SELECT_ADD); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } } /* free elements */ BLI_freelistN(&ked.list); BLI_freelistN(&anim_data); }
static void actkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; KeyframeEditFunc ok_cb, select_cb; KeyframeEditData ked = {{NULL}}; Scene *scene = ac->scene; /* if select mode is replace, deselect all keyframes (and channels) first */ if (select_mode == SELECT_REPLACE) { select_mode = SELECT_ADD; /* - deselect all other keyframes, so that just the newly selected remain * - channels aren't deselected, since we don't re-select any as a consequence */ deselect_action_keys(ac, 0, SELECT_SUBTRACT); } /* set callbacks and editing data */ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); select_cb = ANIM_editkeyframes_select(select_mode); if (leftright == ACTKEYS_LRSEL_LEFT) { ked.f1 = MINAFRAMEF; ked.f2 = (float)(CFRA + 0.1f); } else { ked.f1 = (float)(CFRA - 0.1f); ked.f2 = MAXFRAMEF; } /* filter data */ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* select keys */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); if (adt) { ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else if (ale->type == ANIMTYPE_GPLAYER) ED_gplayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode); else if (ale->type == ANIMTYPE_MASKLAYER) ED_masklayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } /* Sync marker support */ if (select_mode == SELECT_ADD) { SpaceAction *saction = (SpaceAction *)ac->sl; if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) { ListBase *markers = ED_animcontext_get_markers(ac); TimeMarker *marker; for (marker = markers->first; marker; marker = marker->next) { if (((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < CFRA)) || ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA))) { marker->flag |= SELECT; } else { marker->flag &= ~SELECT; } } } } /* Cleanup */ BLI_freelistN(&anim_data); }
/* Borderselect only selects keyframes now, as overshooting handles often get caught too, * which means that they may be inadvertently moved as well. However, incl_handles overrides * this, and allow handles to be considered independently too. * Also, for convenience, handles should get same status as keyframe (if it was within bounds). */ static void borderselect_graphkeys( bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles, void *data) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter, mapping_flag; SpaceIpo *sipo = (SpaceIpo *)ac->sl; KeyframeEditData ked; KeyframeEditFunc ok_cb, select_cb; View2D *v2d = &ac->ar->v2d; rctf rectf, scaled_rectf; /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */ UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf); /* filter data */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* get beztriple editing/validation funcs */ select_cb = ANIM_editkeyframes_select(selectmode); ok_cb = ANIM_editkeyframes_ok(mode); /* init editing data */ memset(&ked, 0, sizeof(KeyframeEditData)); if (mode == BEZT_OK_REGION_LASSO) { struct KeyframeEdit_LassoData *data_lasso = data; data_lasso->rectf_scaled = &scaled_rectf; ked.data = data_lasso; } else if (mode == BEZT_OK_REGION_CIRCLE) { struct KeyframeEdit_CircleData *data_circle = data; data_circle->rectf_scaled = &scaled_rectf; ked.data = data; } else { ked.data = &scaled_rectf; } /* treat handles separately? */ if (incl_handles) { ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES; mapping_flag = 0; } else mapping_flag = ANIM_UNITCONV_ONLYKEYS; mapping_flag |= ANIM_get_normalization_flags(ac); /* loop over data, doing border select */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); FCurve *fcu = (FCurve *)ale->key_data; float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); /* apply NLA mapping to all the keyframes, since it's easier than trying to * guess when a callback might use something different */ if (adt) ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0); scaled_rectf.xmin = rectf.xmin; scaled_rectf.xmax = rectf.xmax; scaled_rectf.ymin = rectf.ymin / unit_scale; scaled_rectf.ymax = rectf.ymax / unit_scale; /* set horizontal range (if applicable) * NOTE: these values are only used for x-range and y-range but not region * (which uses ked.data, i.e. rectf) */ if (mode != BEZT_OK_VALUERANGE) { ked.f1 = rectf.xmin; ked.f2 = rectf.xmax; } else { ked.f1 = rectf.ymin; ked.f2 = rectf.ymax; } /* firstly, check if any keyframes will be hit by this */ if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) { /* select keyframes that are in the appropriate places */ ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL); /* only change selection of channel when the visibility of keyframes doesn't depend on this */ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { /* select the curve too now that curve will be touched */ if (selectmode == SELECT_ADD) fcu->flag |= FCURVE_SELECTED; } } /* un-apply NLA mapping from all the keyframes */ if (adt) ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0); } /* cleanup */ ANIM_animdata_freelist(&anim_data); }
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short select_mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; KeyframeEditFunc select_cb, ok_cb; KeyframeEditData ked; tNearestVertInfo *nvi; float selx = (float)ac->scene->r.cfra; /* find the beztriple that we're selecting, and the handle that was clicked on */ nvi = find_nearest_fcurve_vert(ac, mval); /* check if anything to select */ if (nvi == NULL) return; /* get frame number on which elements should be selected */ // TODO: should we restrict to integer frames only? if (nvi->bezt) selx = nvi->bezt->vec[1][0]; else if (nvi->fpt) selx = nvi->fpt->vec[0]; /* if select mode is replace, deselect all keyframes first */ if (select_mode == SELECT_REPLACE) { /* reset selection mode to add to selection */ select_mode = SELECT_ADD; /* - deselect all other keyframes, so that just the newly selected remain * - channels aren't deselected, since we don't re-select any as a consequence */ deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false); } /* initialize keyframe editing data */ memset(&ked, 0, sizeof(KeyframeEditData)); /* set up BezTriple edit callbacks */ select_cb = ANIM_editkeyframes_select(select_mode); ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME); /* loop through all of the keys and select additional keyframes * based on the keys found to be selected above */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* set frame for validation callback to refer to */ if (adt) ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP); else ked.f1 = selx; /* select elements with frame number matching cfra */ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } /* free elements */ MEM_freeN(nvi); BLI_freelistN(&ked.list); ANIM_animdata_freelist(&anim_data); }
/* This function adds data to the keyframes copy/paste buffer, freeing existing data first */ short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data) { bAnimListElem *ale; Scene *scene= ac->scene; /* clear buffer first */ free_anim_copybuf(); /* assume that each of these is an F-Curve */ for (ale= anim_data->first; ale; ale= ale->next) { FCurve *fcu= (FCurve *)ale->key_data; tAnimCopybufItem *aci; BezTriple *bezt, *nbezt, *newbuf; int i; /* firstly, check if F-Curve has any selected keyframes * - skip if no selected keyframes found (so no need to create unnecessary copy-buffer data) * - this check should also eliminate any problems associated with using sample-data */ if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0) continue; /* init copybuf item info */ aci= MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem"); aci->id= ale->id; aci->id_type= GS(ale->id->name); aci->grp= fcu->grp; aci->rna_path= MEM_dupallocN(fcu->rna_path); aci->array_index= fcu->array_index; BLI_addtail(&animcopybuf, aci); /* add selected keyframes to buffer */ // TODO: currently, we resize array everytime we add a new vert - this works ok as long as it is assumed only a few keys are copied for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) { if (BEZSELECTED(bezt)) { /* add to buffer */ newbuf= MEM_callocN(sizeof(BezTriple)*(aci->totvert+1), "copybuf beztriple"); /* assume that since we are just resizing the array, just copy all existing data across */ if (aci->bezt) memcpy(newbuf, aci->bezt, sizeof(BezTriple)*(aci->totvert)); /* copy current beztriple across too */ nbezt= &newbuf[aci->totvert]; *nbezt= *bezt; /* ensure copy buffer is selected so pasted keys are selected */ BEZ_SEL(nbezt); /* free old array and set the new */ if (aci->bezt) MEM_freeN(aci->bezt); aci->bezt= newbuf; aci->totvert++; /* check if this is the earliest frame encountered so far */ if (bezt->vec[1][0] < animcopy_firstframe) animcopy_firstframe= bezt->vec[1][0]; if (bezt->vec[1][0] > animcopy_lastframe) animcopy_lastframe= bezt->vec[1][0]; } } } /* check if anything ended up in the buffer */ if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) return -1; /* incase 'relative' paste method is used */ animcopy_cfra= CFRA; /* everything went fine */ return 0; }
/* This function adds data to the keyframes copy/paste buffer, freeing existing data first */ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) { bAnimListElem *ale; Scene *scene = ac->scene; /* clear buffer first */ free_anim_copybuf(); /* assume that each of these is an F-Curve */ for (ale = anim_data->first; ale; ale = ale->next) { FCurve *fcu = (FCurve *)ale->key_data; tAnimCopybufItem *aci; BezTriple *bezt, *nbezt, *newbuf; int i; /* firstly, check if F-Curve has any selected keyframes * - skip if no selected keyframes found (so no need to create unnecessary copy-buffer data) * - this check should also eliminate any problems associated with using sample-data */ if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0) continue; /* init copybuf item info */ aci = MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem"); aci->id = ale->id; aci->id_type = GS(ale->id->name); aci->grp = fcu->grp; aci->rna_path = MEM_dupallocN(fcu->rna_path); aci->array_index = fcu->array_index; /* detect if this is a bone. We do that here rather than during pasting because ID pointers will get invalidated if we undo. * storing the relevant information here helps avoiding crashes if we undo-repaste */ if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) { Object *ob = (Object *)aci->id; bPoseChannel *pchan; char *bone_name; bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones["); pchan = BKE_pose_channel_find_name(ob->pose, bone_name); if (pchan) { aci->is_bone = true; } if (bone_name) MEM_freeN(bone_name); } BLI_addtail(&animcopybuf, aci); /* add selected keyframes to buffer */ /* TODO: currently, we resize array every time we add a new vert - * this works ok as long as it is assumed only a few keys are copied */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { if (BEZT_ISSEL_ANY(bezt)) { /* add to buffer */ newbuf = MEM_callocN(sizeof(BezTriple) * (aci->totvert + 1), "copybuf beztriple"); /* assume that since we are just re-sizing the array, just copy all existing data across */ if (aci->bezt) memcpy(newbuf, aci->bezt, sizeof(BezTriple) * (aci->totvert)); /* copy current beztriple across too */ nbezt = &newbuf[aci->totvert]; *nbezt = *bezt; /* ensure copy buffer is selected so pasted keys are selected */ BEZT_SEL_ALL(nbezt); /* free old array and set the new */ if (aci->bezt) MEM_freeN(aci->bezt); aci->bezt = newbuf; aci->totvert++; /* check if this is the earliest frame encountered so far */ if (bezt->vec[1][0] < animcopy_firstframe) animcopy_firstframe = bezt->vec[1][0]; if (bezt->vec[1][0] > animcopy_lastframe) animcopy_lastframe = bezt->vec[1][0]; } } } /* check if anything ended up in the buffer */ if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) return -1; /* in case 'relative' paste method is used */ animcopy_cfra = CFRA; /* everything went fine */ return 0; }
/* This function is used to loop over the keyframe data in a DopeSheet summary */ static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter, ret_code = 0; /* sanity check */ if (ac == NULL) return 0; /* get F-Curves to take keyframes from */ filter = ANIMFILTER_DATA_VISIBLE; ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* loop through each F-Curve, working on the keyframes until the first curve aborts */ for (ale = anim_data.first; ale; ale = ale->next) { switch (ale->datatype) { case ALE_MASKLAY: case ALE_GPFRAME: break; case ALE_FCURVE: default: { if (ked && ked->iterflags) { /* make backups of the current values, so that a localised fix * (e.g. NLA time remapping) can be applied to these values */ float f1 = ked->f1; float f2 = ked->f2; if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); if (ked->iterflags & KED_F1_NLA_UNMAP) ked->f1 = BKE_nla_tweakedit_remap(adt, f1, NLATIME_CONVERT_UNMAP); if (ked->iterflags & KED_F2_NLA_UNMAP) ked->f2 = BKE_nla_tweakedit_remap(adt, f2, NLATIME_CONVERT_UNMAP); } /* now operate on the channel as per normal */ ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb); /* reset */ ked->f1 = f1; ked->f2 = f2; } else { /* no special handling required... */ ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb); } break; } } if (ret_code) break; } ANIM_animdata_freelist(&anim_data); return ret_code; }