diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index 7267a86e432..7d44f75ad49 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -85,6 +85,7 @@ #include "BLI_span.hh" #include "BLI_string_ref.hh" #include "BLI_task.hh" +#include "BLI_timeit.hh" #include "BLI_vector.hh" #include "BKE_attribute.hh" @@ -949,23 +950,6 @@ static void bm_to_mesh_shape(BMesh *bm, /** \} */ -template -static void write_fn_to_attribute(blender::bke::MutableAttributeAccessor attributes, - const StringRef attribute_name, - const eAttrDomain domain, - const GetFn &get_fn) -{ - using namespace blender; - bke::SpanAttributeWriter attribute = attributes.lookup_or_add_for_write_only_span( - attribute_name, domain); - threading::parallel_for(attribute.span.index_range(), 4096, [&](IndexRange range) { - for (const int i : range) { - attribute.span[i] = get_fn(i); - } - }); - attribute.finish(); -} - static void assert_bmesh_has_no_mesh_only_attributes(const BMesh &bm) { (void)bm; /* Unused in the release builds. */ @@ -981,68 +965,70 @@ static void assert_bmesh_has_no_mesh_only_attributes(const BMesh &bm) BLI_assert(CustomData_get_layer_named(&bm.pdata, CD_PROP_BOOL, ".select_poly") == nullptr); } -static void convert_bmesh_hide_flags_to_mesh_attributes(BMesh &bm, - const bool need_hide_vert, - const bool need_hide_edge, - const bool need_hide_poly, - Mesh &mesh) +static void bmesh_to_mesh_calc_object_remap(Main &bmain, + Mesh &me, + BMesh &bm, + const int old_totvert) { - using namespace blender; - /* The "hide" attributes are stored as flags on #BMesh. */ - assert_bmesh_has_no_mesh_only_attributes(bm); + BMVert **vertMap = nullptr; + BMVert *eve; - if (!(need_hide_vert || need_hide_edge || need_hide_poly)) { - return; + LISTBASE_FOREACH (Object *, ob, &bmain.objects) { + if ((ob->parent) && (ob->parent->data == &me) && ELEM(ob->partype, PARVERT1, PARVERT3)) { + + if (vertMap == nullptr) { + vertMap = bm_to_mesh_vertex_map(&bm, old_totvert); + } + + if (ob->par1 < old_totvert) { + eve = vertMap[ob->par1]; + if (eve) { + ob->par1 = BM_elem_index_get(eve); + } + } + if (ob->par2 < old_totvert) { + eve = vertMap[ob->par2]; + if (eve) { + ob->par2 = BM_elem_index_get(eve); + } + } + if (ob->par3 < old_totvert) { + eve = vertMap[ob->par3]; + if (eve) { + ob->par3 = BM_elem_index_get(eve); + } + } + } + if (ob->data == &me) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type == eModifierType_Hook) { + HookModifierData *hmd = (HookModifierData *)md; + + if (vertMap == nullptr) { + vertMap = bm_to_mesh_vertex_map(&bm, old_totvert); + } + int i, j; + for (i = j = 0; i < hmd->indexar_num; i++) { + if (hmd->indexar[i] < old_totvert) { + eve = vertMap[hmd->indexar[i]]; + + if (eve) { + hmd->indexar[j++] = BM_elem_index_get(eve); + } + } + else { + j++; + } + } + + hmd->indexar_num = j; + } + } + } } - bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); - BM_mesh_elem_table_ensure(&bm, BM_VERT | BM_EDGE | BM_FACE); - - if (need_hide_vert) { - write_fn_to_attribute(attributes, ".hide_vert", ATTR_DOMAIN_POINT, [&](const int i) { - return BM_elem_flag_test(BM_vert_at_index(&bm, i), BM_ELEM_HIDDEN); - }); - } - if (need_hide_edge) { - write_fn_to_attribute(attributes, ".hide_edge", ATTR_DOMAIN_EDGE, [&](const int i) { - return BM_elem_flag_test(BM_edge_at_index(&bm, i), BM_ELEM_HIDDEN); - }); - } - if (need_hide_poly) { - write_fn_to_attribute(attributes, ".hide_poly", ATTR_DOMAIN_FACE, [&](const int i) { - return BM_elem_flag_test(BM_face_at_index(&bm, i), BM_ELEM_HIDDEN); - }); - } -} - -static void convert_bmesh_selection_flags_to_mesh_attributes(BMesh &bm, - const bool need_select_vert, - const bool need_select_edge, - const bool need_select_poly, - Mesh &mesh) -{ - using namespace blender; - if (!(need_select_vert || need_select_edge || need_select_poly)) { - return; - } - - bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); - BM_mesh_elem_table_ensure(&bm, BM_VERT | BM_EDGE | BM_FACE); - - if (need_select_vert) { - write_fn_to_attribute(attributes, ".select_vert", ATTR_DOMAIN_POINT, [&](const int i) { - return BM_elem_flag_test(BM_vert_at_index(&bm, i), BM_ELEM_SELECT); - }); - } - if (need_select_edge) { - write_fn_to_attribute(attributes, ".select_edge", ATTR_DOMAIN_EDGE, [&](const int i) { - return BM_elem_flag_test(BM_edge_at_index(&bm, i), BM_ELEM_SELECT); - }); - } - if (need_select_poly) { - write_fn_to_attribute(attributes, ".select_poly", ATTR_DOMAIN_FACE, [&](const int i) { - return BM_elem_flag_test(BM_face_at_index(&bm, i), BM_ELEM_SELECT); - }); + if (vertMap) { + MEM_freeN(vertMap); } } @@ -1110,6 +1096,7 @@ static void bm_vert_table_build(BMesh &bm, BM_elem_index_set(vert, i); /* set_inline */ table[i] = vert; hflag |= vert->head.hflag; + BM_CHECK_ELEMENT(vert); } need_select_vert = (hflag & BM_ELEM_SELECT) != 0; need_hide_vert = (hflag & BM_ELEM_HIDDEN) != 0; @@ -1130,6 +1117,7 @@ static void bm_edge_table_build(BMesh &bm, BM_elem_index_set(edge, i); /* set_inline */ table[i] = edge; hflag |= edge->head.hflag; + BM_CHECK_ELEMENT(edge); } need_select_edge = (hflag & BM_ELEM_SELECT) != 0; need_hide_edge = (hflag & BM_ELEM_HIDDEN) != 0; @@ -1156,11 +1144,13 @@ static void bm_face_loop_table_build(BMesh &bm, hflag |= face->head.hflag; need_sharp_face |= (face->head.hflag & BM_ELEM_SMOOTH) == 0; need_material_index |= face->mat_nr != 0; + BM_CHECK_ELEMENT(face); BMLoop *loop = BM_FACE_FIRST_LOOP(face); for ([[maybe_unused]] const int i : IndexRange(face->len)) { BM_elem_index_set(loop, loop_i); /* set_inline */ loop_table[loop_i] = loop; + BM_CHECK_ELEMENT(loop); loop = loop->next; loop_i++; } @@ -1186,6 +1176,8 @@ static void bm_to_mesh_verts(const BMesh &bm, MutableSpan select_vert, MutableSpan hide_vert) { + CustomData_add_layer_named( + &mesh.vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, mesh.totvert, "position"); const Vector info = bm_to_mesh_copy_info_calc(bm.vdata, mesh.vdata); MutableSpan dst_vert_positions = mesh.vert_positions_for_write(); threading::parallel_for(dst_vert_positions.index_range(), 1024, [&](const IndexRange range) { @@ -1215,6 +1207,7 @@ static void bm_to_mesh_edges(const BMesh &bm, MutableSpan sharp_edge, MutableSpan uv_seams) { + CustomData_add_layer(&mesh.edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, mesh.totedge); const Vector info = bm_to_mesh_copy_info_calc(bm.edata, mesh.edata); MutableSpan dst_edges = mesh.edges_for_write(); threading::parallel_for(dst_edges.index_range(), 512, [&](const IndexRange range) { @@ -1256,6 +1249,7 @@ static void bm_to_mesh_faces(const BMesh &bm, MutableSpan sharp_faces, MutableSpan material_indices) { + CustomData_add_layer(&mesh.pdata, CD_MPOLY, CD_CONSTRUCT, nullptr, mesh.totpoly); const Vector info = bm_to_mesh_copy_info_calc(bm.pdata, mesh.pdata); MutableSpan dst_polys = mesh.polys_for_write(); threading::parallel_for(dst_polys.index_range(), 1024, [&](const IndexRange range) { @@ -1291,6 +1285,7 @@ static void bm_to_mesh_faces(const BMesh &bm, static void bm_to_mesh_loops(const BMesh &bm, const Span bm_loops, Mesh &mesh) { + CustomData_add_layer(&mesh.ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, mesh.totloop); const Vector info = bm_to_mesh_copy_info_calc(bm.ldata, mesh.ldata); MutableSpan dst_loops = mesh.loops_for_write(); threading::parallel_for(dst_loops.index_range(), 1024, [&](const IndexRange range) { @@ -1309,13 +1304,8 @@ static void bm_to_mesh_loops(const BMesh &bm, const Span bm_loop void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) { using namespace blender; - BMVert *v, *eve; - BMEdge *e; BMFace *f; BMIter iter; - int i, j; - - const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); const int ototvert = me->totvert; @@ -1333,11 +1323,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh /* Add new custom data. */ me->totvert = bm->totvert; me->totedge = bm->totedge; + me->totface = 0; me->totloop = bm->totloop; me->totpoly = bm->totface; - /* Will be overwritten with a valid value if 'dotess' is set, otherwise we - * end up with 'me->totface' and `me->mface == nullptr` which can crash #28625. */ - me->totface = 0; me->act_face = -1; /* Mark UV selection layers which are all false as 'nocopy'. */ @@ -1418,26 +1406,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly); } - const Vector vert_info = bm_to_mesh_copy_info_calc(bm->vdata, me->vdata); - const Vector edge_info = bm_to_mesh_copy_info_calc(bm->edata, me->edata); - const Vector poly_info = bm_to_mesh_copy_info_calc(bm->pdata, me->pdata); - const Vector loop_info = bm_to_mesh_copy_info_calc(bm->ldata, me->ldata); - - /* Clear the CD_FLAG_NOCOPY flags for the layers they were temporarily set on */ - for (const int i : ldata_layers_marked_nocopy) { - bm->ldata.layers[i].flag &= ~CD_FLAG_NOCOPY; - } - - CustomData_add_layer_named( - &me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, me->totvert, "position"); - CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, me->totedge); - CustomData_add_layer(&me->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, me->totloop); - CustomData_add_layer(&me->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, me->totpoly); - MutableSpan positions = me->vert_positions_for_write(); - MutableSpan edges = me->edges_for_write(); - MutableSpan polys = me->polys_for_write(); - MutableSpan mloop = me->loops_for_write(); - bool need_select_vert = false; bool need_select_edge = false; bool need_select_poly = false; @@ -1445,239 +1413,180 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh bool need_hide_edge = false; bool need_hide_poly = false; bool need_material_index = false; - bool need_sharp_face = false; bool need_sharp_edge = false; - bool need_uv_seam = false; + bool need_sharp_face = false; + bool need_uv_seams = false; + Array vert_table; + Array edge_table; + Array face_table; + Array loop_table; + threading::parallel_invoke( + me->totface > 1024, + [&]() { + vert_table.reinitialize(bm->totvert); + bm_vert_table_build(*bm, vert_table, need_select_vert, need_hide_vert); + }, + [&]() { + edge_table.reinitialize(bm->totedge); + bm_edge_table_build( + *bm, edge_table, need_select_edge, need_hide_edge, need_sharp_edge, need_uv_seams); + }, + [&]() { + face_table.reinitialize(bm->totface); + loop_table.reinitialize(bm->totloop); + bm_face_loop_table_build(*bm, + face_table, + loop_table, + need_select_poly, + need_hide_poly, + need_sharp_face, + need_material_index); + }); + bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE | BM_LOOP); - i = 0; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - copy_v3_v3(positions[i], v->co); - - if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - need_hide_vert = true; - } - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - need_select_vert = true; - } - - BM_elem_index_set(v, i); /* set_inline */ - - bmesh_block_copy_to_mesh_attributes(vert_info, i, v->head.data); - - i++; - - BM_CHECK_ELEMENT(v); + /* Add optional mesh attributes before parallel iteration. */ + assert_bmesh_has_no_mesh_only_attributes(*bm); + bke::MutableAttributeAccessor attrs = me->attributes_for_write(); + bke::SpanAttributeWriter select_vert; + bke::SpanAttributeWriter hide_vert; + bke::SpanAttributeWriter select_edge; + bke::SpanAttributeWriter hide_edge; + bke::SpanAttributeWriter sharp_edge; + bke::SpanAttributeWriter uv_seams; + bke::SpanAttributeWriter select_poly; + bke::SpanAttributeWriter hide_poly; + bke::SpanAttributeWriter sharp_face; + bke::SpanAttributeWriter material_index; + if (need_select_vert) { + select_vert = attrs.lookup_or_add_for_write_only_span(".select_vert", ATTR_DOMAIN_POINT); } - bm->elem_index_dirty &= ~BM_VERT; - - i = 0; - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - edges[i].v1 = BM_elem_index_get(e->v1); - edges[i].v2 = BM_elem_index_get(e->v2); - - if (BM_elem_flag_test(e, BM_ELEM_SEAM)) { - need_uv_seam = true; - } - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - need_hide_edge = true; - } - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - need_select_edge = true; - } - if (!BM_elem_flag_test(e, BM_ELEM_SMOOTH)) { - need_sharp_edge = true; - } - - BM_elem_index_set(e, i); /* set_inline */ - - bmesh_block_copy_to_mesh_attributes(edge_info, i, e->head.data); - - i++; - BM_CHECK_ELEMENT(e); + if (need_hide_vert) { + hide_vert = attrs.lookup_or_add_for_write_only_span(".hide_vert", ATTR_DOMAIN_POINT); } - bm->elem_index_dirty &= ~BM_EDGE; - - i = 0; - j = 0; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - polys[i].loopstart = j; - polys[i].totloop = f->len; - if (f->mat_nr != 0) { - need_material_index = true; - } - if (!BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { - need_sharp_face = true; - } - if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - need_hide_poly = true; - } - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - need_select_poly = true; - } - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - mloop[j].e = BM_elem_index_get(l_iter->e); - mloop[j].v = BM_elem_index_get(l_iter->v); - - bmesh_block_copy_to_mesh_attributes(loop_info, j, l_iter->head.data); - - j++; - BM_CHECK_ELEMENT(l_iter); - BM_CHECK_ELEMENT(l_iter->e); - BM_CHECK_ELEMENT(l_iter->v); - } while ((l_iter = l_iter->next) != l_first); - - if (f == bm->act_face) { - me->act_face = i; - } - - bmesh_block_copy_to_mesh_attributes(poly_info, i, f->head.data); - - i++; - BM_CHECK_ELEMENT(f); - } - - if (need_material_index) { - BM_mesh_elem_table_ensure(bm, BM_FACE); - write_fn_to_attribute(me->attributes_for_write(), - "material_index", - ATTR_DOMAIN_FACE, - [&](const int i) { return int(BM_face_at_index(bm, i)->mat_nr); }); + if (need_select_edge) { + select_edge = attrs.lookup_or_add_for_write_only_span(".select_edge", ATTR_DOMAIN_EDGE); } if (need_sharp_edge) { - BM_mesh_elem_table_ensure(bm, BM_EDGE); - write_fn_to_attribute( - me->attributes_for_write(), "sharp_edge", ATTR_DOMAIN_EDGE, [&](const int i) { - return !BM_elem_flag_test(BM_edge_at_index(bm, i), BM_ELEM_SMOOTH); - }); + sharp_edge = attrs.lookup_or_add_for_write_only_span("sharp_edge", ATTR_DOMAIN_EDGE); + } + if (need_uv_seams) { + uv_seams = attrs.lookup_or_add_for_write_only_span(".uv_seam", ATTR_DOMAIN_EDGE); + } + if (need_hide_edge) { + hide_edge = attrs.lookup_or_add_for_write_only_span(".hide_edge", ATTR_DOMAIN_EDGE); + } + if (need_select_poly) { + select_poly = attrs.lookup_or_add_for_write_only_span(".select_poly", ATTR_DOMAIN_FACE); + } + if (need_hide_poly) { + hide_poly = attrs.lookup_or_add_for_write_only_span(".hide_poly", ATTR_DOMAIN_FACE); } if (need_sharp_face) { - BM_mesh_elem_table_ensure(bm, BM_FACE); - write_fn_to_attribute( - me->attributes_for_write(), "sharp_face", ATTR_DOMAIN_FACE, [&](const int i) { - return !BM_elem_flag_test(BM_face_at_index(bm, i), BM_ELEM_SMOOTH); - }); + sharp_face = attrs.lookup_or_add_for_write_only_span("sharp_face", ATTR_DOMAIN_FACE); } - if (need_uv_seam) { - BM_mesh_elem_table_ensure(bm, BM_EDGE); - write_fn_to_attribute( - me->attributes_for_write(), ".uv_seam", ATTR_DOMAIN_EDGE, [&](const int i) { - return BM_elem_flag_test(BM_edge_at_index(bm, i), BM_ELEM_SEAM); - }); + if (need_material_index) { + material_index = attrs.lookup_or_add_for_write_only_span("material_index", + ATTR_DOMAIN_FACE); } - /* Patch hook indices and vertex parents. */ - if (params->calc_object_remap && (ototvert > 0)) { - BLI_assert(bmain != nullptr); - BMVert **vertMap = nullptr; - - LISTBASE_FOREACH (Object *, ob, &bmain->objects) { - if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) { - - if (vertMap == nullptr) { - vertMap = bm_to_mesh_vertex_map(bm, ototvert); + /* Loop over all elements in parallel, copying attributes and building the Mesh topology. */ + threading::parallel_invoke( + me->totvert > 1024, + [&]() { + bm_to_mesh_verts(*bm, vert_table, *me, select_vert.span, hide_vert.span); + if (me->key) { + bm_to_mesh_shape( + bm, me->key, me->vert_positions_for_write(), params->active_shapekey_to_mvert); } + }, + [&]() { + bm_to_mesh_edges(*bm, + edge_table, + *me, + select_edge.span, + hide_edge.span, + sharp_edge.span, + uv_seams.span); + }, + [&]() { + bm_to_mesh_faces(*bm, + face_table, + *me, + select_poly.span, + hide_poly.span, + sharp_face.span, + material_index.span); + if (bm->act_face) { + me->act_face = BM_elem_index_get(bm->act_face); + } + }, + [&]() { + bm_to_mesh_loops(*bm, loop_table, *me); + /* Topology could be changed, ensure #CD_MDISPS are ok. */ + multires_topology_changed(me); + /* Clear the CD_FLAG_NOCOPY flags for the layers they were temporarily set on */ + for (const int i : ldata_layers_marked_nocopy) { + bm->ldata.layers[i].flag &= ~CD_FLAG_NOCOPY; + } + }, + [&]() { + /* Patch hook indices and vertex parents. */ + if (params->calc_object_remap && (ototvert > 0)) { + bmesh_to_mesh_calc_object_remap(*bmain, *me, *bm, ototvert); + } + }, + [&]() { + me->totselect = BLI_listbase_count(&(bm->selected)); - if (ob->par1 < ototvert) { - eve = vertMap[ob->par1]; - if (eve) { - ob->par1 = BM_elem_index_get(eve); + MEM_SAFE_FREE(me->mselect); + if (me->totselect != 0) { + me->mselect = static_cast( + MEM_mallocN(sizeof(MSelect) * me->totselect, "Mesh selection history")); + } + int i; + LISTBASE_FOREACH_INDEX (BMEditSelection *, selected, &bm->selected, i) { + if (selected->htype == BM_VERT) { + me->mselect[i].type = ME_VSEL; } - } - if (ob->par2 < ototvert) { - eve = vertMap[ob->par2]; - if (eve) { - ob->par2 = BM_elem_index_get(eve); + else if (selected->htype == BM_EDGE) { + me->mselect[i].type = ME_ESEL; } - } - if (ob->par3 < ototvert) { - eve = vertMap[ob->par3]; - if (eve) { - ob->par3 = BM_elem_index_get(eve); + else if (selected->htype == BM_FACE) { + me->mselect[i].type = ME_FSEL; } - } - } - if (ob->data == me) { - LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { - if (md->type == eModifierType_Hook) { - HookModifierData *hmd = (HookModifierData *)md; - if (vertMap == nullptr) { - vertMap = bm_to_mesh_vertex_map(bm, ototvert); + me->mselect[i].index = BM_elem_index_get(selected->ele); + } + }, + [&]() { + /* Run this even when shape keys aren't used since it may be used for hooks or vertex + * parents. */ + if (params->update_shapekey_indices) { + /* We have written a new shape key, if this mesh is _not_ going to be freed, + * update the shape key indices to match the newly updated. */ + const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, + CD_SHAPE_KEYINDEX); + if (cd_shape_keyindex_offset != -1) { + BMIter iter; + BMVert *vert; + int i; + BM_ITER_MESH_INDEX (vert, &iter, bm, BM_VERTS_OF_MESH, i) { + BM_ELEM_CD_SET_INT(vert, cd_shape_keyindex_offset, i); } - - for (i = j = 0; i < hmd->indexar_num; i++) { - if (hmd->indexar[i] < ototvert) { - eve = vertMap[hmd->indexar[i]]; - - if (eve) { - hmd->indexar[j++] = BM_elem_index_get(eve); - } - } - else { - j++; - } - } - - hmd->indexar_num = j; } } - } - } + }); - if (vertMap) { - MEM_freeN(vertMap); - } - } - - convert_bmesh_hide_flags_to_mesh_attributes( - *bm, need_hide_vert, need_hide_edge, need_hide_poly, *me); - convert_bmesh_selection_flags_to_mesh_attributes( - *bm, need_select_vert, need_select_edge, need_select_poly, *me); - - { - me->totselect = BLI_listbase_count(&(bm->selected)); - - MEM_SAFE_FREE(me->mselect); - if (me->totselect != 0) { - me->mselect = static_cast( - MEM_mallocN(sizeof(MSelect) * me->totselect, "Mesh selection history")); - } - - LISTBASE_FOREACH_INDEX (BMEditSelection *, selected, &bm->selected, i) { - if (selected->htype == BM_VERT) { - me->mselect[i].type = ME_VSEL; - } - else if (selected->htype == BM_EDGE) { - me->mselect[i].type = ME_ESEL; - } - else if (selected->htype == BM_FACE) { - me->mselect[i].type = ME_FSEL; - } - - me->mselect[i].index = BM_elem_index_get(selected->ele); - } - } - - if (me->key) { - bm_to_mesh_shape(bm, me->key, positions, params->active_shapekey_to_mvert); - } - - /* Run this even when shape keys aren't used since it may be used for hooks or vertex parents. */ - if (params->update_shapekey_indices) { - /* We have written a new shape key, if this mesh is _not_ going to be freed, - * update the shape key indices to match the newly updated. */ - if (cd_shape_keyindex_offset != -1) { - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - BM_ELEM_CD_SET_INT(eve, cd_shape_keyindex_offset, i); - } - } - } - - /* Topology could be changed, ensure #CD_MDISPS are ok. */ - multires_topology_changed(me); + select_vert.finish(); + hide_vert.finish(); + select_edge.finish(); + hide_edge.finish(); + sharp_edge.finish(); + uv_seams.finish(); + select_poly.finish(); + hide_poly.finish(); + sharp_face.finish(); + material_index.finish(); } /* NOTE: The function is called from multiple threads with the same input BMesh and different @@ -1698,14 +1607,6 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * me->totloop = bm->totloop; me->totpoly = bm->totface; - if (!CustomData_get_layer_named(&me->vdata, CD_PROP_FLOAT3, "position")) { - CustomData_add_layer_named( - &me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, bm->totvert, "position"); - } - CustomData_add_layer(&me->edata, CD_MEDGE, CD_CONSTRUCT, nullptr, bm->totedge); - CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CONSTRUCT, nullptr, bm->totloop); - CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CONSTRUCT, nullptr, bm->totface); - /* Don't process shape-keys, we only feed them through the modifier stack as needed, * e.g. for applying modifiers or the like. */ CustomData_MeshMasks mask = CD_MASK_DERIVEDMESH;