[Bf-blender-cvs] [0ae02b130a7] soc-2020-greasepencil-curve: GPencil: Split transform code

Falk David noreply at git.blender.org
Sat Aug 8 16:43:43 CEST 2020


Commit: 0ae02b130a78237a8850b616da99edfe8e5fc66d
Author: Falk David
Date:   Sat Aug 8 16:39:05 2020 +0200
Branches: soc-2020-greasepencil-curve
https://developer.blender.org/rB0ae02b130a78237a8850b616da99edfe8e5fc66d

GPencil: Split transform code

This commit splits the grease pencil transform code, so that editcurves and strokes get handled separately.
This fixes a bug where in normal edit mode, proportional editing would be very slow.
The center point of the transform is also more predictable and behaves similar to bezier triples in curve objects.

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

M	source/blender/editors/transform/transform_convert_gpencil.c
M	source/blender/editors/transform/transform_generics.c

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

diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c
index 8f4a44c6a34..deb6e6e27aa 100644
--- a/source/blender/editors/transform/transform_convert_gpencil.c
+++ b/source/blender/editors/transform/transform_convert_gpencil.c
@@ -46,27 +46,6 @@
  *
  * \{ */
 
-static void createTransGPencil_curve_center_get(bGPDcurve *gpc, float r_center[3])
-{
-  zero_v3(r_center);
-  int tot_sel = 0;
-  for (int i = 0; i < gpc->tot_curve_points; i++) {
-    bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
-    if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
-      BezTriple *bezt = &gpc_pt->bezt;
-      /* only allow rotation around control point for now... */
-      if (bezt->f2 & SELECT) {
-        add_v3_v3(r_center, bezt->vec[1]);
-        tot_sel++;
-      }
-    }
-  }
-
-  if (tot_sel > 0) {
-    mul_v3_fl(r_center, 1.0f / tot_sel);
-  }
-}
-
 static void createTransGPencil_center_get(bGPDstroke *gps, float r_center[3])
 {
   bGPDspoint *pt;
@@ -86,55 +65,190 @@ static void createTransGPencil_center_get(bGPDstroke *gps, float r_center[3])
   }
 }
 
-void createTransGPencil(bContext *C, TransInfo *t)
+static short get_bezt_sel_triple_flag(BezTriple *bezt, const bool handles_visible)
 {
-  if (t->data_container_len == 0) {
-    return;
-  }
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
+#define SEL_ALL ((1 << 0) | (1 << 1) | (1 << 2))
 
-  Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
-  const Scene *scene = CTX_data_scene(C);
-  ToolSettings *ts = scene->toolsettings;
-  Object *obact = CTX_data_active_object(C);
-  bGPdata *gpd = obact->data;
-  BLI_assert(gpd != NULL);
+  short flag = 0;
 
-  TransData *td = NULL;
-  float mtx[3][3], smtx[3][3];
+  if (handles_visible) {
+    flag = ((bezt->f1 & SELECT) ? SEL_F1 : 0) | ((bezt->f2 & SELECT) ? SEL_F2 : 0) |
+           ((bezt->f3 & SELECT) ? SEL_F3 : 0);
+  }
+  else {
+    if (bezt->f2 & SELECT) {
+      flag = SEL_ALL;
+    }
+  }
 
-  const int cfra_scene = CFRA;
+  /* Special case for auto & aligned handles */
+  if (flag != SEL_ALL && flag & SEL_F2) {
+    if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) {
+      flag = SEL_ALL;
+    }
+  }
 
-  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
-  const bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) !=
-                                      0;
-  const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
+#undef SEL_F1
+#undef SEL_F2
+#undef SEL_F3
+  return flag;
+}
 
