Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h5
-rw-r--r--source/blender/blenkernel/intern/fcurve.c62
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c17
-rw-r--r--source/blender/blenkernel/intern/ipo.c2
4 files changed, 78 insertions, 8 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 */