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:
authorSebastian Parborg <darkdefende@gmail.com>2020-10-28 13:45:24 +0300
committerSebastian Parborg <darkdefende@gmail.com>2020-10-28 13:45:24 +0300
commitfb88d4eda8a807e79ecb100e82ac930250d871db (patch)
treeb18023b5af1b8c0c728309a97ae53a8dee0d3c35
parent2f7c6149fce00993e7c2c45ab071a7e8b5588f92 (diff)
Add a Un-Bake FCurves operator
We already had the ability to bake fcurves but no way to convert the baked result back without using python. This patch adds and operator that is available now next to the bake operator in the drop down menu, Reviewed By: Sybren Differential Revision: http://developer.blender.org/D6379
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py1
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h3
-rw-r--r--source/blender/blenkernel/intern/fcurve.c78
-rw-r--r--source/blender/editors/space_graph/graph_edit.c69
-rw-r--r--source/blender/editors/space_graph/graph_intern.h1
-rw-r--r--source/blender/editors/space_graph/graph_ops.c1
-rw-r--r--source/blender/makesrna/intern/rna_fcurve_api.c47
7 files changed, 154 insertions, 46 deletions
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 1bf7465e54c..3fee0ae9d47 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -301,6 +301,7 @@ class GRAPH_MT_key(Menu):
layout.operator("graph.smooth")
layout.operator("graph.sample")
layout.operator("graph.bake")
+ layout.operator("graph.unbake")
layout.separator()
layout.operator("graph.euler_filter", text="Discontinuity (Euler) Filter")
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index c9bc5e83a1f..f527f40d0d7 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -325,6 +325,9 @@ float fcurve_samplingcb_evalcurve(struct FCurve *fcu, void *data, float evaltime
void fcurve_store_samples(
struct FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb);
+/* Convert baked/sampled fcurves into bezt/regular fcurves. */
+void fcurve_samples_to_keyframes(struct FCurve *fcu, const int start, const int end);
+
/* ************* F-Curve .blend file API ******************** */
void BKE_fmodifiers_blend_write(struct BlendWriter *writer, struct ListBase *fmodifiers);
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index c4055c0f611..bd7d65f1e6f 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1064,6 +1064,84 @@ void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSample
fcu->totvert = end - start + 1;
}
+static void init_unbaked_bezt_data(BezTriple *bezt)
+{
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ /* Baked FCurve points always use linear interpolation. */
+ bezt->ipo = BEZT_IPO_LIN;
+ bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
+}
+
+/* Convert baked/sampled fcurves into bezt/regular fcurves. */
+void fcurve_samples_to_keyframes(FCurve *fcu, const int start, const int end)
+{
+
+ /* Sanity checks. */
+ /* TODO: make these tests report errors using reports not CLOG's (Joshua Leung 2009). */
+ if (fcu == NULL) {
+ CLOG_ERROR(&LOG, "No F-Curve with F-Curve Modifiers to Un-Bake");
+ return;
+ }
+
+ if (start > end) {
+ CLOG_ERROR(&LOG, "Error: Frame range to unbake F-Curve is inappropriate");
+ return;
+ }
+
+ if (fcu->fpt == NULL) {
+ /* No data to unbake. */
+ CLOG_ERROR(&LOG, "Error: Curve containts no baked keyframes");
+ return;
+ }
+
+ /* Free any existing sample/keyframe data on the curve. */
+ if (fcu->bezt) {
+ MEM_freeN(fcu->bezt);
+ }
+
+ BezTriple *bezt;
+ FPoint *fpt = fcu->fpt;
+ int keyframes_to_insert = end - start;
+ int sample_points = fcu->totvert;
+
+ bezt = fcu->bezt = MEM_callocN(sizeof(*fcu->bezt) * (size_t)keyframes_to_insert, __func__);
+ fcu->totvert = keyframes_to_insert;
+
+ /* Get first sample point to 'copy' as keyframe. */
+ for (; sample_points && (fpt->vec[0] < start); fpt++, sample_points--) {
+ /* pass */
+ }
+
+ /* Current position in the timeline. */
+ int cur_pos = start;
+
+ /* Add leading dummy flat points if needed. */
+ for (; keyframes_to_insert && (fpt->vec[0] > start); cur_pos++, bezt++, keyframes_to_insert--) {
+ init_unbaked_bezt_data(bezt);
+ bezt->vec[1][0] = (float)cur_pos;
+ bezt->vec[1][1] = fpt->vec[1];
+ }
+
+ /* Copy actual sample points. */
+ for (; keyframes_to_insert && sample_points;
+ cur_pos++, bezt++, keyframes_to_insert--, fpt++, sample_points--) {
+ init_unbaked_bezt_data(bezt);
+ copy_v2_v2(bezt->vec[1], fpt->vec);
+ }
+
+ /* Add trailing dummy flat points if needed. */
+ for (fpt--; keyframes_to_insert; cur_pos++, bezt++, keyframes_to_insert--) {
+ init_unbaked_bezt_data(bezt);
+ bezt->vec[1][0] = (float)cur_pos;
+ bezt->vec[1][1] = fpt->vec[1];
+ }
+
+ MEM_SAFE_FREE(fcu->fpt);
+
+ /* Not strictly needed since we use linear interpolation, but better be consistent here. */
+ calchandles_fcurve(fcu);
+}
+
/* ***************************** F-Curve Sanity ********************************* */
/* The functions here are used in various parts of Blender, usually after some editing
* of keyframe data has occurred. They ensure that keyframe data is properly ordered and
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index b25a275a0ab..753e41b7ec7 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1863,6 +1863,75 @@ void GRAPH_OT_bake(wmOperatorType *ot)
/* TODO: add props for start/end frames (Joshua Leung 2009) */
}
+/* ******************** Un-Bake F-Curve Operator *********************** */
+/* This operator unbakes the data of the selected F-Points to F-Curves. */
+
+/* Un-Bake F-Points into F-Curves. */
+static void unbake_graph_curves(bAnimContext *ac, int start, int end)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+
+ /* Filter data. */
+ const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Loop through filtered data and add keys between selected keyframes on every frame. */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ fcurve_samples_to_keyframes(fcu, start, end);
+
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_unbake_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bAnimContext ac;
+ Scene *scene = NULL;
+ int start, end;
+
+ /* Get editor data. */
+ if (ANIM_animdata_get_context(C, &ac) == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ scene = ac.scene;
+ start = PSFRA;
+ end = PEFRA;
+
+ /* Unbake keyframes. */
+ unbake_graph_curves(&ac, start, end);
+
+ /* Set notifier that keyframes have changed. */
+ /* NOTE: some distinction between order/number of keyframes and type should be made? */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPH_OT_unbake(wmOperatorType *ot)
+{
+ /* Identifiers */
+ ot->name = "Un-Bake Curve";
+ ot->idname = "GRAPH_OT_unbake";
+ ot->description = "Un-Bake selected F-Points to F-Curves";
+
+ /* API callbacks */
+ ot->exec = graphkeys_unbake_exec;
+ ot->poll = graphop_selected_fcurve_poll;
+
+ /* Flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
#ifdef WITH_AUDASPACE
/* ******************** Sound Bake F-Curve Operator *********************** */
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index eaa14fedb93..7add2f7cbb8 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -103,6 +103,7 @@ void GRAPH_OT_clean(struct wmOperatorType *ot);
void GRAPH_OT_decimate(struct wmOperatorType *ot);
void GRAPH_OT_sample(struct wmOperatorType *ot);
void GRAPH_OT_bake(struct wmOperatorType *ot);
+void GRAPH_OT_unbake(struct wmOperatorType *ot);
void GRAPH_OT_sound_bake(struct wmOperatorType *ot);
void GRAPH_OT_smooth(struct wmOperatorType *ot);
void GRAPH_OT_euler_filter(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index fd68303e759..63acc2a1774 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -459,6 +459,7 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPH_OT_easing_type);
WM_operatortype_append(GRAPH_OT_sample);
WM_operatortype_append(GRAPH_OT_bake);
+ WM_operatortype_append(GRAPH_OT_unbake);
WM_operatortype_append(GRAPH_OT_sound_bake);
WM_operatortype_append(GRAPH_OT_smooth);
WM_operatortype_append(GRAPH_OT_clean);
diff --git a/source/blender/makesrna/intern/rna_fcurve_api.c b/source/blender/makesrna/intern/rna_fcurve_api.c
index f7be65b4e75..5a720b91f87 100644
--- a/source/blender/makesrna/intern/rna_fcurve_api.c
+++ b/source/blender/makesrna/intern/rna_fcurve_api.c
@@ -76,52 +76,7 @@ static void rna_FCurve_convert_to_keyframes(FCurve *fcu, ReportList *reports, in
BKE_report(reports, RPT_WARNING, "FCurve has no sample points");
}
else {
- BezTriple *bezt;
- FPoint *fpt = fcu->fpt;
- int tot_kf = end - start;
- int tot_sp = fcu->totvert;
-
- bezt = fcu->bezt = MEM_callocN(sizeof(*fcu->bezt) * (size_t)tot_kf, __func__);
- fcu->totvert = tot_kf;
-
- /* Get first sample point to 'copy' as keyframe. */
- for (; tot_sp && (fpt->vec[0] < (float)start); fpt++, tot_sp--) {
- /* pass */
- }
-
- /* Add heading dummy flat points if needed. */
- for (; tot_kf && (fpt->vec[0] > (float)start); start++, bezt++, tot_kf--) {
- /* Linear interpolation, of course. */
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->ipo = BEZT_IPO_LIN;
- bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
- bezt->vec[1][0] = (float)start;
- bezt->vec[1][1] = fpt->vec[1];
- }
-
- /* Copy actual sample points. */
- for (; tot_kf && tot_sp; start++, bezt++, tot_kf--, fpt++, tot_sp--) {
- /* Linear interpolation, of course. */
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->ipo = BEZT_IPO_LIN;
- bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
- copy_v2_v2(bezt->vec[1], fpt->vec);
- }
-
- /* Add leading dummy flat points if needed. */
- for (fpt--; tot_kf; start++, bezt++, tot_kf--) {
- /* Linear interpolation, of course. */
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->ipo = BEZT_IPO_LIN;
- bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
- bezt->vec[1][0] = (float)start;
- bezt->vec[1][1] = fpt->vec[1];
- }
-
- MEM_SAFE_FREE(fcu->fpt);
-
- /* Not strictly needed since we use linear interpolation, but better be consistent here. */
- calchandles_fcurve(fcu);
+ fcurve_samples_to_keyframes(fcu, start, end);
WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
}
}