diff options
47 files changed, 952 insertions, 559 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index ef57c9a2e0e..c1f4d9733aa 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -870,16 +870,7 @@ void BKE_mesh_merge_customdata_for_apply_modifier(struct Mesh *me); */ void BKE_mesh_flush_hidden_from_verts(struct Mesh *me); void BKE_mesh_flush_hidden_from_polys(struct Mesh *me); -/** - * simple poly -> vert/edge selection. - */ -void BKE_mesh_flush_select_from_polys_ex(struct MVert *mvert, - int totvert, - const struct MLoop *mloop, - struct MEdge *medge, - int totedge, - const struct MPoly *mpoly, - int totpoly); + void BKE_mesh_flush_select_from_polys(struct Mesh *me); void BKE_mesh_flush_select_from_verts(struct Mesh *me); diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h index f45dfd8bc8d..d3e582ff197 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h @@ -55,6 +55,16 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(struct Mesh *mesh); void BKE_mesh_legacy_convert_flags_to_hide_layers(struct Mesh *mesh); /** + * Convert the selected element attributes to the old flag format for writing. + */ +void BKE_mesh_legacy_convert_selection_layers_to_flags(struct Mesh *mesh); +/** + * Convert the old selection flags (#SELECT/#ME_FACE_SEL) to the selected element attribute for + * reading. Only add the attributes when there are any elements in each domain selected. + */ +void BKE_mesh_legacy_convert_flags_to_selection_layers(struct Mesh *mesh); + +/** * Move material indices from a generic attribute to #MPoly. */ void BKE_mesh_legacy_convert_material_indices_to_mpoly(struct Mesh *mesh); diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index cf9763d50a4..2ee50fbaaee 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -93,6 +93,7 @@ typedef struct MeshElemMap { /* mapping */ UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly, const bool *hide_poly, + const bool *select_poly, const struct MLoop *mloop, const struct MLoopUV *mloopuv, unsigned int totpoly, diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index df7787986db..b86353bdb74 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -58,7 +58,7 @@ const char *no_procedural_access_message = bool allow_procedural_attribute_access(StringRef attribute_name) { - return !attribute_name.startswith(".sculpt") && !attribute_name.startswith(".selection") && + return !attribute_name.startswith(".sculpt") && !attribute_name.startswith(".select") && !attribute_name.startswith(".hide"); } diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 084fe76cd10..51c3b405ebc 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2372,7 +2372,14 @@ bool CustomData_merge(const CustomData *source, static bool attribute_stored_in_bmesh_flag(const StringRef name) { - return ELEM(name, ".hide_vert", ".hide_edge", ".hide_poly", "material_index"); + return ELEM(name, + ".hide_vert", + ".hide_edge", + ".hide_poly", + ".select_vert", + ".select_edge", + ".select_poly", + "material_index"); } static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src) diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 49963c333ec..48fadd2e9b8 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -1447,7 +1447,6 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob) MVert *mvert = CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CONSTRUCT, NULL, mesh->totvert); for (int i = 0; i < mesh->totvert; i++) { copy_v3_v3(mvert[i].co, process.co[i]); - mvert->flag = 0; } MEM_freeN(process.co); diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 34cebeaa5d4..6df6cd31cf4 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -68,6 +68,7 @@ using blender::BitVector; using blender::float3; using blender::MutableSpan; using blender::Span; +using blender::StringRef; using blender::VArray; using blender::Vector; @@ -248,12 +249,19 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address Set<std::string> names_to_skip; if (!BLO_write_is_undo(writer)) { BKE_mesh_legacy_convert_hide_layers_to_flags(mesh); + BKE_mesh_legacy_convert_selection_layers_to_flags(mesh); BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh); BKE_mesh_legacy_bevel_weight_from_layers(mesh); BKE_mesh_legacy_face_set_from_generic(mesh); BKE_mesh_legacy_edge_crease_from_layers(mesh); /* When converting to the old mesh format, don't save redundant attributes. */ - names_to_skip.add_multiple_new({".hide_vert", ".hide_edge", ".hide_poly", "material_index"}); + names_to_skip.add_multiple_new({".hide_vert", + ".hide_edge", + ".hide_poly", + "material_index", + ".select_vert", + ".select_edge", + ".select_poly"}); /* Set deprecated mesh data pointers for forward compatibility. */ mesh->mvert = const_cast<MVert *>(mesh->verts().data()); @@ -689,7 +697,6 @@ static int customdata_compare( case CD_PROP_BOOL: { const bool *l1_data = (bool *)l1->data; const bool *l2_data = (bool *)l2->data; - for (int i = 0; i < total_length; i++) { if (l1_data[i] != l2_data[i]) { return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; @@ -1638,39 +1645,46 @@ void BKE_mesh_mselect_clear(Mesh *me) void BKE_mesh_mselect_validate(Mesh *me) { + using namespace blender; + using namespace blender::bke; MSelect *mselect_src, *mselect_dst; int i_src, i_dst; if (me->totselect == 0) { return; } - const Span<MVert> verts = me->verts(); - const Span<MEdge> edges = me->edges(); - const Span<MPoly> polys = me->polys(); mselect_src = me->mselect; mselect_dst = (MSelect *)MEM_malloc_arrayN( (me->totselect), sizeof(MSelect), "Mesh selection history"); + const AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const VArray<bool> select_edge = attributes.lookup_or_default<bool>( + ".select_edge", ATTR_DOMAIN_EDGE, false); + const VArray<bool> select_poly = attributes.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + for (i_src = 0, i_dst = 0; i_src < me->totselect; i_src++) { int index = mselect_src[i_src].index; switch (mselect_src[i_src].type) { case ME_VSEL: { - if (verts[index].flag & SELECT) { + if (select_vert[index]) { mselect_dst[i_dst] = mselect_src[i_src]; i_dst++; } break; } case ME_ESEL: { - if (edges[index].flag & SELECT) { + if (select_edge[index]) { mselect_dst[i_dst] = mselect_src[i_src]; i_dst++; } break; } case ME_FSEL: { - if (polys[index].flag & SELECT) { + if (select_poly[index]) { mselect_dst[i_dst] = mselect_src[i_src]; i_dst++; } diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index 3d6ecec44e1..be6c27ee6f9 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -375,14 +375,10 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes, * `mv` is in `dest_mesh` with index `mv_index`. * The `orig_mv` vertex came from Mesh `orig_me` and had index `index_in_orig_me` there. */ static void copy_vert_attributes(Mesh *dest_mesh, - MVert *mv, - const MVert *orig_mv, const Mesh *orig_me, int mv_index, int index_in_orig_me) { - mv->flag = orig_mv->flag; - /* For all layers in the orig mesh, copy the layer information. */ CustomData *target_cd = &dest_mesh->vdata; const CustomData *source_cd = &orig_me->vdata; @@ -723,14 +719,14 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) MutableSpan<MVert> verts = result->verts_for_write(); for (int vi : im->vert_index_range()) { const Vert *v = im->vert(vi); - MVert *mv = &verts[vi]; - copy_v3fl_v3db(mv->co, v->co); if (v->orig != NO_INDEX) { const Mesh *orig_me; int index_in_orig_me; - const MVert *orig_mv = mim.input_mvert_for_orig_index(v->orig, &orig_me, &index_in_orig_me); - copy_vert_attributes(result, mv, orig_mv, orig_me, vi, index_in_orig_me); + mim.input_mvert_for_orig_index(v->orig, &orig_me, &index_in_orig_me); + copy_vert_attributes(result, orig_me, vi, index_in_orig_me); } + MVert *mv = &verts[vi]; + copy_v3fl_v3db(mv->co, v->co); } /* Set the loopstart and totloop for each output poly, diff --git a/source/blender/blenkernel/intern/mesh_calc_edges.cc b/source/blender/blenkernel/intern/mesh_calc_edges.cc index cc315130ad1..038133c33ae 100644 --- a/source/blender/blenkernel/intern/mesh_calc_edges.cc +++ b/source/blender/blenkernel/intern/mesh_calc_edges.cc @@ -13,6 +13,7 @@ #include "BLI_threads.h" #include "BLI_timeit.hh" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_mesh.h" @@ -120,8 +121,7 @@ static void add_polygon_edges_to_hash_maps(Mesh *mesh, } static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edge_maps, - MutableSpan<MEdge> new_edges, - short new_edge_flag) + MutableSpan<MEdge> new_edges) { /* All edges are distributed in the hash tables now. They have to be serialized into a single * array below. To be able to parallelize this, we have to compute edge index offsets for each @@ -147,7 +147,7 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg /* Initialize new edge. */ new_edge.v1 = item.key.v_low; new_edge.v2 = item.key.v_high; - new_edge.flag = new_edge_flag; + new_edge.flag = ME_EDGEDRAW | ME_EDGERENDER; } item.value.index = new_edge_index; new_edge_index++; @@ -236,8 +236,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select /* Create new edges. */ MutableSpan<MEdge> new_edges{ static_cast<MEdge *>(MEM_calloc_arrayN(new_totedge, sizeof(MEdge), __func__)), new_totedge}; - const short new_edge_flag = (ME_EDGEDRAW | ME_EDGERENDER) | (select_new_edges ? SELECT : 0); - calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, new_edges, new_edge_flag); + calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, new_edges); calc_edges::update_edge_indices_in_poly_loops(mesh, edge_maps, parallel_mask); /* Free old CustomData and assign new one. */ @@ -246,6 +245,24 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_ASSIGN, new_edges.data(), new_totedge); mesh->totedge = new_totedge; + if (select_new_edges) { + MutableAttributeAccessor attributes = mesh->attributes_for_write(); + SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_span<bool>( + ".select_edge", ATTR_DOMAIN_EDGE); + if (select_edge) { + int new_edge_index = 0; + for (const EdgeMap &edge_map : edge_maps) { + for (EdgeMap::Item item : edge_map.items()) { + if (item.value.original_edge == nullptr) { + select_edge.span[new_edge_index] = true; + } + new_edge_index++; + } + } + select_edge.finish(); + } + } + /* Explicitly clear edge maps, because that way it can be parallelized. */ clear_hash_tables(edge_maps); } diff --git a/source/blender/blenkernel/intern/mesh_evaluate.cc b/source/blender/blenkernel/intern/mesh_evaluate.cc index 938d7e42aa3..4f8391263a1 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.cc +++ b/source/blender/blenkernel/intern/mesh_evaluate.cc @@ -818,103 +818,88 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me) hide_edge.finish(); } -void BKE_mesh_flush_select_from_polys_ex(MVert *mvert, - const int totvert, - const MLoop *mloop, - MEdge *medge, - const int totedge, - const MPoly *mpoly, - const int totpoly) +void BKE_mesh_flush_select_from_polys(Mesh *me) { - MVert *mv; - MEdge *med; - const MPoly *mp; - - int i = totvert; - for (mv = mvert; i--; mv++) { - mv->flag &= (char)~SELECT; + using namespace blender::bke; + MutableAttributeAccessor attributes = me->attributes_for_write(); + const VArray<bool> select_poly = attributes.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + if (select_poly.is_single() && !select_poly.get_internal_single()) { + attributes.remove(".select_vert"); + attributes.remove(".select_edge"); + return; } + SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_only_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_only_span<bool>( + ".select_edge", ATTR_DOMAIN_EDGE); - i = totedge; - for (med = medge; i--; med++) { - med->flag &= ~SELECT; - } + /* Use generic domain interpolation to read the polygon attribute on the other domains. + * Assume selected faces are not hidden and none of their vertices/edges are hidden. */ + attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_POINT, false) + .materialize(select_vert.span); + attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_EDGE, false) + .materialize(select_edge.span); - i = totpoly; - for (mp = mpoly; i--; mp++) { - /* Assume if its selected its not hidden and none of its verts/edges are hidden - * (a common assumption). */ - if (mp->flag & ME_FACE_SEL) { - const MLoop *ml; - int j; - j = mp->totloop; - for (ml = &mloop[mp->loopstart]; j--; ml++) { - mvert[ml->v].flag |= SELECT; - medge[ml->e].flag |= SELECT; - } - } - } -} -void BKE_mesh_flush_select_from_polys(Mesh *me) -{ - BKE_mesh_flush_select_from_polys_ex(me->verts_for_write().data(), - me->totvert, - me->loops().data(), - me->edges_for_write().data(), - me->totedge, - me->polys().data(), - me->totpoly); + select_vert.finish(); + select_edge.finish(); } -static void mesh_flush_select_from_verts(const Span<MVert> verts, +static void mesh_flush_select_from_verts(const Span<MEdge> edges, + const Span<MPoly> polys, const Span<MLoop> loops, const VArray<bool> &hide_edge, const VArray<bool> &hide_poly, - MutableSpan<MEdge> edges, - MutableSpan<MPoly> polys) + const VArray<bool> &select_vert, + MutableSpan<bool> select_edge, + MutableSpan<bool> select_poly) { + /* Select visible edges that have both of their vertices selected. */ for (const int i : edges.index_range()) { if (!hide_edge[i]) { - MEdge &edge = edges[i]; - if ((verts[edge.v1].flag & SELECT) && (verts[edge.v2].flag & SELECT)) { - edge.flag |= SELECT; - } - else { - edge.flag &= ~SELECT; - } + const MEdge &edge = edges[i]; + select_edge[i] = select_vert[edge.v1] && select_vert[edge.v2]; } } + /* Select visible faces that have all of their vertices selected. */ for (const int i : polys.index_range()) { - if (hide_poly[i]) { - continue; - } - MPoly &poly = polys[i]; - bool all_verts_selected = true; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - if (!(verts[loop.v].flag & SELECT)) { - all_verts_selected = false; - } - } - if (all_verts_selected) { - poly.flag |= ME_FACE_SEL; - } - else { - poly.flag &= (char)~ME_FACE_SEL; + if (!hide_poly[i]) { + const MPoly &poly = polys[i]; + const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop); + select_poly[i] = std::all_of(poly_loops.begin(), poly_loops.end(), [&](const MLoop &loop) { + return select_vert[loop.v]; + }); } } } void BKE_mesh_flush_select_from_verts(Mesh *me) { - const blender::bke::AttributeAccessor attributes = me->attributes(); + using namespace blender::bke; + MutableAttributeAccessor attributes = me->attributes_for_write(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + if (select_vert.is_single() && !select_vert.get_internal_single()) { + attributes.remove(".select_edge"); + attributes.remove(".select_poly"); + return; + } + SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_only_span<bool>( + ".select_edge", ATTR_DOMAIN_EDGE); + SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_only_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); mesh_flush_select_from_verts( - me->verts(), + me->edges(), + me->polys(), me->loops(), attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false), attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false), - me->edges_for_write(), - me->polys_for_write()); + select_vert, + select_edge.span, + select_poly.span); + select_edge.finish(); + select_poly.finish(); } /** \} */ diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 09982f15afa..506501ead2a 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -13,6 +13,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "BLI_edgehash.h" #include "BLI_math.h" @@ -1058,7 +1059,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh) ".hide_vert", ATTR_DOMAIN_POINT, false); threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) { for (const int i : range) { - SET_FLAG_FROM_TEST(verts[i].flag, hide_vert[i], ME_HIDE); + SET_FLAG_FROM_TEST(verts[i].flag_legacy, hide_vert[i], ME_HIDE); } }); @@ -1088,13 +1089,14 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh) MutableAttributeAccessor attributes = mesh->attributes_for_write(); const Span<MVert> verts = mesh->verts(); - if (std::any_of( - verts.begin(), verts.end(), [](const MVert &vert) { return vert.flag & ME_HIDE; })) { + if (std::any_of(verts.begin(), verts.end(), [](const MVert &vert) { + return vert.flag_legacy & ME_HIDE; + })) { SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_only_span<bool>( ".hide_vert", ATTR_DOMAIN_POINT); threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) { for (const int i : range) { - hide_vert.span[i] = verts[i].flag & ME_HIDE; + hide_vert.span[i] = verts[i].flag_legacy & ME_HIDE; } }); hide_vert.finish(); @@ -1128,6 +1130,7 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh) } /** \} */ + /* -------------------------------------------------------------------- */ /** \name Material Index Conversion * \{ */ @@ -1167,3 +1170,90 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Selection Attribute and Legacy Flag Conversion + * \{ */ + +void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + const AttributeAccessor attributes = mesh->attributes(); + + MutableSpan<MVert> verts = mesh->verts_for_write(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(verts[i].flag_legacy, select_vert[i], SELECT); + } + }); + + MutableSpan<MEdge> edges = mesh->edges_for_write(); + const VArray<bool> select_edge = attributes.lookup_or_default<bool>( + ".select_edge", ATTR_DOMAIN_EDGE, false); + threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(edges[i].flag, select_edge[i], SELECT); + } + }); + + MutableSpan<MPoly> polys = mesh->polys_for_write(); + const VArray<bool> select_poly = attributes.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(polys[i].flag, select_poly[i], ME_FACE_SEL); + } + }); +} + +void BKE_mesh_legacy_convert_flags_to_selection_layers(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + MutableAttributeAccessor attributes = mesh->attributes_for_write(); + + const Span<MVert> verts = mesh->verts(); + if (std::any_of(verts.begin(), verts.end(), [](const MVert &vert) { + return vert.flag_legacy & SELECT; + })) { + SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_only_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + select_vert.span[i] = (verts[i].flag_legacy & SELECT) != 0; + } + }); + select_vert.finish(); + } + + const Span<MEdge> edges = mesh->edges(); + if (std::any_of( + edges.begin(), edges.end(), [](const MEdge &edge) { return edge.flag & SELECT; })) { + SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_only_span<bool>( + ".select_edge", ATTR_DOMAIN_EDGE); + threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + select_edge.span[i] = (edges[i].flag & SELECT) != 0; + } + }); + select_edge.finish(); + } + + const Span<MPoly> polys = mesh->polys(); + if (std::any_of( + polys.begin(), polys.end(), [](const MPoly &poly) { return poly.flag & ME_FACE_SEL; })) { + SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_only_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); + threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + select_poly.span[i] = (polys[i].flag & ME_FACE_SEL) != 0; + } + }); + select_poly.finish(); + } +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/mesh_mapping.cc b/source/blender/blenkernel/intern/mesh_mapping.cc index db091361223..b612564ef09 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.cc +++ b/source/blender/blenkernel/intern/mesh_mapping.cc @@ -31,6 +31,7 @@ /* ngon version wip, based on BM_uv_vert_map_create */ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly, const bool *hide_poly, + const bool *select_poly, const MLoop *mloop, const MLoopUV *mloopuv, uint totpoly, @@ -53,7 +54,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly, /* generate UvMapVert array */ mp = mpoly; for (a = 0; a < totpoly; a++, mp++) { - if (!selected || (!(hide_poly && hide_poly[a]) && (mp->flag & ME_FACE_SEL))) { + if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) { totuv += mp->totloop; } } @@ -76,7 +77,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly, mp = mpoly; for (a = 0; a < totpoly; a++, mp++) { - if (!selected || (!(hide_poly && hide_poly[a]) && (mp->flag & ME_FACE_SEL))) { + if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) { float(*tf_uv)[2] = NULL; if (use_winding) { diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index 1fe5d7aa0e7..a72d68710ed 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -163,14 +163,14 @@ bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_sele } else { if (BKE_mesh_deform_verts(me)) { - const MVert *mv; + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".select_vert"); int i; - mv = BKE_mesh_verts(me); dv = BKE_mesh_deform_verts_for_write(me); - for (i = 0; i < me->totvert; i++, mv++, dv++) { - if (dv->dw && (!use_selection || (mv->flag & SELECT))) { + for (i = 0; i < me->totvert; i++, dv++) { + if (dv->dw && (!use_selection || (select_vert && select_vert[i]))) { MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr); BKE_defvert_remove_group(dv, dw); /* dw can be NULL */ changed = true; diff --git a/source/blender/blenkernel/intern/subdiv_converter_mesh.c b/source/blender/blenkernel/intern/subdiv_converter_mesh.c index 369e7f7060a..aabed2cea28 100644 --- a/source/blender/blenkernel/intern/subdiv_converter_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_converter_mesh.c @@ -212,6 +212,7 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create( storage->polys, (const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"), + (const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".select_poly"), storage->loops, mloopuv, num_poly, diff --git a/source/blender/blenkernel/intern/subdiv_mesh.cc b/source/blender/blenkernel/intern/subdiv_mesh.cc index 04389b43fd9..6bc188fd1fc 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_mesh.cc @@ -1137,8 +1137,6 @@ static void subdiv_mesh_vertex_of_loose_edge(const SubdivForeachContext *foreach is_simple, u, subdiv_vertex->co); - /* Reset flags and such. */ - subdiv_vertex->flag = 0; } /** \} */ diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 98d4ee6e8c2..c95c43a8099 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -285,7 +285,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, * Also, initially intention is to treat merged vertices from mirror modifier as seams. * This fixes a very old regression (2.49 was correct here) */ vmap = BKE_mesh_uv_vert_map_create( - mpoly, NULL, mloop, mloopuv, totface, totvert, limit, false, true); + mpoly, NULL, NULL, mloop, mloopuv, totface, totvert, limit, false, true); if (!vmap) { return 0; } @@ -880,7 +880,6 @@ static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float r_no[3]) BLI_INLINE void ccgDM_to_MVert(MVert *mv, const CCGKey *key, CCGElem *elem) { copy_v3_v3(mv->co, CCG_elem_co(key, elem)); - mv->flag = 0; } static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index d6d7ae03740..2616bb890a3 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -21,6 +21,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh) { + BKE_mesh_legacy_convert_flags_to_selection_layers(&mesh); BKE_mesh_legacy_convert_flags_to_hide_layers(&mesh); BKE_mesh_legacy_convert_mpoly_to_material_indices(&mesh); BKE_mesh_legacy_bevel_weight_to_layers(&mesh); diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 8b770050ba0..3ee9fa7aee4 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -21,8 +21,6 @@ #include "bmesh.h" #include "intern/bmesh_private.h" -#define SELECT 1 - bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len) { int i, i_prev = len - 1; @@ -712,35 +710,21 @@ BMesh *BM_mesh_copy(BMesh *bm_old) return bm_new; } -char BM_vert_flag_from_mflag(const char mflag) -{ - return ((mflag & SELECT) ? BM_ELEM_SELECT : 0); -} char BM_edge_flag_from_mflag(const short mflag) { - return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | - ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) | + return (((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) | ((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0)); } char BM_face_flag_from_mflag(const char mflag) { - return (((mflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) | - ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0)); -} - -char BM_vert_flag_to_mflag(BMVert *v) -{ - const char hflag = v->head.hflag; - - return (((hflag & BM_ELEM_SELECT) ? SELECT : 0)); + return ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0); } short BM_edge_flag_to_mflag(BMEdge *e) { const char hflag = e->head.hflag; - return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | - ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) | + return (((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) | ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) | (BM_edge_is_wire(e) ? ME_LOOSEEDGE : 0) | /* not typical */ ME_EDGERENDER); @@ -749,6 +733,5 @@ char BM_face_flag_to_mflag(BMFace *f) { const char hflag = f->head.hflag; - return (((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) | - ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0)); + return ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0); } diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index 1851cf58d4e..225e15c90e9 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -169,8 +169,5 @@ BMesh *BM_mesh_copy(BMesh *bm_old); char BM_face_flag_from_mflag(char mflag); char BM_edge_flag_from_mflag(short mflag); /* ME -> BM */ -char BM_vert_flag_from_mflag(char mflag); char BM_face_flag_to_mflag(BMFace *f); short BM_edge_flag_to_mflag(BMEdge *e); -/* BM -> ME */ -char BM_vert_flag_to_mflag(BMVert *v); diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index a52f95c1e9d..a97c7d1ea20 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -268,6 +268,12 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : -1; + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".select_vert"); + const bool *select_edge = (const bool *)CustomData_get_layer_named( + &me->edata, CD_PROP_BOOL, ".select_edge"); + const bool *select_poly = (const bool *)CustomData_get_layer_named( + &me->pdata, CD_PROP_BOOL, ".select_poly"); const bool *hide_vert = (const bool *)CustomData_get_layer_named( &me->vdata, CD_PROP_BOOL, ".hide_vert"); const bool *hide_edge = (const bool *)CustomData_get_layer_named( @@ -284,14 +290,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar bm, keyco ? keyco[i] : mvert[i].co, nullptr, BM_CREATE_SKIP_CD); BM_elem_index_set(v, i); /* set_ok */ - /* Transfer flag. */ - v->head.hflag = BM_vert_flag_from_mflag(mvert[i].flag & ~SELECT); if (hide_vert && hide_vert[i]) { BM_elem_flag_enable(v, BM_ELEM_HIDDEN); } - - /* This is necessary for selection counts to work properly. */ - if (mvert[i].flag & SELECT) { + if (select_vert && select_vert[i]) { BM_vert_select_set(bm, v, true); } @@ -327,13 +329,11 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar BM_elem_index_set(e, i); /* set_ok */ /* Transfer flags. */ - e->head.hflag = BM_edge_flag_from_mflag(medge[i].flag & ~SELECT); + e->head.hflag = BM_edge_flag_from_mflag(medge[i].flag); if (hide_edge && hide_edge[i]) { BM_elem_flag_enable(e, BM_ELEM_HIDDEN); } - - /* This is necessary for selection counts to work properly. */ - if (medge[i].flag & SELECT) { + if (select_edge && select_edge[i]) { BM_edge_select_set(bm, e, true); } @@ -376,13 +376,11 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar BM_elem_index_set(f, bm->totface - 1); /* set_ok */ /* Transfer flag. */ - f->head.hflag = BM_face_flag_from_mflag(mpoly[i].flag & ~ME_FACE_SEL); + f->head.hflag = BM_face_flag_from_mflag(mpoly[i].flag); if (hide_poly && hide_poly[i]) { BM_elem_flag_enable(f, BM_ELEM_HIDDEN); } - - /* This is necessary for selection counts to work properly. */ - if (mpoly[i].flag & ME_FACE_SEL) { + if (select_poly && select_poly[i]) { BM_face_select_set(bm, f, true); } @@ -829,24 +827,17 @@ template<typename T, typename GetFn> static void write_fn_to_attribute(blender::bke::MutableAttributeAccessor attributes, const StringRef attribute_name, const eAttrDomain domain, - const bool do_write, const GetFn &get_fn) { using namespace blender; - if (do_write) { - bke::SpanAttributeWriter<T> attribute = attributes.lookup_or_add_for_write_only_span<T>( - 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(); - } - else { - /* To avoid overhead, remove the hide attribute if possible. */ - attributes.remove(attribute_name); - } + bke::SpanAttributeWriter<T> attribute = attributes.lookup_or_add_for_write_only_span<T>( + 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) @@ -857,6 +848,10 @@ static void assert_bmesh_has_no_mesh_only_attributes(const BMesh &bm) BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_BOOL, ".hide_vert") == nullptr); BLI_assert(CustomData_get_layer_named(&bm.edata, CD_PROP_BOOL, ".hide_edge") == nullptr); BLI_assert(CustomData_get_layer_named(&bm.pdata, CD_PROP_BOOL, ".hide_poly") == nullptr); + /* The "selection" attributes are stored as flags on #BMesh. */ + BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_BOOL, ".select_vert") == nullptr); + BLI_assert(CustomData_get_layer_named(&bm.edata, CD_PROP_BOOL, ".select_edge") == nullptr); + 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, @@ -876,18 +871,52 @@ static void convert_bmesh_hide_flags_to_mesh_attributes(BMesh &bm, bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); BM_mesh_elem_table_ensure(&bm, BM_VERT | BM_EDGE | BM_FACE); - write_fn_to_attribute<bool>( - attributes, ".hide_vert", ATTR_DOMAIN_POINT, need_hide_vert, [&](const int i) { - return BM_elem_flag_test(BM_vert_at_index(&bm, i), BM_ELEM_HIDDEN); - }); - write_fn_to_attribute<bool>( - attributes, ".hide_edge", ATTR_DOMAIN_EDGE, need_hide_edge, [&](const int i) { - return BM_elem_flag_test(BM_edge_at_index(&bm, i), BM_ELEM_HIDDEN); - }); - write_fn_to_attribute<bool>( - attributes, ".hide_poly", ATTR_DOMAIN_FACE, need_hide_poly, [&](const int i) { - return BM_elem_flag_test(BM_face_at_index(&bm, i), BM_ELEM_HIDDEN); - }); + if (need_hide_vert) { + write_fn_to_attribute<bool>(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<bool>(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<bool>(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<bool>(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<bool>(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<bool>(attributes, ".select_poly", ATTR_DOMAIN_FACE, [&](const int i) { + return BM_elem_flag_test(BM_face_at_index(&bm, i), BM_ELEM_SELECT); + }); + } } void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) @@ -937,6 +966,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh MutableSpan<MPoly> mpoly = me->polys_for_write(); MutableSpan<MLoop> mloop = me->loops_for_write(); + bool need_select_vert = false; + bool need_select_edge = false; + bool need_select_poly = false; bool need_hide_vert = false; bool need_hide_edge = false; bool need_hide_poly = false; @@ -950,10 +982,12 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { copy_v3_v3(mvert[i].co, v->co); - mvert[i].flag = BM_vert_flag_to_mflag(v); 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 */ @@ -975,6 +1009,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh 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; + } BM_elem_index_set(e, i); /* set_inline */ @@ -1001,6 +1038,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh 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 { @@ -1030,7 +1070,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh if (need_material_index) { BM_mesh_elem_table_ensure(bm, BM_FACE); write_fn_to_attribute<int>( - me->attributes_for_write(), "material_index", ATTR_DOMAIN_FACE, true, [&](const int i) { + me->attributes_for_write(), "material_index", ATTR_DOMAIN_FACE, [&](const int i) { return static_cast<int>(BM_face_at_index(bm, i)->mat_nr); }); } @@ -1101,6 +1141,8 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh 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)); @@ -1201,6 +1243,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * bke::MutableAttributeAccessor mesh_attributes = me->attributes_for_write(); bke::SpanAttributeWriter<bool> hide_vert_attribute; + bke::SpanAttributeWriter<bool> select_vert_attribute; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { MVert *mv = &mvert[i]; @@ -1208,7 +1251,6 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * BM_elem_index_set(eve, i); /* set_inline */ - mv->flag = BM_vert_flag_to_mflag(eve); if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { if (!hide_vert_attribute) { hide_vert_attribute = mesh_attributes.lookup_or_add_for_write_span<bool>( @@ -1216,12 +1258,20 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * } hide_vert_attribute.span[i] = true; } + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (!select_vert_attribute) { + select_vert_attribute = mesh_attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + } + select_vert_attribute.span[i] = true; + } CustomData_from_bmesh_block(&bm->vdata, &me->vdata, eve->head.data, i); } bm->elem_index_dirty &= ~BM_VERT; bke::SpanAttributeWriter<bool> hide_edge_attribute; + bke::SpanAttributeWriter<bool> select_edge_attribute; BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { MEdge *med = &medge[i]; @@ -1238,6 +1288,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * } hide_edge_attribute.span[i] = true; } + if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + if (!select_edge_attribute) { + select_edge_attribute = mesh_attributes.lookup_or_add_for_write_span<bool>( + ".select_edge", ATTR_DOMAIN_EDGE); + } + select_edge_attribute.span[i] = true; + } /* Handle this differently to editmode switching, * only enable draw for single user edges rather than calculating angle. */ @@ -1254,6 +1311,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * j = 0; bke::SpanAttributeWriter<int> material_index_attribute; bke::SpanAttributeWriter<bool> hide_poly_attribute; + bke::SpanAttributeWriter<bool> select_poly_attribute; BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { BMLoop *l_iter; BMLoop *l_first; @@ -1270,6 +1328,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * } hide_poly_attribute.span[i] = true; } + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + if (!select_poly_attribute) { + select_poly_attribute = mesh_attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); + } + select_poly_attribute.span[i] = true; + } mp->loopstart = j; if (efa->mat_nr != 0) { @@ -1302,4 +1367,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * hide_vert_attribute.finish(); hide_edge_attribute.finish(); hide_poly_attribute.finish(); + select_vert_attribute.finish(); + select_edge_attribute.finish(); + select_poly_attribute.finish(); } diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index 2fc54da774d..392144246df 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -569,6 +569,13 @@ MeshRenderData *mesh_render_data_create(Object *object, CustomData_get_layer_named(&me->edata, CD_PROP_BOOL, ".hide_edge")); mr->hide_poly = static_cast<const bool *>( CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, ".hide_poly")); + + mr->select_vert = static_cast<const bool *>( + CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".select_vert")); + mr->select_edge = static_cast<const bool *>( + CustomData_get_layer_named(&me->edata, CD_PROP_BOOL, ".select_edge")); + mr->select_poly = static_cast<const bool *>( + CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, ".select_poly")); } else { /* #BMesh */ diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index c57406fe460..d4b3e392113 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -678,7 +678,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData * if ((polys[i].flag & ME_SMOOTH) != 0) { flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH; } - if ((polys[i].flag & ME_FACE_SEL) != 0) { + if (mr->select_poly && mr->select_poly[i]) { flag |= SUBDIV_COARSE_FACE_FLAG_SELECT; } if (mr->hide_poly && mr->hide_poly[i]) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index 2a8b7332cc5..0bce05577b2 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -86,6 +86,9 @@ struct MeshRenderData { const bool *hide_vert; const bool *hide_edge; const bool *hide_poly; + const bool *select_vert; + const bool *select_edge; + const bool *select_poly; float (*loop_normals)[3]; int *lverts, *ledges; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc index 2f2e59c8c3b..bf8dd1a51f8 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc @@ -220,7 +220,7 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, } else { mp_hidden = (mr->hide_poly) ? mr->hide_poly[mp_index] : false; - mp_select = (mp->flag & ME_FACE_SEL) != 0; + mp_select = mr->select_poly && mr->select_poly[mp_index]; } for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { @@ -291,16 +291,16 @@ static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache *subdiv_c { MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index); - + const int coarse_poly_index = coarse_poly - mr->mpoly; bool mp_hidden, mp_select; if (mr->bm) { - const BMFace *efa = bm_original_face_get(mr, coarse_poly - mr->mpoly); + const BMFace *efa = bm_original_face_get(mr, coarse_poly_index); mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true; mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false; } else { - mp_hidden = (mr->hide_poly) ? mr->hide_poly[coarse_poly - mr->mpoly] : false; - mp_select = (coarse_poly->flag & ME_FACE_SEL) != 0; + mp_hidden = (mr->hide_poly) ? mr->hide_poly[coarse_poly_index] : false; + mp_select = mr->select_poly && mr->select_poly[coarse_poly_index]; } uint start_loop_idx = subdiv_quad_index * 4; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc index 31e5c515129..9fbbfc3d705 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc @@ -37,7 +37,7 @@ static void extract_lines_paint_mask_init(const MeshRenderData *mr, static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, const MPoly *mp, - const int UNUSED(mp_index), + const int mp_index, void *_data) { MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(_data); @@ -52,7 +52,7 @@ static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_last = mp->totloop + mp->loopstart - 1; const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); - if (mp->flag & ME_FACE_SEL) { + if (mr->select_poly && mr->select_poly[mp_index]) { if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, e_index)) { /* Hide edge as it has more than 2 selected loop. */ GPU_indexbuf_set_line_restart(&data->elb, e_index); @@ -110,6 +110,8 @@ static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subd int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index); int *subdiv_loop_subdiv_edge_index = subdiv_cache->subdiv_loop_subdiv_edge_index; + const int coarse_quad_index = coarse_quad - mr->mpoly; + uint start_loop_idx = subdiv_quad_index * 4; uint end_loop_idx = (subdiv_quad_index + 1) * 4; for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) { @@ -124,7 +126,7 @@ static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subd ((mr->e_origindex) && (mr->e_origindex[coarse_edge_index] == ORIGINDEX_NONE)))) { const uint ml_index_other = (loop_idx == (end_loop_idx - 1)) ? start_loop_idx : loop_idx + 1; - if (coarse_quad->flag & ME_FACE_SEL) { + if (mr->select_poly && mr->select_poly[coarse_quad_index]) { if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, coarse_edge_index)) { /* Hide edge as it has more than 2 selected loop. */ GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc index 01d07fa5f83..b27d6577877 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -86,7 +86,7 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, (mr->edit_bmesh && (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { lnor_data->w = -1; } - else if (mp->flag & ME_FACE_SEL) { + else if (mr->select_poly && mr->select_poly[mp_index]) { lnor_data->w = 1; } else { @@ -211,7 +211,7 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, (mr->edit_bmesh && (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { lnor_data->w = -1; } - else if (mp->flag & ME_FACE_SEL) { + else if (mr->select_poly && mr->select_poly[mp_index]) { lnor_data->w = 1; } else { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index a822845c688..9d8197964ee 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -104,7 +104,7 @@ static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, ((mr->v_origindex) && (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { vert->nor.w = -1; } - else if (mv->flag & SELECT) { + else if (mr->select_vert && mr->select_vert[ml->v]) { vert->nor.w = 1; } else { @@ -451,7 +451,7 @@ static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, ((mr->v_origindex) && (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { vert->nor[3] = -1; } - else if (mv->flag & SELECT) { + else if (mr->select_vert && mr->select_vert[ml->v]) { vert->nor[3] = 1; } else { diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index e39cc157c19..6155aac621d 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -203,10 +203,13 @@ static void envelope_bone_weighting(Object *ob, use_mask = true; } + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &mesh->vdata, CD_PROP_BOOL, ".select_vert"); + /* for each vertex in the mesh */ - const MVert *mesh_verts = BKE_mesh_verts(mesh); for (int i = 0; i < mesh->totvert; i++) { - if (use_mask && !(mesh_verts[i].flag & SELECT)) { + + if (use_mask && !(select_vert && select_vert[i])) { continue; } diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 904e6213466..567977e51c4 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -669,17 +669,25 @@ void heat_bone_weighting(Object *ob, /* (added selectedVerts content for vertex mask, they used to just equal 1) */ if (use_vert_sel) { - for (a = 0, mp = polys; a < me->totpoly; mp++, a++) { - for (j = 0, ml = loops + mp->loopstart; j < mp->totloop; j++, ml++) { - mask[ml->v] = (mesh_verts[ml->v].flag & SELECT) != 0; + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".select_vert"); + if (select_vert) { + for (a = 0, mp = polys; a < me->totpoly; mp++, a++) { + for (j = 0, ml = loops + mp->loopstart; j < mp->totloop; j++, ml++) { + mask[ml->v] = select_vert[ml->v]; + } } } } else if (use_face_sel) { - for (a = 0, mp = polys; a < me->totpoly; mp++, a++) { - if (mp->flag & ME_FACE_SEL) { - for (j = 0, ml = loops + mp->loopstart; j < mp->totloop; j++, ml++) { - mask[ml->v] = 1; + const bool *select_poly = (const bool *)CustomData_get_layer_named( + &me->pdata, CD_PROP_BOOL, ".select_poly"); + if (select_poly) { + for (a = 0, mp = polys; a < me->totpoly; mp++, a++) { + if (select_poly[a]) { + for (j = 0, ml = loops + mp->loopstart; j < mp->totloop; j++, ml++) { + mask[ml->v] = 1; + } } } } diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc index f729db29b8c..ac8dd87bed6 100644 --- a/source/blender/editors/mesh/editface.cc +++ b/source/blender/editors/mesh/editface.cc @@ -73,14 +73,9 @@ void paintface_flush_flags(bContext *C, Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval; bke::MutableAttributeAccessor attributes_eval = me_eval->attributes_for_write(); bool updated = false; - const Span<MPoly> me_polys = me->polys(); if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) { /* Update the COW copy of the mesh. */ - MutableSpan<MPoly> orig_polys = me_orig->polys_for_write(); - for (int i = 0; i < me->totpoly; i++) { - orig_polys[i].flag = me_polys[i].flag; - } if (flush_hidden) { const VArray<bool> hide_poly_me = attributes_me.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); @@ -89,28 +84,46 @@ void paintface_flush_flags(bContext *C, hide_poly_me.materialize(hide_poly_orig.span); hide_poly_orig.finish(); } + if (flush_selection) { + const VArray<bool> select_poly_me = attributes_me.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> select_poly_orig = + attributes_orig.lookup_or_add_for_write_only_span<bool>(".select_poly", + ATTR_DOMAIN_FACE); + select_poly_me.materialize(select_poly_orig.span); + select_poly_orig.finish(); + } /* Mesh polys => Final derived polys */ if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) { - MutableSpan<MPoly> eval_polys = me_orig->polys_for_write(); - /* loop over final derived polys */ - for (const int i : eval_polys.index_range()) { - if (index_array[i] != ORIGINDEX_NONE) { - /* Copy flags onto the final derived poly from the original mesh poly */ - eval_polys[i].flag = me_polys[index_array[i]].flag; + if (flush_hidden) { + const VArray<bool> hide_poly_orig = attributes_orig.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> hide_poly_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_poly", + ATTR_DOMAIN_FACE); + for (const int i : IndexRange(me_eval->totpoly)) { + const int orig_poly_index = index_array[i]; + if (orig_poly_index != ORIGINDEX_NONE) { + hide_poly_eval.span[i] = hide_poly_orig[orig_poly_index]; + } } + hide_poly_eval.finish(); } - const VArray<bool> hide_poly_orig = attributes_orig.lookup_or_default<bool>( - ".hide_poly", ATTR_DOMAIN_FACE, false); - bke::SpanAttributeWriter<bool> hide_poly_eval = - attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE); - for (const int i : IndexRange(me_eval->totpoly)) { - const int orig_poly_index = index_array[i]; - if (orig_poly_index != ORIGINDEX_NONE) { - hide_poly_eval.span[i] = hide_poly_orig[orig_poly_index]; + if (flush_selection) { + const VArray<bool> select_poly_orig = attributes_orig.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> select_poly_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".select_poly", + ATTR_DOMAIN_FACE); + for (const int i : IndexRange(me_eval->totpoly)) { + const int orig_poly_index = index_array[i]; + if (orig_poly_index != ORIGINDEX_NONE) { + select_poly_eval.span[i] = select_poly_orig[orig_poly_index]; + } } + select_poly_eval.finish(); } - hide_poly_eval.finish(); updated = true; } @@ -141,25 +154,26 @@ void paintface_hide(bContext *C, Object *ob, const bool unselected) return; } - MutableSpan<MPoly> polys = me->polys_for_write(); bke::MutableAttributeAccessor attributes = me->attributes_for_write(); bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>( ".hide_poly", ATTR_DOMAIN_FACE); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &polys[i]; if (!hide_poly.span[i]) { - if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) { + if (!select_poly.span[i] == unselected) { hide_poly.span[i] = true; } } if (hide_poly.span[i]) { - mpoly->flag &= ~ME_FACE_SEL; + select_poly.span[i] = false; } } hide_poly.finish(); + select_poly.finish(); BKE_mesh_flush_hidden_from_polys(me); @@ -174,18 +188,19 @@ void paintface_reveal(bContext *C, Object *ob, const bool select) return; } - MutableSpan<MPoly> polys = me->polys_for_write(); bke::MutableAttributeAccessor attributes = me->attributes_for_write(); if (select) { const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); - for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &polys[i]; + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); + for (const int i : hide_poly.index_range()) { if (hide_poly[i]) { - mpoly->flag |= ME_FACE_SEL; + select_poly.span[i] = true; } } + select_poly.finish(); } attributes.remove(".hide_poly"); @@ -207,27 +222,29 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__); const Span<MEdge> edges = me->edges(); - MutableSpan<MPoly> polys = me->polys_for_write(); + const Span<MPoly> polys = me->polys(); const Span<MLoop> loops = me->loops(); - bke::AttributeAccessor attributes = me->attributes(); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); if (index != (uint)-1) { /* only put face under cursor in array */ - const MPoly *mp = &polys[index]; - BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, &loops[mp->loopstart]); + const MPoly &poly = polys[index]; + BKE_mesh_poly_edgebitmap_insert(edge_tag, &poly, &loops[poly.loopstart]); BLI_BITMAP_ENABLE(poly_tag, index); } else { /* fill array by selection */ for (int i = 0; i < me->totpoly; i++) { - MPoly *mp = &polys[i]; if (hide_poly[i]) { /* pass */ } - else if (mp->flag & ME_FACE_SEL) { - BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, &loops[mp->loopstart]); + else if (select_poly.span[i]) { + const MPoly &poly = polys[i]; + BKE_mesh_poly_edgebitmap_insert(edge_tag, &poly, &loops[poly.loopstart]); BLI_BITMAP_ENABLE(poly_tag, i); } } @@ -238,7 +255,6 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo /* expand selection */ for (int i = 0; i < me->totpoly; i++) { - MPoly *mp = &polys[i]; if (hide_poly[i]) { continue; } @@ -246,8 +262,9 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo if (!BLI_BITMAP_TEST(poly_tag, i)) { mark = false; - const MLoop *ml = &loops[mp->loopstart]; - for (int b = 0; b < mp->totloop; b++, ml++) { + const MPoly &poly = polys[i]; + const MLoop *ml = &loops[poly.loopstart]; + for (int b = 0; b < poly.totloop; b++, ml++) { if ((edges[ml->e].flag & ME_SEAM) == 0) { if (BLI_BITMAP_TEST(edge_tag, ml->e)) { mark = true; @@ -258,7 +275,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo if (mark) { BLI_BITMAP_ENABLE(poly_tag, i); - BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, &loops[mp->loopstart]); + BKE_mesh_poly_edgebitmap_insert(edge_tag, &poly, &loops[poly.loopstart]); do_it = true; } } @@ -268,9 +285,8 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo MEM_freeN(edge_tag); for (int i = 0; i < me->totpoly; i++) { - MPoly *mp = &polys[index]; if (BLI_BITMAP_TEST(poly_tag, i)) { - SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL); + select_poly.span[i] = select; } } @@ -305,17 +321,17 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl return false; } - MutableSpan<MPoly> polys = me->polys_for_write(); - bke::AttributeAccessor attributes = me->attributes(); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); if (action == SEL_TOGGLE) { action = SEL_SELECT; for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &polys[i]; - if (!hide_poly[i] && mpoly->flag & ME_FACE_SEL) { + if (!hide_poly[i] && select_poly.span[i]) { action = SEL_DESELECT; break; } @@ -325,29 +341,29 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl bool changed = false; for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &polys[i]; - if (!hide_poly[i]) { - switch (action) { - case SEL_SELECT: - if ((mpoly->flag & ME_FACE_SEL) == 0) { - mpoly->flag |= ME_FACE_SEL; - changed = true; - } - break; - case SEL_DESELECT: - if ((mpoly->flag & ME_FACE_SEL) != 0) { - mpoly->flag &= ~ME_FACE_SEL; - changed = true; - } - break; - case SEL_INVERT: - mpoly->flag ^= ME_FACE_SEL; - changed = true; - break; - } + if (hide_poly[i]) { + continue; + } + const bool old_selection = select_poly.span[i]; + switch (action) { + case SEL_SELECT: + select_poly.span[i] = true; + break; + case SEL_DESELECT: + select_poly.span[i] = false; + break; + case SEL_INVERT: + select_poly.span[i] = !select_poly.span[i]; + changed = true; + break; + } + if (old_selection != select_poly.span[i]) { + changed = true; } } + select_poly.finish(); + if (changed) { if (flush_flags) { paintface_flush_flags(C, ob, true, false); @@ -375,15 +391,17 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) bke::AttributeAccessor attributes = me->attributes(); const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); + const VArray<bool> select_poly = attributes.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); for (int i = 0; i < me->totpoly; i++) { - const MPoly *mp = &polys[i]; - if (hide_poly[i] || !(mp->flag & ME_FACE_SEL)) { + if (hide_poly[i] || !select_poly[i]) { continue; } - const MLoop *ml = &loops[mp->loopstart]; - for (int b = 0; b < mp->totloop; b++, ml++) { + const MPoly &poly = polys[i]; + const MLoop *ml = &loops[poly.loopstart]; + for (int b = 0; b < poly.totloop; b++, ml++) { mul_v3_m3v3(vec, bmat, verts[ml->v].co); add_v3_v3v3(vec, vec, ob->obmat[3]); minmax_v3v3_v3(r_min, r_max, vec); @@ -401,7 +419,6 @@ bool paintface_mouse_select(bContext *C, Object *ob) { using namespace blender; - MPoly *mpoly_sel = nullptr; uint index; bool changed = false; bool found = false; @@ -409,14 +426,14 @@ bool paintface_mouse_select(bContext *C, /* Get the face under the cursor */ Mesh *me = BKE_mesh_from_object(ob); - MutableSpan<MPoly> polys = me->polys_for_write(); - bke::AttributeAccessor attributes = me->attributes(); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::AttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write<bool>( + ".select_poly", ATTR_DOMAIN_FACE); if (ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { if (index < me->totpoly) { - mpoly_sel = polys.data() + index; if (!hide_poly[index]) { found = true; } @@ -424,7 +441,7 @@ bool paintface_mouse_select(bContext *C, } if (params->sel_op == SEL_OP_SET) { - if ((found && params->select_passthrough) && (mpoly_sel->flag & ME_FACE_SEL)) { + if ((found && params->select_passthrough) && select_poly.varray[index]) { found = false; } else if (found || params->deselect_all) { @@ -437,31 +454,19 @@ bool paintface_mouse_select(bContext *C, me->act_face = (int)index; switch (params->sel_op) { - case SEL_OP_ADD: { - mpoly_sel->flag |= ME_FACE_SEL; + case SEL_OP_SET: + case SEL_OP_ADD: + select_poly.varray.set(index, true); break; - } - case SEL_OP_SUB: { - mpoly_sel->flag &= ~ME_FACE_SEL; + case SEL_OP_SUB: + select_poly.varray.set(index, false); break; - } - case SEL_OP_XOR: { - if (mpoly_sel->flag & ME_FACE_SEL) { - mpoly_sel->flag &= ~ME_FACE_SEL; - } - else { - mpoly_sel->flag |= ME_FACE_SEL; - } - break; - } - case SEL_OP_SET: { - mpoly_sel->flag |= ME_FACE_SEL; + case SEL_OP_XOR: + select_poly.varray.set(index, !select_poly.varray[index]); break; - } - case SEL_OP_AND: { + case SEL_OP_AND: BLI_assert_unreachable(); /* Doesn't make sense for picking. */ break; - } } /* image window redraw */ @@ -476,10 +481,9 @@ bool paintface_mouse_select(bContext *C, void paintvert_flush_flags(Object *ob) { using namespace blender; + using namespace blender; Mesh *me = BKE_mesh_from_object(ob); Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); - const int *index_array = nullptr; - if (me == nullptr) { return; } @@ -492,25 +496,42 @@ void paintvert_flush_flags(Object *ob) return; } - index_array = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); + const bke::AttributeAccessor attributes_orig = me->attributes(); + bke::MutableAttributeAccessor attributes_eval = me_eval->attributes_for_write(); - const Span<MVert> verts = me->verts_for_write(); - MutableSpan<MVert> verts_eval = me_eval->verts_for_write(); + const int *orig_indices = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); - if (index_array) { - int orig_index; - for (const int i : verts_eval.index_range()) { - orig_index = index_array[i]; - if (orig_index != ORIGINDEX_NONE) { - verts_eval[i].flag = verts[index_array[i]].flag; + const VArray<bool> hide_vert_orig = attributes_orig.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> hide_vert_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_vert", ATTR_DOMAIN_POINT); + if (orig_indices) { + for (const int i : hide_vert_eval.span.index_range()) { + if (orig_indices[i] != ORIGINDEX_NONE) { + hide_vert_eval.span[i] = hide_vert_orig[orig_indices[i]]; } } } else { - for (const int i : verts_eval.index_range()) { - verts_eval[i].flag = verts[i].flag; + hide_vert_orig.materialize(hide_vert_eval.span); + } + hide_vert_eval.finish(); + + const VArray<bool> select_vert_orig = attributes_orig.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".select_vert", ATTR_DOMAIN_POINT); + if (orig_indices) { + for (const int i : select_vert_eval.span.index_range()) { + if (orig_indices[i] != ORIGINDEX_NONE) { + select_vert_eval.span[i] = select_vert_orig[orig_indices[i]]; + } } } + else { + select_vert_orig.materialize(select_vert_eval.span); + } + select_vert_eval.finish(); BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL); } @@ -529,17 +550,17 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) return false; } - MutableSpan<MVert> verts = me->verts_for_write(); - bke::AttributeAccessor attributes = me->attributes(); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); if (action == SEL_TOGGLE) { action = SEL_SELECT; for (int i = 0; i < me->totvert; i++) { - MVert *mvert = &verts[i]; - if (!hide_vert[i] && mvert->flag & SELECT) { + if (!hide_vert[i] && select_vert.span[i]) { action = SEL_DESELECT; break; } @@ -548,29 +569,28 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) bool changed = false; for (int i = 0; i < me->totvert; i++) { - MVert *mvert = &verts[i]; - if (!hide_vert[i]) { - switch (action) { - case SEL_SELECT: - if ((mvert->flag & SELECT) == 0) { - mvert->flag |= SELECT; - changed = true; - } - break; - case SEL_DESELECT: - if ((mvert->flag & SELECT) != 0) { - mvert->flag &= ~SELECT; - changed = true; - } - break; - case SEL_INVERT: - mvert->flag ^= SELECT; - changed = true; - break; - } + if (hide_vert[i]) { + continue; + } + const bool old_selection = select_vert.span[i]; + switch (action) { + case SEL_SELECT: + select_vert.span[i] = true; + break; + case SEL_DESELECT: + select_vert.span[i] = false; + break; + case SEL_INVERT: + select_vert.span[i] = !select_vert.span[i]; + break; + } + if (old_selection != select_vert.span[i]) { + changed = true; } } + select_vert.finish(); + if (changed) { /* handle mselect */ if (action == SEL_SELECT) { @@ -606,22 +626,23 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) paintvert_deselect_all_visible(ob, SEL_DESELECT, false); } - MutableSpan<MVert> verts = me->verts_for_write(); - bke::AttributeAccessor attributes = me->attributes(); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); - for (int i = 0; i < me->totvert; i++) { - MVert *mv = &verts[i]; - const MDeformVert *dv = &dverts[i]; + for (const int i : select_vert.span.index_range()) { if (!hide_vert[i]) { - if (dv->dw == nullptr) { + if (dverts[i].dw == nullptr) { /* if null weight then not grouped */ - mv->flag |= SELECT; + select_vert.span[i] = true; } } } + select_vert.finish(); + if (flush_flags) { paintvert_flush_flags(ob); } @@ -635,24 +656,25 @@ void paintvert_hide(bContext *C, Object *ob, const bool unselected) return; } - MutableSpan<MVert> verts = me->verts_for_write(); bke::MutableAttributeAccessor attributes = me->attributes_for_write(); bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>( ".hide_vert", ATTR_DOMAIN_POINT); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); - for (const int i : verts.index_range()) { - MVert &vert = verts[i]; + for (const int i : hide_vert.span.index_range()) { if (!hide_vert.span[i]) { - if (((vert.flag & SELECT) == 0) == unselected) { + if (!select_vert.span[i] == unselected) { hide_vert.span[i] = true; } } if (hide_vert.span[i]) { - vert.flag &= ~SELECT; + select_vert.span[i] = false; } } hide_vert.finish(); + select_vert.finish(); BKE_mesh_flush_hidden_from_verts(me); @@ -668,18 +690,20 @@ void paintvert_reveal(bContext *C, Object *ob, const bool select) return; } - MutableSpan<MVert> verts = me->verts_for_write(); bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); - for (const int i : verts.index_range()) { - MVert &vert = verts[i]; + for (const int i : select_vert.span.index_range()) { if (hide_vert[i]) { - SET_FLAG_FROM_TEST(vert.flag, select, SELECT); + select_vert.span[i] = select; } } + select_vert.finish(); + /* Remove the hide attribute to reveal all vertices. */ attributes.remove(".hide_vert"); diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 710cc6c88d9..dc3389844b8 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -1134,6 +1134,7 @@ void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_lo static void mesh_add_verts(Mesh *mesh, int len) { + using namespace blender; if (len == 0) { return; } @@ -1152,17 +1153,18 @@ static void mesh_add_verts(Mesh *mesh, int len) BKE_mesh_runtime_clear_cache(mesh); - const int old_vertex_num = mesh->totvert; mesh->totvert = totvert; - MutableSpan<MVert> verts = mesh->verts_for_write(); - for (MVert &vert : verts.drop_front(old_vertex_num)) { - vert.flag = SELECT; - } + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + select_vert.span.take_back(len).fill(true); + select_vert.finish(); } static void mesh_add_edges(Mesh *mesh, int len) { + using namespace blender; CustomData edata; int totedge; @@ -1185,13 +1187,18 @@ static void mesh_add_edges(Mesh *mesh, int len) BKE_mesh_runtime_clear_cache(mesh); - const int old_edges_num = mesh->totedge; mesh->totedge = totedge; MutableSpan<MEdge> edges = mesh->edges_for_write(); - for (MEdge &edge : edges.drop_front(old_edges_num)) { - edge.flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; + for (MEdge &edge : edges.take_back(len)) { + edge.flag = ME_EDGEDRAW | ME_EDGERENDER; } + + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_span<bool>( + ".select_edge", ATTR_DOMAIN_EDGE); + select_edge.span.take_back(len).fill(true); + select_edge.finish(); } static void mesh_add_loops(Mesh *mesh, int len) @@ -1223,6 +1230,7 @@ static void mesh_add_loops(Mesh *mesh, int len) static void mesh_add_polys(Mesh *mesh, int len) { + using namespace blender; CustomData pdata; int totpoly; @@ -1245,13 +1253,13 @@ static void mesh_add_polys(Mesh *mesh, int len) BKE_mesh_runtime_clear_cache(mesh); - const int old_polys_num = mesh->totpoly; mesh->totpoly = totpoly; - MutableSpan<MPoly> polys = mesh->polys_for_write(); - for (MPoly &poly : polys.drop_front(old_polys_num)) { - poly.flag = ME_FACE_SEL; - } + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); + select_poly.span.take_back(len).fill(true); + select_poly.finish(); } /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index f82c0938b51..3d995c84639 100644 --- a/source/blender/editors/object/object_modifier.cc +++ b/source/blender/editors/object/object_modifier.cc @@ -530,6 +530,7 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), Object *ob, ModifierData *md) { + using namespace blender; int cvert = 0; if (md->type != eModifierType_ParticleSystem) { @@ -599,13 +600,18 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), MVert *mvert = verts.data(); MEdge *medge = edges.data(); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + /* copy coordinates */ + int vert_index = 0; cache = psys_eval->pathcache; for (int a = 0; a < part_num; a++) { ParticleCacheKey *key = cache[a]; int kmax = key->segments; - for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { - copy_v3_v3(mvert->co, key->co); + for (int k = 0; k <= kmax; k++, key++, cvert++, vert_index++) { + copy_v3_v3(mvert[vert_index].co, key->co); if (k) { medge->v1 = cvert - 1; medge->v2 = cvert; @@ -614,7 +620,7 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), } else { /* cheap trick to select the roots */ - mvert->flag |= SELECT; + select_vert.span[vert_index] = true; } } } @@ -623,8 +629,8 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), for (int a = 0; a < child_num; a++) { ParticleCacheKey *key = cache[a]; int kmax = key->segments; - for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { - copy_v3_v3(mvert->co, key->co); + for (int k = 0; k <= kmax; k++, key++, cvert++, vert_index++) { + copy_v3_v3(mvert[vert_index].co, key->co); if (k) { medge->v1 = cvert - 1; medge->v2 = cvert; @@ -633,11 +639,13 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), } else { /* cheap trick to select the roots */ - mvert->flag |= SELECT; + select_vert.span[vert_index] = true; } } } + select_vert.finish(); + DEG_relations_tag_update(bmain); return true; diff --git a/source/blender/editors/object/object_vgroup.cc b/source/blender/editors/object/object_vgroup.cc index 1d1263494c7..44fea0b32f0 100644 --- a/source/blender/editors/object/object_vgroup.cc +++ b/source/blender/editors/object/object_vgroup.cc @@ -31,6 +31,7 @@ #include "BLI_utildefines_stack.h" #include "BLI_vector.hh" +#include "BKE_attribute.hh" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -154,6 +155,7 @@ bool ED_vgroup_parray_alloc(ID *id, int *dvert_tot, const bool use_vert_sel) { + using namespace blender; *dvert_tot = 0; *dvert_arr = nullptr; @@ -200,7 +202,6 @@ bool ED_vgroup_parray_alloc(ID *id, return true; } if (!me->deform_verts().is_empty()) { - const Span<MVert> verts = me->verts(); MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); *dvert_tot = me->totvert; @@ -208,8 +209,12 @@ bool ED_vgroup_parray_alloc(ID *id, MEM_mallocN(sizeof(void *) * me->totvert, __func__)); if (use_vert_sel) { + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + for (int i = 0; i < me->totvert; i++) { - (*dvert_arr)[i] = (verts[i].flag & SELECT) ? &dverts[i] : nullptr; + (*dvert_arr)[i] = select_vert[i] ? &dverts[i] : nullptr; } } else { @@ -636,6 +641,7 @@ static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) { + using namespace blender; Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; MDeformVert *dvert_act; @@ -663,14 +669,17 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) } } else { - const Span<MVert> verts = me->verts(); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + int v_act; dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act); if (dvert_act) { MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); for (i = 0; i < me->totvert; i++) { - if ((verts[i].flag & SELECT) && &dverts[i] != dvert_act) { + if (select_vert[i] && &dverts[i] != dvert_act) { BKE_defvert_copy_subset(&dverts[i], dvert_act, vgroup_validmap, vgroup_tot); if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, i); @@ -1011,6 +1020,7 @@ void ED_vgroup_select_by_name(Object *ob, const char *name) /* only in editmode */ static void vgroup_select_verts(Object *ob, int select) { + using namespace blender; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const ListBase *defbase = BKE_object_defgroup_list(ob); @@ -1051,26 +1061,21 @@ static void vgroup_select_verts(Object *ob, int select) else { const Span<MDeformVert> dverts = me->deform_verts(); if (!dverts.is_empty()) { - const bool *hide_vert = (const bool *)CustomData_get_layer_named( - &me->vdata, CD_PROP_BOOL, ".hide_vert"); - MVert *mv; - int i; - - mv = me->verts_for_write().data(); - - for (i = 0; i < me->totvert; i++, mv++) { - if (!(hide_vert != nullptr && hide_vert[i])) { + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert = + attributes.lookup_or_add_for_write_only_span<bool>(".select_vert", ATTR_DOMAIN_POINT); + + for (const int i : select_vert.span.index_range()) { + if (!hide_vert[i]) { if (BKE_defvert_find_index(&dverts[i], def_nr)) { - if (select) { - mv->flag |= SELECT; - } - else { - mv->flag &= ~SELECT; - } + select_vert.span[i] = select; } } } + select_vert.finish(); paintvert_flush_flags(ob); } } @@ -1519,6 +1524,7 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, static void vgroup_fix( const bContext *C, Scene *UNUSED(scene), Object *ob, float distToBe, float strength, float cp) { + using namespace blender; Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); @@ -1529,8 +1535,11 @@ static void vgroup_fix( if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL)) { return; } + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); for (i = 0; i < me->totvert && mvert; i++, mvert++) { - if (mvert->flag & SELECT) { + if (select_vert[i]) { blender::Vector<int> verts = getSurroundingVerts(me, i); const int count = verts.size(); if (!verts.is_empty()) { @@ -1893,6 +1902,7 @@ static void vgroup_smooth_subset(Object *ob, const int repeat, const float fac_expand) { + using namespace blender; const float ifac = 1.0f - fac; MDeformVert **dvert_array = nullptr; int dvert_tot = 0; @@ -1912,6 +1922,10 @@ static void vgroup_smooth_subset(Object *ob, BMesh *bm = em ? em->bm : nullptr; Mesh *me = em ? nullptr : static_cast<Mesh *>(ob->data); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + MeshElemMap *emap; int *emap_mem; @@ -1955,7 +1969,7 @@ static void vgroup_smooth_subset(Object *ob, nullptr; #define IS_ME_VERT_READ(v) (use_hide ? !(hide_vert && hide_vert[v]) : true) -#define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true) +#define IS_ME_VERT_WRITE(v) (use_select ? select_vert[v] : true) /* initialize used verts */ if (bm) { @@ -1975,11 +1989,9 @@ static void vgroup_smooth_subset(Object *ob, } } else { - const Span<MVert> verts = me->verts(); const blender::Span<MEdge> edges = me->edges(); for (int i = 0; i < dvert_tot; i++) { - const MVert *v = &verts[i]; - if (IS_ME_VERT_WRITE(v)) { + if (IS_ME_VERT_WRITE(i)) { for (int j = 0; j < emap[i].count; j++) { const MEdge *e = &edges[emap[i].indices[j]]; const int i_other = (e->v1 == i) ? e->v2 : e->v1; @@ -2053,7 +2065,7 @@ static void vgroup_smooth_subset(Object *ob, const blender::Span<MEdge> edges = me->edges(); /* checked already */ - BLI_assert(IS_ME_VERT_WRITE(&me->verts()[i])); + BLI_assert(IS_ME_VERT_WRITE(i)); for (j = 0; j < emap[i].count; j++) { const MEdge *e = &edges[emap[i].indices[j]]; @@ -2360,6 +2372,7 @@ void ED_vgroup_mirror(Object *ob, int *r_totmirr, int *r_totfail) { + using namespace blender; /* TODO: vgroup locking. * TODO: face masking. */ @@ -2458,7 +2471,6 @@ void ED_vgroup_mirror(Object *ob, } else { /* object mode / weight paint */ - const MVert *mv, *mv_mirr; int vidx, vidx_mirr; const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; @@ -2471,19 +2483,20 @@ void ED_vgroup_mirror(Object *ob, } BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__); - const MVert *verts = me->verts().data(); MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); - for (vidx = 0, mv = verts; vidx < me->totvert; vidx++, mv++) { + for (vidx = 0; vidx < me->totvert; vidx++) { if (!BLI_BITMAP_TEST(vert_tag, vidx)) { if ((vidx_mirr = mesh_get_x_mirror_vert(ob, nullptr, vidx, use_topology)) != -1) { if (vidx != vidx_mirr) { - mv_mirr = &verts[vidx_mirr]; if (!BLI_BITMAP_TEST(vert_tag, vidx_mirr)) { if (use_vert_sel) { - sel = mv->flag & SELECT; - sel_mirr = mv_mirr->flag & SELECT; + sel = select_vert[vidx]; + sel_mirr = select_vert[vidx_mirr]; } if (sel || sel_mirr) { @@ -2587,6 +2600,7 @@ static void vgroup_delete_active(Object *ob) /* only in editmode */ static void vgroup_assign_verts(Object *ob, const float weight) { + using namespace blender; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const ListBase *defbase = BKE_object_defgroup_list(ob); @@ -2625,15 +2639,16 @@ static void vgroup_assign_verts(Object *ob, const float weight) } } else { - const Span<MVert> verts = me->verts(); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); - MDeformVert *dv = dverts.data(); - for (int i = 0; i < me->totvert; i++, dv++) { - const MVert *mv = &verts[i]; - if (mv->flag & SELECT) { + for (int i = 0; i < me->totvert; i++) { + if (select_vert[i]) { MDeformWeight *dw; - dw = BKE_defvert_ensure_index(dv, def_nr); + dw = BKE_defvert_ensure_index(&dverts[i], def_nr); if (dw) { dw->weight = weight; } @@ -4314,6 +4329,7 @@ void OBJECT_OT_vertex_group_move(wmOperatorType *ot) static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) { + using namespace blender; MDeformVert *dvert_act; Mesh *me = static_cast<Mesh *>(ob->data); @@ -4348,7 +4364,6 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) } } else { - MDeformVert *dv; int v_act; dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act); @@ -4356,14 +4371,14 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) return; } - const Span<MVert> verts = me->verts(); MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); - dv = dverts.data(); - for (i = 0; i < me->totvert; i++, dv++) { - if ((verts[i].flag & SELECT) && (dv != dvert_act)) { - - BKE_defvert_copy_index(dv, def_nr, dvert_act, def_nr); + for (i = 0; i < me->totvert; i++) { + if (select_vert[i] && (&dverts[i] != dvert_act)) { + BKE_defvert_copy_index(&dverts[i], def_nr, dvert_act, def_nr); if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, i); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 946a59d0001..bae5050f0ac 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -415,6 +415,7 @@ typedef struct ProjPaintState { const float (*vert_normals)[3]; const MEdge *medge_eval; const MPoly *mpoly_eval; + const bool *select_poly_eval; const int *material_indices; const MLoop *mloop_eval; const MLoopTri *mlooptri_eval; @@ -4062,6 +4063,8 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p } ps->mloop_eval = BKE_mesh_loops(ps->me_eval); ps->mpoly_eval = BKE_mesh_polys(ps->me_eval); + ps->select_poly_eval = (const bool *)CustomData_get_layer_named( + &ps->me_eval->pdata, CD_PROP_BOOL, ".select_poly"); ps->material_indices = (const int *)CustomData_get_layer_named( &ps->me_eval->pdata, CD_PROP_INT32, "material_index"); @@ -4145,7 +4148,7 @@ static bool project_paint_clone_face_skip(ProjPaintState *ps, } typedef struct { - const MPoly *mpoly_orig; + const bool *select_poly_orig; const int *index_mp_to_orig; } ProjPaintFaceLookup; @@ -4154,8 +4157,10 @@ static void proj_paint_face_lookup_init(const ProjPaintState *ps, ProjPaintFaceL { memset(face_lookup, 0, sizeof(*face_lookup)); if (ps->do_face_sel) { + Mesh *orig_mesh = (Mesh *)ps->ob->data; face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX); - face_lookup->mpoly_orig = BKE_mesh_polys((Mesh *)ps->ob->data); + face_lookup->select_poly_orig = CustomData_get_layer_named( + &orig_mesh->pdata, CD_PROP_BOOL, ".select_poly"); } } @@ -4166,17 +4171,12 @@ static bool project_paint_check_face_sel(const ProjPaintState *ps, { if (ps->do_face_sel) { int orig_index; - const MPoly *mp; if ((face_lookup->index_mp_to_orig != NULL) && (((orig_index = (face_lookup->index_mp_to_orig[lt->poly]))) != ORIGINDEX_NONE)) { - mp = &face_lookup->mpoly_orig[orig_index]; + return face_lookup->select_poly_orig && face_lookup->select_poly_orig[orig_index]; } - else { - mp = &ps->mpoly_eval[lt->poly]; - } - - return ((mp->flag & ME_FACE_SEL) != 0); + return ps->select_poly_eval && ps->select_poly_eval[lt->poly]; } return true; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index c38a79cb6bb..9abc3c5112e 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -32,6 +32,7 @@ #include "RNA_prototypes.h" #include "BKE_attribute.h" +#include "BKE_attribute.hh" #include "BKE_brush.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -1958,6 +1959,10 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( ss, data->brush->falloff_shape); + const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + /* For each vertex */ PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -1967,9 +1972,8 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, * Otherwise, take the current vert. */ const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const char v_flag = ss->mvert[v_index].flag; /* If the vertex is selected */ - if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { + if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { /* Get the average poly weight */ int total_hit_loops = 0; float weight_final = 0.0f; @@ -2045,6 +2049,10 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, sub_v3_v3v3(brush_dir, cache->location, cache->last_location); project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal); + const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) { SculptBrushTest test; @@ -2065,7 +2073,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, const MVert *mv_curr = &ss->mvert[v_index]; /* If the vertex is selected */ - if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) { + if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { float brush_strength = cache->bstrength; const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : @@ -2158,6 +2166,10 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( ss, data->brush->falloff_shape); + const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + /* For each vertex */ PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2169,9 +2181,8 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const char v_flag = ss->mvert[v_index].flag; /* If the vertex is selected */ - if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { + if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { float brush_strength = cache->bstrength; const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : 1.0f; @@ -2224,6 +2235,10 @@ static void do_wpaint_brush_calc_average_weight_cb_ex( const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( ss, data->brush->falloff_shape); + const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + /* For each vertex */ PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2234,10 +2249,9 @@ static void do_wpaint_brush_calc_average_weight_cb_ex( if (angle_cos > 0.0 && BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) { const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; - const char v_flag = ss->mvert[v_index].flag; /* If the vertex is selected. */ - if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { + if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { const MDeformVert *dv = &data->wpi->dvert[v_index]; accum->len += 1; accum->value += wpaint_get_active_weight(dv, data->wpi); @@ -2956,6 +2970,11 @@ static void do_vpaint_brush_blur_loops(bContext *C, Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint); + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { for (int n : range) { const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh); @@ -2987,10 +3006,9 @@ static void do_vpaint_brush_blur_loops(bContext *C, const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &ss->mvert[v_index]; /* If the vertex is selected for painting. */ - if (!use_vert_sel || mv->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { float brush_strength = cache->bstrength; const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : @@ -3011,7 +3029,7 @@ static void do_vpaint_brush_blur_loops(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { int p_index = gmap->vert_to_poly[v_index].indices[j]; const MPoly *mp = &ss->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { total_hit_loops += mp->totloop; for (int k = 0; k < mp->totloop; k++) { const uint l_index = mp->loopstart + k; @@ -3045,8 +3063,7 @@ static void do_vpaint_brush_blur_loops(bContext *C, const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; BLI_assert(ss->mloop[l_index].v == v_index); - const MPoly *mp = &ss->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ if (previous_color != nullptr) { @@ -3098,6 +3115,11 @@ static void do_vpaint_brush_blur_verts(bContext *C, Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint); + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { for (int n : range) { const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh); @@ -3129,10 +3151,9 @@ static void do_vpaint_brush_blur_verts(bContext *C, const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &ss->mvert[v_index]; /* If the vertex is selected for painting. */ - if (!use_vert_sel || mv->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { float brush_strength = cache->bstrength; const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : @@ -3153,7 +3174,7 @@ static void do_vpaint_brush_blur_verts(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { int p_index = gmap->vert_to_poly[v_index].indices[j]; const MPoly *mp = &ss->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { total_hit_loops += mp->totloop; for (int k = 0; k < mp->totloop; k++) { const uint l_index = mp->loopstart + k; @@ -3190,8 +3211,7 @@ static void do_vpaint_brush_blur_verts(bContext *C, BLI_assert(ss->mloop[gmap->vert_to_loop[v_index].indices[j]].v == v_index); - const MPoly *mp = &ss->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ if (previous_color != nullptr) { @@ -3247,6 +3267,11 @@ static void do_vpaint_brush_smear(bContext *C, Color *color_prev_smear = static_cast<Color *>(vpd->smear.color_prev); Color *color_prev = reinterpret_cast<Color *>(ss->cache->prev_colors_vpaint); + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { for (int n : range) { float brush_size_pressure, brush_alpha_value, brush_alpha_pressure; @@ -3283,7 +3308,7 @@ static void do_vpaint_brush_smear(bContext *C, const MVert *mv_curr = &ss->mvert[v_index]; /* if the vertex is selected for painting. */ - if (!use_vert_sel || mv_curr->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { /* Calc the dot prod. between ray norm on surf and current vert * (ie splash prevention factor), and only paint front facing verts. */ float brush_strength = cache->bstrength; @@ -3312,7 +3337,7 @@ static void do_vpaint_brush_smear(bContext *C, BLI_assert(ss->mloop[l_index].v == v_index); UNUSED_VARS_NDEBUG(l_index); const MPoly *mp = &ss->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { const MLoop *ml_other = &ss->mloop[mp->loopstart]; for (int k = 0; k < mp->totloop; k++, ml_other++) { const uint v_other_index = ml_other->v; @@ -3366,8 +3391,7 @@ static void do_vpaint_brush_smear(bContext *C, BLI_assert(ss->mloop[l_index].v == v_index); } - const MPoly *mp = &ss->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { /* Get the previous element color */ Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3413,6 +3437,9 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd, { using Blend = typename Traits::BlendType; + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + VPaintAverageAccum<Blend> *accum = (VPaintAverageAccum<Blend> *)MEM_mallocN( sizeof(*accum) * totnode, __func__); blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { @@ -3443,8 +3470,7 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd, vd.vert_indices[vd.i]; if (BKE_brush_curve_strength(brush, 0.0, cache->radius) > 0.0) { /* If the vertex is selected for painting. */ - const MVert *mv = &ss->mvert[v_index]; - if (!use_vert_sel || mv->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { accum2->len += gmap->vert_to_loop[v_index].count; /* if a vertex is within the brush region, then add its color to the blend. */ for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) { @@ -3529,6 +3555,11 @@ static void vpaint_do_draw(bContext *C, Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint); + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { for (int n : range) { const bool has_grids = (pbvh_type == PBVH_GRIDS); @@ -3562,10 +3593,9 @@ static void vpaint_do_draw(bContext *C, const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &ss->mvert[v_index]; /* If the vertex is selected for painting. */ - if (!use_vert_sel || mv->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { /* Calc the dot prod. between ray norm on surf and current vert * (ie splash prevention factor), and only paint front facing verts. */ float brush_strength = cache->bstrength; @@ -3617,8 +3647,7 @@ static void vpaint_do_draw(bContext *C, const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; BLI_assert(ss->mloop[l_index].v == v_index); - const MPoly *mp = &ss->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { Color color_orig = Color(0, 0, 0, 0); /* unused when array is nullptr */ if (previous_color != nullptr) { @@ -4045,6 +4074,11 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLay return false; } + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + Color paintcol = fromFloat<Color>(paintcol_in); const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; @@ -4088,21 +4122,20 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLay } else { Color *color_layer = static_cast<Color *>(layer->data); - const Span<MVert> verts = me->verts(); const Span<MPoly> polys = me->polys(); const Span<MLoop> loops = me->loops(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - if (use_face_sel && !(poly.flag & ME_FACE_SEL)) { + if (use_face_sel && !select_poly[i]) { continue; } + const MPoly &poly = polys[i]; int j = 0; do { uint vidx = loops[poly.loopstart + j].v; - if (!(use_vert_sel && !(verts[vidx].flag & SELECT))) { + if (!(use_vert_sel && !(select_vert[vidx]))) { if constexpr (domain == ATTR_DOMAIN_CORNER) { color_layer[poly.loopstart + j] = paintcol; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc index a8e64462a2a..a284d1608cb 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc @@ -159,29 +159,19 @@ static IndexMask get_selected_indices(const Mesh &mesh, Vector<int64_t> &indices) { using namespace blender; - const Span<MVert> verts = mesh.verts(); - const Span<MPoly> polys = mesh.polys(); - - bke::AttributeAccessor attributes = mesh.attributes(); + const bke::AttributeAccessor attributes = mesh.attributes(); if (mesh.editflag & ME_EDIT_PAINT_FACE_SEL) { - const VArray<bool> selection = attributes.adapt_domain( - VArray<bool>::ForFunc(polys.size(), - [&](const int i) { return polys[i].flag & ME_FACE_SEL; }), - ATTR_DOMAIN_FACE, - domain); - + const VArray<bool> selection = attributes.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); return index_mask_ops::find_indices_from_virtual_array( - IndexMask(attributes.domain_size(domain)), selection, 4096, indices); + selection.index_range(), selection, 4096, indices); } if (mesh.editflag & ME_EDIT_PAINT_VERT_SEL) { - const VArray<bool> selection = attributes.adapt_domain( - VArray<bool>::ForFunc(verts.size(), [&](const int i) { return verts[i].flag & SELECT; }), - ATTR_DOMAIN_POINT, - domain); - + const VArray<bool> selection = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); return index_mask_ops::find_indices_from_virtual_array( - IndexMask(attributes.domain_size(domain)), selection, 4096, indices); + selection.index_range(), selection, 4096, indices); } return IndexMask(attributes.domain_size(domain)); } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index 0a0d7cff214..a7f43830e6b 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -445,7 +445,6 @@ static bool weight_paint_set(Object *ob, float paintweight) /* mutually exclusive, could be made into a */ const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me); - const MVert *verts = BKE_mesh_verts(me); const MPoly *polys = BKE_mesh_polys(me); const MLoop *loops = BKE_mesh_loops(me); MDeformVert *dvert = BKE_mesh_deform_verts_for_write(me); @@ -464,10 +463,15 @@ static bool weight_paint_set(Object *ob, float paintweight) struct WPaintPrev wpp; wpaint_prev_create(&wpp, dvert, me->totvert); + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".select_vert"); + const bool *select_poly = (const bool *)CustomData_get_layer_named( + &me->pdata, CD_PROP_BOOL, ".select_poly"); + for (index = 0, mp = polys; index < me->totpoly; index++, mp++) { uint fidx = mp->totloop - 1; - if ((paint_selmode == SCE_SELECT_FACE) && !(mp->flag & ME_FACE_SEL)) { + if ((paint_selmode == SCE_SELECT_FACE) && !(select_poly && select_poly[index])) { continue; } @@ -475,7 +479,7 @@ static bool weight_paint_set(Object *ob, float paintweight) uint vidx = loops[mp->loopstart + fidx].v; if (!dvert[vidx].flag) { - if ((paint_selmode == SCE_SELECT_VERTEX) && !(verts[vidx].flag & SELECT)) { + if ((paint_selmode == SCE_SELECT_VERTEX) && !(select_vert && select_vert[vidx])) { continue; } diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 447bf99b000..a0b3802076a 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -45,6 +45,7 @@ #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_attribute.hh" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_editmesh.h" @@ -337,28 +338,29 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, EditSelectBuf_Cache *esel, const eSelectOp sel_op) { - MVert *verts = BKE_mesh_verts_for_write(me); - MVert *mv = verts; + using namespace blender; bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - if (mv) { - const bool *hide_vert = (const bool *)CustomData_get_layer_named( - &me->vdata, CD_PROP_BOOL, ".hide_vert"); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); - for (int index = 0; index < me->totvert; index++, mv++) { - if (!(hide_vert && hide_vert[index])) { - const bool is_select = mv->flag & SELECT; - const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); - changed = true; - } + for (int index = 0; index < me->totvert; index++) { + if (!hide_vert[index]) { + const bool is_select = select_vert.span[index]; + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + select_vert.span[index] = sel_op_result == 1; + changed = true; } } } + select_vert.finish(); return changed; } @@ -367,27 +369,29 @@ static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me, EditSelectBuf_Cache *esel, const eSelectOp sel_op) { - MPoly *polys = BKE_mesh_polys_for_write(me); + using namespace blender; bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - if (polys) { - const bool *hide_poly = (const bool *)CustomData_get_layer_named( - &me->vdata, CD_PROP_BOOL, ".hide_poly"); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); - for (int index = 0; index < me->totpoly; index++) { - if (!(hide_poly && hide_poly[index])) { - const bool is_select = polys[index].flag & ME_FACE_SEL; - const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(polys[index].flag, sel_op_result, ME_FACE_SEL); - changed = true; - } + for (int index = 0; index < me->totpoly; index++) { + if (!hide_poly[index]) { + const bool is_select = select_poly.span[index]; + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + select_poly.span[index] = sel_op_result == 1; + changed = true; } } } + select_poly.finish(); return changed; } @@ -1154,20 +1158,27 @@ static bool do_lasso_select_meta(ViewContext *vc, return data.is_changed; } +struct LassoSelectUserData_ForMeshVert { + LassoSelectUserData lasso_data; + blender::MutableSpan<bool> select_vert; +}; static void do_lasso_select_meshobject__doSelectVert(void *userData, - MVert *mv, + MVert * /*mv*/, const float screen_co[2], - int UNUSED(index)) + int index) { - LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); - const bool is_select = mv->flag & SELECT; + using namespace blender; + LassoSelectUserData_ForMeshVert *mesh_data = static_cast<LassoSelectUserData_ForMeshVert *>( + userData); + LassoSelectUserData *data = &mesh_data->lasso_data; + const bool is_select = mesh_data->select_vert[index]; const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && BLI_lasso_is_point_inside( data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); + mesh_data->select_vert[index] = sel_op_result == 1; data->is_changed = true; } } @@ -1177,6 +1188,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc, const int mcoords_len, const eSelectOp sel_op) { + using namespace blender; const bool use_zbuf = !XRAY_ENABLED(vc->v3d); Object *ob = vc->obact; Mesh *me = static_cast<Mesh *>(ob->data); @@ -1210,16 +1222,22 @@ static bool do_lasso_select_paintvert(ViewContext *vc, } } else { - LassoSelectUserData data; + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + + LassoSelectUserData_ForMeshVert data; + data.select_vert = select_vert.span; - view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); + view3d_userdata_lassoselect_init(&data.lasso_data, vc, &rect, mcoords, mcoords_len, sel_op); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); meshobject_foreachScreenVert( vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; + changed |= data.lasso_data.is_changed; + select_vert.finish(); } if (changed) { @@ -2825,20 +2843,22 @@ static bool ed_wpaint_vertex_select_pick(bContext *C, const SelectPick_Params *params, Object *obact) { + using namespace blender; View3D *v3d = CTX_wm_view3d(C); const bool use_zbuf = !XRAY_ENABLED(v3d); Mesh *me = static_cast<Mesh *>(obact->data); /* already checked for nullptr */ uint index = 0; - MVert *verts = BKE_mesh_verts_for_write(me); - - MVert *mv; bool changed = false; bool found = ED_mesh_pick_vert(C, obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, use_zbuf, &index); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::AttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + if (params->sel_op == SEL_OP_SET) { - if ((found && params->select_passthrough) && (verts[index].flag & SELECT)) { + if ((found && params->select_passthrough) && select_vert.varray[index]) { found = false; } else if (found || params->deselect_all) { @@ -2848,23 +2868,22 @@ static bool ed_wpaint_vertex_select_pick(bContext *C, } if (found) { - mv = &verts[index]; switch (params->sel_op) { case SEL_OP_ADD: { - mv->flag |= SELECT; + select_vert.varray.set(index, true); break; } case SEL_OP_SUB: { - mv->flag &= ~SELECT; + select_vert.varray.set(index, false); break; } case SEL_OP_XOR: { - mv->flag ^= SELECT; + select_vert.varray.set(index, !select_vert.varray[index]); break; } case SEL_OP_SET: { paintvert_deselect_all_visible(obact, SEL_DESELECT, false); - mv->flag |= SELECT; + select_vert.varray.set(index, true); break; } case SEL_OP_AND: { @@ -2874,13 +2893,15 @@ static bool ed_wpaint_vertex_select_pick(bContext *C, } /* update mselect */ - if (mv->flag & SELECT) { + if (select_vert.varray[index]) { BKE_mesh_mselect_active_set(me, index, ME_VSEL); } else { BKE_mesh_mselect_validate(me); } + select_vert.finish(); + paintvert_flush_flags(obact); changed = true; @@ -3117,17 +3138,23 @@ bool edge_inside_circle(const float cent[2], return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared); } +struct BoxSelectUserData_ForMeshVert { + BoxSelectUserData box_data; + blender::MutableSpan<bool> select_vert; +}; static void do_paintvert_box_select__doSelectVert(void *userData, - MVert *mv, + MVert * /*mv*/, const float screen_co[2], - int UNUSED(index)) + int index) { - BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData); - const bool is_select = mv->flag & SELECT; + BoxSelectUserData_ForMeshVert *mesh_data = static_cast<BoxSelectUserData_ForMeshVert *>( + userData); + BoxSelectUserData *data = &mesh_data->box_data; + const bool is_select = mesh_data->select_vert[index]; const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); + mesh_data->select_vert[index] = sel_op_result == 1; data->is_changed = true; } } @@ -3136,6 +3163,7 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op) { + using namespace blender; const bool use_zbuf = !XRAY_ENABLED(vc->v3d); Mesh *me = static_cast<Mesh *>(vc->obact->data); @@ -3164,15 +3192,21 @@ static bool do_paintvert_box_select(ViewContext *vc, } } else { - BoxSelectUserData data; + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + BoxSelectUserData_ForMeshVert data; + data.select_vert = select_vert.span; + + view3d_userdata_boxselect_init(&data.box_data, vc, rect, sel_op); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); meshobject_foreachScreenVert( vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; + changed |= data.box_data.is_changed; + select_vert.finish(); } if (changed) { @@ -4124,15 +4158,21 @@ static bool paint_facesel_circle_select(ViewContext *vc, return changed; } +struct CircleSelectUserData_ForMeshVert { + CircleSelectUserData circle_data; + blender::MutableSpan<bool> select_vert; +}; static void paint_vertsel_circle_select_doSelectVert(void *userData, - MVert *mv, + MVert * /*mv*/, const float screen_co[2], - int UNUSED(index)) + int index) { - CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); + CircleSelectUserData_ForMeshVert *mesh_data = static_cast<CircleSelectUserData_ForMeshVert *>( + userData); + CircleSelectUserData *data = &mesh_data->circle_data; if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); + mesh_data->select_vert[index] = data->select; data->is_changed = true; } } @@ -4142,6 +4182,7 @@ static bool paint_vertsel_circle_select(ViewContext *vc, const int mval[2], float rad) { + using namespace blender; BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); const bool use_zbuf = !XRAY_ENABLED(vc->v3d); Object *ob = vc->obact; @@ -4173,14 +4214,20 @@ static bool paint_vertsel_circle_select(ViewContext *vc, } } else { - CircleSelectUserData data; + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + + CircleSelectUserData_ForMeshVert data; + data.select_vert = select_vert.span; ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data.circle_data, vc, select, mval, rad); meshobject_foreachScreenVert( vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; + changed |= data.circle_data.is_changed; + select_vert.finish(); } if (changed) { diff --git a/source/blender/geometry/intern/mesh_merge_by_distance.cc b/source/blender/geometry/intern/mesh_merge_by_distance.cc index 20de471a9e1..d7c35a4fcc1 100644 --- a/source/blender/geometry/intern/mesh_merge_by_distance.cc +++ b/source/blender/geometry/intern/mesh_merge_by_distance.cc @@ -1265,7 +1265,6 @@ static void customdata_weld( no[1] += mv_src_no[1]; no[2] += mv_src_no[2]; #endif - flag |= mv_src->flag; } } else if (type == CD_MEDGE) { @@ -1316,8 +1315,6 @@ static void customdata_weld( mv_no[1] = (short)no[1]; mv_no[2] = (short)no[2]; #endif - - mv->flag = (char)flag; } else if (type == CD_MEDGE) { MEdge *me = &((MEdge *)layer_dst->data)[dest_index]; diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index fdb389b61c5..4b7c4275568 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -563,7 +563,7 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len) /* set default flags */ medge = &edges[mesh->totedge]; for (int i = 0; i < len; i++, medge++) { - medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; + medge->flag = ME_EDGEDRAW | ME_EDGERENDER; } mesh->totedge = totedge; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 10880b016fb..27b71319f39 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -302,8 +302,16 @@ void OBJMesh::store_uv_coords_and_indices() } const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT}; - UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create( - polys.data(), nullptr, loops.data(), mloopuv, polys.size(), totvert, limit, false, false); + UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(polys.data(), + nullptr, + nullptr, + loops.data(), + mloopuv, + polys.size(), + totvert, + limit, + false, + false); uv_indices_.resize(polys.size()); /* At least total vertices of a mesh will be present in its texture map. So diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index f7e6714d495..52e398ffff5 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -25,7 +25,11 @@ extern "C" { */ typedef struct MVert { float co[3]; - char flag; + /** + * Deprecated flag for storing hide status and selection, which are now stored in separate + * generic attributes. Kept for file read and write. + */ + char flag_legacy; /** * Deprecated bevel weight storage, now located in #CD_BWEIGHT, except for file read and write. */ @@ -37,6 +41,7 @@ typedef struct MVert { #ifdef DNA_DEPRECATED_ALLOW enum { + /** Deprecated selection status. Now stored in ".select_vert" attribute. */ /* SELECT = (1 << 0), */ /** Deprecated hide status. Now stored in ".hide_vert" attribute. */ ME_HIDE = (1 << 4), @@ -62,6 +67,7 @@ typedef struct MEdge { /** #MEdge.flag */ enum { + /** Deprecated selection status. Now stored in ".select_edge" attribute. */ /* SELECT = (1 << 0), */ ME_EDGEDRAW = (1 << 1), ME_SEAM = (1 << 2), @@ -91,7 +97,10 @@ typedef struct MPoly { /** #MPoly.flag */ enum { ME_SMOOTH = (1 << 0), +#ifdef DNA_DEPRECATED_ALLOW + /** Deprecated selection status. Now stored in ".select_poly" attribute. */ ME_FACE_SEL = (1 << 1), +#endif /** Deprecated hide status. Now stored in ".hide_poly" attribute. */ /* ME_HIDE = (1 << 4), */ }; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 84dd692f4dd..cc0a396932f 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -446,6 +446,32 @@ static void rna_MeshVertex_hide_set(PointerRNA *ptr, bool value) hide_vert[index] = value; } +static bool rna_MeshVertex_select_get(PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &mesh->vdata, CD_PROP_BOOL, ".select_vert"); + const int index = rna_MeshVertex_index_get(ptr); + return select_vert == NULL ? false : select_vert[index]; +} + +static void rna_MeshVertex_select_set(PointerRNA *ptr, bool value) +{ + Mesh *mesh = rna_mesh(ptr); + bool *select_vert = (bool *)CustomData_duplicate_referenced_layer_named( + &mesh->vdata, CD_PROP_BOOL, ".select_vert", mesh->totvert); + if (!select_vert) { + if (!value) { + /* Skip adding layer if it doesn't exist already anyway and we're not hiding an element. */ + return; + } + select_vert = (bool *)CustomData_add_layer_named( + &mesh->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totvert, ".select_vert"); + } + const int index = rna_MeshVertex_index_get(ptr); + select_vert[index] = value; +} + static float rna_MeshVertex_bevel_weight_get(PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); @@ -596,6 +622,32 @@ static void rna_MeshPolygon_hide_set(PointerRNA *ptr, bool value) hide_poly[index] = value; } +static bool rna_MeshPolygon_select_get(PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + const bool *select_poly = (const bool *)CustomData_get_layer_named( + &mesh->pdata, CD_PROP_BOOL, ".select_poly"); + const int index = rna_MeshPolygon_index_get(ptr); + return select_poly == NULL ? false : select_poly[index]; +} + +static void rna_MeshPolygon_select_set(PointerRNA *ptr, bool value) +{ + Mesh *mesh = rna_mesh(ptr); + bool *select_poly = (bool *)CustomData_duplicate_referenced_layer_named( + &mesh->pdata, CD_PROP_BOOL, ".select_poly", mesh->totpoly); + if (!select_poly) { + if (!value) { + /* Skip adding layer if it doesn't exist already anyway and we're not hiding an element. */ + return; + } + select_poly = (bool *)CustomData_add_layer_named( + &mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totpoly, ".select_poly"); + } + const int index = rna_MeshPolygon_index_get(ptr); + select_poly[index] = value; +} + static int rna_MeshPolygon_material_index_get(PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); @@ -1381,6 +1433,32 @@ static void rna_MeshEdge_hide_set(PointerRNA *ptr, bool value) hide_edge[index] = value; } +static bool rna_MeshEdge_select_get(PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + const bool *select_edge = (const bool *)CustomData_get_layer_named( + &mesh->edata, CD_PROP_BOOL, ".select_edge"); + const int index = rna_MeshEdge_index_get(ptr); + return select_edge == NULL ? false : select_edge[index]; +} + +static void rna_MeshEdge_select_set(PointerRNA *ptr, bool value) +{ + Mesh *mesh = rna_mesh(ptr); + bool *select_edge = (bool *)CustomData_duplicate_referenced_layer_named( + &mesh->edata, CD_PROP_BOOL, ".select_edge", mesh->totedge); + if (!select_edge) { + if (!value) { + /* Skip adding layer if it doesn't exist already anyway and we're not hiding an element. */ + return; + } + select_edge = (bool *)CustomData_add_layer_named( + &mesh->edata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totedge, ".select_edge"); + } + const int index = rna_MeshEdge_index_get(ptr); + select_edge[index] = value; +} + static int rna_MeshLoopTriangle_material_index_get(PointerRNA *ptr) { const Mesh *me = rna_mesh(ptr); @@ -2140,7 +2218,7 @@ static void rna_def_mvert(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Normal", "Vertex Normal"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); + RNA_def_property_boolean_funcs(prop, "rna_MeshVertex_select_get", "rna_MeshVertex_select_set"); RNA_def_property_ui_text(prop, "Select", ""); RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); @@ -2216,7 +2294,7 @@ static void rna_def_medge(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); + RNA_def_property_boolean_funcs(prop, "rna_MeshEdge_select_get", "rna_MeshEdge_select_set"); RNA_def_property_ui_text(prop, "Select", ""); RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); @@ -2430,7 +2508,7 @@ static void rna_def_mpolygon(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FACE_SEL); + RNA_def_property_boolean_funcs(prop, "rna_MeshPolygon_select_get", "rna_MeshPolygon_select_set"); RNA_def_property_ui_text(prop, "Select", ""); RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 7feff30968f..bf534b0d586 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -293,8 +293,6 @@ static void mesh_merge_transform(Mesh *result, for (i = 0; i < cap_nverts; i++, mv++) { mul_m4_v3(cap_offset, mv->co); - /* Reset MVert flags for caps */ - mv->flag = 0; } /* We have to correct normals too, if we do not tag them as dirty later! */ diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index b5f884b1843..af167bf9b32 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -5,6 +5,8 @@ * \ingroup modifiers */ +#define DNA_DEPRECATED_ALLOW /* For #ME_FACE_SEL. */ + #include "BLI_utildefines.h" #include "BLI_edgehash.h" diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index b9b80f3668c..c41a9e8f828 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -2006,7 +2006,6 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (g->new_vert != MOD_SOLIDIFY_EMPTY_TAG) { CustomData_copy_data(&mesh->vdata, &result->vdata, (int)i, (int)g->new_vert, 1); copy_v3_v3(mvert[g->new_vert].co, g->co); - mvert[g->new_vert].flag = orig_mvert[i].flag; } } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index ce33515bb67..5614d5b66dc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -289,7 +289,6 @@ static void extrude_mesh_vertices(Mesh &mesh, for (const int i : range) { const float3 offset = offsets[selection[i]]; add_v3_v3(new_verts[i].co, offset); - new_verts[i].flag = 0; } }); }); @@ -615,7 +614,6 @@ static void extrude_mesh_edges(Mesh &mesh, threading::parallel_for(new_verts.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { add_v3_v3(new_verts[i].co, offset); - new_verts[i].flag = 0; } }); } @@ -623,7 +621,6 @@ static void extrude_mesh_edges(Mesh &mesh, threading::parallel_for(new_verts.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { add_v3_v3(new_verts[i].co, vert_offsets[new_vert_indices[i]]); - new_verts[i].flag = 0; } }); } @@ -1008,10 +1005,6 @@ static void extrude_mesh_face_regions(Mesh &mesh, }); } - for (MVert &vert : verts.slice(new_vert_range)) { - vert.flag = 0; - } - MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); @@ -1269,7 +1262,6 @@ static void extrude_individual_mesh_faces(Mesh &mesh, const IndexRange poly_corner_range = selected_corner_range(index_offsets, i_selection); for (MVert &vert : new_verts.slice(poly_corner_range)) { add_v3_v3(vert.co, poly_offset[poly_selection[i_selection]]); - vert.flag = 0; } } }); |