Mesh: Move selection status from flags to generic attributes (WIP)
This commit is contained in:
parent
39bad22008
commit
f0e4307792
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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), */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue