/* 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; }
static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt) { /* if we've got info on what to select, use it, otherwise select 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_SEL_ALL(bezt); } return 0; }
void ED_curve_nurb_select_all(Nurb *nu) { int i; if (nu->bezt) { BezTriple *bezt; for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { if (bezt->hide == 0) { BEZT_SEL_ALL(bezt); } } } else if (nu->bp) { BPoint *bp; for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { if (bp->hide == 0) { bp->f1 |= SELECT; } } } }
/* 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; }
/* 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); }