/* 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 */ BEZ_DESEL(&fcu->bezt[i]); i++; /* Select the copied key */ BEZ_SEL(&fcu->bezt[i]); } } }
/* flush selection map values to the given beztriple */ short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt) { char *map = ked->data; short on = map[ked->curIndex]; /* select or deselect based on whether the map allows it or not */ if (on) { BEZ_SEL(bezt); } else { BEZ_DESEL(bezt); } return 0; }
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 { BEZ_DESEL(bezt); } return 0; }
/* 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 (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; /* 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 (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) */ /* 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, ANIMTYPE_FCURVE); } /* free temp sample data for filtering */ MEM_freeN(nvi); }