Mesh: Move selection status from flags to generic attributes (WIP)

This commit is contained in:
Hans Goudey 2022-08-14 10:43:18 -04:00
parent 39bad22008
commit f0e4307792
4 changed files with 223 additions and 214 deletions

View File

@ -867,16 +867,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);

View File

@ -820,98 +820,86 @@ 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)
{
MVert *mv;
MEdge *med;
const MPoly *mp;
int i = totvert;
for (mv = mvert; i--; mv++) {
mv->flag &= (char)~SELECT;
}
i = totedge;
for (med = medge; i--; med++) {
med->flag &= ~SELECT;
}
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->mvert, me->totvert, me->mloop, me->medge, me->totedge, me->mpoly, me->totpoly);
using namespace blender::bke;
MutableAttributeAccessor attributes = mesh_attributes_for_write(*me);
const VArray<bool> selection_poly = attributes.lookup_or_default<bool>(
".selection_poly", ATTR_DOMAIN_FACE, false);
if (selection_poly.is_single() && !selection_poly.get_internal_single()) {
attributes.remove(".selection_vert");
attributes.remove(".selection_edge");
return;
}
SpanAttributeWriter<bool> selection_vert = attributes.lookup_or_add_for_write_only_span<bool>(
".selection_vert", ATTR_DOMAIN_POINT);
SpanAttributeWriter<bool> selection_edge = attributes.lookup_or_add_for_write_only_span<bool>(
".selection_edge", ATTR_DOMAIN_EDGE);
/* Use generic domain interpolation to read the polygon attribute on the other domains.
* Assume selected faces are not hidden and none of their verts/edges are hidden. */
attributes.lookup_or_default<bool>(".selection_poly", ATTR_DOMAIN_POINT, false)
.materialize(selection_vert.span);
attributes.lookup_or_default<bool>(".selection_poly", ATTR_DOMAIN_EDGE, false)
.materialize(selection_edge.span);
selection_vert.finish();
selection_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> &selection_vert,
MutableSpan<bool> selection_edge,
MutableSpan<bool> selection_poly)
{
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];
selection_edge[i] = selection_vert[edge.v1] && selection_vert[edge.v2];
}
}
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);
selection_poly[i] = std::all_of(poly_loops.begin(),
poly_loops.end(),
[&](const MLoop &loop) { return selection_vert[loop.v]; });
}
}
}
void BKE_mesh_flush_select_from_verts(Mesh *me)
{
const blender::bke::AttributeAccessor attributes = blender::bke::mesh_attributes(*me);
using namespace blender::bke;
MutableAttributeAccessor attributes = mesh_attributes_for_write(*me);
const VArray<bool> selection_vert = attributes.lookup_or_default<bool>(
".selection_vert", ATTR_DOMAIN_POINT, false);
if (selection_vert.is_single() && !selection_vert.get_internal_single()) {
attributes.remove(".selection_edge");
attributes.remove(".selection_poly");
return;
}
SpanAttributeWriter<bool> selection_edge = attributes.lookup_or_add_for_write_only_span<bool>(
".selection_edge", ATTR_DOMAIN_EDGE);
SpanAttributeWriter<bool> selection_poly = attributes.lookup_or_add_for_write_only_span<bool>(
".selection_poly", ATTR_DOMAIN_FACE);
mesh_flush_select_from_verts(
{me->mvert, me->totvert},
{me->medge, me->totedge},
{me->mpoly, me->totpoly},
{me->mloop, me->totloop},
attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false),
attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false),
{me->medge, me->totedge},
{me->mpoly, me->totpoly});
selection_vert,
selection_edge.span,
selection_poly.span);
selection_edge.finish();
selection_poly.finish();
}
/** \} */

View File

