Fix #139258: Grease Pencil: Strokes lose deform groups when moved to another layer
Strokes would lose their deform group values after moving them to a different layer, because `vertex_group_names` weren't transferred to the newly created `CurvesGeometry` inside `execute_realize_curve_tasks`. This commit adds another version of `copy_vertex_group_names` for Curves, and separates the duplicate code into `copy_vertex_group_name`, which is used by both meshes and curves. This also fixed strokes losing deform weights in multiple situations, such as: - When performing a layer merge. - When applying generative modifiers like Mirror or Array Pull Request: https://projects.blender.org/blender/blender/pulls/142881
This commit is contained in:
committed by
Falk David
parent
831969f4f0
commit
c95aa8dbd1
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_bounds.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_geom.h"
|
||||
#include "BLI_math_numbers.hh"
|
||||
#include "BLI_math_vector.hh"
|
||||
@@ -1947,15 +1948,32 @@ void apply_eval_grease_pencil_data(const GreasePencil &eval_grease_pencil,
|
||||
}
|
||||
}
|
||||
|
||||
/* Gather the original vertex group names. */
|
||||
Set<StringRef> orig_vgroup_names;
|
||||
LISTBASE_FOREACH (bDeformGroup *, dg, &orig_grease_pencil.vertex_group_names) {
|
||||
orig_vgroup_names.add(dg->name);
|
||||
}
|
||||
|
||||
/* Update the drawings. */
|
||||
VectorSet<Drawing *> all_updated_drawings;
|
||||
|
||||
Set<StringRef> new_vgroup_names;
|
||||
for (auto [layer_eval, layer_orig] : eval_to_orig_layer_map.items()) {
|
||||
const Drawing *drawing_eval = merged_layers_grease_pencil.get_drawing_at(*layer_eval,
|
||||
eval_frame);
|
||||
Drawing *drawing_eval = merged_layers_grease_pencil.get_drawing_at(*layer_eval, eval_frame);
|
||||
Drawing *drawing_orig = orig_grease_pencil.get_drawing_at(*layer_orig, eval_frame);
|
||||
|
||||
if (drawing_orig && drawing_eval) {
|
||||
CurvesGeometry &eval_strokes = drawing_eval->strokes_for_write();
|
||||
|
||||
/* Check for new vertex groups in CurvesGeometry. */
|
||||
LISTBASE_FOREACH (bDeformGroup *, dg, &eval_strokes.vertex_group_names) {
|
||||
if (!orig_vgroup_names.contains(dg->name)) {
|
||||
new_vgroup_names.add(dg->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the data to the original drawing. */
|
||||
drawing_orig->strokes_for_write() = std::move(drawing_eval->strokes());
|
||||
drawing_orig->strokes_for_write() = std::move(eval_strokes);
|
||||
/* Anonymous attributes shouldn't be available on original geometry. */
|
||||
drawing_orig->strokes_for_write().attributes_for_write().remove_anonymous();
|
||||
drawing_orig->tag_topology_changed();
|
||||
@@ -1963,6 +1981,13 @@ void apply_eval_grease_pencil_data(const GreasePencil &eval_grease_pencil,
|
||||
}
|
||||
}
|
||||
|
||||
/* Add new vertex groups to GreasePencil object. */
|
||||
for (StringRef new_vgroup_name : new_vgroup_names) {
|
||||
bDeformGroup *dst = MEM_callocN<bDeformGroup>(__func__);
|
||||
new_vgroup_name.copy_utf8_truncated(dst->name);
|
||||
BLI_addtail(&orig_grease_pencil.vertex_group_names, dst);
|
||||
}
|
||||
|
||||
/* Get the original material pointers from the result geometry. */
|
||||
VectorSet<Material *> original_materials;
|
||||
const Span<Material *> eval_materials = Span{eval_grease_pencil.material_array,
|
||||
|
||||
@@ -1663,6 +1663,26 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
|
||||
domain_to_range,
|
||||
dst_attribute_writers);
|
||||
}
|
||||
static void copy_vertex_group_name(ListBase *dst_deform_group,
|
||||
const OrderedAttributes &ordered_attributes,
|
||||
const bDeformGroup &src_deform_group)
|
||||
{
|
||||
const StringRef src_name = src_deform_group.name;
|
||||
const int attribute_index = ordered_attributes.ids.index_of_try(src_name);
|
||||
if (attribute_index == -1) {
|
||||
/* The attribute is not propagated to the result (possibly because the mesh isn't included
|
||||
* in the realized output because of the #VariedDepthOptions input). */
|
||||
return;
|
||||
}
|
||||
const bke::AttributeDomainAndType kind = ordered_attributes.kinds[attribute_index];
|
||||
if (kind.domain != bke::AttrDomain::Point || kind.data_type != bke::AttrType::Float) {
|
||||
/* Skip if the source attribute can't possibly contain vertex weights. */
|
||||
return;
|
||||
}
|
||||
bDeformGroup *dst = MEM_callocN<bDeformGroup>(__func__);
|
||||
src_name.copy_utf8_truncated(dst->name);
|
||||
BLI_addtail(dst_deform_group, dst);
|
||||
}
|
||||
|
||||
static void copy_vertex_group_names(Mesh &dst_mesh,
|
||||
const OrderedAttributes &ordered_attributes,
|
||||
@@ -1674,24 +1694,10 @@ static void copy_vertex_group_names(Mesh &dst_mesh,
|
||||
}
|
||||
for (const Mesh *mesh : src_meshes) {
|
||||
LISTBASE_FOREACH (const bDeformGroup *, src, &mesh->vertex_group_names) {
|
||||
const StringRef src_name = src->name;
|
||||
const int attribute_index = ordered_attributes.ids.index_of_try(src_name);
|
||||
if (attribute_index == -1) {
|
||||
/* The attribute is not propagated to the result (possibly because the mesh isn't included
|
||||
* in the realized output because of the #VariedDepthOptions input). */
|
||||
if (existing_names.contains(src->name)) {
|
||||
continue;
|
||||
}
|
||||
const bke::AttributeDomainAndType kind = ordered_attributes.kinds[attribute_index];
|
||||
if (kind.domain != bke::AttrDomain::Point || kind.data_type != bke::AttrType::Float) {
|
||||
/* Prefer using the highest priority domain and type from all input meshes. */
|
||||
continue;
|
||||
}
|
||||
if (existing_names.contains(src_name)) {
|
||||
continue;
|
||||
}
|
||||
bDeformGroup *dst = MEM_callocN<bDeformGroup>(__func__);
|
||||
src_name.copy_utf8_truncated(dst->name);
|
||||
BLI_addtail(&dst_mesh.vertex_group_names, dst);
|
||||
copy_vertex_group_name(&dst_mesh.vertex_group_names, ordered_attributes, *src);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2060,6 +2066,25 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
|
||||
dst_attribute_writers);
|
||||
}
|
||||
|
||||
static void copy_vertex_group_names(CurvesGeometry &dst_curve,
|
||||
const OrderedAttributes &ordered_attributes,
|
||||
const Span<const Curves *> src_curves)
|
||||
{
|
||||
Set<StringRef> existing_names;
|
||||
LISTBASE_FOREACH (const bDeformGroup *, defgroup, &dst_curve.vertex_group_names) {
|
||||
existing_names.add(defgroup->name);
|
||||
}
|
||||
for (const Curves *src_curve : src_curves) {
|
||||
LISTBASE_FOREACH (const bDeformGroup *, src, &src_curve->geometry.vertex_group_names) {
|
||||
if (existing_names.contains(src->name)) {
|
||||
continue;
|
||||
}
|
||||
copy_vertex_group_name(&dst_curve.vertex_group_names, ordered_attributes, *src);
|
||||
existing_names.add(src->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
|
||||
const AllCurvesInfo &all_curves_info,
|
||||
const Span<RealizeCurveTask> tasks,
|
||||
@@ -2105,6 +2130,8 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
|
||||
const Curves &first_curves_id = *first_task.curve_info->curves;
|
||||
bke::curves_copy_parameters(first_curves_id, *dst_curves_id);
|
||||
|
||||
copy_vertex_group_names(dst_curves, ordered_attributes, all_curves_info.order);
|
||||
|
||||
/* Prepare id attribute. */
|
||||
SpanAttributeWriter<int> point_ids;
|
||||
if (all_curves_info.create_id_attribute) {
|
||||
|
||||
Reference in New Issue
Block a user