diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_fcurve.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 62 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fmodifier.c | 17 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/ipo.c | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 7 | ||||
-rw-r--r-- | source/blender/editors/animation/drivers.c | 2 | ||||
-rw-r--r-- | source/blender/editors/animation/fmodifier_ui.c | 10 | ||||
-rw-r--r-- | source/blender/editors/include/ED_anim_api.h | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_constraint.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_relations.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_edit.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_edit.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_edit.c | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_anim_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_curve_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_fcurve.c | 6 |
16 files changed, 109 insertions, 23 deletions
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index b38f1299763..09f5ecce050 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -188,7 +188,7 @@ const FModifierTypeInfo *get_fmodifier_typeinfo(const int type); /* ---------------------- */ -struct FModifier *add_fmodifier(ListBase *modifiers, int type); +struct FModifier *add_fmodifier(ListBase *modifiers, int type, struct FCurve *owner_fcu); struct FModifier *copy_fmodifier(const struct FModifier *src); void copy_fmodifiers(ListBase *dst, const ListBase *src); bool remove_fmodifier(ListBase *modifiers, struct FModifier *fcm); @@ -266,6 +266,9 @@ bool fcurve_are_keyframes_usable(struct FCurve *fcu); bool fcurve_is_keyframable(struct FCurve *fcu); bool BKE_fcurve_is_protected(struct FCurve *fcu); +/* The curve is an infinite cycle via Cycles modifier */ +bool BKE_fcurve_is_cyclic(struct FCurve *fcu); + /* -------- Curve Sanity -------- */ void calchandles_fcurve(struct FCurve *fcu); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index aee465ad0a0..103f23a2c18 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -881,6 +881,46 @@ void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSample * that the handles are correctly */ +/* Checks if the F-Curve has a Cycles modifier with simple settings that warrant transition smoothing */ +bool BKE_fcurve_is_cyclic(FCurve *fcu) +{ + FModifier *fcm = fcu->modifiers.first; + + if (!fcm || fcm->type != FMODIFIER_TYPE_CYCLES) + return false; + + if (fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) + return false; + + if (fcm->flag & (FMODIFIER_FLAG_RANGERESTRICT | FMODIFIER_FLAG_USEINFLUENCE)) + return false; + + FMod_Cycles *data = (FMod_Cycles*)fcm->data; + + return data && data->after_cycles == 0 && data->before_cycles == 0 && + ELEM(data->before_mode, FCM_EXTRAPOLATE_CYCLIC, FCM_EXTRAPOLATE_CYCLIC_OFFSET) && + ELEM(data->after_mode, FCM_EXTRAPOLATE_CYCLIC, FCM_EXTRAPOLATE_CYCLIC_OFFSET); +} + +/* Shifts 'in' by the difference in coordinates between 'to' and 'from', using 'out' as the output buffer. + * When 'to' and 'from' are end points of the loop, this moves the 'in' point one loop cycle. + */ +static BezTriple *cycle_offset_triple(bool cycle, BezTriple *out, const BezTriple *in, const BezTriple *from, const BezTriple *to) +{ + if (!cycle) + return NULL; + + memcpy(out, in, sizeof(BezTriple)); + + float delta[3]; + sub_v3_v3v3(delta, to->vec[1], from->vec[1]); + + for (int i = 0; i < 3; i++) + add_v3_v3(out->vec[i], delta); + + return out; +} + /* This function recalculates the handles of an F-Curve * If the BezTriples have been rearranged, sort them first before using this. */ @@ -896,10 +936,16 @@ void calchandles_fcurve(FCurve *fcu) */ if (ELEM(NULL, fcu, fcu->bezt) || (a < 2) /*|| ELEM(fcu->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN)*/) return; - + + /* if the first modifier is Cycles, smooth the curve through the cycle */ + BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert-1]; + BezTriple tmp; + + bool cycle = BKE_fcurve_is_cyclic(fcu) && BEZT_IS_AUTOH(first) && BEZT_IS_AUTOH(last); + /* get initial pointers */ bezt = fcu->bezt; - prev = NULL; + prev = cycle_offset_triple(cycle, &tmp, &fcu->bezt[fcu->totvert-2], last, first); next = (bezt + 1); /* loop over all beztriples, adjusting handles */ @@ -912,7 +958,7 @@ void calchandles_fcurve(FCurve *fcu) BKE_nurb_handle_calc(bezt, prev, next, true); /* for automatic ease in and out */ - if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { + if (BEZT_IS_AUTOH(bezt) && !cycle) { /* only do this on first or last beztriple */ if ((a == 0) || (a == fcu->totvert - 1)) { /* set both handles to have same horizontal value as keyframe */ @@ -924,8 +970,14 @@ void calchandles_fcurve(FCurve *fcu) /* advance pointers for next iteration */ prev = bezt; - if (a == 1) next = NULL; - else next++; + + if (a == 1) { + next = cycle_offset_triple(cycle, &tmp, &fcu->bezt[1], first, last); + } + else { + next++; + } + bezt++; } } diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index f1732ee7a9a..f1834bdf8a6 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -1077,7 +1077,7 @@ const FModifierTypeInfo *fmodifier_get_typeinfo(const FModifier *fcm) /* API --------------------------- */ /* Add a new F-Curve Modifier to the given F-Curve of a certain type */ -FModifier *add_fmodifier(ListBase *modifiers, int type) +FModifier *add_fmodifier(ListBase *modifiers, int type, FCurve *owner_fcu) { const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type); FModifier *fcm; @@ -1098,6 +1098,7 @@ FModifier *add_fmodifier(ListBase *modifiers, int type) fcm = MEM_callocN(sizeof(FModifier), "F-Curve Modifier"); fcm->type = type; fcm->flag = FMODIFIER_FLAG_EXPANDED; + fcm->curve = owner_fcu; fcm->influence = 1.0f; BLI_addtail(modifiers, fcm); @@ -1111,6 +1112,10 @@ FModifier *add_fmodifier(ListBase *modifiers, int type) /* init custom settings if necessary */ if (fmi->new_data) fmi->new_data(fcm->data); + + /* update the fcurve if the Cycles modifier is added */ + if ((owner_fcu) && (type == FMODIFIER_TYPE_CYCLES)) + calchandles_fcurve(owner_fcu); /* return modifier for further editing */ return fcm; @@ -1129,6 +1134,7 @@ FModifier *copy_fmodifier(const FModifier *src) /* copy the base data, clearing the links */ dst = MEM_dupallocN(src); dst->next = dst->prev = NULL; + dst->curve = NULL; /* make a new copy of the F-Modifier's data */ dst->data = MEM_dupallocN(src->data); @@ -1157,6 +1163,7 @@ void copy_fmodifiers(ListBase *dst, const ListBase *src) /* make a new copy of the F-Modifier's data */ fcm->data = MEM_dupallocN(fcm->data); + fcm->curve = NULL; /* only do specific constraints if required */ if (fmi && fmi->copy_data) @@ -1173,6 +1180,9 @@ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm) if (fcm == NULL) return false; + /* removing the cycles modifier requires a handle update */ + FCurve *update_fcu = (fcm->type == FMODIFIER_TYPE_CYCLES) ? fcm->curve : NULL; + /* free modifier's special data (stored inside fcm->data) */ if (fcm->data) { if (fmi && fmi->free_data) @@ -1185,6 +1195,11 @@ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm) /* remove modifier from stack */ if (modifiers) { BLI_freelinkN(modifiers, fcm); + + /* update the fcurve if the Cycles modifier is removed */ + if (update_fcu) + calchandles_fcurve(update_fcu); + return true; } else { diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index f3a85dcee2b..90247441631 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1192,7 +1192,7 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i /* Add a new FModifier (Cyclic) instead of setting extend value * as that's the new equivalent of that option. */ - FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES); + FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu); FMod_Cycles *data = (FMod_Cycles *)fcm->data; /* if 'offset' one is in use, set appropriate settings */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 3b7662be2b2..231b467a0af 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2441,13 +2441,14 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) /* NOTE: this assumes that link_list has already been called on the list */ -static void direct_link_fmodifiers(FileData *fd, ListBase *list) +static void direct_link_fmodifiers(FileData *fd, ListBase *list, FCurve *curve) { FModifier *fcm; for (fcm = list->first; fcm; fcm = fcm->next) { /* relink general data */ fcm->data = newdataadr(fd, fcm->data); + fcm->curve = curve; /* do relinking of data for specific types */ switch (fcm->type) { @@ -2537,7 +2538,7 @@ static void direct_link_fcurves(FileData *fd, ListBase *list) /* modifiers */ link_list(fd, &fcu->modifiers); - direct_link_fmodifiers(fd, &fcu->modifiers); + direct_link_fmodifiers(fd, &fcu->modifiers, fcu); } } @@ -2642,7 +2643,7 @@ static void direct_link_nladata_strips(FileData *fd, ListBase *list) /* strip's F-Modifiers */ link_list(fd, &strip->modifiers); - direct_link_fmodifiers(fd, &strip->modifiers); + direct_link_fmodifiers(fd, &strip->modifiers, NULL); } } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 52b93edae15..0d329898c41 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -123,7 +123,7 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde * Create FModifier so that old scripts won't break * for now before 2.7 series -- (September 4, 2013) */ - add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu); } else { /* add 2 keyframes so that user has something to work with diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 6bb73416fec..8d77460e197 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -736,7 +736,7 @@ bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active) /* 'Paste' the F-Modifier(s) from the buffer to the specified list * - replace: free all the existing modifiers to leave only the pasted ones */ -bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace) +bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *curve) { FModifier *fcm; bool ok = false; @@ -745,6 +745,8 @@ bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace) if (modifiers == NULL) return 0; + bool was_cyclic = curve && BKE_fcurve_is_cyclic(curve); + /* if replacing the list, free the existing modifiers */ if (replace) free_fmodifiers(modifiers); @@ -753,6 +755,8 @@ bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace) for (fcm = fmodifier_copypaste_buf.first; fcm; fcm = fcm->next) { /* make a copy of it */ FModifier *fcmN = copy_fmodifier(fcm); + + fcmN->curve = curve; /* make sure the new one isn't active, otherwise the list may get several actives */ fcmN->flag &= ~FMODIFIER_FLAG_ACTIVE; @@ -762,6 +766,10 @@ bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace) ok = 1; } + /* adding or removing the Cycles modifier requires an update to handles */ + if (curve && BKE_fcurve_is_cyclic(curve) != was_cyclic) + calchandles_fcurve(curve); + /* did we succeed? */ return ok; } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 68a5dd8a94e..ab02fd1ccc8 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -572,7 +572,7 @@ bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active); /* 'Paste' the F-Modifier(s) from the buffer to the specified list * - replace: free all the existing modifiers to leave only the pasted ones */ -bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace); +bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, struct FCurve *curve); /* ************************************************* */ /* ASSORTED TOOLS */ diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 59d78f13ccb..f348806c6f1 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1025,7 +1025,7 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op) * and define basic slope of this curve based on the properties */ if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) { - FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); + FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu); FMod_Generator *gen = fcm->data; /* Assume that we have the following equation: diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index d5b516257a1..91fdfcacf6c 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -637,7 +637,7 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */ if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) - add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu); } /* fall back on regular parenting now (for follow only) */ diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index a9920389980..2df5aa29e9a 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -1146,7 +1146,7 @@ static void setexpo_action_keys(bAnimContext *ac, short mode) /* only add if one doesn't exist */ if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) { /* TODO: add some more preset versions which set different extrapolation options? */ - add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES); + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu); } } else if (mode == CLEAR_CYCLIC_EXPO) { diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 861a38da2c7..4f737ef164b 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1504,7 +1504,7 @@ static void setexpo_graph_keys(bAnimContext *ac, short mode) /* only add if one doesn't exist */ if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) { // TODO: add some more preset versions which set different extrapolation options? - add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES); + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu); } } else if (mode == CLEAR_CYCLIC_EXPO) { @@ -2446,7 +2446,7 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) FModifier *fcm; /* add F-Modifier of specified type to active F-Curve, and make it the active one */ - fcm = add_fmodifier(&fcu->modifiers, type); + fcm = add_fmodifier(&fcu->modifiers, type, fcu); if (fcm) { set_active_fmodifier(&fcu->modifiers, fcm); } @@ -2582,7 +2582,7 @@ static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op) FCurve *fcu = (FCurve *)ale->data; int tot; - tot = ANIM_fmodifiers_paste_from_buf(&fcu->modifiers, replace); + tot = ANIM_fmodifiers_paste_from_buf(&fcu->modifiers, replace, fcu); if (tot) { ale->update |= ANIM_UPDATE_DEPS; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index f7f7c82171d..a6f76e1d556 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -2316,7 +2316,7 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) continue; /* add F-Modifier of specified type to selected, and make it the active one */ - fcm = add_fmodifier(&strip->modifiers, type); + fcm = add_fmodifier(&strip->modifiers, type, NULL); if (fcm) { set_active_fmodifier(&strip->modifiers, fcm); @@ -2470,7 +2470,7 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op) } /* paste FModifiers from buffer */ - ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, replace); + ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, replace, NULL); ale->update |= ANIM_UPDATE_DEPS; } } diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 935a893f689..977cd2347ad 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -52,6 +52,7 @@ extern "C" { typedef struct FModifier { struct FModifier *next, *prev; + struct FCurve *curve; /* containing curve, only used for updates to CYCLES */ void *data; /* pointer to modifier data */ char name[64]; /* user-defined description for the modifier - MAX_ID_NAME-2 */ diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 902fa4ce987..16647e78eff 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -436,6 +436,8 @@ typedef enum eBezTriple_KeyframeType { #define BEZT_SEL_ALL(bezt) { (bezt)->f1 |= SELECT; (bezt)->f2 |= SELECT; (bezt)->f3 |= SELECT; } ((void)0) #define BEZT_DESEL_ALL(bezt) { (bezt)->f1 &= ~SELECT; (bezt)->f2 &= ~SELECT; (bezt)->f3 &= ~SELECT; } ((void)0) +#define BEZT_IS_AUTOH(bezt) (ELEM((bezt)->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM((bezt)->h2, HD_AUTO, HD_AUTO_ANIM)) + /* *************** CHARINFO **************** */ /* CharInfo.flag */ diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index ad63a652b12..f7da5a0fda4 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -495,7 +495,7 @@ static void rna_FCurve_active_modifier_set(PointerRNA *ptr, PointerRNA value) static FModifier *rna_FCurve_modifiers_new(FCurve *fcu, int type) { - return add_fmodifier(&fcu->modifiers, type); + return add_fmodifier(&fcu->modifiers, type, fcu); } static void rna_FCurve_modifiers_remove(FCurve *fcu, ReportList *reports, PointerRNA *fcm_ptr) @@ -586,11 +586,15 @@ static void rna_FModifier_blending_range(PointerRNA *ptr, float *min, float *max static void rna_FModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; + FModifier *fcm = (FModifier *)ptr->data; AnimData *adt = BKE_animdata_from_id(id); DAG_id_tag_update(id, (GS(id->name) == ID_OB) ? OB_RECALC_OB : OB_RECALC_DATA); if (adt != NULL) { adt->recalc |= ADT_RECALC_ANIM; } + if (fcm->curve && fcm->type == FMODIFIER_TYPE_CYCLES) { + calchandles_fcurve(fcm->curve); + } } static void rna_FModifier_verify_data_update(Main *bmain, Scene *scene, PointerRNA *ptr) |