diff options
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/armature/armature_skinning.c | 7 | ||||
-rw-r--r-- | source/blender/editors/armature/meshlaplacian.c | 22 | ||||
-rw-r--r-- | source/blender/editors/mesh/editface.cc | 318 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_data.cc | 34 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.cc | 20 | ||||
-rw-r--r-- | source/blender/editors/object/object_vgroup.cc | 103 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_proj.c | 18 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex.cc | 95 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc | 24 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c | 10 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.cc | 167 |
11 files changed, 479 insertions, 339 deletions
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) { |