diff --git a/source/blender/bmesh/intern/bmesh_marking.cc b/source/blender/bmesh/intern/bmesh_marking.cc index f484195fda0..ba574951aa5 100644 --- a/source/blender/bmesh/intern/bmesh_marking.cc +++ b/source/blender/bmesh/intern/bmesh_marking.cc @@ -1116,6 +1116,19 @@ void BM_select_history_validate(BMesh *bm) } } +char BM_select_history_htype_all(const BMesh *bm) +{ + char htype_selected = 0; + LISTBASE_FOREACH (const BMEditSelection *, ese, &bm->selected) { + htype_selected |= ese->htype; + /* Early exit if all types found. */ + if (htype_selected == (BM_VERT | BM_EDGE | BM_FACE)) { + break; + } + } + return htype_selected; +} + bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) { BMEditSelection *ese_last = static_cast(bm->selected.last); diff --git a/source/blender/bmesh/intern/bmesh_marking.hh b/source/blender/bmesh/intern/bmesh_marking.hh index 8e8600b1f39..5f9e8689a93 100644 --- a/source/blender/bmesh/intern/bmesh_marking.hh +++ b/source/blender/bmesh/intern/bmesh_marking.hh @@ -171,6 +171,10 @@ void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, void BM_select_history_validate(BMesh *bm); void BM_select_history_clear(BMesh *bm); +/** + * Get all element types present in a selection history. + */ +[[nodiscard]] char BM_select_history_htype_all(const BMesh *bm); /** * Get the active mesh element (with active-face fallback). */ diff --git a/source/blender/editors/mesh/editmesh_tools.cc b/source/blender/editors/mesh/editmesh_tools.cc index 3b9961836cb..8148149bd0c 100644 --- a/source/blender/editors/mesh/editmesh_tools.cc +++ b/source/blender/editors/mesh/editmesh_tools.cc @@ -25,6 +25,7 @@ #include "BLI_linklist.h" #include "BLI_linklist_stack.h" #include "BLI_listbase.h" +#include "BLI_math_bits.h" #include "BLI_math_geom.h" #include "BLI_math_matrix.h" #include "BLI_math_rotation.h" @@ -1542,6 +1543,7 @@ static wmOperatorStatus edbm_vert_connect_path_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); uint failed_selection_order_len = 0; uint failed_connect_len = 0; + bool has_select_history_mixed = false; const Vector objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( scene, view_layer, CTX_wm_view3d(C)); @@ -1563,6 +1565,14 @@ static wmOperatorStatus edbm_vert_connect_path_exec(bContext *C, wmOperator *op) continue; } + /* Skip mixed selections since path handling only supports uniform types, see #147150. */ + const char htype_selected = BM_select_history_htype_all(bm); + if (count_bits_i(htype_selected) > 1) { + has_select_history_mixed = true; + failed_selection_order_len++; + continue; + } + if (bm->selected.first) { BMEditSelection *ese = static_cast(bm->selected.first); if (ese->htype == BM_EDGE) { @@ -1596,7 +1606,12 @@ static wmOperatorStatus edbm_vert_connect_path_exec(bContext *C, wmOperator *op) } if (failed_selection_order_len == objects.size()) { - BKE_report(op->reports, RPT_ERROR, "Invalid selection order"); + if (has_select_history_mixed) { + BKE_report(op->reports, RPT_ERROR, "Could not connect mixed selection types"); + } + else { + BKE_report(op->reports, RPT_ERROR, "Invalid selection order"); + } return OPERATOR_CANCELLED; } if (failed_connect_len == objects.size()) {