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/intern/fcurve.c')
-rw-r--r--source/blender/blenkernel/intern/fcurve.c62
1 files changed, 57 insertions, 5 deletions
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++;
}
}