[Bf-blender-cvs] [38685b5a397] master: Edit Curve: Improve Curve extrude

Germano Cavalcante noreply at git.blender.org
Tue Mar 31 17:54:57 CEST 2020


Commit: 38685b5a3976954634b441858cf9c5df65bbe83f
Author: Germano Cavalcante
Date:   Mon Mar 30 10:10:43 2020 -0300
Branches: master
https://developer.blender.org/rB38685b5a3976954634b441858cf9c5df65bbe83f

Edit Curve: Improve Curve extrude

The original code has two logics, extrude the end points or duplicate points (making new splines).
Now all the logic has been redone by extruding contiguous selected segments.

Fix T47169

Reviewed By: campbellbarton

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

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

M	source/blender/editors/curve/editcurve.c

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

diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 2911611c516..47dcc8538d6 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -5217,9 +5217,6 @@ void CURVE_OT_spin(wmOperatorType *ot)
 
 static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb, View3D *v3d)
 {
-  Nurb *nu = NULL;
-  Nurb *nu_last = NULL;
-
   bool changed = false;
 
   Nurb *cu_actnu;
@@ -5234,211 +5231,168 @@ static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb, View3D *v3d)
   }
 
   BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p);
-  BKE_curve_nurb_vert_active_set(cu, NULL, NULL);
-
-  /* first pass (endpoints) */
-  for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
-
-    if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
-      continue;
-    }
+  int act_offset = 0;
 
+  for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) {
+    BLI_assert(nu->pntsu > 0);
+    int i;
+    int pnt_len = nu->pntsu;
+    int new_points = 0;
+    int offset = 0;
+    bool is_prev_selected = false;
     if (nu->type == CU_BEZIER) {
-
-      /* Check to see if the first bezier point is selected */
-      if (nu->pntsu > 0 && nu->bezt != NULL) {
-        BezTriple *nu_bezt_old = nu->bezt;
-        BezTriple *bezt = nu->bezt;
-
-        if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
-          BezTriple *bezt_new;
-          BEZT_DESEL_ALL(bezt);
-
-          bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__);
-          ED_curve_beztcpy(editnurb, bezt_new + 1, bezt, nu->pntsu);
-          *bezt_new = *bezt;
-
-          MEM_freeN(nu->bezt);
-          nu->bezt = bezt_new;
-
-          nu->pntsu += 1;
-
-          if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) {
-            cu_actvert.bezt = (cu_actvert.bezt == bezt) ?
-                                  bezt_new :
-                                  &nu->bezt[(cu_actvert.bezt - nu_bezt_old) + 1];
-            BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt);
-          }
-
-          BEZT_SEL_ALL(bezt_new);
-          changed = true;
+      BezTriple *bezt, *bezt_prev = NULL;
+      bool is_cyclic = false;
+      if (pnt_len == 1) {
+        /* Single point extrusion.
+         * Keep `is_prev_selected` false to force extrude. */
+        bezt_prev = &nu->bezt[0];
+      }
+      else if (nu->flagu & CU_NURB_CYCLIC) {
+        is_cyclic = true;
+        bezt_prev = &nu->bezt[pnt_len - 1];
+        is_prev_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt_prev);
+      }
+      i = pnt_len;
+      for (bezt = &nu->bezt[0]; i--; bezt++) {
+        bool is_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt);
+        if (bezt_prev && is_prev_selected != is_selected) {
+          new_points++;
+        }
+        if (bezt == cu_actvert.bezt) {
+          act_offset = new_points;
+        }
+        bezt_prev = bezt;
+        is_prev_selected = is_selected;
+      }
+
+      if (new_points) {
+        if (pnt_len == 1) {
+          /* Single point extrusion.
+           * Set `is_prev_selected` as false to force extrude. */
+          BLI_assert(bezt_prev == &nu->bezt[0]);
+          is_prev_selected = false;
+        }
+        else if (is_cyclic) {
+          BLI_assert(bezt_prev == &nu->bezt[pnt_len - 1]);
+          BLI_assert(is_prev_selected == BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt_prev));
         }
-      }
-
-      /* Check to see if the last bezier point is selected */
-      if (nu->pntsu > 1) {
-        BezTriple *nu_bezt_old = nu->bezt;
-        BezTriple *bezt = &nu->bezt[nu->pntsu - 1];
-
-        if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
-          BezTriple *bezt_new;
-          BEZT_DESEL_ALL(bezt);
-
-          bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__);
-          ED_curve_beztcpy(editnurb, bezt_new, nu->bezt, nu->pntsu);
-          bezt_new[nu->pntsu] = *bezt;
-
-          MEM_freeN(nu->bezt);
-          nu->bezt = bezt_new;
-
-          bezt_new += nu->pntsu;
-          nu->pntsu += 1;
+        else {
+          bezt_prev = NULL;
+        }
+        BezTriple *bezt_src, *bezt_dst, *bezt_src_iter, *bezt_dst_iter;
+        bezt_src = nu->bezt;
+        bezt_dst = MEM_mallocN((pnt_len + new_points) * sizeof(BezTriple), __func__);
+        bezt_src_iter = &bezt_src[0];
+        bezt_dst_iter = &bezt_dst[0];
+        i = 0;
+        for (bezt = &nu->bezt[0]; i < pnt_len; i++, bezt++) {
+          bool is_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt);
+          if (bezt_prev && is_prev_selected != is_selected) {
+            int count = i - offset + 1;
+            if (is_prev_selected) {
+              ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, count - 1);
+              ED_curve_beztcpy(editnurb, &bezt_dst_iter[count - 1], bezt_prev, 1);
+            }
+            else {
+              ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, count);
+            }
+            ED_curve_beztcpy(editnurb, &bezt_dst_iter[count], bezt, 1);
+            BEZT_DESEL_ALL(&bezt_dst_iter[count - 1]);
 
