[Bf-blender-cvs] [7868db9343d] master: Make curve decimation only take into account the selected curve points

Sebastian Parborg noreply at git.blender.org
Wed Dec 4 16:01:40 CET 2019


Commit: 7868db9343d577784aa754418f2b888793a01d25
Author: Sebastian Parborg
Date:   Wed Dec 4 16:00:03 2019 +0100
Branches: master
https://developer.blender.org/rB7868db9343d577784aa754418f2b888793a01d25

Make curve decimation only take into account the selected curve points

Previously the decimation would take the whole curve into account when
decimating and not just the selected part.

This also contains various smaller bug fixes for the fcurve decimation.

Reviewed By: Sybren

Differential Revision: http://developer.blender.org/D6286

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

M	release/scripts/startup/bl_ui/space_graph.py
M	source/blender/blenkernel/intern/curve_decimate.c
M	source/blender/editors/animation/keyframes_general.c
M	source/blender/editors/include/ED_keyframes_edit.h
M	source/blender/editors/include/UI_view2d.h
M	source/blender/editors/interface/interface_region_hud.c
M	source/blender/editors/interface/view2d.c
M	source/blender/editors/screen/area.c
M	source/blender/editors/space_graph/graph_edit.c
M	source/blender/editors/space_graph/space_graph.c
M	source/blender/makesdna/DNA_screen_types.h
M	source/blender/makesrna/intern/rna_space.c

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

diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 188741956ab..752e1741984 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -113,6 +113,7 @@ class GRAPH_MT_view(Menu):
         st = context.space_data
 
         layout.prop(st, "show_region_ui")
+        layout.prop(st, "show_region_hud")
         layout.separator()
 
         layout.prop(st, "use_realtime_update")
@@ -290,7 +291,14 @@ class GRAPH_MT_key(Menu):
         layout.operator_menu_enum("graph.easing_type", "type", text="Easing Type")
 
         layout.separator()
-        layout.operator("graph.decimate")
+        operator_context = layout.operator_context
+
+        layout.operator("graph.decimate", text="Decimate (Ratio)").mode = 'RATIO'
+        # Using the modal operation doesn't make sense for this variant as we do not have a modal mode for it, so just execute it.
+        layout.operator_context = 'EXEC_DEFAULT'
+        layout.operator("graph.decimate", text="Decimate (Allowed Change)").mode = 'ERROR'
+        layout.operator_context = operator_context
+
         layout.operator("graph.clean").channels = False
         layout.operator("graph.clean", text="Clean Channels").channels = True
         layout.operator("graph.smooth")
