[Bf-blender-cvs] [f34e17fcb7e] temp-gpencil-bezier-stroke-type: GPencil: seperate for bezier strokes operator

Falk David noreply at git.blender.org
Mon Mar 15 00:36:27 CET 2021


Commit: f34e17fcb7e98bda0083b2a364d065c2d3befde8
Author: Falk David
Date:   Mon Mar 15 00:35:32 2021 +0100
Branches: temp-gpencil-bezier-stroke-type
https://developer.blender.org/rBf34e17fcb7e98bda0083b2a364d065c2d3befde8

GPencil: seperate for bezier strokes operator

This also adds a "Keep Ends" option that will keep the ends on both
parts, which is especially useful with curves.

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

M	source/blender/editors/gpencil/gpencil_edit.c

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

diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index e7135f915ea..0c52f12dcb2 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -4650,11 +4650,11 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
   bGPdata *gpd_dst = NULL;
   bGPDlayer *gpl_dst = NULL;
   bGPDframe *gpf_dst = NULL;
-  bGPDspoint *pt;
   Material *ma = NULL;
-  int i, idx;
+  int idx;
 
   eGP_SeparateModes mode = RNA_enum_get(op->ptr, "mode");
+  const bool keep_ends = RNA_boolean_get(op->ptr, "keep_ends");
 
   /* sanity checks */
   if (ELEM(NULL, gpd_src)) {
@@ -4667,7 +4667,6 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
   }
 
   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_src);
-  const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_src);
 
   /* Create a new object. */
   /* Take into account user preferences for duplicating actions. */
@@ -4699,6 +4698,13 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
           gpf_dst = NULL;
 
           LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+            bool is_stroke_selected = GPENCIL_STROKE_TYPE_BEZIER(gps) ?
+                                          (bool)(gps->editcurve->flag & GP_CURVE_SELECT) :
+                                          (bool)(gps->flag & GP_STROKE_SELECT);
+
+            if (!is_stroke_selected) {
+              continue;
+            }
 
             /* skip strokes that are invalid for current view */
             if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -4708,67 +4714,199 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
             if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
               continue;
             }
-            /* Separate selected strokes. */
-            if (gps->flag & GP_STROKE_SELECT) {
-              /* add layer if not created before */
-              if (gpl_dst == NULL) {
-                gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false);
-              }
 
-              /* add frame if not created before */
-              if (gpf_dst == NULL) {
-                gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
-              }
+            /* add layer if not created before */
+            if (gpl_dst == NULL) {
+              gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false);
+            }
+
+            /* add frame if not created before */
+            if (gpf_dst == NULL) {
+              gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
+            }
+
+            /* add duplicate materials */
+
+            /* XXX same material can be in multiple slots. */
+            ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
+
+            idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
 
-              /* add duplicate materials */
+            /* selected points mode */
+            if (mode == GP_SEPARATE_POINT) {
+              /* make copy of source stroke */
+              bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true, true);
 
-              /* XXX same material can be in multiple slots. */
-              ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
+              /* Reassign material. */
+              gps_dst->mat_nr = idx;
 
-              idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
+              /* link to destination frame */
+              BLI_addtail(&gpf_dst->strokes, gps_dst);
 