-  const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-  const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
-  const bool is_scale_thickness = ((t->mode == TFM_GPENCIL_SHRINKFATTEN) ||
-                                   (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SCALE_THICKNESS));
+static void createTransGPencil_curves(bContext *C,
+                                      TransInfo *t,
+                                      Depsgraph *depsgraph,
+                                      ToolSettings *ts,
+                                      Object *obact,
+                                      bGPdata *gpd,
+                                      const int cfra_scene,
+                                      const bool is_multiedit,
+                                      const bool use_multiframe_falloff,
+                                      const bool is_prop_edit,
+                                      const bool is_prop_edit_connected,
+                                      const bool is_scale_thickness)
+{
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
 
-  TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+  View3D *v3d = t->view;
+  const bool handle_only_selected_visible = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
+  const bool handle_all_visible = (v3d->overlay.handle_display == CURVE_HANDLE_ALL);
 
-  /* .Grease Pencil Strokes to Transform Data.  */
+  TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
   tc->data_len = 0;
 
-  /* initialize falloff curve */
-  if (is_multiedit) {
-    BKE_curvemapping_init(ts->gp_sculpt.cur_falloff);
+  /* Number of selected curve points */
+  int tot_curve_points = 0, tot_sel_curve_points = 0, tot_points = 0, tot_sel_points = 0;
+  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+    /* Only editable and visible layers are considered. */
+    if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+      bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+      for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+        if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+          LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+            /* skip strokes that are invalid for current view */
+            if (ED_gpencil_stroke_can_use(C, gps) == false) {
+              continue;
+            }
+            /* Check if the color is editable. */
+            if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
+              continue;
+            }
+            /* Check if stroke has an editcurve */
+            if (gps->editcurve == NULL) {
+              continue;
+            }
+
+            bGPDcurve *gpc = gps->editcurve;
+            for (int i = 0; i < gpc->tot_curve_points; i++) {
+              bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+              BezTriple *bezt = &gpc_pt->bezt;
+              if (bezt->hide) {
+                continue;
+              }
+
+              const bool handles_visible = (handle_all_visible ||
+                                            (handle_only_selected_visible &&
+                                             (gpc_pt->flag & GP_CURVE_POINT_SELECT)));
+
+              const short sel_flag = get_bezt_sel_triple_flag(bezt, handles_visible);
+              if (sel_flag & (SEL_F1 | SEL_F2 | SEL_F3)) {
+                if (sel_flag & SEL_F1) {
+                  tot_sel_points++;
+                }
+                if (sel_flag & SEL_F2) {
+                  tot_sel_points++;
+                }
+                if (sel_flag & SEL_F3) {
+                  tot_sel_points++;
+                }
+                tot_sel_curve_points++;
+              }
+
+              if (is_prop_edit) {
+                tot_points += 3;
+                tot_curve_points++;
+              }
+            }
+          }
+        }
+
+        /* If not multiedit out of loop. */
+        if (!is_multiedit) {
+          break;
+        }
+      }
+    }
   }
 
-  /* First Pass: Count the number of data-points required for the strokes,
-   * (and additional info about the configuration - e.g. 2D/3D?).
-   */
+  int data_len_pt = 0;
+
+  if (is_prop_edit) {
+    tc->data_len = tot_points;
+    data_len_pt = tot_curve_points;
+  }
+  else {
+    tc->data_len = tot_sel_points;
+    data_len_pt = tot_sel_curve_points;
+  }
+
+  if (tc->data_len == 0) {
+    return;
+  }
+
+  transform_around_single_fallback_ex(t, data_len_pt);
+
+  tc->data = MEM_callocN(tc->data_len * sizeof(TransData), __func__);
+  TransData *td = tc->data;
+
   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
     /* Only editable and visible layers are considered. */
     if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
-      bGPDframe *gpf;
+      const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
+      bGPDframe *gpf = gpl->actframe;
       bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+      float diff_mat[4][4], mtx[3][3];
+      float smtx[3][3];
+
+      /* Init multiframe falloff options. */
+      int f_init = 0;
+      int f_end = 0;
+
+      if (use_multiframe_falloff) {
+        BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
+      }
+
+      if ((gpf->framenum != cfra) && (!is_multiedit)) {
+        gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
+        /* in some weird situations (framelock enabled) return NULL */
+        if (gpf == NULL) {
+          continue;
+        }
+        if (!is_multiedit) {
+          init_gpf = gpf;
+        }
+      }
+
+      /* Calculate difference matrix. */
+      BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
+      copy_m3_m4(mtx, diff_mat);
+      pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
 
       for (gpf = init_gpf; gpf; gpf = gpf->next) {
         if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+          /* If multi-frame and falloff, recalculate and save value. */
+          float falloff = 1.0f; /* by default no falloff */
+          if ((is_multiedit) && (use_multiframe_falloff)) {
+            /* Falloff depends on distance to active frame
+             * (relative to the overall frame range). */
+            falloff = BKE_gpencil_multiframe_falloff_calc(
+                gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
+          }
+
           LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
             /* skip strokes that are invalid for current view */
             if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -144,63 +258,185 @@ void createTransGPencil(bContext *C, TransInfo *t)
             if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
               continue;
             }
+            /* Check if stroke has an editcurve */
+            if (gps->editcurve == NULL) {
+              continue;
+            }
+            TransData *head, *tail;
+            head = tail = td;
 
-            if (is_curve_edit && gps->editcurve != NULL) {
-              bGPDcurve *gpc = gps->editcurve;
-              if (is_prop_edit) {
-                if (is_prop_edit_connected) {
-                  if (gpc->flag & GP_CURVE_SELECT) {
-                    tc->data_len += gpc->tot_curve_points * 3;
-                  }
-                }
-                else {
-                  tc->data_len += gpc->tot_curve_points * 3;
-                }
+            gps->runtime.multi_frame_falloff = falloff;
+
+ 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list