-          if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) {
-            cu_actvert.bezt = (cu_actvert.bezt == bezt) ? bezt_new :
-                                                          &nu->bezt[cu_actvert.bezt - nu_bezt_old];
-            BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt);
+            bezt_dst_iter += count + 1;
+            bezt_src_iter += count;
+            offset = i + 1;
           }
+          bezt_prev = bezt;
+          is_prev_selected = is_selected;
+        }
 
-          BEZT_SEL_ALL(bezt_new);
-          changed = true;
+        int remain = pnt_len - offset;
+        if (remain) {
+          ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, pnt_len - offset);
         }
+
+        MEM_freeN(nu->bezt);
+        nu->bezt = bezt_dst;
+        nu->pntsu += new_points;
+        changed = true;
       }
     }
     else {
-
-      /* Check to see if the first bpoint is selected */
-      if (nu->pntsu > 0 && nu->bp != NULL) {
-        BPoint *nu_bp_old = nu->bp;
-        BPoint *bp = nu->bp;
-
-        if (bp->f1 & SELECT) {
-          BPoint *bp_new;
-          bp->f1 &= ~SELECT;
-
-          bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__);
-          ED_curve_bpcpy(editnurb, bp_new + 1, bp, nu->pntsu);
-          *bp_new = *bp;
-
-          MEM_freeN(nu->bp);
-          nu->bp = bp_new;
-
-          nu->pntsu += 1;
-          BKE_nurb_knot_calc_u(nu);
-
-          if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) {
-            cu_actvert.bp = (cu_actvert.bp == bp) ? bp_new :
-                                                    &nu->bp[(cu_actvert.bp - nu_bp_old) + 1];
-            BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp);
-          }
-
-          bp_new->f1 |= SELECT;
-          changed = true;
-        }
+      BPoint *bp, *bp_prev = NULL;
+      if (pnt_len == 1) {
+        /* Single point extrusion.
+         * Reference a `prev_bp` to force extrude. */
+        bp_prev = &nu->bp[0];
       }
-
-      /* Check to see if the last bpoint is selected */
-      if (nu->pntsu > 1) {
-        BPoint *nu_bp_old = nu->bp;
-        BPoint *bp = &nu->bp[nu->pntsu - 1];
-
-        if (bp->f1 & SELECT) {
-          BPoint *bp_new;
-          bp->f1 &= ~SELECT;
-
-          bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__);
-          ED_curve_bpcpy(editnurb, bp_new, nu->bp, nu->pntsu);
-          bp_new[nu->pntsu] = *bp;
-
-          MEM_freeN(nu->bp);
-          nu->bp = bp_new;
-
-          bp_new += nu->pntsu;
-          nu->pntsu += 1;
-
-          if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) {
-            cu_actvert.bp = (cu_actvert.bp == bp) ? bp_new : &nu->bp[cu_actvert.bp - nu_bp_old];
-            BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp);
-          }
-
-          BKE_nurb_knot_calc_u(nu);
-
-          bp_new->f1 |= SELECT;
-          changed = true;
+      i = pnt_len;
+      for (bp = &nu->bp[0]; i--; bp++) {
+        bool is_selected = (bp->f1 & SELECT) != 0;
+        if (bp_prev && is_prev_selected != is_selected) {
+          new_points++;
         }
+        if (bp == cu_actvert.bp) {
+          act_offset = new_points;
+        }
+        bp_prev = bp;
+        is_prev_selected = is_selected;
       }
-    }
-  }
-
-  /* second pass (interior points) */
-  nu_last = editnurb->nurbs.last;
-  for (nu = editnurb->nurbs.first; (nu != nu_last->next); nu = nu->next) {
-    int i, i_end;
-
-    if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
-      /* all points are interior */
-      i = 0;
-      i_end = nu->pntsu;
-    }
-    else {
-      /* skip endpoints */
-      i = 1;
-      i_end = nu->pntsu - 1;
-    }
-
-    if (nu->type == CU_BEZIER) {
-      BezTriple *bezt;
 
-      for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) {
-        if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
-          Nurb *nurb_new;
-          BezTriple *bezt_new;
-
-          BEZT_DESEL_ALL(bezt);
-          nurb_new = BKE_nurb_copy(nu, 1, 1);
-          nurb_new->flagu &= ~CU_NURB_CYCLIC;
-          BLI_addtail(&editnurb->nurbs, nurb_new);
-          bezt_new = nurb_new->bezt;
-          ED_curve_beztcpy(editnurb, bezt_new, bezt, 1);
-          BEZT_SEL_ALL(bezt_new);
+      if (new_points) {
+        BPoint *bp_src, *bp_dst, *bp_src_iter, *bp_dst_iter;
+        is_prev_selected = false;
+        if (pnt_len == 1) {
+          /* Single point extrusion.
+           * Keep `is_prev_selected` false to force extrude. */
+          BLI_assert(bp_prev == &nu->bp[0]);
+        }
+        else {
+          bp_prev = NULL;
+        }
+        bp_src = nu->bp;
+        bp_dst = MEM_mallocN((pnt_len + new_points) * sizeof(BPoint), __func__);
+        bp_src_iter = &bp_src[0];
+        bp_dst_iter = &bp_dst[0];
+        i = 0;
+        for (bp = &nu->bp[0]; i < pnt_len; i++, bp++) {
+          bool is_selected = (bp->f1 & SELECT) != 0;
+          if (bp_prev && is_prev_selected != is_selected) {
+            int count = i - offset + 1;
+            if (is_prev_selected) {
+   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list