diff options
-rw-r--r-- | source/blender/bmesh/intern/bmesh_edgeloop.c | 49 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_edgeloop.h | 1 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 5 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_bridge.c | 59 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 7 |
5 files changed, 110 insertions, 11 deletions
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c index ce2a80c6cfc..1c302668409 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.c +++ b/source/blender/bmesh/intern/bmesh_edgeloop.c @@ -188,6 +188,55 @@ void BM_mesh_edgeloops_calc_normal(BMesh *bm, ListBase *eloops) } } +void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops) +{ + ListBase eloops_ordered = {NULL}; + BMEdgeLoopStore *el_store; + float cent[3]; + int tot = 0; + zero_v3(cent); + /* assumes we calculated centers already */ + for (el_store = eloops->first; el_store; el_store = el_store->next, tot++) { + add_v3_v3(cent, el_store->co); + } + mul_v3_fl(cent, 1.0f / (float)tot); + + /* find far outest loop */ + { + BMEdgeLoopStore *el_store_best = NULL; + float len_best = -1.0f; + for (el_store = eloops->first; el_store; el_store = el_store->next) { + const float len = len_squared_v3v3(cent, el_store->co); + if (len > len_best) { + len_best = len; + el_store_best = el_store; + } + } + + BLI_remlink(eloops, el_store_best); + BLI_addtail(&eloops_ordered, el_store_best); + } + + /* not so efficient re-ordering */ + while (eloops->first) { + BMEdgeLoopStore *el_store_best = NULL; + const float *co = ((BMEdgeLoopStore *)eloops_ordered.last)->co; + float len_best = FLT_MAX; + for (el_store = eloops->first; el_store; el_store = el_store->next) { + const float len = len_squared_v3v3(co, el_store->co); + if (len < len_best) { + len_best = len; + el_store_best = el_store; + } + } + + BLI_remlink(eloops, el_store_best); + BLI_addtail(&eloops_ordered, el_store_best); + } + + *eloops = eloops_ordered; +} + /* -------------------------------------------------------------------- */ /* BM_edgeloop_*** functions */ diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h index 06a457c3dd6..e6ea65fa85d 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.h +++ b/source/blender/bmesh/intern/bmesh_edgeloop.h @@ -38,6 +38,7 @@ int BM_mesh_edgeloops_find(BMesh *bm, struct ListBase *r_lb, void BM_mesh_edgeloops_free(struct ListBase *eloops); void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops); void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops); +void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops); /* single edgeloop */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 77e45648813..f145d6939d9 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -515,8 +515,9 @@ static BMOpDefine bmo_bridge_loops_def = { "bridge_loops", /* slots_in */ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"use_merge", BMO_OP_SLOT_BOOL}, - {"merge_factor", BMO_OP_SLOT_FLT}, + {"use_cyclic", BMO_OP_SLOT_BOOL}, + {"use_merge", BMO_OP_SLOT_BOOL}, + {"merge_factor", BMO_OP_SLOT_FLT}, {{'\0'}}, }, /* slots_out */ diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index a9201fb8de5..5642cc5e8c1 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -289,10 +289,13 @@ static void bridge_loop_pair(BMesh *bm, void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) { ListBase eloops = {NULL}; + LinkData *el_store; + int eloop_len; /* merge-bridge support */ const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge"); const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor"); + const bool use_cyclic = BMO_slot_bool_get(op->slots_in, "use_cyclic") && (use_merge == false); int count; bool change = false; @@ -303,20 +306,64 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) BM_mesh_edgeloops_calc_normal(bm, &eloops); BM_mesh_edgeloops_calc_center(bm, &eloops); - if ((count == 2) && (BM_edgeloop_length_get(eloops.first) == BM_edgeloop_length_get(eloops.last))) { - bridge_loop_pair(bm, eloops.first, eloops.last, use_merge, merge_factor); + if (count < 2) { + BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, + "Select at least two edge loops"); + goto cleanup; + + } + else { + bool match = true; + eloop_len = BM_edgeloop_length_get(eloops.first); + for (el_store = eloops.first; el_store; el_store = el_store->next) { + if (eloop_len != BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store)) { + match = false; + break; + } + } + if (!match) { + BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, + "Selected loops must have equal edge counts"); + goto cleanup; + } + } + + if (count > 2) { + BM_mesh_edgeloops_calc_order(bm, &eloops); + } + + for (el_store = eloops.first; el_store; el_store = el_store->next) { + LinkData *el_store_next = el_store->next; + + if (el_store_next == NULL) { + if (use_cyclic && (count > 2)) { + el_store_next = eloops.first; + } + else { + break; + } + } + + bridge_loop_pair(bm, + (struct BMEdgeLoopStore *)el_store, + (struct BMEdgeLoopStore *)el_store_next, + use_merge, merge_factor); change = true; + } + + if ((count == 2) && (BM_edgeloop_length_get(eloops.first) == BM_edgeloop_length_get(eloops.last))) { + + } else if (count == 2) { - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, - "Selected loops must have equal edge counts"); + } else { - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, - "Select only two edge loops"); + } +cleanup: BM_mesh_edgeloops_free(&eloops); if (change) { diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 4b325d2212f..84b93384abe 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3672,12 +3672,13 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op) BMOperator bmop; Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); + const bool use_cyclic = RNA_boolean_get(op->ptr, "use_cyclic"); const bool use_merge = RNA_boolean_get(op->ptr, "use_merge"); const float merge_factor = RNA_float_get(op->ptr, "merge_factor"); EDBM_op_init(em, &bmop, op, - "bridge_loops edges=%he use_merge=%b merge_factor=%f", - BM_ELEM_SELECT, use_merge, merge_factor); + "bridge_loops edges=%he use_cyclic=%b use_merge=%b merge_factor=%f", + BM_ELEM_SELECT, use_cyclic, use_merge, merge_factor); BMO_op_exec(em->bm, &bmop); @@ -3711,7 +3712,7 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "inside", 0, "Inside", ""); + RNA_def_boolean(ot->srna, "use_cyclic", 0, "Cyclic", "Close the bridge loop when using 3 or more"); RNA_def_boolean(ot->srna, "use_merge", false, "Merge", "Merge rather than creating faces"); RNA_def_float(ot->srna, "merge_factor", 0.5f, 0.0f, 1.0f, "Merge Factor", "", 0.0f, 1.0f); |