diff --git a/source/blender/blenkernel/BKE_grease_pencil.hh b/source/blender/blenkernel/BKE_grease_pencil.hh index cc2acab50fc..091f667f769 100644 --- a/source/blender/blenkernel/BKE_grease_pencil.hh +++ b/source/blender/blenkernel/BKE_grease_pencil.hh @@ -1111,6 +1111,10 @@ void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil * \note Used for "move only origins" in object_data_transform.cc. */ int BKE_grease_pencil_stroke_point_count(const GreasePencil &grease_pencil); +/** + * \note Used for "move only origins" in object_data_transform.cc. + */ +bool BKE_grease_pencil_has_curve_with_type(const GreasePencil &grease_pencil, CurveType type); /** * \note Used for "move only origins" in object_data_transform.cc. */ diff --git a/source/blender/blenkernel/intern/grease_pencil.cc b/source/blender/blenkernel/intern/grease_pencil.cc index 2851ca0a201..56206881c03 100644 --- a/source/blender/blenkernel/intern/grease_pencil.cc +++ b/source/blender/blenkernel/intern/grease_pencil.cc @@ -2393,6 +2393,25 @@ void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil * \note Used for "move only origins" in object_data_transform.cc. * \{ */ +bool BKE_grease_pencil_has_curve_with_type(const GreasePencil &grease_pencil, const CurveType type) +{ + using namespace blender; + + for (const GreasePencilDrawingBase *base : grease_pencil.drawings()) { + if (base->type != GP_DRAWING) { + continue; + } + const bke::greasepencil::Drawing &drawing = + reinterpret_cast(base)->wrap(); + const bke::CurvesGeometry &curves = drawing.strokes(); + if (curves.has_curve_with_type(type)) { + return true; + } + } + + return false; +} + int BKE_grease_pencil_stroke_point_count(const GreasePencil &grease_pencil) { using namespace blender; @@ -2440,10 +2459,26 @@ void BKE_grease_pencil_point_coords_get(const GreasePencil &grease_pencil, const Span positions = curves.positions(); const VArray radii = drawing.radii(); - for (const int i : curves.points_range()) { - all_positions[index] = math::transform_point(layer_to_object, positions[i]); - all_radii[index] = radii[i]; - index++; + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { + for (const int i : curves.points_range()) { + all_positions[index] = math::transform_point(layer_to_object, positions[i]); + all_radii[index] = radii[i]; + index++; + } + } + else { + const Span handle_positions_left = curves.handle_positions_left(); + const Span handle_positions_right = curves.handle_positions_right(); + for (const int i : curves.points_range()) { + const int index_pos = index * 3; + all_positions[index_pos] = math::transform_point(layer_to_object, + handle_positions_left[i]); + all_positions[index_pos + 1] = math::transform_point(layer_to_object, positions[i]); + all_positions[index_pos + 2] = math::transform_point(layer_to_object, + handle_positions_right[i]); + all_radii[index] = radii[i]; + index++; + } } }); } @@ -2471,10 +2506,26 @@ void BKE_grease_pencil_point_coords_apply(GreasePencil &grease_pencil, MutableSpan positions = curves.positions_for_write(); MutableSpan radii = drawing.radii_for_write(); - for (const int i : curves.points_range()) { - positions[i] = math::transform_point(object_to_layer, all_positions[index]); - radii[i] = all_radii[index]; - index++; + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { + for (const int i : curves.points_range()) { + positions[i] = math::transform_point(object_to_layer, all_positions[index]); + radii[i] = all_radii[index]; + index++; + } + } + else { + MutableSpan handle_positions_left = curves.handle_positions_left_for_write(); + MutableSpan handle_positions_right = curves.handle_positions_right_for_write(); + for (const int i : curves.points_range()) { + const int index_pos = index * 3; + handle_positions_left[i] = math::transform_point(object_to_layer, + all_positions[index_pos]); + positions[i] = math::transform_point(object_to_layer, all_positions[index_pos + 1]); + handle_positions_right[i] = math::transform_point(object_to_layer, + all_positions[index_pos + 2]); + radii[i] = all_radii[index]; + index++; + } } curves.tag_radii_changed(); @@ -2507,10 +2558,27 @@ void BKE_grease_pencil_point_coords_apply_with_mat4(GreasePencil &grease_pencil, MutableSpan positions = curves.positions_for_write(); MutableSpan radii = drawing.radii_for_write(); - for (const int i : curves.points_range()) { - positions[i] = math::transform_point(object_to_layer * mat, all_positions[index]); - radii[i] = all_radii[index] * scalef; - index++; + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { + for (const int i : curves.points_range()) { + positions[i] = math::transform_point(object_to_layer * mat, all_positions[index]); + radii[i] = all_radii[index] * scalef; + index++; + } + } + else { + MutableSpan handle_positions_left = curves.handle_positions_left_for_write(); + MutableSpan handle_positions_right = curves.handle_positions_right_for_write(); + for (const int i : curves.points_range()) { + const int index_pos = index * 3; + handle_positions_left[i] = math::transform_point(object_to_layer * mat, + all_positions[index_pos]); + positions[i] = math::transform_point(object_to_layer * mat, + all_positions[index_pos + 1]); + handle_positions_right[i] = math::transform_point(object_to_layer * mat, + all_positions[index_pos + 2]); + radii[i] = all_radii[index] * scalef; + index++; + } } curves.tag_radii_changed(); diff --git a/source/blender/editors/object/object_data_transform.cc b/source/blender/editors/object/object_data_transform.cc index ade3cb05339..0dee7366c33 100644 --- a/source/blender/editors/object/object_data_transform.cc +++ b/source/blender/editors/object/object_data_transform.cc @@ -31,6 +31,7 @@ #include "BKE_armature.hh" #include "BKE_curve.hh" +#include "BKE_curves_utils.hh" #include "BKE_editmesh.hh" #include "BKE_grease_pencil.hh" #include "BKE_key.hh" @@ -455,7 +456,12 @@ static std::unique_ptr data_xform_create_ex(ID *id, bool is_edi const int elem_array_len = BKE_grease_pencil_stroke_point_count(*grease_pencil); auto xod = std::make_unique(); xod->id = id; - xod->positions.reinitialize(elem_array_len); + if (!BKE_grease_pencil_has_curve_with_type(*grease_pencil, CURVE_TYPE_BEZIER)) { + xod->positions.reinitialize(elem_array_len); + } + else { + xod->positions.reinitialize(elem_array_len * 3); + } xod->radii.reinitialize(elem_array_len); BKE_grease_pencil_point_coords_get(*grease_pencil, xod->positions, xod->radii); return xod; @@ -463,9 +469,17 @@ static std::unique_ptr data_xform_create_ex(ID *id, bool is_edi case ID_CV: { Curves *curves_id = reinterpret_cast(id); const bke::CurvesGeometry &curves = curves_id->geometry.wrap(); - auto xod = std::make_unique(); + auto xod = std::make_unique(); xod->id = id; - xod->positions = curves.positions(); + + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { + xod->positions = curves.positions(); + } + else { + xod->positions = bke::curves::bezier::retrieve_all_positions(curves, + curves.curves_range()); + } + xod->radii.reinitialize(curves.points_num()); curves.radius().materialize(xod->radii); return xod; @@ -626,7 +640,15 @@ void data_xform_by_mat4(XFormObjectData &xod_base, const float4x4 &transform) Curves *curves_id = reinterpret_cast(xod_base.id); bke::CurvesGeometry &curves = curves_id->geometry.wrap(); const auto &xod = reinterpret_cast(xod_base); - copy_transformed_positions(xod.positions, transform, curves.positions_for_write()); + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { + copy_transformed_positions(xod.positions, transform, curves.positions_for_write()); + } + else { + Array transformed_positions(xod.positions.size()); + copy_transformed_positions(xod.positions, transform, transformed_positions); + bke::curves::bezier::write_all_positions( + curves, curves.curves_range(), transformed_positions); + } copy_transformed_radii(xod.radii, transform, curves.radius_for_write()); break; } @@ -741,7 +763,12 @@ void data_xform_restore(XFormObjectData &xod_base) Curves *curves_id = reinterpret_cast(xod_base.id); bke::CurvesGeometry &curves = curves_id->geometry.wrap(); const auto &xod = reinterpret_cast(xod_base); - curves.positions_for_write().copy_from(xod.positions); + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { + curves.positions_for_write().copy_from(xod.positions); + } + else { + bke::curves::bezier::write_all_positions(curves, curves.curves_range(), xod.positions); + } curves.radius_for_write().copy_from(xod.radii); break; }