diff options
Diffstat (limited to 'source/blender/editors/animation/keyframes_general.c')
-rw-r--r-- | source/blender/editors/animation/keyframes_general.c | 212 |
1 files changed, 106 insertions, 106 deletions
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 7d5fbeb7e3b..f8af504f1ed 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -68,19 +68,19 @@ * * - Joshua Leung, Dec 2008 */ - + /* **************************************************** */ -/* Only delete the nominated keyframe from provided F-Curve. +/* Only delete the nominated keyframe from provided F-Curve. * Not recommended to be used many times successively. For that * there is delete_fcurve_keys(). */ void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc) { /* sanity check */ - if (fcu == NULL) + if (fcu == NULL) return; - + /* verify the index: * 1) cannot be greater than the number of available keyframes * 2) negative indices are for specifying a value from the end of the array @@ -89,7 +89,7 @@ void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc) return; else if (index < 0) index += fcu->totvert; - + /* Delete this keyframe */ memmove(&fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1)); fcu->totvert--; @@ -99,7 +99,7 @@ void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc) MEM_freeN(fcu->bezt); fcu->bezt = NULL; } - + /* recalc handles - only if it won't cause problems */ if (do_recalc) calchandles_fcurve(fcu); @@ -110,7 +110,7 @@ bool delete_fcurve_keys(FCurve *fcu) { int i; bool changed = false; - + if (fcu->bezt == NULL) /* ignore baked curves */ return false; @@ -123,7 +123,7 @@ bool delete_fcurve_keys(FCurve *fcu) changed = true; } } - + /* Free the array of BezTriples if there are not keyframes */ if (fcu->totvert == 0) clear_fcurve_keys(fcu); @@ -148,30 +148,30 @@ 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]); } @@ -189,7 +189,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo BezTriple *old_bezts, *bezt, *beztn; BezTriple *lastb; int totCount, i; - + /* check if any points */ if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) || (!cleardefault && fcu->totvert == 1)) @@ -202,7 +202,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo totCount = fcu->totvert; fcu->bezt = NULL; fcu->totvert = 0; - + /* now insert first keyframe, as it should be ok */ bezt = old_bezts; insert_vert_fcurve(fcu, bezt->vec[1][0], bezt->vec[1][1], BEZKEYTYPE(bezt), 0); @@ -210,8 +210,8 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo lastb = fcu->bezt; lastb->f1 = lastb->f2 = lastb->f3 = 0; } - - /* Loop through BezTriples, comparing them. Skip any that do + + /* Loop through BezTriples, comparing them. Skip any that do * not fit the criteria for "ok" points. */ for (i = 1; i < totCount; i++) { @@ -228,22 +228,22 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo } lastb = (fcu->bezt + (fcu->totvert - 1)); bezt = (old_bezts + i); - + /* get references for quicker access */ prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1]; cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1]; - + if (!(bezt->f2 & SELECT)) { insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0); lastb = (fcu->bezt + (fcu->totvert - 1)); lastb->f1 = lastb->f2 = lastb->f3 = 0; continue; } - + /* check if current bezt occurs at same time as last ok */ if (IS_EQT(cur[0], prev[0], thresh)) { - /* If there is a next beztriple, and if occurs at the same time, only insert - * if there is a considerable distance between the points, and also if the + /* If there is a next beztriple, and if occurs at the same time, only insert + * if there is a considerable distance between the points, and also if the * current is further away than the next one is to the previous. */ if (beztn && (IS_EQT(cur[0], next[0], thresh)) && @@ -287,7 +287,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo } } } - + /* now free the memory used by the old BezTriples */ if (old_bezts) MEM_freeN(old_bezts); @@ -346,14 +346,14 @@ void smooth_fcurve(FCurve *fcu) if (BEZT_ISSEL_ANY(bezt)) totSel++; } - + /* if any points were selected, allocate tSmooth_Bezt points to work on */ if (totSel >= 3) { tSmooth_Bezt *tarray, *tsb; - + /* allocate memory in one go */ tsb = tarray = MEM_callocN(totSel * sizeof(tSmooth_Bezt), "tSmooth_Bezt Array"); - + /* populate tarray with data of selected points */ bezt = fcu->bezt; for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) { @@ -362,7 +362,7 @@ void smooth_fcurve(FCurve *fcu) tsb->h1 = &bezt->vec[0][1]; tsb->h2 = &bezt->vec[1][1]; tsb->h3 = &bezt->vec[2][1]; - + /* advance to the next tsb to populate */ if (x < totSel - 1) tsb++; @@ -370,15 +370,15 @@ void smooth_fcurve(FCurve *fcu) break; } } - + /* calculate the new smoothed F-Curve's with weighted averages: * - this is done with two passes to avoid progressive corruption errors * - uses 5 points for each operation (which stores in the relevant handles) * - previous: w/a ratio = 3:5:2:1:1 * - next: w/a ratio = 1:1:2:5:3 */ - - /* round 1: calculate smoothing deltas and new values */ + + /* round 1: calculate smoothing deltas and new values */ tsb = tarray; for (i = 0; i < totSel; i++, tsb++) { /* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */ @@ -387,21 +387,21 @@ void smooth_fcurve(FCurve *fcu) const tSmooth_Bezt *tP2 = (i - 2 > 0) ? (tsb - 2) : (NULL); const tSmooth_Bezt *tN1 = tsb + 1; const tSmooth_Bezt *tN2 = (i + 2 < totSel) ? (tsb + 2) : (NULL); - + const float p1 = *tP1->h2; const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2); const float c1 = *tsb->h2; const float n1 = *tN1->h2; const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2); - + /* calculate previous and next, then new position by averaging these */ tsb->y1 = (3 * p2 + 5 * p1 + 2 * c1 + n1 + n2) / 12; tsb->y3 = (p2 + p1 + 2 * c1 + 5 * n1 + 3 * n2) / 12; - + tsb->y2 = (tsb->y1 + tsb->y3) / 2; } } - + /* round 2: apply new values */ tsb = tarray; for (i = 0; i < totSel; i++, tsb++) { @@ -409,17 +409,17 @@ void smooth_fcurve(FCurve *fcu) if (ELEM(i, 0, (totSel - 1)) == 0) { /* y2 takes the average of the 2 points */ *tsb->h2 = tsb->y2; - + /* handles are weighted between their original values and the averaged values */ - *tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f); + *tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f); *tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f); } } - + /* free memory required for tarray */ MEM_freeN(tarray); } - + /* recalculate handles */ calchandles_fcurve(fcu); } @@ -442,7 +442,7 @@ void sample_fcurve(FCurve *fcu) if (fcu->bezt == NULL) /* ignore baked */ return; - + /* find selected keyframes... once pair has been found, add keyframes */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { /* check if selected, and which end this is */ @@ -459,39 +459,39 @@ void sample_fcurve(FCurve *fcu) continue; } } - + /* set end */ end = bezt; - + /* cache values then add keyframes using these values, as adding * keyframes while sampling will affect the outcome... * - only start sampling+adding from index=1, so that we don't overwrite original keyframe */ range = (int)(ceil(end->vec[1][0] - start->vec[1][0])); sfra = (int)(floor(start->vec[1][0])); - + if (range) { value_cache = MEM_callocN(sizeof(TempFrameValCache) * range, "IcuFrameValCache"); - + /* sample values */ for (n = 1, fp = value_cache; n < range && fp; n++, fp++) { fp->frame = (float)(sfra + n); fp->val = evaluate_fcurve(fcu, fp->frame); } - + /* add keyframes with these, tagging as 'breakdowns' */ for (n = 1, fp = value_cache; n < range && fp; n++, fp++) { insert_vert_fcurve(fcu, fp->frame, fp->val, BEZT_KEYTYPE_BREAKDOWN, 1); } - + /* free temp cache */ MEM_freeN(value_cache); - + /* as we added keyframes, we need to compensate so that bezt is at the right place */ bezt = fcu->bezt + i + range - 1; i += (range - 1); } - + /* the current selection island has ended, so start again from scratch */ start = NULL; end = NULL; @@ -503,14 +503,14 @@ void sample_fcurve(FCurve *fcu) } } } - + /* recalculate channel's handles? */ calchandles_fcurve(fcu); } /* **************************************************** */ /* Copy/Paste Tools */ -/* - The copy/paste buffer currently stores a set of temporary F-Curves containing only the keyframes +/* - The copy/paste buffer currently stores a set of temporary F-Curves containing only the keyframes * that were selected in each of the original F-Curves * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of * the current frame and the 'first keyframe' (i.e. the earliest one in all channels). @@ -526,12 +526,12 @@ static float animcopy_cfra = 0.0; /* datatype for use in copy/paste buffer */ typedef struct tAnimCopybufItem { struct tAnimCopybufItem *next, *prev; - + ID *id; /* ID which owns the curve */ bActionGroup *grp; /* Action Group */ char *rna_path; /* RNA-Path */ int array_index; /* array index */ - + int totvert; /* number of keyframes stored for this channel */ BezTriple *bezt; /* keyframes in buffer */ @@ -544,23 +544,23 @@ typedef struct tAnimCopybufItem { void ANIM_fcurves_copybuf_free(void) { tAnimCopybufItem *aci, *acn; - + /* free each buffer element */ for (aci = animcopybuf.first; aci; aci = acn) { acn = aci->next; - + /* free keyframes */ - if (aci->bezt) + if (aci->bezt) MEM_freeN(aci->bezt); - + /* free RNA-path */ if (aci->rna_path) MEM_freeN(aci->rna_path); - + /* free ourself */ BLI_freelinkN(&animcopybuf, aci); } - + /* restore initial state */ BLI_listbase_clear(&animcopybuf); animcopy_firstframe = 999999999.0f; @@ -571,27 +571,27 @@ void ANIM_fcurves_copybuf_free(void) /* 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 */ ANIM_fcurves_copybuf_free(); - + /* 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; @@ -599,7 +599,7 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) 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) { @@ -614,9 +614,9 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) } 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 */ @@ -624,23 +624,23 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) 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]; @@ -648,9 +648,9 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) animcopy_lastframe = bezt->vec[1][0]; } } - + } - + /* check if anything ended up in the buffer */ if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) return -1; @@ -740,7 +740,7 @@ static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short f * more involved since it needs to to path lookups. * This is not 100% reliable since the user could be editing the curves on a path that wont * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste - * this should work out ok. + * this should work out ok. */ if (BLI_findindex(which_libbase(G.main, aci->id_type), aci->id) == -1) { /* pedantic but the ID could have been removed, and beats crashing! */ @@ -749,9 +749,9 @@ static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short f else { PointerRNA id_ptr, rptr; PropertyRNA *prop; - + RNA_id_pointer_create(aci->id, &id_ptr); - + if (RNA_path_resolve_property(&id_ptr, aci->rna_path, &rptr, &prop)) { const char *identifier = RNA_property_identifier(prop); int len_id = strlen(identifier); @@ -804,7 +804,7 @@ static void do_curve_mirror_flippping(tAnimCopybufItem *aci, BezTriple *bezt) flip = true; else if (BLI_strn_endswith(aci->rna_path, "rotation_axis_angle", slength) && ELEM(aci->array_index, 2, 3)) flip = true; - + if (flip) { bezt->vec[0][1] = -bezt->vec[0][1]; bezt->vec[1][1] = -bezt->vec[1][1]; @@ -829,18 +829,18 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float 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; @@ -849,7 +849,7 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float 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 */ @@ -858,39 +858,39 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float 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); } @@ -921,12 +921,12 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data, const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip) { bAnimListElem *ale; - + const Scene *scene = (ac->scene); - + const bool from_single = BLI_listbase_is_single(&animcopybuf); const bool to_simple = BLI_listbase_is_single(anim_data); - + float offset = 0.0f; int pass; @@ -940,7 +940,7 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data, BKE_report(ac->reports, RPT_ERROR, "No selected F-Curves to paste into"); return -1; } - + /* methods of offset */ switch (offset_mode) { case KEYFRAME_PASTE_OFFSET_CFRA_START: @@ -961,25 +961,25 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data, /* 1:1 match, no tricky checking, just paste */ FCurve *fcu; tAnimCopybufItem *aci; - + ale = anim_data->first; fcu = (FCurve *)ale->data; /* destination F-Curve */ aci = animcopybuf.first; - + paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false); ale->update |= ANIM_UPDATE_DEFAULT; } else { - /* from selected channels + /* from selected channels * This "passes" system aims to try to find "matching" channels to paste keyframes * into with increasingly loose matching heuristics. The process finishes when at least * one F-Curve has been pasted into. */ for (pass = 0; pass < 3; pass++) { unsigned int totmatch = 0; - + for (ale = anim_data->first; ale; ale = ale->next) { - /* find buffer item to paste from + /* 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) @@ -987,28 +987,28 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data, AnimData *adt = ANIM_nla_mapping_get(ac, ale); FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */ tAnimCopybufItem *aci = NULL; - + switch (pass) { case 0: /* most strict, must be exact path match data_path & index */ aci = pastebuf_match_path_full(fcu, from_single, to_simple, flip); break; - + case 1: /* less strict, just compare property names */ aci = pastebuf_match_path_property(fcu, from_single, to_simple); break; - + case 2: /* Comparing properties gave no results, so just do index comparisons */ aci = pastebuf_match_index_only(fcu, from_single, to_simple); break; } - + /* copy the relevant data from the matching buffer curve */ if (aci) { totmatch++; - + if (adt) { ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip); @@ -1018,16 +1018,16 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data, paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip); } } - + ale->update |= ANIM_UPDATE_DEFAULT; } - + /* don't continue if some fcurves were pasted */ if (totmatch) break; } } - + ANIM_animdata_update(ac, anim_data); return 0; |