@ -44,9 +44,7 @@ void paintface_flush_flags(bContext *C,
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
MPoly *polys, *mp_orig;
const int *index_array = nullptr;
int totpoly;
BLI_assert(flush_selection || flush_hidden);
@ -78,9 +76,6 @@ void paintface_flush_flags(bContext *C,
if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) {
/* Update the COW copy of the mesh. */
for (int i = 0; i < me->totpoly; i++) {
me_orig->mpoly[i].flag = me->mpoly[i].flag;
}
if (flush_hidden) {
const VArray<bool> hide_poly_me = attributes_me.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
@ -89,31 +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> selection_poly_me = attributes_me.lookup_or_default<bool>(
".selection_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> selection_poly_orig =
attributes_orig.lookup_or_add_for_write_only_span<bool>(".selection_poly",
ATTR_DOMAIN_FACE);
selection_poly_me.materialize(selection_poly_orig.span);
selection_poly_orig.finish();
}
/* Mesh polys => Final derived polys */
if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
polys = me_eval->mpoly;
totpoly = me_eval->totpoly;
/* loop over final derived polys */
for (int i = 0; i < totpoly; i++) {
if (index_array[i] != ORIGINDEX_NONE) {
/* Copy flags onto the final derived poly from the original mesh poly */
mp_orig = me->mpoly + index_array[i];
polys[i].flag = mp_orig->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> selection_poly_orig = attributes_orig.lookup_or_default<bool>(
".selection_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> selection_poly_eval =
attributes_eval.lookup_or_add_for_write_only_span<bool>(".selection_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) {
selection_poly_eval.span[i] = selection_poly_orig[orig_poly_index];
}
}
selection_poly_eval.finish();
}
hide_poly_eval.finish();
updated = true;
}
@ -147,21 +157,23 @@ void paintface_hide(bContext *C, Object *ob, const bool unselected)
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
".hide_poly", ATTR_DOMAIN_FACE);
bke::SpanAttributeWriter<bool> selection_poly = attributes.lookup_or_add_for_write_span<bool>(
".selection_poly", ATTR_DOMAIN_FACE);
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
if (!hide_poly.span[i]) {
if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
if (!selection_poly.span[i] == unselected) {
hide_poly.span[i] = true;
}
}
if (hide_poly.span[i]) {
mpoly->flag &= ~ME_FACE_SEL;
selection_poly.span[i] = false;
}
}
hide_poly.finish();
selection_poly.finish();
BKE_mesh_flush_hidden_from_polys(me);
@ -181,12 +193,14 @@ void paintface_reveal(bContext *C, Object *ob, const bool select)
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 = &me->mpoly[i];
bke::SpanAttributeWriter<bool> selection_poly = attributes.lookup_or_add_for_write_span<bool>(
".selection_poly", ATTR_DOMAIN_FACE);
for (const int i : hide_poly.index_range()) {
if (hide_poly[i]) {
mpoly->flag |= ME_FACE_SEL;
selection_poly.span[i] = true;
}
}
selection_poly.finish();
}
attributes.remove(".hide_poly");
@ -207,9 +221,11 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__);
BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__);
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> selection_poly = attributes.lookup_or_add_for_write_span<bool>(
".selection_poly", ATTR_DOMAIN_FACE);
if (index != (uint)-1) {
/* only put face under cursor in array */
@ -224,7 +240,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
if (hide_poly[i]) {
/* pass */
}
else if (mp->flag & ME_FACE_SEL) {
else if (selection_poly.span[i]) {
BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
BLI_BITMAP_ENABLE(poly_tag, i);
}
@ -266,9 +282,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 = &me->mpoly[i];
if (BLI_BITMAP_TEST(poly_tag, i)) {
SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL);
selection_poly.span[i] = select;
}
}
@ -303,16 +318,17 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
return false;
}
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> selection_poly = attributes.lookup_or_add_for_write_span<bool>(
".selection_poly", ATTR_DOMAIN_FACE);
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
if (!hide_poly[i] && mpoly->flag & ME_FACE_SEL) {
if (!hide_poly[i] && selection_poly.span[i]) {
action = SEL_DESELECT;
break;
}
@ -322,29 +338,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 = &me->mpoly[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 = selection_poly.span[i];
switch (action) {
case SEL_SELECT:
selection_poly.span[i] = true;
break;
case SEL_DESELECT:
selection_poly.span[i] = false;
break;
case SEL_INVERT:
selection_poly.span[i] = !selection_poly.span[i];
changed = true;
break;
}
if (old_selection != selection_poly.span[i]) {
changed = true;
}
}
selection_poly.finish();
if (changed) {
if (flush_flags) {
paintface_flush_flags(C, ob, true, false);
@ -370,10 +386,12 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
const VArray<bool> selection_poly = attributes.lookup_or_default<bool>(
".selection_poly", ATTR_DOMAIN_FACE, false);
for (int i = 0; i < me->totpoly; i++) {
MPoly *mp = &me->mpoly[i];
if (hide_poly[i] || !(mp->flag & ME_FACE_SEL)) {
if (hide_poly[i] || !selection_poly[i]) {
continue;
}
@ -404,9 +422,11 @@ bool paintface_mouse_select(bContext *C,
/* Get the face under the cursor */
Mesh *me = BKE_mesh_from_object(ob);
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::AttributeWriter<bool> selection_poly = attributes.lookup_or_add_for_write<bool>(
".selection_poly", ATTR_DOMAIN_FACE);
if (ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
if (index < me->totpoly) {
@ -418,7 +438,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) && selection_poly.varray[index]) {
found = false;
}
else if (found || params->deselect_all) {
@ -431,31 +451,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:
selection_poly.varray.set(index, true);
break;
}
case SEL_OP_SUB: {
mpoly_sel->flag &= ~ME_FACE_SEL;
case SEL_OP_SUB:
selection_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;
}
case SEL_OP_XOR:
selection_poly.varray.set(index, !selection_poly.varray[index]);
break;
}
case SEL_OP_SET: {
mpoly_sel->flag |= ME_FACE_SEL;
break;
}
case SEL_OP_AND: {
case SEL_OP_AND:
BLI_assert_unreachable(); /* Doesn't make sense for picking. */
break;
}
}
/* image window redraw */
@ -469,13 +477,9 @@ bool paintface_mouse_select(bContext *C,
void paintvert_flush_flags(Object *ob)
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
MVert *mvert_eval, *mv;
const int *index_array = nullptr;
int totvert;
int i;
if (me == nullptr) {
return;
}
@ -488,27 +492,43 @@ void paintvert_flush_flags(Object *ob)
return;
}
index_array = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
const bke::AttributeAccessor attributes_orig = bke::mesh_attributes(*me);
bke::MutableAttributeAccessor attributes_eval = bke::mesh_attributes_for_write(*me_eval);
mvert_eval = me_eval->mvert;
totvert = me_eval->totvert;
const int *orig_indices = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
mv = mvert_eval;
if (index_array) {
int orig_index;
for (i = 0; i < totvert; i++, mv++) {
orig_index = index_array[i];
if (orig_index != ORIGINDEX_NONE) {
mv->flag = me->mvert[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 (i = 0; i < totvert; i++, mv++) {
mv->flag = me->mvert[i].flag;
hide_vert_orig.materialize(hide_vert_eval.span);
}
hide_vert_eval.finish();
const VArray<bool> selection_vert_orig = attributes_orig.lookup_or_default<bool>(
".selection_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> selection_vert_eval =
attributes_eval.lookup_or_add_for_write_only_span<bool>(".selection_vert",
ATTR_DOMAIN_POINT);
if (orig_indices) {
for (const int i : selection_vert_eval.span.index_range()) {
if (orig_indices[i] != ORIGINDEX_NONE) {
selection_vert_eval.span[i] = selection_vert_orig[orig_indices[i]];
}
}
}
else {
selection_vert_orig.materialize(selection_vert_eval.span);
}
selection_vert_eval.finish();
BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL);
}
@ -527,16 +547,17 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
return false;
}
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> selection_vert = attributes.lookup_or_add_for_write_span<bool>(
".selection_vert", ATTR_DOMAIN_POINT);
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
for (int i = 0; i < me->totvert; i++) {
MVert *mvert = &me->mvert[i];
if (!hide_vert[i] && mvert->flag & SELECT) {
if (!hide_vert[i] && selection_vert.span[i]) {
action = SEL_DESELECT;
break;
}
@ -545,29 +566,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 = &me->mvert[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 = selection_vert.span[i];
switch (action) {
case SEL_SELECT:
selection_vert.span[i] = true;
break;
case SEL_DESELECT:
selection_vert.span[i] = false;
break;
case SEL_INVERT:
selection_vert.span[i] = !selection_vert.span[i];
break;
}
if (old_selection != selection_vert.span[i]) {
changed = true;
}
}
selection_vert.finish();
if (changed) {
/* handle mselect */
if (action == SEL_SELECT) {
@ -600,21 +620,24 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
}
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> selection_vert = attributes.lookup_or_add_for_write_span<bool>(
".selection_vert", ATTR_DOMAIN_POINT);
for (int i = 0; i < me->totvert; i++) {
MVert *mv = &me->mvert[i];
MDeformVert *dv = &me->dvert[i];
const MDeformVert *dv = &me->dvert[i];
if (!hide_vert[i]) {
if (dv->dw == nullptr) {
/* if null weight then not grouped */
mv->flag |= SELECT;
selection_vert.span[i] = true;
}
}
}
selection_vert.finish();
if (flush_flags) {
paintvert_flush_flags(ob);
}
@ -631,21 +654,22 @@ void paintvert_hide(bContext *C, Object *ob, const bool unselected)
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
".hide_vert", ATTR_DOMAIN_POINT);
MutableSpan<MVert> verts(me->mvert, me->totvert);
bke::SpanAttributeWriter<bool> selection_vert = attributes.lookup_or_add_for_write_span<bool>(
".selection_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 (!selection_vert.span[i] == unselected) {
hide_vert.span[i] = true;
}
}
if (hide_vert.span[i]) {
vert.flag &= ~SELECT;
selection_vert.span[i] = false;
}
}
hide_vert.finish();
selection_vert.finish();
BKE_mesh_flush_hidden_from_verts(me);
@ -664,12 +688,12 @@ void paintvert_reveal(bContext *C, Object *ob, const bool select)
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
MutableSpan<MVert> verts(me->mvert, me->totvert);
bke::SpanAttributeWriter<bool> selection_vert = attributes.lookup_or_add_for_write_span<bool>(
".selection_vert", ATTR_DOMAIN_POINT);
for (const int i : verts.index_range()) {
MVert &vert = verts[i];
for (const int i : selection_vert.span.index_range()) {
if (hide_vert[i]) {
SET_FLAG_FROM_TEST(vert.flag, select, SELECT);
selection_vert.span[i] = select;
}
}

View File

@ -25,14 +25,16 @@ extern "C" {
*/
typedef struct MVert {
float co[3];
char flag, bweight;
char _pad[2];
// char flag
char bweight;
char _pad[3];
} MVert;
/** #MVert.flag */
#ifdef DNA_DEPRECATED_ALLOW
enum {
/** Deprecated selection status. Now stored in ".selection_vert" attribute. */
/* SELECT = (1 << 0), */
/** Deprecated hide status. Now stored in ".hide_vert" attribute. */
ME_HIDE = (1 << 4),
@ -53,6 +55,7 @@ typedef struct MEdge {
/** #MEdge.flag */
enum {
/** Deprecated selection status. Now stored in ".selection_edge" attribute. */
/* SELECT = (1 << 0), */
ME_EDGEDRAW = (1 << 1),
ME_SEAM = (1 << 2),
@ -81,7 +84,10 @@ typedef struct MPoly {
/** #MPoly.flag */
enum {
ME_SMOOTH = (1 << 0),
ME_FACE_SEL = (1 << 1),
#ifdef DNA_DEPRECATED_ALLOW
/** Deprecated selection status. Now stored in ".selection_poly" attribute. */
// ME_FACE_SEL = (1 << 1),
#endif
/** Deprecated hide status. Now stored in ".hide_poly" attribute. */
/* ME_HIDE = (1 << 4), */
};