diff --git a/source/blender/blenkernel/BKE_grease_pencil.hh b/source/blender/blenkernel/BKE_grease_pencil.hh index 549e1276465..2322df93546 100644 --- a/source/blender/blenkernel/BKE_grease_pencil.hh +++ b/source/blender/blenkernel/BKE_grease_pencil.hh @@ -706,6 +706,7 @@ TREENODE_COMMON_METHODS_FORWARD_IMPL(LayerGroup); namespace convert { void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, + const ListBase &vertex_group_names, GreasePencilDrawing &r_drawing); void legacy_gpencil_to_grease_pencil(Main &main, GreasePencil &grease_pencil, bGPdata &gpd); diff --git a/source/blender/blenkernel/intern/grease_pencil_convert_legacy.cc b/source/blender/blenkernel/intern/grease_pencil_convert_legacy.cc index 88d65c8ccc2..6749724faee 100644 --- a/source/blender/blenkernel/intern/grease_pencil_convert_legacy.cc +++ b/source/blender/blenkernel/intern/grease_pencil_convert_legacy.cc @@ -8,6 +8,7 @@ #include "BKE_attribute.hh" #include "BKE_curves.hh" +#include "BKE_deform.hh" #include "BKE_grease_pencil.hh" #include "BKE_material.h" @@ -19,10 +20,52 @@ #include "DNA_gpencil_legacy_types.h" #include "DNA_grease_pencil_types.h" +#include "DNA_meshdata_types.h" namespace blender::bke::greasepencil::convert { +/** + * Find vertex groups that have assigned vertices in this drawing. + * Returns: + * - ListBase with used vertex group names (bDeformGroup) + * - Array of indices in the new vertex group list for remapping + */ +static void find_used_vertex_groups(const bGPDframe &gpf, + const ListBase &all_names, + ListBase &r_vertex_group_names, + Array &r_indices) +{ + const int num_vertex_groups = BLI_listbase_count(&all_names); + Array is_group_used(num_vertex_groups, false); + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf.strokes) { + if (!gps->dvert) { + continue; + } + Span dverts = {gps->dvert, gps->totpoints}; + for (const MDeformVert &dvert : dverts) { + for (const MDeformWeight &weight : Span{dvert.dw, dvert.totweight}) { + is_group_used[weight.def_nr] = true; + } + } + } + BLI_listbase_clear(&r_vertex_group_names); + r_indices.reinitialize(num_vertex_groups); + int new_group_i = 0; + int old_group_i; + LISTBASE_FOREACH_INDEX (const bDeformGroup *, def_group, &all_names, old_group_i) { + if (!is_group_used[old_group_i]) { + r_indices[old_group_i] = -1; + continue; + } + r_indices[old_group_i] = new_group_i++; + + bDeformGroup *def_group_copy = static_cast(MEM_dupallocN(def_group)); + BLI_addtail(&r_vertex_group_names, def_group_copy); + } +} + void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, + const ListBase &vertex_group_names, GreasePencilDrawing &r_drawing) { /* Construct an empty CurvesGeometry in-place. */ @@ -54,6 +97,25 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, /* All strokes are poly curves. */ curves.fill_curve_types(CURVE_TYPE_POLY); + /* Find used vertex groups in this drawing. */ + ListBase stroke_vertex_group_names; + Array stroke_def_nr_map; + find_used_vertex_groups(gpf, vertex_group_names, stroke_vertex_group_names, stroke_def_nr_map); + BLI_assert(BLI_listbase_is_empty(&curves.vertex_group_names)); + curves.vertex_group_names = stroke_vertex_group_names; + const bool use_dverts = !BLI_listbase_is_empty(&curves.vertex_group_names); + + /* Copy vertex weights and map the vertex group indices. */ + auto copy_dvert = [&](const MDeformVert &src_dvert, MDeformVert &dst_dvert) { + dst_dvert = src_dvert; + dst_dvert.dw = static_cast(MEM_dupallocN(src_dvert.dw)); + const MutableSpan vertex_weights = {dst_dvert.dw, dst_dvert.totweight}; + for (MDeformWeight &weight : vertex_weights) { + /* Map def_nr to the reduced vertex group list. */ + weight.def_nr = stroke_def_nr_map[weight.def_nr]; + } + }; + /* Point Attributes. */ MutableSpan positions = curves.positions_for_write(); MutableSpan radii = drawing.radii_for_write(); @@ -66,6 +128,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, attributes.lookup_or_add_for_write_span("vertex_color", AttrDomain::Point); SpanAttributeWriter selection = attributes.lookup_or_add_for_write_span( ".selection", AttrDomain::Point); + MutableSpan dverts = use_dverts ? curves.wrap().deform_verts_for_write() : + MutableSpan(); /* Curve Attributes. */ SpanAttributeWriter stroke_cyclic = attributes.lookup_or_add_for_write_span( @@ -126,6 +190,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, MutableSpan stroke_vertex_colors = vertex_colors.span.slice( stroke_points_range); MutableSpan stroke_selections = selection.span.slice(stroke_points_range); + MutableSpan stroke_dverts = use_dverts ? dverts.slice(stroke_points_range) : + MutableSpan(); /* Do first point. */ const bGPDspoint &first_pt = stroke_points.first(); @@ -143,6 +209,9 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, stroke_rotations.first() = first_pt.uv_rot; stroke_vertex_colors.first() = ColorGeometry4f(first_pt.vert_color); stroke_selections.first() = (first_pt.flag & GP_SPOINT_SELECT) != 0; + if (use_dverts && gps->dvert) { + copy_dvert(gps->dvert[0], stroke_dverts.first()); + } /* Do the rest of the points. */ for (const int i : stroke_points.index_range().drop_back(1)) { @@ -156,6 +225,9 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, stroke_rotations[point_i] = pt.uv_rot; stroke_vertex_colors[point_i] = ColorGeometry4f(pt.vert_color); stroke_selections[point_i] = (pt.flag & GP_SPOINT_SELECT) != 0; + if (use_dverts && gps->dvert) { + copy_dvert(gps->dvert[point_i], stroke_dverts[point_i]); + } } } @@ -225,7 +297,7 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b grease_pencil.drawing_array[i]); /* Convert the frame to a drawing. */ - legacy_gpencil_frame_to_grease_pencil_drawing(*gpf, drawing); + legacy_gpencil_frame_to_grease_pencil_drawing(*gpf, gpd.vertex_group_names, drawing); /* Add the frame to the layer. */ if (GreasePencilFrame *new_frame = new_layer.add_frame(gpf->framenum, i)) { @@ -242,6 +314,10 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b /* TODO: Update drawing user counts. */ } + /* Copy vertex group names and settings. */ + BKE_defgroup_copy_list(&grease_pencil.vertex_group_names, &gpd.vertex_group_names); + grease_pencil.vertex_group_active_index = gpd.vertex_group_active_index; + /* Convert the onion skinning settings. */ grease_pencil.onion_skinning_settings.opacity = gpd.onion_factor; grease_pencil.onion_skinning_settings.mode = gpd.onion_mode;