Fix #129632: GPv3: Vgroup operation edits drawings from all keyframes

Verge groups operations such as assign/remove/select/deselect from data
properties tab edits all drawings instead of visible drawings at current
frame. Now fixed with `retrieve_editable_drawings`.
For remove/remove_from operator, separate PR is created: !129890

Pull Request: https://projects.blender.org/blender/blender/pulls/129789
This commit is contained in:
Pratik Borhade
2024-11-06 04:16:48 +01:00
committed by Pratik Borhade
parent 3d76e43e4a
commit 40162873e0
3 changed files with 115 additions and 97 deletions

View File

@@ -22,7 +22,10 @@ void validate_drawing_vertex_groups(GreasePencil &grease_pencil);
int ensure_vertex_group(const StringRef name, ListBase &vertex_group_names);
/** Assign selected vertices to the vertex group. */
void assign_to_vertex_group(GreasePencil &grease_pencil, StringRef name, float weight);
void assign_to_vertex_group(GreasePencil &grease_pencil,
Drawing &drawing,
StringRef name,
float weight);
void assign_to_vertex_group_from_mask(CurvesGeometry &curves,
const IndexMask &mask,
@@ -40,6 +43,7 @@ void clear_vertex_groups(GreasePencil &grease_pencil);
/** Select or deselect vertices assigned to this group. */
void select_from_group(GreasePencil &grease_pencil,
Drawing &drawing,
const AttrDomain selection_domain,
StringRef name,
bool select);

View File

@@ -95,40 +95,38 @@ void assign_to_vertex_group_from_mask(bke::CurvesGeometry &curves,
});
}
void assign_to_vertex_group(GreasePencil &grease_pencil, const StringRef name, const float weight)
void assign_to_vertex_group(GreasePencil &grease_pencil,
Drawing &drawing,
const StringRef name,
const float weight)
{
for (GreasePencilDrawingBase *base : grease_pencil.drawings()) {
if (base->type != GP_DRAWING) {
continue;
}
Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
bke::CurvesGeometry &curves = drawing.strokes_for_write();
ListBase &vertex_group_names = curves.vertex_group_names;
const bke::AttributeAccessor attributes = curves.attributes();
const VArray<bool> selection = *attributes.lookup_or_default<bool>(
".selection", bke::AttrDomain::Point, true);
bke::CurvesGeometry &curves = drawing.strokes_for_write();
ListBase &vertex_group_names = curves.vertex_group_names;
/* Look for existing group, otherwise lazy-initialize if any vertex is selected. */
int def_nr = BKE_defgroup_name_index(&vertex_group_names, name);
const bke::AttributeAccessor attributes = curves.attributes();
const VArray<bool> selection = *attributes.lookup_or_default<bool>(
".selection", bke::AttrDomain::Point, true);
const MutableSpan<MDeformVert> dverts = curves.deform_verts_for_write();
for (const int i : dverts.index_range()) {
if (selection[i]) {
/* Lazily add the vertex group if any vertex is selected. */
if (def_nr < 0) {
bDeformGroup *defgroup = MEM_cnew<bDeformGroup>(__func__);
name.copy(defgroup->name);
/* Look for existing group, otherwise lazy-initialize if any vertex is selected. */
int def_nr = BKE_defgroup_name_index(&vertex_group_names, name);
BLI_addtail(&vertex_group_names, defgroup);
def_nr = BLI_listbase_count(&vertex_group_names) - 1;
BLI_assert(def_nr >= 0);
}
const MutableSpan<MDeformVert> dverts = curves.deform_verts_for_write();
for (const int i : dverts.index_range()) {
if (selection[i]) {
/* Lazily add the vertex group if any vertex is selected. */
if (def_nr < 0) {
bDeformGroup *defgroup = MEM_cnew<bDeformGroup>(__func__);
name.copy(defgroup->name);
MDeformWeight *dw = BKE_defvert_ensure_index(&dverts[i], def_nr);
if (dw) {
dw->weight = weight;
}
BLI_addtail(&vertex_group_names, defgroup);
def_nr = BLI_listbase_count(&vertex_group_names) - 1;
BLI_assert(def_nr >= 0);
}
MDeformWeight *dw = BKE_defvert_ensure_index(&dverts[i], def_nr);
if (dw) {
dw->weight = weight;
}
}
}
@@ -193,73 +191,69 @@ void clear_vertex_groups(GreasePencil &grease_pencil)
}
void select_from_group(GreasePencil &grease_pencil,
Drawing &drawing,
const AttrDomain selection_domain,
const StringRef name,
const bool select)
{
for (GreasePencilDrawingBase *base : grease_pencil.drawings()) {
if (base->type != GP_DRAWING) {
continue;
}
Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
bke::CurvesGeometry &curves = drawing.strokes_for_write();
ListBase &vertex_group_names = curves.vertex_group_names;
const int def_nr = BKE_defgroup_name_index(&vertex_group_names, name);
if (def_nr < 0) {
/* No vertices assigned to the group in this drawing. */
continue;
}
bke::CurvesGeometry &curves = drawing.strokes_for_write();
ListBase &vertex_group_names = curves.vertex_group_names;
const Span<MDeformVert> dverts = curves.deform_verts_for_write();
if (dverts.is_empty()) {
continue;
}
MutableAttributeAccessor attributes = curves.attributes_for_write();
const int num_elements = attributes.domain_size(selection_domain);
SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
".selection",
selection_domain,
bke::AttributeInitVArray(VArray<bool>::ForSingle(true, num_elements)));
switch (selection_domain) {
case AttrDomain::Point:
threading::parallel_for(curves.points_range(), 4096, [&](const IndexRange range) {
for (const int point_i : range) {
if (BKE_defvert_find_index(&dverts[point_i], def_nr)) {
selection.span[point_i] = select;
}
}
});
break;
case AttrDomain::Curve: {
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
threading::parallel_for(curves.curves_range(), 1024, [&](const IndexRange range) {
for (const int curve_i : range) {
const IndexRange points = points_by_curve[curve_i];
bool any_point_in_group = false;
for (const int point_i : points) {
if (BKE_defvert_find_index(&dverts[point_i], def_nr)) {
any_point_in_group = true;
break;
}
}
if (any_point_in_group) {
selection.span[curve_i] = select;
}
}
});
break;
}
default:
BLI_assert_unreachable();
break;
}
selection.finish();
const int def_nr = BKE_defgroup_name_index(&vertex_group_names, name);
if (def_nr < 0) {
/* No vertices assigned to the group in this drawing. */
return;
}
const Span<MDeformVert> dverts = curves.deform_verts_for_write();
if (dverts.is_empty()) {
return;
}
MutableAttributeAccessor attributes = curves.attributes_for_write();
const int num_elements = attributes.domain_size(selection_domain);
SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
".selection",
selection_domain,
bke::AttributeInitVArray(VArray<bool>::ForSingle(true, num_elements)));
switch (selection_domain) {
case AttrDomain::Point:
threading::parallel_for(curves.points_range(), 4096, [&](const IndexRange range) {
for (const int point_i : range) {
if (BKE_defvert_find_index(&dverts[point_i], def_nr)) {
selection.span[point_i] = select;
}
}
});
break;
case AttrDomain::Curve: {
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
threading::parallel_for(curves.curves_range(), 1024, [&](const IndexRange range) {
for (const int curve_i : range) {
const IndexRange points = points_by_curve[curve_i];
bool any_point_in_group = false;
for (const int point_i : points) {
if (BKE_defvert_find_index(&dverts[point_i], def_nr)) {
any_point_in_group = true;
break;
}
}
if (any_point_in_group) {
selection.span[curve_i] = select;
}
}
});
break;
}
default:
BLI_assert_unreachable();
break;
}
selection.finish();
}
/** \} */

View File

@@ -1006,7 +1006,10 @@ void vgroup_select_by_name(Object *ob, const char *name)
* \{ */
/* only in editmode */
static void vgroup_select_verts(const ToolSettings &tool_settings, Object *ob, int select)
static void vgroup_select_verts(const ToolSettings &tool_settings,
Object *ob,
Scene &scene,
int select)
{
const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
@@ -1098,8 +1101,14 @@ static void vgroup_select_verts(const ToolSettings &tool_settings, Object *ob, i
const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get(
&tool_settings);
GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
bke::greasepencil::select_from_group(
*grease_pencil, selection_domain, def_group->name, bool(select));
{
using namespace ed::greasepencil;
Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, *grease_pencil);
for (MutableDrawingInfo info : drawings) {
bke::greasepencil::select_from_group(
*grease_pencil, info.drawing, selection_domain, def_group->name, bool(select));
}
}
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
}
}
@@ -2218,7 +2227,7 @@ static void vgroup_delete_active(Object *ob)
}
/* only in editmode */
static void vgroup_assign_verts(Object *ob, const float weight)
static void vgroup_assign_verts(Object *ob, Scene &scene, const float weight)
{
const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
@@ -2303,7 +2312,15 @@ static void vgroup_assign_verts(Object *ob, const float weight)
GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
const bDeformGroup *defgroup = static_cast<const bDeformGroup *>(
BLI_findlink(BKE_object_defgroup_list(ob), def_nr));
bke::greasepencil::assign_to_vertex_group(*grease_pencil, defgroup->name, weight);
{
using namespace ed::greasepencil;
Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, *grease_pencil);
for (MutableDrawingInfo info : drawings) {
bke::greasepencil::assign_to_vertex_group(
*grease_pencil, info.drawing, defgroup->name, weight);
}
}
}
}
@@ -2566,8 +2583,9 @@ static int vertex_group_assign_exec(bContext *C, wmOperator * /*op*/)
{
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = context_object(C);
Scene &scene = *CTX_data_scene(C);
vgroup_assign_verts(ob, ts->vgroup_weight);
vgroup_assign_verts(ob, scene, ts->vgroup_weight);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -2697,12 +2715,13 @@ static int vertex_group_select_exec(bContext *C, wmOperator * /*op*/)
{
const ToolSettings &tool_settings = *CTX_data_scene(C)->toolsettings;
Object *ob = context_object(C);
Scene &scene = *CTX_data_scene(C);
if (!ob || !ID_IS_EDITABLE(ob) || ID_IS_OVERRIDE_LIBRARY(ob)) {
return OPERATOR_CANCELLED;
}
vgroup_select_verts(tool_settings, ob, 1);
vgroup_select_verts(tool_settings, ob, scene, 1);
DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_SYNC_TO_EVAL | ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
@@ -2734,8 +2753,9 @@ static int vertex_group_deselect_exec(bContext *C, wmOperator * /*op*/)
{
const ToolSettings &tool_settings = *CTX_data_scene(C)->toolsettings;
Object *ob = context_object(C);
Scene &scene = *CTX_data_scene(C);
vgroup_select_verts(tool_settings, ob, 0);
vgroup_select_verts(tool_settings, ob, scene, 0);
DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_SYNC_TO_EVAL | ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);