/* duplicate selected keyframes for the given F-Curve */ void duplicate_fcurve_keys(FCurve *fcu) { BezTriple *newbezt; int i; /* this can only work when there is an F-Curve, and also when there are some BezTriples */ if (ELEM(NULL, fcu, fcu->bezt)) return; for (i = 0; i < fcu->totvert; i++) { /* If a key is selected */ if (fcu->bezt[i].f2 & SELECT) { /* Expand the list */ newbezt = MEM_callocN(sizeof(BezTriple) * (fcu->totvert + 1), "beztriple"); memcpy(newbezt, fcu->bezt, sizeof(BezTriple) * (i + 1)); memcpy(newbezt + i + 1, fcu->bezt + i, sizeof(BezTriple)); memcpy(newbezt + i + 2, fcu->bezt + i + 1, sizeof(BezTriple) * (fcu->totvert - (i + 1))); fcu->totvert++; /* reassign pointers... (free old, and add new) */ MEM_freeN(fcu->bezt); fcu->bezt = newbezt; /* Unselect the current key */ BEZT_DESEL_ALL(&fcu->bezt[i]); i++; /* Select the copied key */ BEZT_SEL_ALL(&fcu->bezt[i]); } } }
/* flush selection map values to the given beztriple */ short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt) { const char *map = ked->data; short on = map[ked->curIndex]; /* select or deselect based on whether the map allows it or not */ if (on) { BEZT_SEL_ALL(bezt); } else { BEZT_DESEL_ALL(bezt); } return 0; }
void ED_curve_nurb_deselect_all(Nurb *nu) { int i; if (nu->bezt) { BezTriple *bezt; for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { BEZT_DESEL_ALL(bezt); } } else if (nu->bp) { BPoint *bp; for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { bp->f1 &= ~SELECT; } } }
static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt) { /* if we've got info on what to deselect, use it, otherwise deselect all */ if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { if (ked->curflags & KEYFRAME_OK_KEY) bezt->f2 &= ~SELECT; if (ked->curflags & KEYFRAME_OK_H1) bezt->f1 &= ~SELECT; if (ked->curflags & KEYFRAME_OK_H2) bezt->f3 &= ~SELECT; } else { BEZT_DESEL_ALL(bezt); } return 0; }
/* 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, bool flip) { BezTriple *bezt; int i; /* First de-select existing FCurve's keyframes */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { BEZT_DESEL_ALL(bezt); } /* 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 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 */ if (flip) do_curve_mirror_flippping(aci, bezt); bezt->vec[0][0] += offset; bezt->vec[1][0] += offset; bezt->vec[2][0] += offset; /* insert the keyframe * NOTE: we do not want to inherit handles from existing keyframes in this case! */ insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL); /* un-apply offset from src beztriple after copying */ bezt->vec[0][0] -= offset; bezt->vec[1][0] -= offset; bezt->vec[2][0] -= offset; if (flip) do_curve_mirror_flippping(aci, bezt); } /* recalculate F-Curve's handles? */ calchandles_fcurve(fcu); }
/* option 1) select keyframe directly under mouse */ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_mode, short curves_only) { SpaceIpo *sipo = (SpaceIpo *)ac->sl; 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 (+ F-Curves too) */ deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true); /* 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 (BEZT_ISSEL_ANY(bezt)) { BEZT_DESEL_ALL(bezt); } else { BEZT_SEL_ALL(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) { BEZT_SEL_ALL(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; /* initialize 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 (BEZT_ISSEL_ANY(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) */ /* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) otherwise the active flag won't be set [#26452] */ if (nvi->fcu->flag & FCURVE_SELECTED) { int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype); } /* free temp sample data for filtering */ MEM_freeN(nvi); }