[Bf-blender-cvs] [a179246e1fd] master: Move fcurve cleanup from transform system to BKE

Philipp Oeser noreply at git.blender.org
Thu Dec 1 15:43:25 CET 2022


Commit: a179246e1fdf36c19c0c5d196da1190aa3984c4b
Author: Philipp Oeser
Date:   Thu Dec 1 13:04:31 2022 +0100
Branches: master
https://developer.blender.org/rBa179246e1fdf36c19c0c5d196da1190aa3984c4b

Move fcurve cleanup from transform system to BKE

This exposes the fcurve cleanup from transform system to other callers
in anticipation to use it in the snapping operators.

It has been renamed from `posttrans_fcurve_clean` to
`BKE_fcurve_merge_duplicate_keys` to better describe what it does.
No functional change expected.

Ref. T101996

NOTE: same probably has to be done for greasepencil, but that is for
another commit.

Maniphest Tasks: T101996

Differential Revision: https://developer.blender.org/D16663

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

M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/editors/transform/transform_convert.c
M	source/blender/editors/transform/transform_convert.h
M	source/blender/editors/transform/transform_convert_action.c
M	source/blender/editors/transform/transform_convert_graph.c

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

diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index b4de24e3b64..cdade9209b6 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -483,6 +483,18 @@ bool BKE_fcurve_delete_keys_selected(struct FCurve *fcu);
  */
 void BKE_fcurve_delete_keys_all(struct FCurve *fcu);
 
+/**
+ * Called during transform/snapping to make sure selected keyframes replace
+ * any other keyframes which may reside on that frame (that is not selected).
+ *
+ * \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
+ *                  but may want to use a different one at times (if caller does not operate on
+ *                  selection).
+ */
+void BKE_fcurve_merge_duplicate_keys(struct FCurve *fcu,
+                                     const int sel_flag,
+                                     const bool use_handle);
+
 /* -------- Curve Sanity -------- */
 
 /**
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 3e772e37177..3c4a068b42a 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1709,6 +1709,133 @@ void BKE_fcurve_delete_keys_all(FCurve *fcu)
   fcurve_bezt_free(fcu);
 }
 
+/* Time + Average value */
+typedef struct tRetainedKeyframe {
+  struct tRetainedKeyframe *next, *prev;
+  float frame; /* frame to cluster around */
+  float val;   /* average value */
+
+  size_t tot_count; /* number of keyframes that have been averaged */
+  size_t del_count; /* number of keyframes of this sort that have been deleted so far */
+} tRetainedKeyframe;
+
+void BKE_fcurve_merge_duplicate_keys(FCurve *fcu, const int sel_flag, const bool use_handle)
+{
+  /* NOTE: We assume that all keys are sorted */
+  ListBase retained_keys = {NULL, NULL};
+  const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) ==
+                                   0);
+
+  /* sanity checks */
+  if ((fcu->totvert == 0) || (fcu->bezt == NULL)) {
+    return;
+  }
+
+  /* 1) Identify selected keyframes, and average the values on those
+   * in case there are collisions due to multiple keys getting scaled
+   * to all end up on the same frame
+   */
+  for (int i = 0; i < fcu->totvert; i++) {
+    BezTriple *bezt = &fcu->bezt[i];
+
+    if (BEZT_ISSEL_ANY(bezt)) {
+      bool found = false;
+
+      /* If there's another selected frame here, merge it */
+      for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
+        if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
+          rk->val += bezt->vec[1][1];
+          rk->tot_count++;
+
+          found = true;
+          break;
+        }
+        if (rk->frame < bezt->vec[1][0]) {
+          /* Terminate early if have passed the supposed insertion point? */
+          break;
+        }
+      }
+
+      /* If nothing found yet, create a new one */
+      if (found == false) {
+        tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
+
+        rk->frame = bezt->vec[1][0];
+        rk->val = bezt->vec[1][1];
+        rk->tot_count = 1;
+
+        BLI_addtail(&retained_keys, rk);
+      }
+    }
+  }
+
+  if (BLI_listbase_is_empty(&retained_keys)) {
+    /* This may happen if none of the points were selected... */
+    if (G.debug & G_DEBUG) {
+      printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
+    }
+    return;
+  }
+
+  /* Compute the average values for each retained keyframe */
+  LISTBASE_FOREACH (tRetainedKeyframe *, rk, &retained_keys) {
+    rk->val = rk->val / (float)rk->tot_count;
+  }
+
+  /* 2) Delete all keyframes duplicating the "retained keys" found above
+   *   - Most of these will be unselected keyframes
+   *   - Some will be selected keyframes though. For those, we only keep the last one
+   *     (or else everything is gone), and replace its value with the averaged value.
+   */
+  for (int i = fcu->totvert - 1; i >= 0; i--) {
+    BezTriple *bezt = &fcu->bezt[i];
+
+    /* Is this keyframe a candidate for deletion? */
+    /* TODO: Replace loop with an O(1) lookup instead */
+    for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
+      if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
+        /* Selected keys are treated with greater care than unselected ones... */
+        if (BEZT_ISSEL_ANY(bezt)) {
+          /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
+           *   (or else we wouldn't have any keyframe left here)
+           * - Otherwise, there are still other selected keyframes on this frame
+           *   to be merged down still ==> DELETE IT
+           */
+          if (rk->del_count == rk->tot_count - 1) {
+            /* Update keyframe... */
+            if (can_average_points) {
+              /* TODO: update handles too? */
+              bezt->vec[1][1] = rk->val;
+            }
+          }
+          else {
+            /* Delete Keyframe */
+            BKE_fcurve_delete_key(fcu, i);
+          }
+
+          /* Update count of how many we've deleted
+           * - It should only matter that we're doing this for all but the last one
+           */
+          rk->del_count++;
+        }
+        else {
+          /* Always delete - Unselected keys don't matter */
+          BKE_fcurve_delete_key(fcu, i);
+        }
+
+        /* Stop the RK search... we've found our match now */
+        break;
+      }
+    }
+  }
+
+  /* 3) Recalculate handles */
+  testhandles_fcurve(fcu, sel_flag, use_handle);
+
+  /* cleanup */
+  BLI_freelistN(&retained_keys);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 75627370a85..00e7b15c59a 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -538,139 +538,6 @@ bool FrameOnMouseSide(char side, float frame, float cframe)
 
 /** \} */
 
