[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60834] trunk/blender/source/blender: Patch [#37115] Surface split and separate operators

Kevin Mackay mackay.ka at gmail.com
Thu Oct 17 21:57:15 CEST 2013


Revision: 60834
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60834
Author:   yakca
Date:     2013-10-17 19:57:14 +0000 (Thu, 17 Oct 2013)
Log Message:
-----------
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

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_curve.h
    trunk/blender/source/blender/blenkernel/intern/curve.c
    trunk/blender/source/blender/editors/curve/editcurve.c
    trunk/blender/source/blender/makesdna/DNA_curve_types.h

Modified: trunk/blender/source/blender/blenkernel/BKE_curve.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_curve.h	2013-10-17 19:31:59 UTC (rev 60833)
+++ trunk/blender/source/blender/blenkernel/BKE_curve.h	2013-10-17 19:57:14 UTC (rev 60834)
@@ -119,6 +119,7 @@
 
 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]);

Modified: trunk/blender/source/blender/blenkernel/intern/curve.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/curve.c	2013-10-17 19:31:59 UTC (rev 60833)
+++ trunk/blender/source/blender/blenkernel/intern/curve.c	2013-10-17 19:57:14 UTC (rev 60834)
@@ -579,6 +579,26 @@
 	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;

Modified: trunk/blender/source/blender/editors/curve/editcurve.c
===================================================================
--- trunk/blender/source/blender/editors/curve/editcurve.c	2013-10-17 19:31:59 UTC (rev 60833)
+++ trunk/blender/source/blender/editors/curve/editcurve.c	2013-10-17 19:57:14 UTC (rev 60834)
@@ -111,7 +111,7 @@
 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 @@
 {
 	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 @@
 	}
 
 	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 @@
 	/* 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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
 			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;
+			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;
 					}
-					else {
-						keyIndex_delBP(cu->editnurb, bp);
-					}
-					bp += nu->pntsu;
+					nu->pntsv = newv;
+					MEM_freeN(nu->bp);
+					nu->bp = newbp;
+					BKE_nurb_order_clamp_v(nu);
+
+					BKE_nurb_knot_calc_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;
-					}
-				}
-				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 @@
                                 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 @@
 					bezt++;
 				}
 				if (enda >= starta) {
-					diffa = enda - starta + 1;
+					newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
 
-					if (startnu != NULL && enda == nu->pntsu - 1) {

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list