From a461216885694053049e74a3d855d2802ba1c078 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 5 Mar 2017 23:20:04 +1100 Subject: 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. --- source/blender/editors/mesh/editmesh_intersect.c | 51 ++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'source/blender/editors/mesh/editmesh_intersect.c') diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 853a1f3d2e2..bc9088401db 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -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 */ -- cgit v1.2.3