Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <germano.costa@ig.com.br>2020-03-30 16:10:43 +0300
committerGermano Cavalcante <germano.costa@ig.com.br>2020-03-31 18:39:53 +0300
commit38685b5a3976954634b441858cf9c5df65bbe83f (patch)
tree023207adb47e0837b3f15b9bd9d650fbb2ab4d89 /source/blender/editors/curve/editcurve.c
parent1c1a14dcdfffd8572bade4f9a55784eb6bc94d5f (diff)
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
Diffstat (limited to 'source/blender/editors/curve/editcurve.c')
-rw-r--r--source/blender/editors/curve/editcurve.c322
1 files changed, 138 insertions, 184 deletions
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) {
+ ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, count - 1);
+ ED_curve_bpcpy(editnurb, &bp_dst_iter[count - 1], bp_prev, 1);
+ }
+ else {
+ ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, count);
+ }
+ ED_curve_bpcpy(editnurb, &bp_dst_iter[count], bp, 1);
+ bp_dst_iter[count - 1].f1 &= ~SELECT;
- if (cu_actvert.bezt == bezt || cu_actnu == NULL) {
- BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new);
+ bp_dst_iter += count + 1;
+ bp_src_iter += count;
+ offset = i + 1;
}
-
- changed = true;
+ bp_prev = bp;
+ is_prev_selected = is_selected;
}
- }
- }
- else {
- BPoint *bp;
- for (bp = &nu->bp[i]; i < i_end; i++, bp++) {
- if (bp->f1 & SELECT) {
- Nurb *nurb_new;
- BPoint *bp_new;
-
- bp->f1 &= ~SELECT;
- nurb_new = BKE_nurb_copy(nu, 1, 1);
- nurb_new->flagu &= ~CU_NURB_CYCLIC;
- BLI_addtail(&editnurb->nurbs, nurb_new);
- bp_new = nurb_new->bp;
- ED_curve_bpcpy(editnurb, bp_new, bp, 1);
- bp_new->f1 |= SELECT;
+ int remain = pnt_len - offset;
+ if (remain) {
+ ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, pnt_len - offset);
+ }
- if (cu_actvert.bp == bp || cu_actnu == NULL) {
- BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new);
- }
+ MEM_freeN(nu->bp);
+ nu->bp = bp_dst;
+ nu->pntsu += new_points;
- changed = true;
- }
+ BKE_nurb_knot_calc_u(nu);
+ changed = true;
}
}
}
- if (changed == false) {
- BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p);
- }
+ cu->actvert += act_offset;
return changed;
}