Commit: 027361c898b343a9c89182ebc15c1737e60946fc
Author: Campbell Barton
Date:   Mon Jan 26 20:55:41 2015 +1100
Branches: master
https://developer.blender.org/rB027361c898b343a9c89182ebc15c1737e60946fc

Fix T41834: Ctrl+LMB, Extrude Curves 2+ splines

Extrude and Ctrl+LMB now support multiple selected vertices.
Also maintain active vertices.

D964 by Tyler Sliwkanich with own modifications

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

M       source/blender/blenkernel/BKE_curve.h
M       source/blender/blenkernel/intern/curve.c
M       source/blender/editors/curve/editcurve.c

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

diff --git a/source/blender/blenkernel/BKE_curve.h 
b/source/blender/blenkernel/BKE_curve.h
index 13a1468..60cbf8b 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -176,6 +176,7 @@ void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct 
BezTriple *bezt, float r_p
 void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev,  
struct BezTriple *next,
                           const bool is_fcurve);
 void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
+void BKE_nurb_handle_calc_simple_auto(struct Nurb *nu, struct BezTriple *bezt);
 
 void BKE_nurb_handles_calc(struct Nurb *nu);
 void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
diff --git a/source/blender/blenkernel/intern/curve.c 
b/source/blender/blenkernel/intern/curve.c
index f1e9f2b..51330f2 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -3351,6 +3351,21 @@ void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple 
*bezt)
        }
 }
 
+void BKE_nurb_handle_calc_simple_auto(Nurb *nu, BezTriple *bezt)
+{
+       if (nu->pntsu > 1) {
+               const char h1_back = bezt->h1, h2_back = bezt->h2;
+
+               bezt->h1 = bezt->h2 = HD_AUTO;
+
+               /* Override handle types to HD_AUTO and recalculate */
+               BKE_nurb_handle_calc_simple(nu, bezt);
+
+               bezt->h1 = h1_back;
+               bezt->h2 = h2_back;
+       }
+}
+
 /**
  * Use when something has changed handle positions.
  *
@@ -3608,24 +3623,12 @@ void BKE_nurbList_handles_recalculate(ListBase 
*editnurb, const bool calc_length
 
                                if (h1_select || h2_select) {
 
-                                       /* Override handle types to HD_AUTO and 
recalculate */
-
-                                       char h1_back, h2_back;
                                        float co1_back[3], co2_back[3];
 
-                                       h1_back = bezt->h1;
-                                       h2_back = bezt->h2;
-
-                                       bezt->h1 = HD_AUTO;
-                                       bezt->h2 = HD_AUTO;
-
                                        copy_v3_v3(co1_back, bezt->vec[0]);
                                        copy_v3_v3(co2_back, bezt->vec[2]);
 
-                                       BKE_nurb_handle_calc_simple(nu, bezt);
-
-                                       bezt->h1 = h1_back;
-                                       bezt->h2 = h2_back;
+                                       BKE_nurb_handle_calc_simple_auto(nu, 
bezt);
 
                                        if (h1_select) {
                                                if (!calc_length) {
diff --git a/source/blender/editors/curve/editcurve.c 
b/source/blender/editors/curve/editcurve.c
index 25dedee..f17c462 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -2007,7 +2007,7 @@ static void ed_curve_delete_selected(Object *obedit)
 }
 
 /* only for OB_SURF */
-bool ed_editnurb_extrude_flag(EditNurb *editnurb, short flag)
+bool ed_editnurb_extrude_flag(EditNurb *editnurb, const short flag)
 {
        Nurb *nu;
        BPoint *bp, *bpn, *newbp;
@@ -4888,285 +4888,405 @@ void CURVE_OT_spin(wmOperatorType *ot)
        RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, 
"Axis", "Axis in global view space", -1.0f, 1.0f);
 }
 
-/***************** add vertex operator **********************/
+/***************** extrude vertex operator **********************/
 
