BMesh: Add 'cut' separate mode for intersect tool

It was only possible to separate all geometry from an intersection or none.

Made this into an enum with a 3rd option to 'Cut', (now default)
which keeps each side of the intersection separate
without splitting faces in half.
This commit is contained in:
Campbell Barton
2017-03-05 23:20:04 +11:00
parent 3caeb51d7f
commit a461216885

View File

@@ -137,6 +137,12 @@ enum {
ISECT_SEL_UNSEL = 1,
};
enum {
ISECT_SEPARATE_ALL = 0,
ISECT_SEPARATE_CUT = 1,
ISECT_SEPARATE_NONE = 2,
};
static int edbm_intersect_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -144,7 +150,9 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
const int mode = RNA_enum_get(op->ptr, "mode");
int (*test_fn)(BMFace *, void *);
bool use_separate = RNA_boolean_get(op->ptr, "use_separate");
bool use_separate_all = false;
bool use_separate_cut = false;
const int separate_mode = RNA_enum_get(op->ptr, "separate_mode");
const float eps = RNA_float_get(op->ptr, "threshold");
bool use_self;
bool has_isect;
@@ -160,15 +168,42 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
break;
}
switch (separate_mode) {
case ISECT_SEPARATE_ALL:
use_separate_all = true;
break;
case ISECT_SEPARATE_CUT:
if (use_self == false) {
use_separate_cut = true;
}
else {
/* we could support this but would require more advanced logic inside 'BM_mesh_intersect'
* for now just separate all */
use_separate_all = true;
}
break;
default: /* ISECT_SEPARATE_NONE */
break;
}
has_isect = BM_mesh_intersect(
bm,
em->looptris, em->tottri,
test_fn, NULL,
use_self, use_separate, true, true, true,
use_self, use_separate_all, true, true, true,
-1,
eps);
if (use_separate_cut) {
/* detach selected/un-selected faces */
BMOperator bmop;
EDBM_op_init(em, &bmop, op, "split geom=%hf use_only_faces=%b", BM_ELEM_SELECT, true);
BMO_op_exec(em->bm, &bmop);
if (!EDBM_op_finish(em, &bmop, op, true)) {
/* should never happen! */
BKE_report(op->reports, RPT_ERROR, "Error separating");
}
}
if (has_isect) {
edbm_intersect_select(em);
@@ -190,6 +225,16 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem isect_separate_items[] = {
{ISECT_SEPARATE_ALL, "ALL", 0, "All",
"Separate all geometry from intersections"},
{ISECT_SEPARATE_CUT, "CUT", 0, "Cut",
"Cut into geometry keeping each side separate (Selected/Unselected only)"},
{ISECT_SEPARATE_NONE, "NONE", 0, "Merge",
"Merge all geometry from the intersection"},
{0, NULL, 0, NULL, NULL}
};
/* identifiers */
ot->name = "Intersect (Knife)";
ot->description = "Cut an intersection into faces";
@@ -201,7 +246,7 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
/* props */
RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
RNA_def_boolean(ot->srna, "use_separate", true, "Separate", "");
RNA_def_enum(ot->srna, "separate_mode", isect_separate_items, ISECT_SEPARATE_CUT, "Separate Mode", "");
RNA_def_float_distance(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
/* flags */