Cleanup: Refactor spline copying functions

Make the virtual functions protected and simpler, so that the logic is
better contained in the base class's implementation. Also introduce a
`copy_without_attributes` method to be used for realizing instances.
This commit is contained in:
Hans Goudey 2021-06-22 11:32:50 -05:00
parent 026de343e3
commit f3eecfe386
Notes: blender-bot 2023-02-14 05:50:03 +01:00
Referenced by issue #89430, Instanced curves arent realised after point instance
Referenced by issue #89344, Join curve attributes when realizing instances
7 changed files with 104 additions and 40 deletions

View File

@ -105,9 +105,9 @@ class Spline {
copy_base_settings(other, *this);
}
virtual SplinePtr copy() const = 0;
/** Return a new spline with the same type and settings like "cyclic", but without any data. */
virtual SplinePtr copy_settings() const = 0;
SplinePtr copy() const;
SplinePtr copy_only_settings() const;
SplinePtr copy_without_attributes() const;
Spline::Type type() const;
@ -206,12 +206,10 @@ class Spline {
protected:
virtual void correct_end_tangents() const = 0;
/** Copy settings stored in the base spline class. */
static void copy_base_settings(const Spline &src, Spline &dst)
{
dst.normal_mode = src.normal_mode;
dst.is_cyclic_ = src.is_cyclic_;
}
virtual void copy_settings(Spline &dst) const = 0;
virtual void copy_data(Spline &dst) const = 0;
static void copy_base_settings(const Spline &src, Spline &dst);
};
/**
@ -264,8 +262,6 @@ class BezierSpline final : public Spline {
mutable bool mapping_cache_dirty_ = true;
public:
virtual SplinePtr copy() const final;
SplinePtr copy_settings() const final;
BezierSpline() : Spline(Type::Bezier)
{
}
@ -340,8 +336,11 @@ class BezierSpline final : public Spline {
bool segment_is_vector(const int start_index) const;
private:
void ensure_auto_handles() const;
void correct_end_tangents() const final;
void copy_settings(Spline &dst) const final;
void copy_data(Spline &dst) const final;
void ensure_auto_handles() const;
};
/**
@ -406,8 +405,6 @@ class NURBSpline final : public Spline {
mutable bool position_cache_dirty_ = true;
public:
SplinePtr copy() const final;
SplinePtr copy_settings() const final;
NURBSpline() : Spline(Type::NURBS)
{
}
@ -458,6 +455,9 @@ class NURBSpline final : public Spline {
protected:
void correct_end_tangents() const final;
void copy_settings(Spline &dst) const final;
void copy_data(Spline &dst) const final;
void calculate_knots() const;
blender::Span<BasisCache> calculate_basis_cache() const;
};
@ -473,8 +473,6 @@ class PolySpline final : public Spline {
blender::Vector<float> tilts_;
public:
SplinePtr copy() const final;
SplinePtr copy_settings() const final;
PolySpline() : Spline(Type::Poly)
{
}
@ -507,6 +505,8 @@ class PolySpline final : public Spline {
protected:
void correct_end_tangents() const final;
void copy_settings(Spline &dst) const final;
void copy_data(Spline &dst) const final;
};
/**

View File

@ -40,6 +40,60 @@ Spline::Type Spline::type() const
return type_;
}
void Spline::copy_base_settings(const Spline &src, Spline &dst)
{
dst.normal_mode = src.normal_mode;
dst.is_cyclic_ = src.is_cyclic_;
}
static SplinePtr create_spline(const Spline::Type type)
{
switch (type) {
case Spline::Type::Poly:
return std::make_unique<PolySpline>();
case Spline::Type::Bezier:
return std::make_unique<BezierSpline>();
case Spline::Type::NURBS:
return std::make_unique<NURBSpline>();
}
BLI_assert_unreachable();
return {};
}
/**
* Return a new spline with the same data, settings, and attributes.
*/
SplinePtr Spline::copy() const
{
SplinePtr dst = this->copy_without_attributes();
dst->attributes = this->attributes;
return dst;
}
/**
* Return a new spline with the same type and settings like "cyclic", but without any data.
*/
SplinePtr Spline::copy_only_settings() const
{
SplinePtr dst = create_spline(type_);
this->copy_base_settings(*this, *dst);
this->copy_settings(*dst);
return dst;
}
/**
* The same as #copy, but skips copying dynamic attributes to the new spline.
*/
SplinePtr Spline::copy_without_attributes() const
{
SplinePtr dst = this->copy_only_settings();
this->copy_data(*dst);
/* Though the attributes storage is empty, it still needs to know the correct size. */
dst->attributes.reallocate(dst->size());
return dst;
}
void Spline::translate(const blender::float3 &translation)
{
for (float3 &position : this->positions()) {

View File

@ -29,17 +29,22 @@ using blender::fn::GVArray;
using blender::fn::GVArray_For_ArrayContainer;
using blender::fn::GVArrayPtr;
SplinePtr BezierSpline::copy() const
void BezierSpline::copy_settings(Spline &dst) const
{
return std::make_unique<BezierSpline>(*this);
BezierSpline &bezier = static_cast<BezierSpline &>(dst);
bezier.resolution_ = resolution_;
}
SplinePtr BezierSpline::copy_settings() const
void BezierSpline::copy_data(Spline &dst) const
{
std::unique_ptr<BezierSpline> copy = std::make_unique<BezierSpline>();
copy_base_settings(*this, *copy);
copy->resolution_ = resolution_;
return copy;
BezierSpline &bezier = static_cast<BezierSpline &>(dst);
bezier.positions_ = positions_;
bezier.handle_types_left_ = handle_types_left_;
bezier.handle_positions_left_ = handle_positions_left_;
bezier.handle_types_right_ = handle_types_right_;
bezier.handle_positions_right_ = handle_positions_right_;
bezier.radii_ = radii_;
bezier.tilts_ = tilts_;
}
int BezierSpline::size() const

View File

@ -31,19 +31,23 @@ using blender::fn::GVArray_For_ArrayContainer;
using blender::fn::GVArray_Typed;
using blender::fn::GVArrayPtr;
SplinePtr NURBSpline::copy() const
void NURBSpline::copy_settings(Spline &dst) const
{
return std::make_unique<NURBSpline>(*this);
NURBSpline &nurbs = static_cast<NURBSpline &>(dst);
nurbs.knots_mode = knots_mode;
nurbs.resolution_ = resolution_;
nurbs.order_ = order_;
}
SplinePtr NURBSpline::copy_settings() const
void NURBSpline::copy_data(Spline &dst) const
{
std::unique_ptr<NURBSpline> copy = std::make_unique<NURBSpline>();
copy_base_settings(*this, *copy);
copy->knots_mode = knots_mode;
copy->resolution_ = resolution_;
copy->order_ = order_;
return copy;
NURBSpline &nurbs = static_cast<NURBSpline &>(dst);
nurbs.positions_ = positions_;
nurbs.weights_ = weights_;
nurbs.knots_ = knots_;
nurbs.knots_dirty_ = false;
nurbs.radii_ = radii_;
nurbs.tilts_ = tilts_;
}
int NURBSpline::size() const

View File

@ -25,16 +25,17 @@ using blender::Span;
using blender::fn::GVArray;
using blender::fn::GVArrayPtr;
SplinePtr PolySpline::copy() const
void PolySpline::copy_settings(Spline &UNUSED(dst)) const
{
return std::make_unique<PolySpline>(*this);
/* Poly splines have no settings not covered by the base class. */
}
SplinePtr PolySpline::copy_settings() const
void PolySpline::copy_data(Spline &dst) const
{
std::unique_ptr<PolySpline> copy = std::make_unique<PolySpline>();
copy_base_settings(*this, *copy);
return copy;
PolySpline &poly = static_cast<PolySpline &>(dst);
poly.positions_ = positions_;
poly.radii_ = radii_;
poly.tilts_ = tilts_;
}
int PolySpline::size() const

View File

@ -329,7 +329,7 @@ static SplinePtr subdivide_spline(const Spline &spline,
* point facilitates subdividing in parallel later. */
Array<int> offsets = get_subdivided_offsets(spline, cuts, spline_offset);
const int result_size = offsets.last() + int(!spline.is_cyclic());
SplinePtr new_spline = spline.copy_settings();
SplinePtr new_spline = spline.copy_only_settings();
new_spline->resize(result_size);
subdivide_builtin_attributes(spline, offsets, *new_spline);
subdivide_dynamic_attributes(spline, offsets, *new_spline);

View File

@ -120,7 +120,7 @@ static void copy_dynamic_attributes(const CustomDataAttributes &src,
static SplinePtr spline_delete(const Spline &spline, const IndexMask mask)
{
SplinePtr new_spline = spline.copy_settings();
SplinePtr new_spline = spline.copy_only_settings();
new_spline->resize(mask.size());
spline_copy_builtin_attributes(spline, *new_spline, mask);