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:
@@ -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 */
|
||||
|
Reference in New Issue
Block a user