[Bf-blender-cvs] [fb88d4eda8a] master: Add a Un-Bake FCurves operator

Sebastian Parborg noreply at git.blender.org
Wed Oct 28 11:46:35 CET 2020


Commit: fb88d4eda8a807e79ecb100e82ac930250d871db
Author: Sebastian Parborg
Date:   Wed Oct 28 11:45:24 2020 +0100
Branches: master
https://developer.blender.org/rBfb88d4eda8a807e79ecb100e82ac930250d871db

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

===================================================================

M	release/scripts/startup/bl_ui/space_graph.py
M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/editors/space_graph/graph_edit.c
M	source/blender/editors/space_graph/graph_intern.h
M	source/blender/editors/space_graph/graph_ops.c
M	source/blender/makesrna/intern/rna_fcurve_api.c

===================================================================

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_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list