Fix #138636: "Affect only origins" fails for bezier handles
... for Grease Pencil & Curves
Was only moving the points relative to the origin (so only they stayed
in place, handles were still transformed along with the origin).
In order to fix this this, we now take into account curves handles in
the whole `XFormObjectData` related code (for both Grease Pencil &
Curves). There was a handly existing pair of functions
[`curves::bezier::retrieve_all_positions` &
`curves::bezier::write_all_positions`] which we can use for Curves, for
Grease Pencil this uses code from those functions (but not the functions
directly -- indices would fail there because Grease Pencil would call
this from multiple layers).
This also introduces `BKE_grease_pencil_has_curve_with_type` so we can
know in advance how many elements we need for the
`XFormObjectData_GreasePencil`.
Also corrects a typo in c1c67c918e (swapping `XFormObjectData_Curves`
with `XFormObjectData_GreasePencil`)
Pull Request: https://projects.blender.org/blender/blender/pulls/138665
This commit is contained in:
committed by
Philipp Oeser
parent
01698188e9
commit
82e557eb21
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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<const GreasePencilDrawing *>(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<float3> positions = curves.positions();
|
||||
const VArray<float> 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<float3> handle_positions_left = curves.handle_positions_left();
|
||||
const Span<float3> 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<float3> positions = curves.positions_for_write();
|
||||
MutableSpan<float> 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<float3> handle_positions_left = curves.handle_positions_left_for_write();
|
||||
MutableSpan<float3> 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<float3> positions = curves.positions_for_write();
|
||||
MutableSpan<float> 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<float3> handle_positions_left = curves.handle_positions_left_for_write();
|
||||
MutableSpan<float3> 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();
|
||||
|
||||
@@ -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<XFormObjectData> 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<XFormObjectData_GreasePencil>();
|
||||
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<XFormObjectData> data_xform_create_ex(ID *id, bool is_edi
|
||||
case ID_CV: {
|
||||
Curves *curves_id = reinterpret_cast<Curves *>(id);
|
||||
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
auto xod = std::make_unique<XFormObjectData_GreasePencil>();
|
||||
auto xod = std::make_unique<XFormObjectData_Curves>();
|
||||
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<Curves *>(xod_base.id);
|
||||
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
const auto &xod = reinterpret_cast<const XFormObjectData_Curves &>(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<float3> 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<Curves *>(xod_base.id);
|
||||
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
const auto &xod = reinterpret_cast<const XFormObjectData_Curves &>(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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user