-              /* selected points mode */
-              if (mode == GP_SEPARATE_POINT) {
-                if (is_curve_edit) {
-                  BKE_report(op->reports, RPT_ERROR, "Not implemented!");
+              if (GPENCIL_STROKE_TYPE_BEZIER(gps)) {
+                bGPDcurve *gpc_src = gps->editcurve;
+                bGPDcurve *gpc_dst = gps_dst->editcurve;
+
+                /* Flip the selection */
+                for (int i = 0; i < gpc_dst->tot_curve_points; i++) {
+                  bGPDcurve_point *cpt = &gpc_dst->curve_points[i];
+                  BezTriple *bezt = &cpt->bezt;
+                  if (cpt->flag & GP_CURVE_POINT_SELECT) {
+                    cpt->flag &= ~GP_CURVE_POINT_SELECT;
+                    BEZT_DESEL_ALL(bezt);
+                  }
+                  else {
+                    cpt->flag |= GP_CURVE_POINT_SELECT;
+                    BEZT_SEL_ALL(bezt);
+                  }
                 }
-                else {
-                  /* make copy of source stroke */
-                  bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true, true);
 
-                  /* Reassign material. */
-                  gps_dst->mat_nr = idx;
+                if (keep_ends) {
+                  /* Shrink the selection in the original stroke to keep the connecting points. */
+                  int tot_selected = 0, num_deselected = 0;
+
+                  bool prev_sel = false;
+                  int i;
+                  for (i = 0; i < gpc_src->tot_curve_points; i++) {
+                    bGPDcurve_point *gpc_pt = &gpc_src->curve_points[i];
+                    BezTriple *bezt = &gpc_pt->bezt;
+                    if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
+                      /* shrink if previous wasn't selected */
+                      if (prev_sel == false) {
+                        gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+                        BEZT_DESEL_ALL(bezt);
+                        num_deselected++;
+                      }
+                      prev_sel = true;
+                      tot_selected++;
+                    }
+                    else {
+                      /* mark previous as being unselected - and hence, is trigger for shrinking */
+                      prev_sel = false;
+                    }
+                  }
 
-                  /* link to destination frame */
-                  BLI_addtail(&gpf_dst->strokes, gps_dst);
+                  /* Second Pass: Go in reverse order, doing the same as before (except in opposite
+                   * order)
+                   * - This pass covers the "before" edges of selection islands
+                   */
+                  prev_sel = false;
+                  for (i = gpc_src->tot_curve_points - 1; i > 0; i--) {
+                    bGPDcurve_point *gpc_pt = &gpc_src->curve_points[i];
+                    BezTriple *bezt = &gpc_pt->bezt;
+                    if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
+                      /* shrink if previous wasn't selected */
+                      if (prev_sel == false) {
+                        gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+                        BEZT_DESEL_ALL(bezt);
+                        num_deselected++;
+                      }
+                      prev_sel = true;
+                    }
+                    else {
+                      /* mark previous as being unselected - and hence, is trigger for shrinking */
+                      prev_sel = false;
+                    }
+                  }
 
-                  /* Invert selection status of all points in destination stroke */
-                  for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
-                    pt->flag ^= GP_SPOINT_SELECT;
+                  /* Deselect curve if all points are deselected. */
+                  if (tot_selected - num_deselected == 0) {
+                    gpc_src->flag &= ~GP_CURVE_SELECT;
                   }
+                }
+
+                BKE_gpencil_curve_delete_tagged_points(
+                    gpd_dst, gpf_dst, gps_dst, NULL, gpc_dst, GP_CURVE_POINT_SELECT);
 
-                  /* delete selected points from destination stroke */
-                  BKE_gpencil_stroke_delete_tagged_points(
-                      gpd_dst, gpf_dst, gps_dst, NULL, GP_SPOINT_SELECT, false, 0);
+                BKE_gpencil_curve_delete_tagged_points(
+                    gpd_src, gpf, gps, gps->next, gpc_src, GP_CURVE_POINT_SELECT);
+              }
+              else {
 
-                  /* delete selected points from origin stroke */
-                  BKE_gpencil_stroke_delete_tagged_points(
-                      gpd_src, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
+                /* Invert selection status of all points in destination stroke */
+                for (int i = 0; i < gps_dst->totpoints; i++) {
+                  bGPDspoint *pt = &gps_dst->points[i];
+                  pt->flag ^= GP_SPOINT_SELECT;
                 }
+
+                if (keep_ends) {
+                  bGPDspoint *pt;
+                  int i, tot_selected = 0, num_deselected = 0;
+                  bool prev_sel;
+
+                  /* First Pass: Go in forward order, shrinking selection
+                   * if previous was not selected (pre changes).
+                   * - This pass covers the "after" edges of selection islands
+                   */
+                  prev_sel = false;
+                  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+                    if (pt->flag & GP_SPOINT_SELECT) {
+                      /* shrink if previous wasn't selected */
+                      if (prev_sel == false) {
+                        pt->flag &= ~GP_SPOINT_SELECT;
+                        num_deselected++;
+                      }
+                      prev_sel = true;
+                      tot_selected++;
+                    }
+                    else {
+                      /* mark previous as being unselected - and hence, is trigger for shrinking */
+                      prev_sel = false;
+                    }
+                  }
+
+                  /* Second Pass: Go in reverse order, doing the same as before (except in opposite
+                   * order)
+                   * - This pass covers the "before" edges of selection islands
+                   */
+                  prev_sel = false;
+                  for (pt -= 1; i > 0; i--, pt--) {
+                    if (pt->flag & GP_SPOINT_SELECT) {
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list