[Bf-blender-cvs] [1cb884be35e] master: Make auto handle placement aware of cyclic extrapolation.
Alexander Gavrilov
noreply at git.blender.org
Tue Oct 17 18:50:13 CEST 2017
Commit: 1cb884be35e160740e97065afd6548e6a052c9d8
Author: Alexander Gavrilov
Date: Tue Oct 17 19:39:10 2017 +0300
Branches: master
https://developer.blender.org/rB1cb884be35e160740e97065afd6548e6a052c9d8
Make auto handle placement aware of cyclic extrapolation.
Cyclic extrapolation is implemented as an f-curve modifier, so this
technically violates abstraction separation and is something of a hack.
However without such behavior achieving smooth looping with cyclic
extrapolation is extremely cumbersome.
The new behavior is applied when the first modifier is Cyclic
extrapolation in Repeat or Repeat with Offset mode without
using influence, repeat count or range restrictions.
This change in behavior means that curve handles have to be updated
when the modifier is added, removed or its options change. Due to the
way code is structured, it seems it requires a helper link to the
containing curve from the modifier object.
Reviewers: aligorith
Differential Revision: https://developer.blender.org/D2783
===================================================================
M source/blender/blenkernel/BKE_fcurve.h
M source/blender/blenkernel/intern/fcurve.c
M source/blender/blenkernel/intern/fmodifier.c
M source/blender/blenkernel/intern/ipo.c
M source/blender/blenloader/intern/readfile.c
M source/blender/editors/animation/drivers.c
M source/blender/editors/animation/fmodifier_ui.c
M source/blender/editors/include/ED_anim_api.h
M source/blender/editors/object/object_constraint.c
M source/blender/editors/object/object_relations.c
M source/blender/editors/space_action/action_edit.c
M source/blender/editors/space_graph/graph_edit.c
M source/blender/editors/space_nla/nla_edit.c
M source/blender/makesdna/DNA_anim_types.h
M source/blender/makesdna/DNA_curve_types.h
M source/blender/makesrna/intern/rna_fcurve.c
===================================================================
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_fro
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list