Animation: Weight Paint select more/less for vertices #105633

Merged
Christoph Lendenfeld merged 14 commits from ChrisLend/blender:weight_paint_grow_sel_vert into main 2023-03-31 14:48:09 +02:00
7 changed files with 144 additions and 0 deletions
Showing only changes of commit b944cb281a - Show all commits

View File

@ -4437,6 +4437,8 @@ def km_weight_paint_vertex_selection(params):
{"properties": [("select", True)]}),
("paint.vert_select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True},
{"properties": [("select", False)]}),
("paint.vert_select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
("paint.vert_select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
])
return keymap

View File

@ -2032,6 +2032,9 @@ class VIEW3D_MT_select_paint_mask_vertex(Menu):
layout.operator("paint.vert_select_all", text="None").action = 'DESELECT'
layout.operator("paint.vert_select_all", text="Invert").action = 'INVERT'
layout.operator("paint.vert_select_more"),
layout.operator("paint.vert_select_less"),
layout.separator()
layout.operator("view3d.select_box")

View File

@ -444,6 +444,8 @@ void paintvert_select_linked_pick(struct bContext *C,
struct Object *ob,
const int region_coordinates[2],
bool select);
void paintvert_select_more(struct bContext *C, struct Object *ob, bool face_step);
void paintvert_select_less(struct bContext *C, struct Object *ob, bool face_step);
void paintvert_hide(struct bContext *C, struct Object *ob, bool unselected);
void paintvert_reveal(struct bContext *C, struct Object *ob, bool select);

View File

@ -659,6 +659,93 @@ void paintvert_select_linked(bContext *C, Object *ob)
paintvert_select_linked_vertices(C, ob, indices, true);
}
void paintvert_select_more(bContext *C, Object *ob, const bool face_step)
{
using namespace blender;
Mesh *mesh = BKE_mesh_from_object(ob);
if (mesh == nullptr || mesh->totpoly == 0) {
return;
}
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);
const VArray<bool> hide_edge = attributes.lookup_or_default<bool>(
".hide_edge", ATTR_DOMAIN_EDGE, false);
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
const Span<MEdge> edges = mesh->edges();
/* Need a copy of the selected verts that we can read from and is not modified. */
BitVector<> select_vert_original(mesh->totvert, false);
for (int i = 0; i < mesh->totvert; i++) {
select_vert_original[i].set(select_vert.span[i]);
}

You set every value of the bit vector, so there's no need to explicitly initialize it to false here.

You set every value of the bit vector, so there's no need to explicitly initialize it to false here.
for (const int i : edges.index_range()) {

The functionality is the same, but mesh_topology::build_edge_to_poly_map(..) has an interface that's a bit more friendly in C++. Performance might be slightly worse currently, but there are plans to improve those functions in the near future.

The functionality is the same, but `mesh_topology::build_edge_to_poly_map(..)` has an interface that's a bit more friendly in C++. Performance might be slightly worse currently, but there are plans to improve those functions in the near future.
const MEdge &edge = edges[i];
bool has_vertex_selected = false;
if ((!select_vert_original[edge.v1] && !select_vert_original[edge.v2]) || hide_edge[i]) {
continue;
}
has_vertex_selected = true;
select_vert.span[edge.v1] = true;
select_vert.span[edge.v2] = true;
if (face_step && has_vertex_selected) {
}
}
select_vert.finish();
paintvert_flush_flags(ob);
paintvert_tag_select_update(C, ob);
}
void paintvert_select_less(bContext *C, Object *ob, const bool face_step)
{
using namespace blender;
Mesh *mesh = BKE_mesh_from_object(ob);
if (mesh == nullptr || mesh->totpoly == 0) {
return;
}
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);
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
const Span<MEdge> edges = mesh->edges();
/* Need a copy of the selected verts that we can read from and is not modified. */
BitVector<> select_vert_original(mesh->totvert, false);
for (int i = 0; i < mesh->totvert; i++) {
select_vert_original[i].set(select_vert.span[i]);
}
for (const MPoly &poly : polys) {
bool has_vertex_selected = false;
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
if (select_vert_original[loop.v]) {
continue;
}
has_vertex_selected = true;
const MEdge &edge = edges[loop.e];
select_vert.span[edge.v1] = false;
select_vert.span[edge.v2] = false;
}
if (face_step && has_vertex_selected) {
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
select_vert.span[loop.v] = false;
}
}
}
select_vert.finish();
paintvert_flush_flags(ob);
paintvert_tag_select_update(C, ob);
}
void paintvert_tag_select_update(bContext *C, Object *ob)
{
DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);

View File

@ -387,6 +387,8 @@ void PAINT_OT_vert_select_ungrouped(struct wmOperatorType *ot);
void PAINT_OT_vert_select_hide(struct wmOperatorType *ot);
void PAINT_OT_vert_select_linked(struct wmOperatorType *ot);
void PAINT_OT_vert_select_linked_pick(struct wmOperatorType *ot);
void PAINT_OT_vert_select_more(struct wmOperatorType *ot);
void PAINT_OT_vert_select_less(struct wmOperatorType *ot);
bool vert_paint_poll(struct bContext *C);
bool mask_paint_poll(struct bContext *C);

View File

@ -1501,6 +1501,8 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_vert_select_hide);
WM_operatortype_append(PAINT_OT_vert_select_linked);
WM_operatortype_append(PAINT_OT_vert_select_linked_pick);
WM_operatortype_append(PAINT_OT_vert_select_more);
WM_operatortype_append(PAINT_OT_vert_select_less);
/* vertex */
WM_operatortype_append(PAINT_OT_vertex_paint_toggle);

View File

@ -796,6 +796,52 @@ void PAINT_OT_vert_select_linked_pick(wmOperatorType *ot)
"Whether to select or deselect linked vertices under the cursor");
}
static int paintvert_select_more_exec(bContext *C, wmOperator *op)
{
const bool face_step = RNA_boolean_get(op->ptr, "face_step");
paintvert_select_more(C, CTX_data_active_object(C), face_step);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}
void PAINT_OT_vert_select_more(wmOperatorType *ot)
{
ot->name = "Select More";
ot->description = "Select Vertices connected to existing selection";
ot->idname = "PAINT_OT_vert_select_more";
ot->exec = paintvert_select_more_exec;
ot->poll = vert_paint_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(
ot->srna, "face_step", true, "Face Step", "Also select faces that only touch on a corner");
}
static int paintvert_select_less_exec(bContext *C, wmOperator *op)
{
const bool face_step = RNA_boolean_get(op->ptr, "face_step");
paintvert_select_less(C, CTX_data_active_object(C), face_step);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}
void PAINT_OT_vert_select_less(wmOperatorType *ot)
{
ot->name = "Select Less";
ot->description = "Deselect Vertices connected to existing selection";
ot->idname = "PAINT_OT_vert_select_less";
ot->exec = paintvert_select_less_exec;
ot->poll = vert_paint_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(
ot->srna, "face_step", true, "Face Step", "Also deselect faces that only touch on a corner");
}
static int face_select_hide_exec(bContext *C, wmOperator *op)
{
const bool unselected = RNA_boolean_get(op->ptr, "unselected");