Refactor: Weight Paint Select Linked Faces #104577

Merged
Christoph Lendenfeld merged 15 commits from ChrisLend/blender:weight_paint_refactor_face_select into main 2023-02-23 08:26:44 +01:00
1 changed files with 24 additions and 14 deletions
Showing only changes of commit 187bcb9f13 - Show all commits

View File

@ -212,6 +212,7 @@ void paintface_reveal(bContext *C, Object *ob, const bool select)
paintface_flush_flags(C, ob, true, true);
}
/* Select faces connected to the given face_indices. Seams are treated as separation. */
static void paintface_select_linked_faces(Mesh *mesh,
ChrisLend marked this conversation as resolved
Review

Mesh *mesh -> Mesh &mesh

Using a reference indicates that the pointer won't be null

`Mesh *mesh` -> `Mesh &mesh` Using a reference indicates that the pointer won't be null
const blender::Span<int> face_indices,
const bool select)
ChrisLend marked this conversation as resolved
Review
`@param islands` -> `\param islands:` https://wiki.blender.org/wiki/Style_Guide/C_Cpp#Comments
@ -232,16 +233,21 @@ static void paintface_select_linked_faces(Mesh *mesh,
* are not a seam) we can find connected faces. */
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const MPoly &poly : polys.slice(range)) {
const MLoop *prev_loop = &loops[poly.loopstart];
/* A Poly cannot be made of only 1 loop. So this should be save. */
const MLoop *current_loop = &loops[poly.loopstart + 1];
for (int b = 1; b < poly.totloop; b++, current_loop++, prev_loop++) {
if ((edges[current_loop->e].flag & ME_SEAM) != 0 ||
(edges[prev_loop->e].flag & ME_SEAM) != 0) {
/* All edges of the face need to be joined in the DisjointSet. Unless the are marked as seam.
ChrisLend marked this conversation as resolved
Review

Grammar: "Unless the are"

Also, the previous comment said the same thing, this is redundant.

Grammar: "Unless the are" Also, the previous comment said the same thing, this is redundant.
*/
for (int outer_loop_index = 0; outer_loop_index < poly.totloop; outer_loop_index++) {
ChrisLend marked this conversation as resolved
Review

for (const int loop : IndexRange(poly.loopstart, poly.totloop)) {

`for (const int loop : IndexRange(poly.loopstart, poly.totloop)) {`
const MLoop *outer_mloop = &loops[poly.loopstart + outer_loop_index];
if ((edges[outer_mloop->e].flag & ME_SEAM) != 0) {
continue;
}
ChrisLend marked this conversation as resolved
Review

I suggest using a separate const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop); variable. Then the next loop can use for (const int outer_loop_index : poly_loops.index_range()) { and you don't have to add poly.totloop every time a loop in the poly is accessed.

I suggest using a separate `const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);` variable. Then the next loop can use `for (const int outer_loop_index : poly_loops.index_range()) {` and you don't have to add `poly.totloop` every time a loop in the poly is accessed.
islands.join(prev_loop->e, current_loop->e);
for (int inner_loop_idx = outer_loop_index + 1; inner_loop_idx < poly.totloop;
Review

Use references instead of pointers, that should be your default in C++ code.

Use references instead of pointers, that should be your default in C++ code.

sure thing, missed that
out of curiosity: what is the reason for it?

sure thing, missed that out of curiosity: what is the reason for it?
Review

There are quite a few benefits-- they indicate non-null, they allow using . instead of ->, they can't be indexed (so they can't be mistaken for pointers to arrays). There's more info here:

https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable

There are quite a few benefits-- they indicate non-null, they allow using `.` instead of `->`, they can't be indexed (so they can't be mistaken for pointers to arrays). There's more info here: https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable
inner_loop_idx++) {
const MLoop *inner_mloop = &loops[poly.loopstart + inner_loop_idx];
if ((edges[inner_mloop->e].flag & ME_SEAM) != 0) {
continue;
}
islands.join(inner_mloop->e, outer_mloop->e);
}
}
}
});
@ -251,6 +257,9 @@ static void paintface_select_linked_faces(Mesh *mesh,
MPoly poly = polys[i];
const MLoop *loop = &loops[poly.loopstart];
for (int i = 0; i < poly.totloop; i++, loop++) {
if ((edges[loop->e].flag & ME_SEAM) != 0) {
continue;
}
const int root = islands.find_root(loop->e);
selected_roots.add(root);
}
@ -283,29 +292,30 @@ void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const b
blender::Vector<int> indices;
blender::bke::MutableAttributeAccessor attributes = me->attributes_for_write();
blender::bke::SpanAttributeWriter<bool> select_poly =
attributes.lookup_or_add_for_write_span<bool>(".select_poly", ATTR_DOMAIN_FACE);
if (mval) {
uint index = uint(-1);
if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
return;
ChrisLend marked this conversation as resolved
Review

Looks like this early return will skip select_poly.finish();. That will probably print a warning to the terminal.

Looks like this early return will skip `select_poly.finish();`. That will probably print a warning to the terminal.
}
select_poly.span[index] = true;
indices.append(index);
}
else {
blender::bke::MutableAttributeAccessor attributes = me->attributes_for_write();
blender::bke::SpanAttributeWriter<bool> select_poly =
attributes.lookup_or_add_for_write_span<bool>(".select_poly", ATTR_DOMAIN_FACE);
for (const int i : select_poly.span.index_range()) {
if (!select_poly.span[i]) {
continue;
}
indices.append(i);
}
ChrisLend marked this conversation as resolved
Review

Declare this closer to where it's first used, right above if (mval) {

Declare this closer to where it's first used, right above `if (mval) {`
select_poly.finish();
}
select_poly.finish();
paintface_select_linked_faces(me, indices, select);
paintface_flush_flags(C, ob, true, false);
}