/* helper for paste_animedit_keys() - performs the actual pasting */ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode) { BezTriple *bezt; int i; /* First de-select existing FCurve's keyframes */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { bezt->f2 &= ~SELECT; } /* mix mode with existing data */ switch (merge_mode) { case KEYFRAME_PASTE_MERGE_MIX: /* do-nothing */ break; case KEYFRAME_PASTE_MERGE_OVER: /* remove all keys */ clear_fcurve_keys(fcu); break; case KEYFRAME_PASTE_MERGE_OVER_RANGE: case KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL: { float f_min; float f_max; if (merge_mode == KEYFRAME_PASTE_MERGE_OVER_RANGE) { f_min = aci->bezt[0].vec[1][0] + offset; f_max = aci->bezt[aci->totvert - 1].vec[1][0] + offset; } else { /* Entire Range */ f_min = animcopy_firstframe + offset; f_max = animcopy_lastframe + offset; } /* remove keys in range */ if (f_min < f_max) { /* select verts in range for removal */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { if ((f_min < bezt[0].vec[1][0]) && (bezt[0].vec[1][0] < f_max)) { bezt->f2 |= SELECT; } } /* remove frames in the range */ delete_fcurve_keys(fcu); } break; } } /* just start pasting, with the the first keyframe on the current frame, and so on */ for (i = 0, bezt = aci->bezt; i < aci->totvert; i++, bezt++) { /* temporarily apply offset to src beztriple while copying */ bezt->vec[0][0] += offset; bezt->vec[1][0] += offset; bezt->vec[2][0] += offset; /* insert the keyframe * NOTE: no special flags here for now */ insert_bezt_fcurve(fcu, bezt, 0); /* un-apply offset from src beztriple after copying */ bezt->vec[0][0] -= offset; bezt->vec[1][0] -= offset; bezt->vec[2][0] -= offset; } /* recalculate F-Curve's handles? */ calchandles_fcurve(fcu); }
/* This function pastes data from the keyframes copy/paste buffer */ short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data) { bAnimListElem *ale; const Scene *scene= (ac->scene); const float offset = (float)(CFRA - animcopy_firstframe); short no_name= 0; /* check if buffer is empty */ if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) { //error("No data in buffer to paste"); return -1; } /* check if single channel in buffer (disregard names if so) */ if (animcopybuf.first == animcopybuf.last) no_name= 1; /* from selected channels */ for (ale= anim_data->first; ale; ale= ale->next) { FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */ tAnimCopybufItem *aci= NULL; BezTriple *bezt; int i; /* find buffer item to paste from * - if names don't matter (i.e. only 1 channel in buffer), don't check id/group * - if names do matter, only check if id-type is ok for now (group check is not that important) * - most importantly, rna-paths should match (array indices are unimportant for now) */ // TODO: the matching algorithm here is pathetic! for (aci= animcopybuf.first; aci; aci= aci->next) { /* check that paths exist */ if (aci->rna_path && fcu->rna_path) { // FIXME: this breaks for bone names! if (strcmp(aci->rna_path, fcu->rna_path) == 0) { /* should be a match unless there's more than one of these */ if ((no_name) || (aci->array_index == fcu->array_index)) break; } } } /* copy the relevant data from the matching buffer curve */ if (aci) { /* just start pasting, with the the first keyframe on the current frame, and so on */ for (i=0, bezt=aci->bezt; i < aci->totvert; i++, bezt++) { /* temporarily apply offset to src beztriple while copying */ bezt->vec[0][0] += offset; bezt->vec[1][0] += offset; bezt->vec[2][0] += offset; /* insert the keyframe * NOTE: no special flags here for now */ insert_bezt_fcurve(fcu, bezt, 0); /* un-apply offset from src beztriple after copying */ bezt->vec[0][0] -= offset; bezt->vec[1][0] -= offset; bezt->vec[2][0] -= offset; } /* recalculate F-Curve's handles? */ calchandles_fcurve(fcu); } } return 0; }