-static int addvert_Nurb(bContext *C, short mode, float location[3])
+static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb)
 {
-       Object *obedit = CTX_data_edit_object(C);
-       Curve *cu = (Curve *)obedit->data;
-       EditNurb *editnurb = cu->editnurb;
-       Nurb *nu, *newnu = NULL;
-       BezTriple *bezt, *newbezt = NULL;
-       BPoint *bp, *newbp = NULL;
-       float imat[4][4], temp[3];
-       bool ok = false;
-       BezTriple *bezt_recalc[3] = {NULL};
+       Nurb *nu = NULL;
+       Nurb *nu_last = NULL;
 
-       invert_m4_m4(imat, obedit->obmat);
+       bool changed = false;
 
-       findselectedNurbvert(&editnurb->nurbs, &nu, &bezt, &bp);
-
-       if ((nu == NULL) || (nu->type == CU_BEZIER && bezt == NULL) || 
(nu->type != CU_BEZIER && bp == NULL)) {
-               if (mode != 'e') {
-                       if (cu->actnu != CU_ACT_NONE)
-                               nu = BLI_findlink(&editnurb->nurbs, cu->actnu);
-
-                       if (!nu || nu->type == CU_BEZIER) {
-                               newbezt = (BezTriple 
*)MEM_callocN(sizeof(BezTriple), "addvert_Nurb");
-                               newbezt->radius = 1;
-                               newbezt->alfa = 0;
-                               BEZ_SEL(newbezt);
-                               newbezt->h2 = newbezt->h1 = HD_AUTO;
-
-                               newnu = (Nurb *)MEM_callocN(sizeof(Nurb), 
"addvert_Nurb newnu");
-                               if (!nu) {
-                                       /* no selected segment -- create new 
one which is BEZIER type
-                                        * type couldn't be determined from 
Curve bt could be changed
-                                        * in the future, so shouldn't make 
much headache */
-                                       newnu->type = CU_BEZIER;
-                                       newnu->resolu = cu->resolu;
-                                       newnu->flag |= CU_SMOOTH;
-                               }
-                               else {
-                                       memcpy(newnu, nu, sizeof(Nurb));
-                               }
+       Nurb *cu_actnu;
+       union {
+               BezTriple *bezt;
+               BPoint    *bp;
+               void      *p;
+       } cu_actvert;
 
-                               BLI_addtail(&editnurb->nurbs, newnu);
-                               newnu->bezt = newbezt;
-                               newnu->pntsu = 1;
+       BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p);
+       BKE_curve_nurb_vert_active_set(cu, NULL, NULL);
 
-                               temp[0] = 1;
-                               temp[1] = 0;
-                               temp[2] = 0;
+       /* first pass (endpoints) */
+       for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
 
-                               copy_v3_v3(newbezt->vec[1], location);
-                               sub_v3_v3v3(newbezt->vec[0], newbezt->vec[1], 
temp);
-                               add_v3_v3v3(newbezt->vec[2], newbezt->vec[1], 
temp);
+               if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
+                       continue;
+               }
 
-                               mul_m4_v3(imat, newbezt->vec[0]);
-                               mul_m4_v3(imat, newbezt->vec[1]);
-                               mul_m4_v3(imat, newbezt->vec[2]);
+               if (nu->type == CU_BEZIER) {
 
-                               ok = 1;
-                               nu = newnu;
-                       }
-                       else if (nu->pntsv == 1) {
-                               newbp = (BPoint *)MEM_callocN(sizeof(BPoint), 
"addvert_Nurb5");
-                               newbp->radius = 1;
-                               newbp->alfa = 0;
-                               newbp->f1 |= SELECT;
+                       /* 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;
 
-                               newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), 
"addvert_Nurb newnu");
-                               memcpy(newnu, nu, sizeof(Nurb));
-                               BLI_addtail(&editnurb->nurbs, newnu);
-                               newnu->bp = newbp;
-                               newnu->orderu = 2;
-                               newnu->pntsu = 1;
+                               if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+                                       BezTriple *bezt_new;
+                                       BEZ_DESEL(bezt);
 
-                               mul_v3_m4v3(newbp->vec, imat, location);
-                               newbp->vec[3] = 1.0;
+                                       bezt_new = MEM_mallocN((nu->pntsu + 1) 
* sizeof(BezTriple), __func__);
+                                       ED_curve_beztcpy(editnurb, bezt_new + 
1, bezt, nu->pntsu);
+                                       *bezt_new = *bezt;
 
-                               newnu->knotsu = newnu->knotsv = NULL;
-                               BKE_nurb_knot_calc_u(newnu);
 
-                               ok = 1;
-                               nu = newnu;
+                                       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);
+                                       }
+
+                                       BEZ_SEL(bezt_new);
+                                       changed = true;
+                               }
                        }
 
+                       /* 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 (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+                                       BezTriple *bezt_new;
+                                       BEZ_DESEL(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;
+
+                                       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);
+                                       }
+
+                                       BEZ_SEL(bezt_new);
+                                       changed = true;
+                               }
+                       }
                }
+               else {
 
-               if (!ok)
-                       return OPERATOR_CANCELLED;
-       }
+                       /* 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 (!ok && nu->type == CU_BEZIER) {
-               /* which bezpoint? */
-               if (bezt == &nu->bezt[nu->pntsu - 1]) {  /* last */
-                       BEZ_DESEL(bezt);
-                       newbezt = (BezTriple *)MEM_callocN((nu->pntsu + 1) * 
sizeof(BezTriple), "addvert_Nurb");
-                       ED_curve_beztcpy(editnurb, newbezt, nu->bezt, 
nu->pntsu);
-                       newbezt[nu->pntsu] = *bezt;
-                       copy_v3_v3(temp, bezt->vec[1]);
-                       MEM_freeN(nu->bezt);
-                       nu->bezt = newbezt;
-                       newbezt += nu->pntsu;
-                       BEZ_SEL(newbezt);
-                       newbezt->h1 = newbezt->h2;
-                       bezt = &nu->bezt[nu->pntsu - 1];
-                       ok = 1;
+                               if (bp->f1 & SELECT) {
+                                       BPoint *bp_new;
+                                       bp->f1 &= ~SELECT;
 
-                       if (nu->pntsu > 1) {
-                               bezt_recalc[1] = newbezt;
-                               bezt_recalc[0] = newbezt - 1;
-                       }
-               }
-               else if (bezt == nu->bezt) {   /* first */
-                       BEZ_DESEL(bezt);
-                       newbezt = (BezTriple *)MEM_callocN((nu->pntsu + 1) * 
sizeof(BezTriple), "addvert_Nurb");
-                       ED_curve_beztcpy(editnurb, newbezt + 1, bezt, 
nu->pntsu);
-                       *newbezt = *bezt;
-                       BEZ_SEL(newbezt);
-                       newbezt->h2 = newbezt->h1;
-                       copy_v3_v3(temp, bezt->vec[1]);
-                       MEM_freeN(nu->bezt);
-                       nu->bezt = newbezt;
-                       bezt = newbezt + 1;
-                       ok = 1;
+                                       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;
+                               }
+                       }
+
+                       /* Check to see if the last bpoint is selected */
                        if (nu->pntsu > 1) {
-                               bezt_recalc[1] = newbezt;
-                               bezt_recalc[2] = newbezt + 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)

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to