From 84c7684871d7f9b8eb607d93fc44bae170f06e91 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 11 Dec 2024 01:17:23 +0100 Subject: [PATCH] Geometry Nodes: Propagate vertex groups in join / realize instances nodes Currently the realize instances code (which is also used by the join geometry node) always creates generic attributes instead of vertex groups. The expectation was that vertex groups would be replaced by some form of generic attribute sooner rather than later. However, it's clear that won't happen for some time, and this issue causes users a lot of trouble. This commit preserves the vertex groups through the operation. Any attribute name that was a vertex group on any of the input meshes will become a vertex group in the result. In the code this is a simple change because the attribute writer abstraction allows writing to vertex groups as if the were just like other contiguous arrays. In the future we could optimize the code specifically for vertex groups. This resolves the "bug" part of #99197 where the nodes remove vertex groups. However, this doesn't change the fact that generating primitive meshes in geometry nodes won't create vertex groups. In general the property editor settings on the original mesh have no effect on meshes created from scratch in geometry nodes. Pull Request: https://projects.blender.org/blender/blender/pulls/131692 --- .../geometry/intern/realize_instances.cc | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 4b90199a00d..3ceb3df1b78 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -1526,6 +1526,25 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, dst_attribute_writers); } +static void copy_vertex_group_names(Mesh &dst_mesh, const Span src_meshes) +{ + Set existing_names; + LISTBASE_FOREACH (const bDeformGroup *, defgroup, &dst_mesh.vertex_group_names) { + existing_names.add(defgroup->name); + } + for (const Mesh *mesh : src_meshes) { + LISTBASE_FOREACH (const bDeformGroup *, src, &mesh->vertex_group_names) { + const StringRef src_name = src->name; + if (existing_names.contains(src_name)) { + continue; + } + bDeformGroup *dst = MEM_cnew(__func__); + src_name.copy(dst->name); + BLI_addtail(&dst_mesh.vertex_group_names, dst); + } + } +} + static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, const AllMeshesInfo &all_meshes_info, const Span tasks, @@ -1570,9 +1589,11 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, const RealizeMeshTask &first_task = tasks.first(); const Mesh &first_mesh = *first_task.mesh_info->mesh; BKE_mesh_copy_parameters_for_eval(dst_mesh, &first_mesh); - /* The above line also copies vertex group names. We don't want that here because the new - * attributes are added explicitly below. */ - BLI_freelistN(&dst_mesh->vertex_group_names); + + BLI_assert(BLI_listbase_count(&dst_mesh->vertex_group_names) == + BLI_listbase_count(&first_mesh.vertex_group_names)); + copy_vertex_group_names(*dst_mesh, all_meshes_info.order.as_span().drop_front(1)); + dst_mesh->vertex_group_active_index = first_mesh.vertex_group_active_index; /* Add materials. */ for (const int i : IndexRange(ordered_materials.size())) {