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:
authorKevin Mackay <mackay.ka@gmail.com>2013-10-17 23:57:14 +0400
committerKevin Mackay <mackay.ka@gmail.com>2013-10-17 23:57:14 +0400
commit4230b8f9c4cc0b71bb1d361d16c5dbe82e24ee9c (patch)
tree9b933b1e46224b841e1b805836afacaa2d298893 /source/blender
parent27a662f670a8f06a554c32c51f3d4b4884f64848 (diff)
Patch [#37115] Surface split and separate operators
Added surface support to recent curve split operator, completing quick hack todo Updated nurbs separate operator to make use of new split logic, completing tools todo Added 'Delete segment' option to surfaces and improved surface duplication, used for split/separate
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_curve.h1
-rw-r--r--source/blender/blenkernel/intern/curve.c20
-rw-r--r--source/blender/editors/curve/editcurve.c1139
-rw-r--r--source/blender/makesdna/DNA_curve_types.h2
4 files changed, 671 insertions, 491 deletions
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 07116979eab..dee27cebf59 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -119,6 +119,7 @@ void BKE_nurbList_flag_set(ListBase *editnurb, short flag);
void BKE_nurb_free(struct Nurb *nu);
struct Nurb *BKE_nurb_duplicate(struct Nurb *nu);
+struct Nurb *BKE_nurb_copy(struct Nurb *src, int pntsu, int pntsv);
void BKE_nurb_test2D(struct Nurb *nu);
void BKE_nurb_minmax(struct Nurb *nu, float min[3], float max[3]);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index e255732d3fb..ca9f97b754c 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -579,6 +579,26 @@ Nurb *BKE_nurb_duplicate(Nurb *nu)
return newnu;
}
+/* copy the nurb but allow for different number of points (to be copied after this) */
+Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
+{
+ Nurb *newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "copyNurb");
+ memcpy(newnu, src, sizeof(Nurb));
+
+ if (pntsu == 1) SWAP(int, pntsu, pntsv);
+ newnu->pntsu = pntsu;
+ newnu->pntsv = pntsv;
+
+ if (src->bezt) {
+ newnu->bezt = (BezTriple *)MEM_mallocN(pntsu * pntsv * sizeof(BezTriple), "copyNurb2");
+ }
+ else {
+ newnu->bp = (BPoint *)MEM_mallocN(pntsu * pntsv * sizeof(BPoint), "copyNurb3");
+ }
+
+ return newnu;
+}
+
void BKE_nurbList_duplicate(ListBase *lb1, ListBase *lb2)
{
Nurb *nu, *nun;
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 2dc32f711b4..24065321f8b 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -111,7 +111,7 @@ typedef enum eCurveElem_Types {
void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
static void select_adjacent_cp(ListBase *editnurb, short next, const bool cont, const bool selstatus);
static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
-static int curve_delete_selected(Object *obedit, const eCurveElem_Types type, const bool split);
+static int curve_delete_segments(Object *obedit, const bool split);
ListBase *object_editcurve_get(Object *ob)
{
@@ -1373,16 +1373,15 @@ static int separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Nurb *nu, *nu1;
Object *oldob, *newob;
Base *oldbase, *newbase;
Curve *oldcu, *newcu;
- EditNurb *oldedit, *newedit;
+ EditNurb *newedit;
+ ListBase newnurb = {NULL, NULL};
oldbase = CTX_data_active_base(C);
oldob = oldbase->object;
oldcu = oldob->data;
- oldedit = oldcu->editnurb;
if (oldcu->key) {
BKE_report(op->reports, RPT_ERROR, "Cannot separate a curve with vertex keys");
@@ -1390,44 +1389,43 @@ static int separate_exec(bContext *C, wmOperator *op)
}
WM_cursor_wait(1);
-
- /* 1. duplicate the object and data */
+
+ /* 1. duplicate geometry and check for valid selection for separate */
+ adduplicateflagNurb(oldob, &newnurb, SELECT, true);
+
+ if (newnurb.first == NULL) {
+ WM_cursor_wait(0);
+ BKE_report(op->reports, RPT_ERROR, "Cannot separate current selection");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* 2. duplicate the object and data */
newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */
DAG_relations_tag_update(bmain);
- ED_base_object_select(newbase, BA_DESELECT);
newob = newbase->object;
-
newcu = newob->data = BKE_curve_copy(oldcu);
newcu->editnurb = NULL;
oldcu->id.us--; /* because new curve is a copy: reduce user count */
- /* 2. put new object in editmode and clear it */
+ /* 3. put new object in editmode, clear it and set separated nurbs */
make_editNurb(newob);
newedit = newcu->editnurb;
BKE_nurbList_free(&newedit->nurbs);
BKE_curve_editNurb_keyIndex_free(newedit);
newedit->keyindex = NULL;
+ BLI_movelisttolist(&newedit->nurbs, &newnurb);
- /* 3. move over parts from old object */
- for (nu = oldedit->nurbs.first; nu; nu = nu1) {
- nu1 = nu->next;
-
- if (isNurbsel(nu)) {
- keyIndex_delNurb(oldedit, nu);
- BLI_remlink(&oldedit->nurbs, nu);
- BLI_addtail(&newedit->nurbs, nu);
- }
- }
-
- /* 4. put old object out of editmode */
+ /* 4. put old object out of editmode and delete separated geometry */
load_editNurb(newob);
free_editNurb(newob);
+ curve_delete_segments(oldob, true);
DAG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */
DAG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */
WM_event_add_notifier(C, NC_GEOM | ND_DATA, oldob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
WM_cursor_wait(0);
@@ -1439,7 +1437,7 @@ void CURVE_OT_separate(wmOperatorType *ot)
/* identifiers */
ot->name = "Separate";
ot->idname = "CURVE_OT_separate";
- ot->description = "Separate (partly) selected curves or surfaces into a new object";
+ ot->description = "Separate selected points from connected unselected points into a new object";
/* api callbacks */
ot->exec = separate_exec;
@@ -1460,7 +1458,7 @@ static int curve_split_exec(bContext *C, wmOperator *op)
adduplicateflagNurb(obedit, &newnurb, SELECT, true);
if (newnurb.first != NULL) {
- curve_delete_selected(obedit, CURVE_SEGMENT, true);
+ curve_delete_segments(obedit, true);
BLI_movelisttolist(editnurb, &newnurb);
if (ED_curve_updateAnimPaths(obedit->data))
@@ -1486,7 +1484,7 @@ void CURVE_OT_split(wmOperatorType *ot)
/* api callbacks */
ot->exec = curve_split_exec;
- ot->poll = ED_operator_editcurve;
+ ot->poll = ED_operator_editsurfcurve;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1539,6 +1537,57 @@ static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
return 0;
}
+/* return true if U direction is selected and number of selected columns v */
+static bool isNurbselU(Nurb *nu, int *v, int flag)
+{
+ BPoint *bp;
+ int a, b, sel;
+
+ *v = 0;
+
+ for (b = 0, bp = nu->bp; b < nu->pntsv; b++) {
+ sel = 0;
+ for (a = 0; a < nu->pntsu; a++, bp++) {
+ if (bp->f1 & flag) sel++;
+ }
+ if (sel == nu->pntsu) {
+ (*v)++;
+ }
+ else if (sel >= 1) {
+ *v = 0;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* return true if V direction is selected and number of selected rows u */
+static bool isNurbselV(Nurb *nu, int *u, int flag)
+{
+ BPoint *bp;
+ int a, b, sel;
+
+ *u = 0;
+
+ for (a = 0; a < nu->pntsu; a++) {
+ bp = &nu->bp[a];
+ sel = 0;
+ for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) {
+ if (bp->f1 & flag) sel++;
+ }
+ if (sel == nu->pntsv) {
+ (*u)++;
+ }
+ else if (sel >= 1) {
+ *u = 0;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
static void rotateflagNurb(ListBase *editnurb, short flag, const float cent[3], float rotmat[3][3])
{
/* all verts with (flag & 'flag') rotate */
@@ -1622,7 +1671,7 @@ static int deleteflagNurb(Object *obedit, short flag)
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu, *next;
BPoint *bp, *bpn, *newbp;
- int a, b, newu, newv, sel;
+ int a, b, newu, newv;
if (obedit->type != OB_SURF) {
return OPERATOR_CANCELLED;
@@ -1653,62 +1702,36 @@ static int deleteflagNurb(Object *obedit, short flag)
BKE_nurb_free(nu); nu = NULL;
}
else {
- /* is nurb in U direction selected */
- newv = nu->pntsv;
- bp = nu->bp;
- for (b = 0; b < nu->pntsv; b++) {
- sel = 0;
- for (a = 0; a < nu->pntsu; a++, bp++) {
- if (bp->f1 & flag) sel++;
- }
- if (sel == nu->pntsu) {
- newv--;
- }
- else if (sel >= 1) {
- /* don't delete */
- break;
- }
- }
- if (newv != nu->pntsv && b == nu->pntsv) {
- /* delete */
- bp = nu->bp;
- bpn = newbp = (BPoint *)MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb");
- for (b = 0; b < nu->pntsv; b++) {
- if ((bp->f1 & flag) == 0) {
- memcpy(bpn, bp, nu->pntsu * sizeof(BPoint));
- keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu);
- bpn += nu->pntsu;
- }
- else {
- keyIndex_delBP(cu->editnurb, bp);
+ if (isNurbselU(nu, &newv, flag)) {
+ /* U direction selected */
+ newv = nu->pntsv - newv;
+ if (newv != nu->pntsv) {
+ /* delete */
+ bp = nu->bp;
+ bpn = newbp = (BPoint *)MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb");
+ for (b = 0; b < nu->pntsv; b++) {
+ if ((bp->f1 & flag) == 0) {
+ memcpy(bpn, bp, nu->pntsu * sizeof(BPoint));
+ keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu);
+ bpn += nu->pntsu;
+ }
+ else {
+ keyIndex_delBP(cu->editnurb, bp);
+ }
+ bp += nu->pntsu;
}
- bp += nu->pntsu;
- }
- nu->pntsv = newv;
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- BKE_nurb_order_clamp_v(nu);
+ nu->pntsv = newv;
+ MEM_freeN(nu->bp);
+ nu->bp = newbp;
+ BKE_nurb_order_clamp_v(nu);
- BKE_nurb_knot_calc_v(nu);
- }
- else {
- /* is the nurb in V direction selected */
- newu = nu->pntsu;
- for (a = 0; a < nu->pntsu; a++) {
- bp = &nu->bp[a];
- sel = 0;
- for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) {
- if (bp->f1 & flag) sel++;
- }
- if (sel == nu->pntsv) {
- newu--;
- }
- else if (sel >= 1) {
- /* don't delete */
- break;
- }
+ BKE_nurb_knot_calc_v(nu);
}
- if (newu != nu->pntsu && a == nu->pntsu) {
+ }
+ else if (isNurbselV(nu, &newu, flag)) {
+ /* V direction selected */
+ newu = nu->pntsu - newu;
+ if (newu != nu->pntsu) {
/* delete */
bp = nu->bp;
bpn = newbp = (BPoint *)MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb");
@@ -1872,21 +1895,18 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
const short flag, const bool split)
{
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu, *newnu, *startnu;
+ Nurb *nu = editnurb->last, *newnu;
BezTriple *bezt, *bezt1;
- BPoint *bp, *bp1;
+ BPoint *bp, *bp1, *bp2, *bp3;
Curve *cu = (Curve *)obedit->data;
- int a, b, starta, enda, diffa, newu, newv;
+ int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv;
char *usel;
cu->lastsel = NULL;
-
- nu = editnurb->last;
while (nu) {
- startnu = NULL;
+ cyclicu = cyclicv = 0;
if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- for (a = 0; a < nu->pntsu; a++) {
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
enda = -1;
starta = a;
while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) {
@@ -1897,46 +1917,45 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
bezt++;
}
if (enda >= starta) {
- diffa = enda - starta + 1;
-
- if (startnu != NULL && enda == nu->pntsu - 1) {
- /* end point of cyclic spline selected, so merge end points with start points */
- bezt1 = (BezTriple *)MEM_mallocN((startnu->pntsu + diffa) * sizeof(BezTriple), "adduplicateN");
- memcpy(bezt1, &nu->bezt[starta], diffa * sizeof(BezTriple));
- memcpy(&bezt1[diffa], startnu->bezt, startnu->pntsu * sizeof(BezTriple));
-
- MEM_freeN(startnu->bezt);
- startnu->bezt = bezt1;
- startnu->pntsu += diffa;
- newnu = startnu;
+ newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
+
+ if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) {
+ cyclicu = newu;
}
else {
- newnu = ED_curve_nurbcpy(nu, diffa);
+ if (enda == nu->pntsu - 1) newu += cyclicu;
+
+ newnu = BKE_nurb_copy(nu, newu, 1);
BLI_addtail(newnurb, newnu);
set_actNurb(obedit, newnu);
- memcpy(newnu->bezt, &nu->bezt[starta], newnu->pntsu * sizeof(BezTriple));
- }
+ memcpy(newnu->bezt, &nu->bezt[starta], diffa * sizeof(BezTriple));
+ if (newu != diffa) {
+ memcpy(&newnu->bezt[diffa], nu->bezt, cyclicu * sizeof(BezTriple));
+ cyclicu = 0;
+ }
- b = newnu->pntsu;
- bezt1 = newnu->bezt;
- while (b--) {
- select_beztriple(bezt1, SELECT, flag, HIDDEN);
- bezt1++;
- }
+ if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
- if (nu->flagu & CU_NURB_CYCLIC) {
- if (starta != 0 || enda != nu->pntsu - 1) {
- newnu->flagu &= ~CU_NURB_CYCLIC;
- if (starta == 0) startnu = newnu;
+ for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, SELECT, flag, HIDDEN);
}
}
}
- bezt++;
+ }
+
+ if (cyclicu != 0) {
+ newnu = BKE_nurb_copy(nu, cyclicu, 1);
+ BLI_addtail(newnurb, newnu);
+ memcpy(newnu->bezt, nu->bezt, cyclicu * sizeof(BezTriple));
+ newnu->flagu &= ~CU_NURB_CYCLIC;
+
+ for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, SELECT, flag, HIDDEN);
+ }
}
}
else if (nu->pntsv == 1) { /* because UV Nurb has a different method for dupli */
- bp = nu->bp;
- for (a = 0; a < nu->pntsu; a++) {
+ for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
enda = -1;
starta = a;
while (bp->f1 & flag) {
@@ -1947,46 +1966,48 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
bp++;
}
if (enda >= starta) {
- diffa = enda - starta + 1;
-
- if (startnu != NULL && enda == nu->pntsu - 1) {
- /* end point of cyclic spline selected, so merge end points with start points */
- bp1 = (BPoint *)MEM_mallocN((startnu->pntsu + diffa) * sizeof(BPoint), "adduplicateN2");
- memcpy(bp1, &nu->bp[starta], diffa * sizeof(BPoint));
- memcpy(&bp1[diffa], startnu->bp, startnu->pntsu * sizeof(BPoint));
-
- MEM_freeN(startnu->bp);
- startnu->bp = bp1;
- startnu->pntsu += diffa;
- newnu = startnu;
+ newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
+
+ if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) {
+ cyclicu = newu;
}
else {
- newnu = ED_curve_nurbcpy(nu, diffa);
+ if (enda == nu->pntsu - 1) newu += cyclicu;
+
+ newnu = BKE_nurb_copy(nu, newu, 1);
BLI_addtail(newnurb, newnu);
set_actNurb(obedit, newnu);
- memcpy(newnu->bp, &nu->bp[starta], newnu->pntsu * sizeof(BPoint));
- }
+ memcpy(newnu->bp, &nu->bp[starta], diffa * sizeof(BPoint));
+ if (newu != diffa) {
+ memcpy(&newnu->bp[diffa], nu->bp, cyclicu * sizeof(BPoint));
+ cyclicu = 0;
+ }
- b = newnu->pntsu;
- bp1 = newnu->bp;
- while (b--) {
- select_bpoint(bp1, SELECT, flag, HIDDEN);
- bp1++;
- }
+ if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
- if (nu->flagu & CU_NURB_CYCLIC) {
- if (starta != 0 || enda != nu->pntsu - 1) {
- newnu->flagu &= ~CU_NURB_CYCLIC;
- if (starta == 0) startnu = newnu;
+ for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
+ select_bpoint(bp1, SELECT, flag, HIDDEN);
}
}
}
- bp++;
+ }
+
+ if (cyclicu != 0) {
+ newnu = BKE_nurb_copy(nu, cyclicu, 1);
+ BLI_addtail(newnurb, newnu);
+ set_actNurb(obedit, newnu);
+
+ memcpy(newnu->bp, nu->bp, cyclicu * sizeof(BPoint));
+ newnu->flagu &= ~CU_NURB_CYCLIC;
+
+ for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
+ select_bpoint(bp1, SELECT, flag, HIDDEN);
+ }
}
}
else {
- /* a rectangular area in nurb has to be selected */
if (isNurbsel(nu)) {
+ /* a rectangular area in nurb has to be selected and if splitting must be in U or V direction */
usel = MEM_callocN(nu->pntsu, "adduplicateN3");
bp = nu->bp;
for (a = 0; a < nu->pntsv; a++) {
@@ -2008,75 +2029,126 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
}
}
}
- if (newu == 0 || newv == 0) {
+ MEM_freeN(usel);
+
+ if ((newu == 0 || newv == 0) ||
+ (split && !isNurbselU(nu, &newv, SELECT) && !isNurbselV(nu, &newu, SELECT))) {
if (G.debug & G_DEBUG)
printf("Can't duplicate Nurb\n");
}
else {
+ for (a = 0, bp1 = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp1++) {
+ newv = newu = 0;
+
+ if ((bp1->f1 & flag) && !(bp1->f1 & SURF_SEEN)) {
+ /* point selected, now loop over points in U and V directions */
+ for (b = a % nu->pntsu, bp2 = bp1; b < nu->pntsu; b++, bp2++) {
+ if (bp2->f1 & flag) {
+ newu++;
+ for (c = a / nu->pntsu, bp3 = bp2; c < nu->pntsv; c++, bp3 += nu->pntsu) {
+ if (bp3->f1 & flag) {
+ bp3->f1 |= SURF_SEEN; /* flag as seen so skipped on future iterations */
+ if (newu == 1) newv++;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
- if (newu == 1) SWAP(int, newu, newv);
+ if ((newu + newv) > 2) {
+ /* ignore single points */
+ if (a == 0) {
+ /* check if need to save cyclic selection and continue if so */
+ if (newu == nu->pntsu && (nu->flagv & CU_NURB_CYCLIC)) cyclicv = newv;
+ if (newv == nu->pntsv && (nu->flagu & CU_NURB_CYCLIC)) cyclicu = newu;
+ if (cyclicu != 0 || cyclicv != 0) continue;
+ }
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN4");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(newnurb, newnu);
- set_actNurb(obedit, newnu);
- newnu->pntsu = newu;
- newnu->pntsv = newv;
- newnu->bp = (BPoint *)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN5");
- BKE_nurb_order_clamp_u(newnu);
- BKE_nurb_order_clamp_v(newnu);
-
- newnu->knotsu = newnu->knotsv = NULL;
-
- bp = newnu->bp;
- bp1 = nu->bp;
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++, bp1++) {
- if (bp1->f1 & flag) {
- memcpy(bp, bp1, sizeof(BPoint));
- select_bpoint(bp1, DESELECT, flag, HIDDEN);
- bp++;
+ if (a + newu == nu->pntsu && cyclicu != 0) {
+ /* cyclic in U direction */
+ newnu = BKE_nurb_copy(nu, newu + cyclicu, newv);
+ for (b = 0; b < newv; b++) {
+ memcpy(&newnu->bp[b * newnu->pntsu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
+ memcpy(&newnu->bp[b * newnu->pntsu + newu], &nu->bp[b * nu->pntsu], cyclicu * sizeof(BPoint));
+ }
+ cyclicu = cyclicv = 0;
}
+ else if ((a / nu->pntsu) + newv == nu->pntsv && cyclicv != 0) {
+ /* cyclic in V direction */
+ newnu = BKE_nurb_copy(nu, newu, newv + cyclicv);
+ memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint));
+ memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint));
+ cyclicu = cyclicv = 0;
+ }
+ else {
+ newnu = BKE_nurb_copy(nu, newu, newv);
+ for (b = 0; b < newv; b++) {
+ memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
+ }
+ }
+ set_actNurb(obedit, newnu);
+ BLI_addtail(newnurb, newnu);
+
+ if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
+ if (newv != nu->pntsv) newnu->flagv &= ~CU_NURB_CYCLIC;
}
}
- if (BKE_nurb_check_valid_u(newnu)) {
- if (nu->pntsu == newnu->pntsu && nu->knotsu) {
- newnu->knotsu = MEM_dupallocN(nu->knotsu);
- }
- else {
- BKE_nurb_knot_calc_u(newnu);
+
+ if (cyclicu != 0 || cyclicv != 0) {
+ /* copy start of a cyclic surface, or copying all selected points */
+ newu = cyclicu == 0 ? nu->pntsu : cyclicu;
+ newv = cyclicv == 0 ? nu->pntsv : cyclicv;
+
+ newnu = BKE_nurb_copy(nu, newu, newv);
+ for (b = 0; b < newv; b++) {
+ memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu], newu * sizeof(BPoint));
}
+ set_actNurb(obedit, newnu);
+ BLI_addtail(newnurb, newnu);
+
+ if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
+ if (newv != nu->pntsv) newnu->flagv &= ~CU_NURB_CYCLIC;
}
- if (BKE_nurb_check_valid_v(newnu)) {
- if (nu->pntsv == newnu->pntsv && nu->knotsv) {
- newnu->knotsv = MEM_dupallocN(nu->knotsv);
- }
- else {
- BKE_nurb_knot_calc_v(newnu);
- }
+
+ for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) {
+ bp1->f1 &= ~SURF_SEEN;
+ if (!split) select_bpoint(bp1, DESELECT, flag, HIDDEN);
}
}
- MEM_freeN(usel);
}
}
-
nu = nu->prev;
}
-
- for (nu = newnurb->first; nu; nu = nu->next) {
- /* knots done after duplicate as pntsu may change */
- if (nu->pntsv == 1) {
- nu->knotsu = NULL;
- BKE_nurb_knot_calc_u(nu);
- }
- if (split) {
- if (nu->type == CU_BEZIER) {
+ for (nu = newnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ if (split) {
/* recalc first and last */
BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]);
BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]);
}
}
+ else {
+ /* knots done after duplicate as pntsu may change */
+ nu->knotsu = nu->knotsv = NULL;
+ BKE_nurb_order_clamp_u(nu);
+ BKE_nurb_knot_calc_u(nu);
+
+ if (obedit->type == OB_SURF) {
+ for (a = 0, bp = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ bp->f1 &= ~SURF_SEEN;
+ }
+
+ BKE_nurb_order_clamp_v(nu);
+ BKE_nurb_knot_calc_v(nu);
+ }
+ }
}
/* actnu changed */
@@ -5708,7 +5780,7 @@ void CURVE_OT_select_nth(wmOperatorType *ot)
/********************** add duplicate operator *********************/
-static int duplicate_exec(bContext *C, wmOperator *UNUSED(op))
+static int duplicate_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
ListBase newnurb = {NULL, NULL};
@@ -5719,6 +5791,10 @@ static int duplicate_exec(bContext *C, wmOperator *UNUSED(op))
BLI_movelisttolist(object_editcurve_get(obedit), &newnurb);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Cannot duplicate current selection");
+ return OPERATOR_CANCELLED;
+ }
return OPERATOR_FINISHED;
}
@@ -5727,7 +5803,7 @@ void CURVE_OT_duplicate(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Duplicate Curve";
- ot->description = "Duplicate selected control points and segments between them";
+ ot->description = "Duplicate selected control points";
ot->idname = "CURVE_OT_duplicate";
/* api callbacks */
@@ -5740,178 +5816,294 @@ void CURVE_OT_duplicate(wmOperatorType *ot)
/********************** delete operator *********************/
-static int curve_delete_selected(Object *obedit, eCurveElem_Types type, const bool split)
+static int curve_delete_vertices(Object *obedit)
{
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
ListBase *nubase = &editnurb->nurbs;
- Nurb *nu, *nu1, *startnu;
- BezTriple *bezt, *bezt1, *bezt2;
- BPoint *bp, *bp1, *bp2;
- int a, b, starta, enda, cut = 0;
- int nuindex = 0;
- ListBase newnurb = {NULL, NULL};
+ Nurb *nu, *next;
+ BezTriple *bezt, *bezt1;
+ BPoint *bp, *bp1;
+ int a, type, nuindex = 0;
if (obedit->type == OB_SURF) {
- if (type == CURVE_VERTEX) {
- return deleteflagNurb(obedit, SELECT);
- }
- else {
- keyIndex_delNurbList(editnurb, nubase);
- BKE_nurbList_free(nubase);
-
- return OPERATOR_FINISHED;
- }
+ return deleteflagNurb(obedit, SELECT);
}
- if (type == CURVE_VERTEX) {
- /* first loop, can we remove entire pieces? */
- Nurb *next;
- nu = nubase->first;
- while (nu) {
- next = nu->next;
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- if (a) {
- while (a) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
- /* pass */
- }
- else {
- break;
- }
- a--;
- bezt++;
+ /* first loop, can we remove entire pieces? */
+ nu = nubase->first;
+ while (nu) {
+ next = nu->next;
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ if (a) {
+ while (a) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ /* pass */
}
- if (a == 0) {
- if (cu->actnu == nuindex)
- cu->actnu = -1;
-
- BLI_remlink(nubase, nu);
- keyIndex_delNurb(editnurb, nu);
- BKE_nurb_free(nu); nu = NULL;
+ else {
+ break;
}
+ a--;
+ bezt++;
+ }
+ if (a == 0) {
+ if (cu->actnu == nuindex)
+ cu->actnu = -1;
+
+ BLI_remlink(nubase, nu);
+ keyIndex_delNurb(editnurb, nu);
+ BKE_nurb_free(nu); nu = NULL;
}
}
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- if (a) {
- while (a) {
- if (bp->f1 & SELECT) {
- /* pass */
- }
- else {
- break;
- }
- a--;
- bp++;
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ if (a) {
+ while (a) {
+ if (bp->f1 & SELECT) {
+ /* pass */
}
- if (a == 0) {
- if (cu->actnu == nuindex)
- cu->actnu = -1;
-
- BLI_remlink(nubase, nu);
- keyIndex_delNurb(editnurb, nu);
- BKE_nurb_free(nu); nu = NULL;
+ else {
+ break;
}
+ a--;
+ bp++;
+ }
+ if (a == 0) {
+ if (cu->actnu == nuindex)
+ cu->actnu = -1;
+
+ BLI_remlink(nubase, nu);
+ keyIndex_delNurb(editnurb, nu);
+ BKE_nurb_free(nu); nu = NULL;
}
}
-
- /* Never allow the order to exceed the number of points
- * - note, this is ok but changes unselected nurbs, disable for now */
+ }
+
+ /* Never allow the order to exceed the number of points
+ * - note, this is ok but changes unselected nurbs, disable for now */
#if 0
- if ((nu != NULL) && (nu->type == CU_NURBS)) {
- clamp_nurb_order_u(nu);
- }
+ if ((nu != NULL) && (nu->type == CU_NURBS)) {
+ clamp_nurb_order_u(nu);
+ }
#endif
- nu = next;
- nuindex++;
+ nu = next;
+ nuindex++;
+ }
+ /* 2nd loop, delete small pieces: just for curves */
+ nu = nubase->first;
+ while (nu) {
+ next = nu->next;
+ type = 0;
+ if (nu->type == CU_BEZIER) {
+ int delta = 0;
+ bezt = nu->bezt;
+ for (a = 0; a < nu->pntsu; a++) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
+ keyIndex_delBezt(editnurb, bezt + delta);
+ keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
+ nu->pntsu--;
+ a--;
+ type = 1;
+ delta++;
+ }
+ else {
+ bezt++;
+ }
+ }
+ if (type) {
+ bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
+ memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple));
+ keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu);
+ MEM_freeN(nu->bezt);
+ nu->bezt = bezt1;
+ BKE_nurb_handles_calc(nu);
+ }
}
- /* 2nd loop, delete small pieces: just for curves */
- nu = nubase->first;
- while (nu) {
- next = nu->next;
- type = 0;
- if (nu->type == CU_BEZIER) {
- int delta = 0;
- bezt = nu->bezt;
- for (a = 0; a < nu->pntsu; a++) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
- memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
- keyIndex_delBezt(editnurb, bezt + delta);
- keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
- nu->pntsu--;
- a--;
- type = 1;
- delta++;
- }
- else {
- bezt++;
- }
+ else if (nu->pntsv == 1) {
+ int delta = 0;
+ bp = nu->bp;
+
+ for (a = 0; a < nu->pntsu; a++) {
+ if (bp->f1 & SELECT) {
+ memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint));
+ keyIndex_delBP(editnurb, bp + delta);
+ keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1);
+ nu->pntsu--;
+ a--;
+ type = 1;
+ delta++;
}
- if (type) {
- bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
- memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple));
- keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu);
- MEM_freeN(nu->bezt);
- nu->bezt = bezt1;
- BKE_nurb_handles_calc(nu);
+ else {
+ bp++;
}
}
- else if (nu->pntsv == 1) {
- int delta = 0;
- bp = nu->bp;
+ if (type) {
+ bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
+ memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint));
+ keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu);
+ MEM_freeN(nu->bp);
+ nu->bp = bp1;
- for (a = 0; a < nu->pntsu; a++) {
- if (bp->f1 & SELECT) {
- memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint));
- keyIndex_delBP(editnurb, bp + delta);
- keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1);
- nu->pntsu--;
- a--;
- type = 1;
- delta++;
+ /* Never allow the order to exceed the number of points
+ * - note, this is ok but changes unselected nurbs, disable for now */
+#if 0
+ if (nu->type == CU_NURBS) {
+ clamp_nurb_order_u(nu);
+ }
+#endif
+ }
+ BKE_nurb_order_clamp_u(nu);
+ BKE_nurb_knot_calc_u(nu);
+ }
+ nu = next;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int curve_delete_segments(Object *obedit, const bool split)
+{
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ ListBase *nubase = &editnurb->nurbs, newnurb = {NULL, NULL};
+ Nurb *nu, *nu1;
+ BezTriple *bezt, *bezt1, *bezt2;
+ BPoint *bp, *bp1, *bp2;
+ int a, b, starta, enda, cut, cyclicut;
+
+ for (nu = nubase->first; nu; nu = nu->next) {
+ nu1 = NULL;
+ starta = enda = cut = -1;
+ cyclicut = 0;
+
+ if (nu->type == CU_BEZIER) {
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (!BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ enda = a;
+ if (starta == -1) starta = a;
+ if (a < nu->pntsu - 1) continue;
+ }
+ else if (a < nu->pntsu - 1 && !BEZSELECTED_HIDDENHANDLES(cu, bezt + 1)) {
+ /* if just single selected point then continue */
+ continue;
+ }
+
+ if (starta >= 0) {
+ /* got selected segment, now check where and copy */
+ if (starta <= 1 && a == nu->pntsu - 1) {
+ /* copying all points in spline */
+ if (starta == 1 && enda != a) nu->flagu &= ~CU_NURB_CYCLIC;
+
+ starta = 0;
+ enda = a;
+ cut = enda - starta + 1;
+ nu1 = BKE_nurb_copy(nu, cut, 1);
+ }
+ else if (starta == 0) {
+ /* if start of curve copy next end point */
+ enda++;
+ cut = enda - starta + 1;
+ bezt1 = &nu->bezt[nu->pntsu - 1];
+ bezt2 = &nu->bezt[nu->pntsu - 2];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ {
+ /* check if need to join start of spline to end */
+ nu1 = BKE_nurb_copy(nu, cut + 1, 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut);
+ starta = nu->pntsu - 1;
+ cut = 1;
+ }
+ else {
+ if (nu->flagu & CU_NURB_CYCLIC) cyclicut = cut;
+ else nu1 = BKE_nurb_copy(nu, cut, 1);
+ }
+ }
+ else if (enda == nu->pntsu - 1) {
+ /* if end of curve copy previous start point */
+ starta--;
+ cut = enda - starta + 1;
+ bezt1 = nu->bezt;
+ bezt2 = &nu->bezt[1];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ {
+ /* check if need to join start of spline to end */
+ nu1 = BKE_nurb_copy(nu, cut + 1, 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1);
+ }
+ else if (cyclicut != 0) {
+ /* if cyclicut exists it is a cyclic spline, start and end should be connected */
+ nu1 = BKE_nurb_copy(nu, cut + cyclicut, 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, cyclicut);
+ cyclicut = 0;
+ }
+ else {
+ nu1 = BKE_nurb_copy(nu, cut, 1);
+ }
}
else {
- bp++;
+ /* mid spline selection, copy adjacent start and end */
+ starta--;
+ enda++;
+ cut = enda - starta + 1;
+ nu1 = BKE_nurb_copy(nu, cut, 1);
}
- }
- if (type) {
- bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
- memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint));
- keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu);
- MEM_freeN(nu->bp);
- nu->bp = bp1;
-
- /* Never allow the order to exceed the number of points
- * - note, this is ok but changes unselected nurbs, disable for now */
-#if 0
- if (nu->type == CU_NURBS) {
- clamp_nurb_order_u(nu);
+
+ if (nu1 != NULL) {
+ ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut);
+ BLI_addtail(&newnurb, nu1);
+
+ if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC;
+ nu1 = NULL;
}
-#endif
+ starta = enda = -1;
+ }
+ }
+
+ if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
+ /* start and points copied if connecting segment was deleted and not cylic spline */
+ bezt1 = nu->bezt;
+ bezt2 = &nu->bezt[1];
+
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt2)) {
+ nu1 = BKE_nurb_copy(nu, 1, 1);
+ ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ BLI_addtail(&newnurb, nu1);
+ }
+
+ bezt1 = &nu->bezt[nu->pntsu - 1];
+ bezt2 = &nu->bezt[nu->pntsu - 2];
+
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt2)) {
+ nu1 = BKE_nurb_copy(nu, 1, 1);
+ ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ BLI_addtail(&newnurb, nu1);
}
- BKE_nurb_order_clamp_u(nu);
- BKE_nurb_knot_calc_u(nu);
}
- nu = next;
}
- }
- else if (type == CURVE_SEGMENT) {
- for (nu = nubase->first; nu; nu = nu->next) {
- startnu = nu1 = NULL;
- starta = enda = cut = -1;
+ else if (nu->pntsv >= 1) {
+ int u, v;
- if (nu->type == CU_BEZIER) {
- for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (!BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ if (isNurbselV(nu, &u, SELECT)) {
+ for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
+ if (!(bp->f1 & SELECT)) {
enda = a;
if (starta == -1) starta = a;
if (a < nu->pntsu - 1) continue;
}
- else if (a < nu->pntsu - 1 && !BEZSELECTED_HIDDENHANDLES(cu, bezt + 1)) {
+ else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) {
/* if just single selected point then continue */
continue;
}
@@ -5925,69 +6117,52 @@ static int curve_delete_selected(Object *obedit, eCurveElem_Types type, const bo
starta = 0;
enda = a;
cut = enda - starta + 1;
-
- nu1 = ED_curve_nurbcpy(nu, cut);
+ nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
}
else if (starta == 0) {
/* if start of curve copy next end point */
enda++;
cut = enda - starta + 1;
+ bp1 = &nu->bp[nu->pntsu - 1];
+ bp2 = &nu->bp[nu->pntsu - 2];
- bezt1 = &nu->bezt[nu->pntsu - 1];
- bezt2 = &nu->bezt[nu->pntsu - 2];
-
- if ((nu->flagu & CU_NURB_CYCLIC) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt2))
- {
+ if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
/* check if need to join start of spline to end */
- nu1 = ED_curve_nurbcpy(nu, cut + 1);
- ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut);
+ nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + 1], &nu->bp[b * nu->pntsu], cut);
+ }
starta = nu->pntsu - 1;
cut = 1;
}
else {
- nu1 = ED_curve_nurbcpy(nu, cut);
-
- if (nu->flagu & CU_NURB_CYCLIC) startnu = nu1;
+ if (nu->flagu & CU_NURB_CYCLIC) cyclicut = cut;
+ else nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
}
}
else if (enda == nu->pntsu - 1) {
/* if end of curve copy previous start point */
starta--;
cut = enda - starta + 1;
+ bp1 = nu->bp;
+ bp2 = &nu->bp[1];
- bezt1 = nu->bezt;
- bezt2 = &nu->bezt[1];
-
- if ((nu->flagu & CU_NURB_CYCLIC) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt2))
- {
+ if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
/* check if need to join start of spline to end */
- nu1 = ED_curve_nurbcpy(nu, cut + 1);
- ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1);
+ nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], 1);
+ }
}
- else if (startnu != NULL) {
- /* if startnu exists it is a cyclic spline, start and end should be connected */
- bezt1 = (BezTriple *)MEM_mallocN((cut + startnu->pntsu) * sizeof(BezTriple), "delNurb3");
- ED_curve_beztcpy(editnurb, bezt1, &nu->bezt[starta], cut);
- ED_curve_beztcpy(editnurb, &bezt1[cut], nu->bezt, startnu->pntsu);
-
- MEM_freeN(startnu->bezt);
- startnu->bezt = bezt1;
- startnu->pntsu += cut;
-
- if (split) {
- for (b = 0; b < startnu->pntsu; b++, bezt1++) {
- select_beztriple(bezt1, DESELECT, SELECT, true);
- }
+ else if (cyclicut != 0) {
+ /* if cyclicut exists it is a cyclic spline, start and end should be connected */
+ nu1 = BKE_nurb_copy(nu, cut + cyclicut, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], cyclicut);
}
-
- BKE_nurb_handles_calc(startnu);
}
else {
- nu1 = ED_curve_nurbcpy(nu, cut);
+ nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
}
}
else {
@@ -5995,24 +6170,16 @@ static int curve_delete_selected(Object *obedit, eCurveElem_Types type, const bo
starta--;
enda++;
cut = enda - starta + 1;
-
- nu1 = ED_curve_nurbcpy(nu, cut);
+ nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
}
if (nu1 != NULL) {
- ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut);
-
- if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC;
-
- if (split) {
- /* deselect for split operator */
- for (b = 0, bezt1 = nu1->bezt; b < nu1->pntsu; b++, bezt1++) {
- select_beztriple(bezt1, DESELECT, SELECT, true);
- }
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu], &nu->bp[b * nu->pntsu + starta], cut);
}
-
BLI_addtail(&newnurb, nu1);
- BKE_nurb_handles_calc(nu1);
+
+ if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC;
nu1 = NULL;
}
starta = enda = -1;
@@ -6021,102 +6188,91 @@ static int curve_delete_selected(Object *obedit, eCurveElem_Types type, const bo
if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
/* start and points copied if connecting segment was deleted and not cylic spline */
- bezt1 = nu->bezt;
- bezt2 = &nu->bezt[1];
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) && BEZSELECTED_HIDDENHANDLES(cu, bezt2)) {
- nu1 = ED_curve_nurbcpy(nu, 1);
- ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ bp1 = nu->bp;
+ bp2 = &nu->bp[1];
+
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = BKE_nurb_copy(nu, 1, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu], 1);
+ }
BLI_addtail(&newnurb, nu1);
}
- bezt1 = &nu->bezt[nu->pntsu - 1];
- bezt2 = &nu->bezt[nu->pntsu - 2];
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) && BEZSELECTED_HIDDENHANDLES(cu, bezt2)) {
- nu1 = ED_curve_nurbcpy(nu, 1);
- ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ bp1 = &nu->bp[nu->pntsu - 1];
+ bp2 = &nu->bp[nu->pntsu - 2];
+
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = BKE_nurb_copy(nu, 1, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu + nu->pntsu - 1], 1);
+ }
BLI_addtail(&newnurb, nu1);
}
}
}
- else if (nu->pntsv == 1) {
- for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
+ else if (isNurbselU(nu, &v, SELECT)) {
+ for (a = 0, bp = nu->bp; a < nu->pntsv; a++, bp += nu->pntsu) {
if (!(bp->f1 & SELECT)) {
enda = a;
if (starta == -1) starta = a;
- if (a < nu->pntsu - 1) continue;
+ if (a < nu->pntsv - 1) continue;
}
- else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) {
+ else if (a < nu->pntsv - 1 && !((bp + nu->pntsu)->f1 & SELECT)) {
/* if just single selected point then continue */
continue;
}
if (starta >= 0) {
/* got selected segment, now check where and copy */
- if (starta <= 1 && a == nu->pntsu - 1) {
+ if (starta <= 1 && a == nu->pntsv - 1) {
/* copying all points in spline */
- if (starta == 1 && enda != a) nu->flagu &= ~CU_NURB_CYCLIC;
+ if (starta == 1 && enda != a) nu->flagv &= ~CU_NURB_CYCLIC;
starta = 0;
enda = a;
cut = enda - starta + 1;
-
- nu1 = ED_curve_nurbcpy(nu, cut);
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
}
else if (starta == 0) {
/* if start of curve copy next end point */
enda++;
cut = enda - starta + 1;
+ bp1 = &nu->bp[nu->pntsv * nu->pntsu - nu->pntsu];
+ bp2 = &nu->bp[nu->pntsv * nu->pntsu - (nu->pntsu * 2)];
- bp1 = &nu->bp[nu->pntsu - 1];
- bp2 = &nu->bp[nu->pntsu - 2];
-
- if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
/* check if need to join start of spline to end */
- nu1 = ED_curve_nurbcpy(nu, cut + 1);
- ED_curve_bpcpy(editnurb, &nu1->bp[1], nu->bp, cut);
- starta = nu->pntsu - 1;
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1);
+ ED_curve_bpcpy(editnurb, &nu1->bp[nu->pntsu], nu->bp, cut * nu->pntsu);
+ starta = nu->pntsv - 1;
cut = 1;
}
else {
- nu1 = ED_curve_nurbcpy(nu, cut);
-
- if (nu->flagu & CU_NURB_CYCLIC) startnu = nu1;
+ if (nu->flagv & CU_NURB_CYCLIC) cyclicut = cut;
+ else nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
}
}
- else if (enda == nu->pntsu - 1) {
+ else if (enda == nu->pntsv - 1) {
/* if end of curve copy previous start point */
starta--;
cut = enda - starta + 1;
-
bp1 = nu->bp;
- bp2 = &nu->bp[1];
+ bp2 = &nu->bp[nu->pntsu];
- if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
/* check if need to join start of spline to end */
- nu1 = ED_curve_nurbcpy(nu, cut + 1);
- ED_curve_bpcpy(editnurb, &nu1->bp[cut], nu->bp, 1);
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1);
+ ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu);
}
- else if (startnu != NULL) {
- /* if startnu exists it is a cyclic spline, start and end should be connected */
- bp1 = (BPoint *)MEM_mallocN((cut + startnu->pntsu) * sizeof(BPoint), "delNurb4");
- ED_curve_bpcpy(editnurb, bp1, &nu->bp[starta], cut);
- ED_curve_bpcpy(editnurb, &bp1[cut], nu->bp, startnu->pntsu);
-
- MEM_freeN(startnu->bp);
- startnu->bp = bp1;
- startnu->pntsu += cut;
-
- if (split) {
- for (b = 0; b < startnu->pntsu; b++, bp1++) {
- select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
- }
- }
-
- BKE_nurb_order_clamp_u(startnu);
- BKE_nurb_knot_calc_u(startnu);
+ else if (cyclicut != 0) {
+ /* if cyclicut exists it is a cyclic spline, start and end should be connected */
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + cyclicut);
+ ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu * cyclicut);
+ cyclicut = 0;
}
else {
- nu1 = ED_curve_nurbcpy(nu, cut);
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
}
}
else {
@@ -6124,62 +6280,84 @@ static int curve_delete_selected(Object *obedit, eCurveElem_Types type, const bo
starta--;
enda++;
cut = enda - starta + 1;
-
- nu1 = ED_curve_nurbcpy(nu, cut);
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
}
if (nu1 != NULL) {
- ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta], cut);
-
- if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC;
-
- if (split) {
- /* deselect for split operator */
- for (b = 0, bp1 = nu1->bp; b < nu1->pntsu; b++, bp1++) {
- select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
- }
- }
-
+ ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta * nu->pntsu], cut * nu->pntsu);
BLI_addtail(&newnurb, nu1);
- nu1->knotsu = NULL;
- BKE_nurb_order_clamp_u(nu1);
- BKE_nurb_knot_calc_u(nu1);
+
+ if (starta != 0 || enda != nu->pntsv - 1) nu1->flagv &= ~CU_NURB_CYCLIC;
nu1 = NULL;
}
starta = enda = -1;
}
}
- if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
+ if (!split && cut != -1 && nu->pntsv > 2 && !(nu->flagv & CU_NURB_CYCLIC)) {
/* start and points copied if connecting segment was deleted and not cylic spline */
bp1 = nu->bp;
- bp2 = &nu->bp[1];
+ bp2 = &nu->bp[nu->pntsu];
+
if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- nu1 = ED_curve_nurbcpy(nu, 1);
- ED_curve_bpcpy(editnurb, nu1->bp, bp1, 1);
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, 1);
+ ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu);
BLI_addtail(&newnurb, nu1);
- nu1->knotsu = NULL;
}
- bp1 = &nu->bp[nu->pntsu - 1];
- bp2 = &nu->bp[nu->pntsu - 2];
+ bp1 = &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu];
+ bp2 = &nu->bp[nu->pntsu * nu->pntsv - (nu->pntsu * 2)];
+
if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- nu1 = ED_curve_nurbcpy(nu, 1);
- ED_curve_bpcpy(editnurb, nu1->bp, bp1, 1);
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, 1);
+ ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu], nu->pntsu);
BLI_addtail(&newnurb, nu1);
- nu1->knotsu = NULL;
}
}
}
+ else {
+ /* selection not valid, just copy nurb to new list */
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, nu->pntsv);
+ ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu * nu->pntsv);
+ BLI_addtail(&newnurb, nu1);
+ }
}
-
- BKE_nurbList_free(nubase);
- BLI_movelisttolist(nubase, &newnurb);
}
- else {
- BLI_assert(0);
+
+ for (nu = newnurb.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ if (split) {
+ /* deselect for split operator */
+ for (b = 0, bezt1 = nu->bezt; b < nu->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, DESELECT, SELECT, true);
+ }
+ }
+
+ BKE_nurb_handles_calc(nu);
+ }
+ else {
+ if (split) {
+ /* deselect for split operator */
+ for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) {
+ select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
+ }
+ }
+
+ nu->knotsu = nu->knotsv = NULL;
+ BKE_nurb_order_clamp_u(nu);
+ BKE_nurb_knot_calc_u(nu);
+
+ if (nu->pntsv > 1) {
+ BKE_nurb_order_clamp_v(nu);
+ BKE_nurb_knot_calc_v(nu);
+ }
+ }
}
+ keyIndex_delNurbList(editnurb, nubase);
+ BKE_nurbList_free(nubase);
+ BLI_movelisttolist(nubase, &newnurb);
+
return OPERATOR_FINISHED;
}
@@ -6187,7 +6365,11 @@ static int curve_delete_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
eCurveElem_Types type = RNA_enum_get(op->ptr, "type");
- int retval = curve_delete_selected(obedit, type, false);
+ int retval;
+
+ if (type == CURVE_VERTEX) retval = curve_delete_vertices(obedit);
+ else if (type == CURVE_SEGMENT) retval = curve_delete_segments(obedit, false);
+ else BLI_assert(0);
if (retval == OPERATOR_FINISHED) {
if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
@@ -6210,23 +6392,14 @@ static EnumPropertyItem curve_delete_type_items[] = {
static EnumPropertyItem *rna_curve_delete_type_itemf(bContext *C, PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), int *free)
{
- Object *obedit;
EnumPropertyItem *item = NULL;
int totitem = 0;
-
if (!C) /* needed for docs and i18n tools */
return curve_delete_type_items;
- obedit = CTX_data_edit_object(C);
- if (obedit->type == OB_SURF) {
- RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
- }
- else {
- RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
- RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT);
- }
-
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT);
RNA_enum_item_end(&item, &totitem);
*free = true;
@@ -6615,22 +6788,6 @@ void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count)
keyIndex_updateBP(editnurb, src, dst, count);
}
-Nurb *ED_curve_nurbcpy(Nurb *src, int count)
-{
- Nurb *newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "copyNurb");
- memcpy(newnu, src, sizeof(Nurb));
- newnu->pntsu = count;
-
- if (src->bezt) {
- newnu->bezt = (BezTriple *)MEM_mallocN(count * sizeof(BezTriple), "copyNurb2");
- }
- else {
- newnu->bp = (BPoint *)MEM_mallocN(count * sizeof(BPoint), "copyNurb3");
- }
-
- return newnu;
-}
-
int ED_curve_actSelection(Curve *cu, float center[3])
{
Nurb *nu = get_lastsel_nurb(cu);
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 2cfbbbd516b..f1a2cd68f28 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -364,6 +364,8 @@ typedef enum eBezTriple_KeyframeType {
/* mixed with KEY_LINEAR but define here since only curve supports */
#define KEY_CU_EASE 3
+/* indicates point has been seen during surface duplication */
+#define SURF_SEEN 4
#endif