-/* -------------------------------------------------------------------- */
-/** \name Animation Editor
- * \{ */
-
-/* Time + Average value */
-typedef struct tRetainedKeyframe {
-  struct tRetainedKeyframe *next, *prev;
-  float frame; /* frame to cluster around */
-  float val;   /* average value */
-
-  size_t tot_count; /* number of keyframes that have been averaged */
-  size_t del_count; /* number of keyframes of this sort that have been deleted so far */
-} tRetainedKeyframe;
-
-void posttrans_fcurve_clean(FCurve *fcu, const int sel_flag, const bool use_handle)
-{
-  /* NOTE: We assume that all keys are sorted */
-  ListBase retained_keys = {NULL, NULL};
-  const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) ==
-                                   0);
-
-  /* sanity checks */
-  if ((fcu->totvert == 0) || (fcu->bezt == NULL)) {
-    return;
-  }
-
-  /* 1) Identify selected keyframes, and average the values on those
-   * in case there are collisions due to multiple keys getting scaled
-   * to all end up on the same frame
-   */
-  for (int i = 0; i < fcu->totvert; i++) {
-    BezTriple *bezt = &fcu->bezt[i];
-
-    if (BEZT_ISSEL_ANY(bezt)) {
-      bool found = false;
-
-      /* If there's another selected frame here, merge it */
-      for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
-        if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
-          rk->val += bezt->vec[1][1];
-          rk->tot_count++;
-
-          found = true;
-          break;
-        }
-        if (rk->frame < bezt->vec[1][0]) {
-          /* Terminate early if have passed the supposed insertion point? */
-          break;
-        }
-      }
-
-      /* If nothing found yet, create a new one */
-      if (found == false) {
-        tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
-
-        rk->frame = bezt->vec[1][0];
-        rk->val = bezt->vec[1][1];
-        rk->tot_count = 1;
-
-        BLI_addtail(&retained_keys, rk);
-      }
-    }
-  }
-
-  if (BLI_listbase_is_empty(&retained_keys)) {
-    /* This may happen if none of the points were selected... */
-    if (G.debug & G_DEBUG) {
-      printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
-    }
-    return;
-  }
-
-  /* Compute the average values for each retained keyframe */
-  LISTBASE_FOREACH (tRetainedKeyframe *, rk, &retained_keys) {
-    rk->val = rk->val / (float)rk->tot_count;
-  }
-
-  /* 2) Delete all keyframes duplicating the "retained keys" found above
-   *   - Most of these will be unselected keyframes
-   *   - Some will be selected keyframes though. For those, we only keep the last one
-   *     (or else everything is gone), and replace its value with the averaged value.
-   */
-  for (int i = fcu->totvert - 1; i >= 0; i--) {
-    BezTriple *bezt = &fcu->bezt[i];
-
-    /* Is this keyframe a candidate for deletion? */
-    /* TODO: Replace loop with an O(1) lookup instead */
-    for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
-      if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
-        /* Selected keys are treated with greater care than unselected ones... */
-        if (BEZT_ISSEL_ANY(bezt)) {
-          /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
-           *   (or else we wouldn't have any keyframe left here)
-           * - Otherwise, there are still other selected keyframes on this frame
-           *   to be merged down still ==> DELETE IT
-           */
-          if (rk->del_count == rk->tot_count - 1) {
-            /* Update keyframe... */
-            if (can_average_points) {
-              /* TODO: update handles too? */
-              bezt->vec[1][1] = rk->val;
-            }
-          }
-          else {
-            /* Delete Keyframe */
-            BKE_fcurve_delete_key(fcu, i);
-          }
-
-          /* Update count 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list