Animation: Weight Paint select more/less for faces #105607
|
@ -370,29 +370,31 @@ void paintface_select_more(bContext *C, Object *ob, const bool face_step)
|
|||
const Span<MLoop> loops = mesh->loops();
|
||||
const Span<MEdge> edges = mesh->edges();
|
||||
|
||||
for (const int i : select_poly.span.index_range()) {
|
||||
if (select_poly.span[i] || hide_poly[i]) {
|
||||
continue;
|
||||
}
|
||||
const MPoly &poly = polys[i];
|
||||
threading::parallel_for(select_poly.span.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
if (select_poly.span[i] || hide_poly[i]) {
|
||||
continue;
|
||||
}
|
||||
const MPoly &poly = polys[i];
|
||||
|
||||
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
|
||||
const MEdge &edge = edges[loop.e];
|
||||
/* If a poly is selected, all of its verts are selected too, meaning that neighboring faces
|
||||
* will have some vertices selected. */
|
||||
bool selected_neighbor = false;
|
||||
if (face_step) {
|
||||
selected_neighbor = select_vert.span[edge.v1] || select_vert.span[edge.v2];
|
||||
}
|
||||
else {
|
||||
selected_neighbor = select_vert.span[edge.v1] && select_vert.span[edge.v2];
|
||||
}
|
||||
if (selected_neighbor) {
|
||||
select_poly.span[i] = true;
|
||||
break;
|
||||
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
|
||||
const MEdge &edge = edges[loop.e];
|
||||
/* If a poly is selected, all of its verts are selected too, meaning that neighboring faces
|
||||
* will have some vertices selected. */
|
||||
bool selected_neighbor = false;
|
||||
if (face_step) {
|
||||
selected_neighbor = select_vert.span[edge.v1] || select_vert.span[edge.v2];
|
||||
}
|
||||
else {
|
||||
|
||||
selected_neighbor = select_vert.span[edge.v1] && select_vert.span[edge.v2];
|
||||
}
|
||||
if (selected_neighbor) {
|
||||
select_poly.span[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Sybren A. Stüvel
commented
The condition can be avoided by doing something like:
Not sure if it's worth it though, you choose @ChrisLend. Could be applied below as well. The condition can be avoided by doing something like:
```cpp
const bool has_selected_neighbour = poly_has_selected_neighbor(...);
select_poly.span[i] |= has_selected_neighbour;
```
Not sure if it's worth it though, you choose @ChrisLend. Could be applied below as well.
|
||||
select_poly.finish();
|
||||
Hans Goudey
commented
Blender uses American English spelling, so Blender uses American English spelling, so `neighbor` instead of `neighbor`
|
||||
select_vert.finish();
|
||||
|
@ -430,29 +432,31 @@ void paintface_select_less(bContext *C, Object *ob, const bool face_step)
|
|||
}
|
||||
}
|
||||
|
||||
for (const int i : select_poly.span.index_range()) {
|
||||
if (!select_poly.span[i] || hide_poly[i]) {
|
||||
continue;
|
||||
}
|
||||
const MPoly &poly = polys[i];
|
||||
threading::parallel_for(select_poly.span.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
if (!select_poly.span[i] || hide_poly[i]) {
|
||||
continue;
|
||||
}
|
||||
const MPoly &poly = polys[i];
|
||||
|
||||
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
|
||||
const MEdge &edge = edges[loop.e];
|
||||
bool unselected_neighbor = false;
|
||||
if (face_step) {
|
||||
unselected_neighbor = verts_of_unselected_faces[edge.v1] ||
|
||||
verts_of_unselected_faces[edge.v2];
|
||||
}
|
||||
else {
|
||||
unselected_neighbor = verts_of_unselected_faces[edge.v1] &&
|
||||
verts_of_unselected_faces[edge.v2];
|
||||
}
|
||||
if (unselected_neighbor) {
|
||||
select_poly.span[i] = false;
|
||||
break;
|
||||
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
|
||||
Hans Goudey
commented
What do you think about splitting this part into a separate function-- something like I think that would make the logic here a bit simpler, and avoid the need for breaking inside the loop. Something similar would be helpful above too. What do you think about splitting this part into a separate function-- something like ` bool poly_has_unselected_neighbor(Span<MLoop> poly_loops, bool face_step)`?
I think that would make the logic here a bit simpler, and avoid the need for breaking inside the loop.
Something similar would be helpful above too.
I've split up this part. the argument list is a bit long though so I am a bit unsure if that is an improvement. Let me know what you think I've split up this part. the argument list is a bit long though so I am a bit unsure if that is an improvement. Let me know what you think
Hans Goudey
commented
`poly_loops` is generally the name for a span containing the loops of a single polygon. The `poly` argument could be removed by slicing the `loops` span before passing it to the function.
|
||||
const MEdge &edge = edges[loop.e];
|
||||
Hans Goudey
commented
`MLoop` has been replaced by two arrays in `main`. This loop can be simplified now:
```
for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) {
...
}
```
|
||||
bool unselected_neighbor = false;
|
||||
if (face_step) {
|
||||
unselected_neighbor = verts_of_unselected_faces[edge.v1] ||
|
||||
verts_of_unselected_faces[edge.v2];
|
||||
}
|
||||
else {
|
||||
Hans Goudey
commented
Might as well change this to I realize that's a bit nitpicky, just hoping you might agree and appreciate the more literal semantic argument :P Might as well change this to `polys.index_range()` instead of `select_poly.span.index_range()` for the same reason I mentioned earlier too-- it just says more clearly "we're iterating over all faces" rather than "we're iterating over the face selection".
I realize that's a bit nitpicky, just hoping you might agree and appreciate the more literal semantic argument :P
|
||||
unselected_neighbor = verts_of_unselected_faces[edge.v1] &&
|
||||
verts_of_unselected_faces[edge.v2];
|
||||
}
|
||||
if (unselected_neighbor) {
|
||||
select_poly.span[i] = false;
|
||||
break;
|
||||
Hans Goudey
commented
`vert_index` -> `vert` here too, though I mentioned that in chat
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
select_poly.finish();
|
||||
paintface_flush_flags(C, ob, true, false);
|
||||
|
|
This is feeling a bit picky, sorry about that, but might as well extract this check for the poly instead of using a
break
like below (poly_has_unselected_neighbour
) I think it makes sense for them to be consistent anyway.