diff --git a/source/blender/blenkernel/intern/curve_decimate.c b/source/blender/blenkernel/intern/curve_decimate.c
index cccdf830854..d569684d55c 100644
--- a/source/blender/blenkernel/intern/curve_decimate.c
+++ b/source/blender/blenkernel/intern/curve_decimate.c
@@ -269,11 +269,11 @@ uint BKE_curve_decimate_bezt_array(BezTriple *bezt_array,
     if (a == HD_VECT) { \
       a = HD_FREE; \
     } \
-    else if (a == HD_AUTO) { \
+    else if (a == HD_AUTO || a == HD_AUTO_ANIM) { \
       a = HD_ALIGN; \
     } \
     /* opposite handle */ \
-    if (b == HD_AUTO) { \
+    if (b == HD_AUTO || b == HD_AUTO_ANIM) { \
       b = HD_ALIGN; \
     } \
   } \
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index ffae402989c..ed5cb65c42e 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -328,34 +328,135 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
 
 /* ---------------- */
 
+/* Check if the keyframe interpolation type is supported */
+static bool prepare_for_decimate(FCurve *fcu, int i)
+{
+  switch (fcu->bezt[i].ipo) {
+    case BEZT_IPO_BEZ:
+      /* We do not need to do anything here as the keyframe already has the required setting.
+       */
+      return true;
+    case BEZT_IPO_LIN:
+      /* Convert to a linear bezt curve to be able to use the decimation algorithm. */
+      fcu->bezt[i].ipo = BEZT_IPO_BEZ;
+      fcu->bezt[i].h1 = HD_FREE;
+      fcu->bezt[i].h2 = HD_FREE;
+
+      if (i != 0) {
+        float h1[3];
+        sub_v3_v3v3(h1, fcu->bezt[i - 1].vec[1], fcu->bezt[i].vec[1]);
+        mul_v3_fl(h1, 1.0f / 3.0f);
+        add_v3_v3(h1, fcu->bezt[i].vec[1]);
+        copy_v3_v3(fcu->bezt[i].vec[0], h1);
+      }
+
+      if (i + 1 != fcu->totvert) {
+        float h2[3];
+        sub_v3_v3v3(h2, fcu->bezt[i + 1].vec[1], fcu->bezt[i].vec[1]);
+        mul_v3_fl(h2, 1.0f / 3.0f);
+        add_v3_v3(h2, fcu->bezt[i].vec[1]);
+        copy_v3_v3(fcu->bezt[i].vec[2], h2);
+      }
+      return true;
+    default:
+      /* These are unsupported. */
+      return false;
+  }
+}
+
+/* Decimate the given curve segment. */
+static void decimate_fcurve_segment(FCurve *fcu,
+                                    int bezt_segment_start_idx,
+                                    int bezt_segment_len,
+                                    float remove_ratio,
+                                    float error_sq_max)
+{
+  int selected_len = bezt_segment_len;
+
+  /* Make sure that we can remove the start/end point of the segment if they
+   * are not the start/end point of the curve. BKE_curve_decimate_bezt_array
+   * has a check that prevents removal of the first and last index in the
+   * passed array. */
+  if (bezt_segment_len + bezt_segment_start_idx != fcu->totvert &&
+      prepare_for_decimate(fcu, bezt_segment_len + bezt_segment_start_idx)) {
+    bezt_segment_len++;
+  }
+  if (bezt_segment_start_idx != 0 && prepare_for_decimate(fcu, bezt_segment_start_idx - 1)) {
+    bezt_segment_start_idx--;
+    bezt_segment_len++;
+  }
+
+  const int target_fcurve_verts = ceil(bezt_segment_len - selected_len * remove_ratio);
+
+  BKE_curve_decimate_bezt_array(&fcu->bezt[bezt_segment_start_idx],
+                                bezt_segment_len,
+                                12, /* The actual resolution displayed in the viewport is dynamic
+                                       so we just pick a value that preserves the curve shape. */
+                                false,
+                                SELECT,
+                                BEZT_FLAG_TEMP_TAG,
+                                error_sq_max,
+                                target_fcurve_verts);
+}
+
 /**
  * F-Curve 'decimate' function that removes a certain ratio of curve
  * points that will affect the curves overall shape the least.
+ * If you want to remove based on a error margin, set remove_ratio to 1 and
+ * simply specify the desired error_sq_max. Otherwise, set the error margin to
+ * FLT_MAX.
  */
-void decimate_fcurve(bAnimListElem *ale, float remove_ratio)
+bool decimate_fcurve(bAnimListElem *ale, float remove_ratio, float error_sq_max)
 {
   FCurve *fcu = (FCurve *)ale->key_data;
 
   /* Check if the curve actually has any points  */
   if (fcu == NULL || fcu->bezt == NULL || fcu->totvert == 0) {
-    return;
+    return true;
   }
 
-  const int target_fcurve_verts = max_ii(2, fcu->totvert - fcu->totvert * remove_ratio);
-
   BezTriple *old_bezts = fcu->bezt;
 
-  if (target_fcurve_verts != fcu->totvert) {
-    /* We don't want to limit the decimation to a certain error margin */
-    const float error_sq_max = FLT_MAX;
-    BKE_curve_decimate_bezt_array(fcu->bezt,
-                                  fcu->totvert,
-                                  12, /* 12 is the resolution of graph editor curves */
-                                  false,
-                                  SELECT,
-                                  BEZT_FLAG_TEMP_TAG,
-                                  error_sq_max,
-                                  target_fcurve_verts);
+  /* Only decimate the individual selected curve segments. */
+  int bezt_segment_start_idx = 0;
+  int bezt_segment_len = 0;
+
+  bool selected;
+  bool can_decimate_all_selected = true;
+  bool in_segment = false;
+
+  for (int i = 0; i < fcu->totvert; i++) {
+    selected = fcu->bezt[i].f2 & SELECT;
+    /* Make sure that the temp flag is unset as we use it to determine what to remove. */
+    fcu->bezt[i].f2 &= ~BEZT_FLAG_TEMP_TAG;
+
+    if (selected && !prepare_for_decimate(fcu, i)) {
+      /* This keyframe is not supported, treat them as if they were unselected. */
+      selected = false;
+      can_decimate_all_selected = false;
+    }
+
+    if (selected) {
+      if (!in_segment) {
+        bezt_segment_start_idx = i;
+        in_segment = true;
+      }
+      bezt_segment_len++;
+    }
+    else if (in_segment) {
+      /* If the curve point is not selected then we have reached the end of the selected curve
+       * segment. */
+      decimate_fcurve_segment(
+          fcu, bezt_segment_start_idx, bezt_segment_len, remove_ratio, error_sq_max);
+      in_segment = false;
+      bezt_segment_len = 0;
+    }
+  }
+
+  /* Did the segment run to the end of the curve? */
+  if (in_segment) {
+    decimate_fcurve_segment(
+        fcu, bezt_segment_start_idx, bezt_segment_len, remove_ratio, error_sq_max);
   }
 
   uint old_totvert = fcu->totvert;
@@ -372,6 +473,8 @@ void decimate_fcurve(bAnimListElem *ale, float remove_ratio)
   if (old_bezts) {
     MEM_freeN(old_bezts);
   }
+
+  return can_decimate_all_selected;
 }
 
 /* ---------------- */
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index 8181cebfe3c..c347d75fa66 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -309,7 +309,7 @@ void clean_fcurve(struct bAnimContext *ac,
                   struct bAnimListElem *ale,
                   float thresh,
                   bool cleardefault);
-void decimate_fcurve(struct bAnimListElem *ale, float remove_ratio);
+bool decimate_fcurve(struct bAnimListElem *ale, float remove_ratio, float error_sq_max);
 void smooth_fcurve(struct FCurve *fcu);
 void sample_fcurve(struct FCurve *fcu);
 
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 0dbf3c710d6..e34f40d057d 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -220,6 +220,7 @@ bool UI_view2d_view_to_region_rcti_clip(struct View2D *v2d,
 struct View2D *UI_view2d_fromcontext(const struct bContext *C);
 struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
 
+void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_y);
 void UI_view2d_scale_get(struct View2D *v2d, float *r_x, float *r_y);
 float UI_view2d_scale_get_x(const struct View2D *v2d);
 float UI_view2d_scale_get_y(const struct View2D *v2d);
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
index 54bdbe0ec6e..fa471441cc9 100644
--- a/source/blender/editors/interface/interface_region_hud.c
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -265,6 +265,14 @@ static ARegion *hud_region_add(ScrArea *sa)
   ar->overlap = true;
   ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
 
+  if (ar_win) {
+    float x, y;
+
+    UI_view2d_scroller_size_get(&ar_win->v2d, &x, &y);
+    ar->runtime.offset_x = x;
+    ar->runtime.offset_y = y;
+  }
+
   return ar;
 }
 
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list