diff options
Diffstat (limited to 'source/blender')
22 files changed, 596 insertions, 79 deletions
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index 646af6f8f98..439f20ee471 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -51,12 +51,6 @@ using SplinePtr = std::unique_ptr<Spline>; */ class Spline { public: - enum class Type { - Bezier, - NURBS, - Poly, - }; - enum NormalCalculationMode { ZUp, Minimum, @@ -67,7 +61,7 @@ class Spline { blender::bke::CustomDataAttributes attributes; protected: - Type type_; + CurveType type_; bool is_cyclic_ = false; /** Direction of the spline at each evaluated point. */ @@ -87,7 +81,7 @@ class Spline { public: virtual ~Spline() = default; - Spline(const Type type) : type_(type) + Spline(const CurveType type) : type_(type) { } Spline(Spline &other) : attributes(other.attributes), type_(other.type_) @@ -109,7 +103,7 @@ class Spline { SplinePtr copy_without_attributes() const; static void copy_base_settings(const Spline &src, Spline &dst); - Spline::Type type() const; + CurveType type() const; /** Return the number of control points. */ virtual int size() const = 0; @@ -285,7 +279,7 @@ class BezierSpline final : public Spline { mutable bool mapping_cache_dirty_ = true; public: - BezierSpline() : Spline(Type::Bezier) + BezierSpline() : Spline(CURVE_TYPE_BEZIER) { } BezierSpline(const BezierSpline &other) @@ -508,7 +502,7 @@ class NURBSpline final : public Spline { mutable bool position_cache_dirty_ = true; public: - NURBSpline() : Spline(Type::NURBS) + NURBSpline() : Spline(CURVE_TYPE_NURBS) { } NURBSpline(const NURBSpline &other) @@ -575,7 +569,7 @@ class PolySpline final : public Spline { blender::Vector<float> tilts_; public: - PolySpline() : Spline(Type::Poly) + PolySpline() : Spline(CURVE_TYPE_POLY) { } PolySpline(const PolySpline &other) @@ -647,7 +641,7 @@ struct CurveEval { * \note If you are looping over all of the splines in the same scope anyway, * it's better to avoid calling this function, in case there are many splines. */ - bool has_spline_with_type(const Spline::Type type) const; + bool has_spline_with_type(const CurveType type) const; void resize(int size); /** diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc index 49010caef24..8529e7ad194 100644 --- a/source/blender/blenkernel/intern/curve_eval.cc +++ b/source/blender/blenkernel/intern/curve_eval.cc @@ -36,7 +36,7 @@ blender::MutableSpan<SplinePtr> CurveEval::splines() return splines_; } -bool CurveEval::has_spline_with_type(const Spline::Type type) const +bool CurveEval::has_spline_with_type(const CurveType type) const { for (const SplinePtr &spline : this->splines()) { if (spline->type() == type) { diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index e62733e36ef..5d80ef47908 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -226,7 +226,7 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info, } /* Mark edge loops from sharp vector control points sharp. */ - if (profile.type() == Spline::Type::Bezier) { + if (profile.type() == CURVE_TYPE_BEZIER) { const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(profile); Span<int> control_point_offsets = bezier_spline.control_point_offsets(); for (const int i : IndexRange(bezier_spline.size())) { diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc index fff77dbd367..2004f1c0609 100644 --- a/source/blender/blenkernel/intern/geometry_component_curve.cc +++ b/source/blender/blenkernel/intern/geometry_component_curve.cc @@ -420,15 +420,18 @@ static Array<float3> curve_normal_point_domain(const CurveEval &curve) const Spline &spline = *splines[i]; MutableSpan spline_normals{normals.as_mutable_span().slice(offsets[i], spline.size())}; switch (splines[i]->type()) { - case Spline::Type::Bezier: + case CURVE_TYPE_BEZIER: calculate_bezier_normals(static_cast<const BezierSpline &>(spline), spline_normals); break; - case Spline::Type::Poly: + case CURVE_TYPE_POLY: calculate_poly_normals(static_cast<const PolySpline &>(spline), spline_normals); break; - case Spline::Type::NURBS: + case CURVE_TYPE_NURBS: calculate_nurbs_normals(static_cast<const NURBSpline &>(spline), spline_normals); break; + case CURVE_TYPE_CATMULL_ROM: + BLI_assert_unreachable(); + break; } } }); @@ -447,7 +450,7 @@ VArray<float3> curve_normals_varray(const CurveComponent &component, const Attri /* Use a reference to evaluated normals if possible to avoid an allocation and a copy. * This is only possible when there is only one poly spline. */ - if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) { + if (splines.size() == 1 && splines.first()->type() == CURVE_TYPE_POLY) { const PolySpline &spline = static_cast<PolySpline &>(*splines.first()); return VArray<float3>::ForSpan(spline.evaluated_normals()); } @@ -955,7 +958,7 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> { { const PointIndices indices = lookup_point_indices(offsets_, index); const Spline &spline = *splines_[indices.spline_index]; - if (spline.type() == Spline::Type::Bezier) { + if (spline.type() == CURVE_TYPE_BEZIER) { const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline); return is_right_ ? bezier_spline.handle_positions_right()[indices.point_index] : bezier_spline.handle_positions_left()[indices.point_index]; @@ -967,7 +970,7 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> { { const PointIndices indices = lookup_point_indices(offsets_, index); Spline &spline = *splines_[indices.spline_index]; - if (spline.type() == Spline::Type::Bezier) { + if (spline.type() == CURVE_TYPE_BEZIER) { BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline); if (is_right_) { bezier_spline.set_handle_position_right(indices.point_index, value); @@ -983,7 +986,7 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> { { for (const int spline_index : splines_.index_range()) { Spline &spline = *splines_[spline_index]; - if (spline.type() == Spline::Type::Bezier) { + if (spline.type() == CURVE_TYPE_BEZIER) { const int offset = offsets_[spline_index]; BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline); @@ -1024,7 +1027,7 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> { { Array<Span<float3>> spans(splines.size()); for (const int i : spans.index_range()) { - if (splines[i]->type() == Spline::Type::Bezier) { + if (splines[i]->type() == CURVE_TYPE_BEZIER) { BezierSpline &bezier_spline = static_cast<BezierSpline &>(*splines[i]); spans[i] = is_right ? bezier_spline.handle_positions_right() : bezier_spline.handle_positions_left(); @@ -1214,7 +1217,7 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo /* Use the regular position virtual array when there aren't any Bezier splines * to avoid the overhead of checking the spline type for every point. */ - if (!curve->has_spline_with_type(Spline::Type::Bezier)) { + if (!curve->has_spline_with_type(CURVE_TYPE_BEZIER)) { return BuiltinPointAttributeProvider<float3>::try_get_for_write(component); } @@ -1255,7 +1258,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { return {}; } - if (!curve->has_spline_with_type(Spline::Type::Bezier)) { + if (!curve->has_spline_with_type(CURVE_TYPE_BEZIER)) { return {}; } @@ -1273,7 +1276,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { return {}; } - if (!curve->has_spline_with_type(Spline::Type::Bezier)) { + if (!curve->has_spline_with_type(CURVE_TYPE_BEZIER)) { return {}; } @@ -1304,7 +1307,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { return false; } - return curve->has_spline_with_type(Spline::Type::Bezier) && + return curve->has_spline_with_type(CURVE_TYPE_BEZIER) && component.attribute_domain_size(ATTR_DOMAIN_POINT) != 0; } }; diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc new file mode 100644 index 00000000000..07b71ab5ae7 --- /dev/null +++ b/source/blender/blenkernel/intern/geometry_component_curves.cc @@ -0,0 +1,517 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_task.hh" + +#include "DNA_ID_enums.h" +#include "DNA_curve_types.h" + +#include "BKE_attribute_access.hh" +#include "BKE_attribute_math.hh" +#include "BKE_curve.h" +#include "BKE_curves.hh" +#include "BKE_geometry_set.hh" +#include "BKE_lib_id.h" +#include "BKE_spline.hh" + +#include "attribute_access_intern.hh" + +using blender::fn::GVArray; + +/* -------------------------------------------------------------------- */ +/** \name Geometry Component Implementation + * \{ */ + +CurveComponent::CurveComponent() : GeometryComponent(GEO_COMPONENT_TYPE_CURVE) +{ +} + +CurveComponent::~CurveComponent() +{ + this->clear(); +} + +GeometryComponent *CurveComponent::copy() const +{ + CurveComponent *new_component = new CurveComponent(); + if (curves_ != nullptr) { + new_component->curves_ = BKE_curves_copy_for_eval(curves_, false); + new_component->ownership_ = GeometryOwnershipType::Owned; + } + return new_component; +} + +void CurveComponent::clear() +{ + BLI_assert(this->is_mutable()); + if (curves_ != nullptr) { + if (ownership_ == GeometryOwnershipType::Owned) { + BKE_id_free(nullptr, curves_); + } + if (curve_for_render_ != nullptr) { + /* The curve created by this component should not have any edit mode data. */ + BLI_assert(curve_for_render_->editfont == nullptr && curve_for_render_->editnurb == nullptr); + BKE_id_free(nullptr, curve_for_render_); + curve_for_render_ = nullptr; + } + + curves_ = nullptr; + } +} + +bool CurveComponent::has_curves() const +{ + return curves_ != nullptr; +} + +void CurveComponent::replace(Curves *curves, GeometryOwnershipType ownership) +{ + BLI_assert(this->is_mutable()); + this->clear(); + curves_ = curves; + ownership_ = ownership; +} + +Curves *CurveComponent::release() +{ + BLI_assert(this->is_mutable()); + Curves *curves = curves_; + curves_ = nullptr; + return curves; +} + +const Curves *CurveComponent::get_for_read() const +{ + return curves_; +} + +Curves *CurveComponent::get_for_write() +{ + BLI_assert(this->is_mutable()); + if (ownership_ == GeometryOwnershipType::ReadOnly) { + curves_ = BKE_curves_copy_for_eval(curves_, false); + ownership_ = GeometryOwnershipType::Owned; + } + return curves_; +} + +bool CurveComponent::is_empty() const +{ + return curves_ == nullptr; +} + +bool CurveComponent::owns_direct_data() const +{ + return ownership_ == GeometryOwnershipType::Owned; +} + +void CurveComponent::ensure_owns_direct_data() +{ + BLI_assert(this->is_mutable()); + if (ownership_ != GeometryOwnershipType::Owned) { + curves_ = BKE_curves_copy_for_eval(curves_, false); + ownership_ = GeometryOwnershipType::Owned; + } +} + +const Curve *CurveComponent::get_curve_for_render() const +{ + if (curves_ == nullptr) { + return nullptr; + } + if (curve_for_render_ != nullptr) { + return curve_for_render_; + } + std::lock_guard lock{curve_for_render_mutex_}; + if (curve_for_render_ != nullptr) { + return curve_for_render_; + } + + curve_for_render_ = (Curve *)BKE_id_new_nomain(ID_CU_LEGACY, nullptr); + curve_for_render_->curve_eval = curves_to_curve_eval(*curves_).release(); + + return curve_for_render_; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Curve Normals Access + * \{ */ + +namespace blender::bke { + +static void calculate_bezier_normals(const BezierSpline &spline, MutableSpan<float3> normals) +{ + Span<int> offsets = spline.control_point_offsets(); + Span<float3> evaluated_normals = spline.evaluated_normals(); + for (const int i : IndexRange(spline.size())) { + normals[i] = evaluated_normals[offsets[i]]; + } +} + +static void calculate_poly_normals(const PolySpline &spline, MutableSpan<float3> normals) +{ + normals.copy_from(spline.evaluated_normals()); +} + +/** + * Because NURBS control points are not necessarily on the path, the normal at the control points + * is not well defined, so create a temporary poly spline to find the normals. This requires extra + * copying currently, but may be more efficient in the future if attributes have some form of CoW. + */ +static void calculate_nurbs_normals(const NURBSpline &spline, MutableSpan<float3> normals) +{ + PolySpline poly_spline; + poly_spline.resize(spline.size()); + poly_spline.positions().copy_from(spline.positions()); + poly_spline.tilts().copy_from(spline.tilts()); + normals.copy_from(poly_spline.evaluated_normals()); +} + +static Array<float3> curve_normal_point_domain(const CurveEval &curve) +{ + Span<SplinePtr> splines = curve.splines(); + Array<int> offsets = curve.control_point_offsets(); + const int total_size = offsets.last(); + Array<float3> normals(total_size); + + threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { + for (const int i : range) { + const Spline &spline = *splines[i]; + MutableSpan spline_normals{normals.as_mutable_span().slice(offsets[i], spline.size())}; + switch (splines[i]->type()) { + case CURVE_TYPE_BEZIER: + calculate_bezier_normals(static_cast<const BezierSpline &>(spline), spline_normals); + break; + case CURVE_TYPE_POLY: + calculate_poly_normals(static_cast<const PolySpline &>(spline), spline_normals); + break; + case CURVE_TYPE_NURBS: + calculate_nurbs_normals(static_cast<const NURBSpline &>(spline), spline_normals); + break; + } + } + }); + return normals; +} + +VArray<float3> curve_normals_varray(const CurveComponent &component, const AttributeDomain domain) +{ + if (component.is_empty()) { + return nullptr; + } + const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read()); + + if (domain == ATTR_DOMAIN_POINT) { + Array<float3> normals = curve_normal_point_domain(*curve); + return VArray<float3>::ForContainer(std::move(normals)); + } + + if (domain == ATTR_DOMAIN_CURVE) { + Array<float3> point_normals = curve_normal_point_domain(*curve); + VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals)); + return component.attribute_try_adapt_domain<float3>( + std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE); + } + + return nullptr; +} + +} // namespace blender::bke + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Attribute Access Helper Functions + * \{ */ + +int CurveComponent::attribute_domain_size(const AttributeDomain domain) const +{ + if (curves_ == nullptr) { + return 0; + } + const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap( + curves_->geometry); + if (domain == ATTR_DOMAIN_POINT) { + return geometry.points_size(); + } + if (domain == ATTR_DOMAIN_CURVE) { + return geometry.curves_size(); + } + return 0; +} + +GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const +{ + return blender::bke::CurvesGeometry::wrap(curves_->geometry) + .adapt_domain(varray, from_domain, to_domain); +} + +static Curves *get_curves_from_component_for_write(GeometryComponent &component) +{ + BLI_assert(component.type() == GEO_COMPONENT_TYPE_CURVE); + CurveComponent &curve_component = static_cast<CurveComponent &>(component); + return curve_component.get_for_write(); +} + +static const Curves *get_curves_from_component_for_read(const GeometryComponent &component) +{ + BLI_assert(component.type() == GEO_COMPONENT_TYPE_CURVE); + const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); + return curve_component.get_for_read(); +} + +static void tag_component_topology_changed(GeometryComponent &component) +{ + Curves *curves = get_curves_from_component_for_write(component); + if (curves) { + blender::bke::CurvesGeometry::wrap(curves->geometry).tag_topology_changed(); + } +} + +static void tag_component_positions_changed(GeometryComponent &component) +{ + Curves *curves = get_curves_from_component_for_write(component); + if (curves) { + blender::bke::CurvesGeometry::wrap(curves->geometry).tag_positions_changed(); + } +} + +static void tag_component_normals_changed(GeometryComponent &component) +{ + Curves *curves = get_curves_from_component_for_write(component); + if (curves) { + blender::bke::CurvesGeometry::wrap(curves->geometry).tag_normals_changed(); + } +} + +/** \} */ + +namespace blender::bke { + +/* -------------------------------------------------------------------- */ +/** \name Attribute Provider Declaration + * \{ */ + +/** + * In this function all the attribute providers for a curves component are created. + * Most data in this function is statically allocated, because it does not change over time. + */ +static ComponentAttributeProviders create_attribute_providers_for_curve() +{ + static CustomDataAccessInfo curve_access = { + [](GeometryComponent &component) -> CustomData * { + Curves *curves = get_curves_from_component_for_write(component); + return curves ? &curves->geometry.curve_data : nullptr; + }, + [](const GeometryComponent &component) -> const CustomData * { + const Curves *curves = get_curves_from_component_for_read(component); + return curves ? &curves->geometry.curve_data : nullptr; + }, + [](GeometryComponent &component) { + Curves *curves = get_curves_from_component_for_write(component); + if (curves) { + blender::bke::CurvesGeometry::wrap(curves->geometry).update_customdata_pointers(); + } + }}; + static CustomDataAccessInfo point_access = { + [](GeometryComponent &component) -> CustomData * { + Curves *curves = get_curves_from_component_for_write(component); + return curves ? &curves->geometry.point_data : nullptr; + }, + [](const GeometryComponent &component) -> const CustomData * { + const Curves *curves = get_curves_from_component_for_read(component); + return curves ? &curves->geometry.point_data : nullptr; + }, + [](GeometryComponent &component) { + Curves *curves = get_curves_from_component_for_write(component); + if (curves) { + blender::bke::CurvesGeometry::wrap(curves->geometry).update_customdata_pointers(); + } + }}; + + static BuiltinCustomDataLayerProvider position("position", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT3, + CD_PROP_FLOAT3, + BuiltinAttributeProvider::NonCreatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::NonDeletable, + point_access, + make_array_read_attribute<float3>, + make_array_write_attribute<float3>, + tag_component_positions_changed); + + static BuiltinCustomDataLayerProvider radius("radius", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT, + CD_PROP_FLOAT, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<float>, + make_array_write_attribute<float>, + tag_component_normals_changed); + + static BuiltinCustomDataLayerProvider id("id", + ATTR_DOMAIN_POINT, + CD_PROP_INT32, + CD_PROP_INT32, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<int>, + make_array_write_attribute<int>, + nullptr); + + static BuiltinCustomDataLayerProvider tilt("tilt", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT, + CD_PROP_FLOAT, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<float>, + make_array_write_attribute<float>, + tag_component_normals_changed); + + static BuiltinCustomDataLayerProvider handle_right("handle_right", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT3, + CD_PROP_FLOAT3, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<float3>, + make_array_write_attribute<float3>, + tag_component_positions_changed); + + static BuiltinCustomDataLayerProvider handle_left("handle_left", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT3, + CD_PROP_FLOAT3, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<float3>, + make_array_write_attribute<float3>, + tag_component_positions_changed); + + static BuiltinCustomDataLayerProvider handle_type_right("handle_type_right", + ATTR_DOMAIN_POINT, + CD_PROP_INT8, + CD_PROP_INT8, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<int8_t>, + make_array_write_attribute<int8_t>, + tag_component_topology_changed); + + static BuiltinCustomDataLayerProvider handle_type_left("handle_type_left", + ATTR_DOMAIN_POINT, + CD_PROP_INT8, + CD_PROP_INT8, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<int8_t>, + make_array_write_attribute<int8_t>, + tag_component_topology_changed); + + static BuiltinCustomDataLayerProvider nurbs_weight("nurbs_weight", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT, + CD_PROP_FLOAT, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<float>, + make_array_write_attribute<float>, + tag_component_positions_changed); + + static BuiltinCustomDataLayerProvider nurbs_order("nurbs_order", + ATTR_DOMAIN_CURVE, + CD_PROP_INT32, + CD_PROP_INT32, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + curve_access, + make_array_read_attribute<int>, + make_array_write_attribute<int>, + tag_component_topology_changed); + + static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode", + ATTR_DOMAIN_CURVE, + CD_PROP_INT8, + CD_PROP_INT8, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + curve_access, + make_array_read_attribute<int8_t>, + make_array_write_attribute<int8_t>, + tag_component_topology_changed); + + static BuiltinCustomDataLayerProvider resolution("resolution", + ATTR_DOMAIN_CURVE, + CD_PROP_INT32, + CD_PROP_INT32, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + curve_access, + make_array_read_attribute<int>, + make_array_write_attribute<int>, + tag_component_positions_changed); + + static BuiltinCustomDataLayerProvider cyclic("cyclic", + ATTR_DOMAIN_CURVE, + CD_PROP_BOOL, + CD_PROP_BOOL, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + curve_access, + make_array_read_attribute<bool>, + make_array_write_attribute<bool>, + tag_component_topology_changed); + + static CustomDataAttributeProvider curve_custom_data(ATTR_DOMAIN_CURVE, curve_access); + static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access); + + return ComponentAttributeProviders({&position, + &radius, + &id, + &tilt, + &handle_right, + &handle_left, + &handle_type_right, + &handle_type_left, + &nurbs_order, + &nurbs_weight & resolution, + &cyclic}, + {&curve_custom_data, &point_custom_data}); +} + +/** \} */ + +} // namespace blender::bke + +const blender::bke::ComponentAttributeProviders *CurveComponent::get_attribute_providers() const +{ + static blender::bke::ComponentAttributeProviders providers = + blender::bke::create_attribute_providers_for_curve(); + return &providers; +} diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc index d1c4756a3b9..dc5b1d28539 100644 --- a/source/blender/blenkernel/intern/spline_base.cc +++ b/source/blender/blenkernel/intern/spline_base.cc @@ -23,7 +23,7 @@ using blender::fn::GMutableSpan; using blender::fn::GSpan; using blender::fn::GVArray; -Spline::Type Spline::type() const +CurveType Spline::type() const { return type_; } @@ -34,15 +34,18 @@ void Spline::copy_base_settings(const Spline &src, Spline &dst) dst.is_cyclic_ = src.is_cyclic_; } -static SplinePtr create_spline(const Spline::Type type) +static SplinePtr create_spline(const CurveType type) { switch (type) { - case Spline::Type::Poly: + case CURVE_TYPE_POLY: return std::make_unique<PolySpline>(); - case Spline::Type::Bezier: + case CURVE_TYPE_BEZIER: return std::make_unique<BezierSpline>(); - case Spline::Type::NURBS: + case CURVE_TYPE_NURBS: return std::make_unique<NURBSpline>(); + case CURVE_TYPE_CATMULL_ROM: + BLI_assert_unreachable(); + return {}; } BLI_assert_unreachable(); return {}; diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc index 091726bdf84..a09a751b550 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc @@ -59,7 +59,7 @@ static void select_curve_by_handle_type(const CurveEval &curve, threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { for (const int i_spline : range) { const Spline &spline = *splines[i_spline]; - if (spline.type() == Spline::Type::Bezier) { + if (spline.type() == CURVE_TYPE_BEZIER) { const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline); Span<int8_t> types_left = bezier_spline.handle_types_left(); Span<int8_t> types_right = bezier_spline.handle_types_right(); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc index 92dbd6afcaa..e5d4d6c1d0f 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc @@ -74,7 +74,7 @@ static void node_geo_exec(GeoNodeExecParams params) int point_index = 0; bool has_bezier_spline = false; for (SplinePtr &spline : splines) { - if (spline->type() != Spline::Type::Bezier) { + if (spline->type() != CURVE_TYPE_BEZIER) { point_index += spline->positions().size(); continue; } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc index e0ce5ae1a97..0826a78b2b9 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc @@ -183,11 +183,11 @@ static SplinePtr nurbs_to_bezier(const Spline &input) static SplinePtr convert_to_bezier(const Spline &input, GeoNodeExecParams params) { switch (input.type()) { - case Spline::Type::Bezier: + case CURVE_TYPE_BEZIER: return input.copy(); - case Spline::Type::Poly: + case CURVE_TYPE_POLY: return poly_to_bezier(input); - case Spline::Type::NURBS: + case CURVE_TYPE_NURBS: if (input.size() < 6) { params.error_message_add( NodeWarningType::Info, @@ -210,11 +210,11 @@ static SplinePtr convert_to_bezier(const Spline &input, GeoNodeExecParams params static SplinePtr convert_to_nurbs(const Spline &input) { switch (input.type()) { - case Spline::Type::NURBS: + case CURVE_TYPE_NURBS: return input.copy(); - case Spline::Type::Bezier: + case CURVE_TYPE_BEZIER: return bezier_to_nurbs(input); - case Spline::Type::Poly: + case CURVE_TYPE_POLY: return poly_to_nurbs(input); } BLI_assert_unreachable(); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc index 38930d5db85..06f0e633e40 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc @@ -235,20 +235,20 @@ static void subdivide_builtin_attributes(const Spline &src_spline, subdivide_attribute<float>(src_spline.radii(), offsets, is_cyclic, dst_spline.radii()); subdivide_attribute<float>(src_spline.tilts(), offsets, is_cyclic, dst_spline.tilts()); switch (src_spline.type()) { - case Spline::Type::Poly: { + case CURVE_TYPE_POLY: { const PolySpline &src = static_cast<const PolySpline &>(src_spline); PolySpline &dst = static_cast<PolySpline &>(dst_spline); subdivide_attribute<float3>(src.positions(), offsets, is_cyclic, dst.positions()); break; } - case Spline::Type::Bezier: { + case CURVE_TYPE_BEZIER: { const BezierSpline &src = static_cast<const BezierSpline &>(src_spline); BezierSpline &dst = static_cast<BezierSpline &>(dst_spline); subdivide_bezier_spline(src, offsets, dst); dst.mark_cache_invalid(); break; } - case Spline::Type::NURBS: { + case CURVE_TYPE_NURBS: { const NURBSpline &src = static_cast<const NURBSpline &>(src_spline); NURBSpline &dst = static_cast<NURBSpline &>(dst_spline); subdivide_attribute<float3>(src.positions(), offsets, is_cyclic, dst.positions()); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc index a0b862546bc..3dc40639627 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc @@ -111,9 +111,9 @@ static void spline_copy_builtin_attributes(const Spline &spline, copy_data(spline.radii(), r_spline.radii(), mask); copy_data(spline.tilts(), r_spline.tilts(), mask); switch (spline.type()) { - case Spline::Type::Poly: + case CURVE_TYPE_POLY: break; - case Spline::Type::Bezier: { + case CURVE_TYPE_BEZIER: { const BezierSpline &src = static_cast<const BezierSpline &>(spline); BezierSpline &dst = static_cast<BezierSpline &>(r_spline); copy_data(src.handle_positions_left(), dst.handle_positions_left(), mask); @@ -122,7 +122,7 @@ static void spline_copy_builtin_attributes(const Spline &spline, copy_data(src.handle_types_right(), dst.handle_types_right(), mask); break; } - case Spline::Type::NURBS: { + case CURVE_TYPE_NURBS: { const NURBSpline &src = static_cast<const NURBSpline &>(spline); NURBSpline &dst = static_cast<NURBSpline &>(r_spline); copy_data(src.weights(), dst.weights(), mask); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc index 149b387b179..ef402d41268 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc @@ -512,7 +512,7 @@ static SplinePtr fillet_spline(const Spline &spline, copy_common_attributes_by_mapping(spline, *dst_spline_ptr, dst_to_src); switch (spline.type()) { - case Spline::Type::Bezier: { + case CURVE_TYPE_BEZIER: { const BezierSpline &src_spline = static_cast<const BezierSpline &>(spline); BezierSpline &dst_spline = static_cast<BezierSpline &>(*dst_spline_ptr); if (fillet_param.mode == GEO_NODE_CURVE_FILLET_POLY) { @@ -525,11 +525,11 @@ static SplinePtr fillet_spline(const Spline &spline, } break; } - case Spline::Type::Poly: { + case CURVE_TYPE_POLY: { update_poly_positions(fd, *dst_spline_ptr, spline, point_counts); break; } - case Spline::Type::NURBS: { + case CURVE_TYPE_NURBS: { const NURBSpline &src_spline = static_cast<const NURBSpline &>(spline); NURBSpline &dst_spline = static_cast<NURBSpline &>(*dst_spline_ptr); copy_attribute_by_mapping(src_spline.weights(), dst_spline.weights(), dst_to_src); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc index a7ef06a48b0..8dc74aa3dea 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc @@ -54,7 +54,7 @@ static void select_by_handle_type(const CurveEval &curve, { int offset = 0; for (const SplinePtr &spline : curve.splines()) { - if (spline->type() != Spline::Type::Bezier) { + if (spline->type() != CURVE_TYPE_BEZIER) { r_selection.slice(offset, spline->size()).fill(false); offset += spline->size(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc index fdc717bb7ee..9f50b29d995 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc @@ -81,7 +81,7 @@ static void node_geo_exec(GeoNodeExecParams params) int point_index = 0; for (SplinePtr &spline : splines) { - if (spline->type() != Spline::Type::Bezier) { + if (spline->type() != CURVE_TYPE_BEZIER) { point_index += spline->positions().size(); continue; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc index a303be99242..f4343965d66 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc @@ -100,15 +100,15 @@ static Array<float> curve_length_point_domain(const CurveEval &curve) MutableSpan spline_factors{lengths.as_mutable_span().slice(offsets[i], spline.size())}; spline_factors.first() = 0.0f; switch (splines[i]->type()) { - case Spline::Type::Bezier: { + case CURVE_TYPE_BEZIER: { calculate_bezier_lengths(static_cast<const BezierSpline &>(spline), spline_factors); break; } - case Spline::Type::Poly: { + case CURVE_TYPE_POLY: { calculate_poly_length(static_cast<const PolySpline &>(spline), spline_factors); break; } - case Spline::Type::NURBS: { + case CURVE_TYPE_NURBS: { calculate_nurbs_lengths(static_cast<const NURBSpline &>(spline), spline_factors); break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc index aec2e106315..c79d1da8b6c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc @@ -315,11 +315,11 @@ static SplinePtr nurbs_to_bezier(const Spline &input) static SplinePtr convert_to_bezier(const Spline &input, GeoNodeExecParams params) { switch (input.type()) { - case Spline::Type::Bezier: + case CURVE_TYPE_BEZIER: return input.copy(); - case Spline::Type::Poly: + case CURVE_TYPE_POLY: return poly_to_bezier(input); - case Spline::Type::NURBS: + case CURVE_TYPE_NURBS: if (input.size() < 4) { params.error_message_add( NodeWarningType::Info, @@ -335,11 +335,11 @@ static SplinePtr convert_to_bezier(const Spline &input, GeoNodeExecParams params static SplinePtr convert_to_nurbs(const Spline &input) { switch (input.type()) { - case Spline::Type::NURBS: + case CURVE_TYPE_NURBS: return input.copy(); - case Spline::Type::Bezier: + case CURVE_TYPE_BEZIER: return bezier_to_nurbs(input); - case Spline::Type::Poly: + case CURVE_TYPE_POLY: return poly_to_nurbs(input); } BLI_assert_unreachable(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc index 79576854548..6e8a505f9c4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc @@ -217,20 +217,20 @@ static void subdivide_builtin_attributes(const Spline &src_spline, subdivide_attribute<float>(src_spline.radii(), offsets, is_cyclic, dst_spline.radii()); subdivide_attribute<float>(src_spline.tilts(), offsets, is_cyclic, dst_spline.tilts()); switch (src_spline.type()) { - case Spline::Type::Poly: { + case CURVE_TYPE_POLY: { const PolySpline &src = static_cast<const PolySpline &>(src_spline); PolySpline &dst = static_cast<PolySpline &>(dst_spline); subdivide_attribute<float3>(src.positions(), offsets, is_cyclic, dst.positions()); break; } - case Spline::Type::Bezier: { + case CURVE_TYPE_BEZIER: { const BezierSpline &src = static_cast<const BezierSpline &>(src_spline); BezierSpline &dst = static_cast<BezierSpline &>(dst_spline); subdivide_bezier_spline(src, offsets, dst); dst.mark_cache_invalid(); break; } - case Spline::Type::NURBS: { + case CURVE_TYPE_NURBS: { const NURBSpline &src = static_cast<const NURBSpline &>(src_spline); NURBSpline &dst = static_cast<NURBSpline &>(dst_spline); subdivide_attribute<float3>(src.positions(), offsets, is_cyclic, dst.positions()); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc index e6d40a8b6f7..652377065b0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -367,13 +367,13 @@ static void trim_spline(SplinePtr &spline, const Spline::LookupResult end) { switch (spline->type()) { - case Spline::Type::Bezier: + case CURVE_TYPE_BEZIER: trim_bezier_spline(*spline, start, end); break; - case Spline::Type::Poly: + case CURVE_TYPE_POLY: trim_poly_spline(*spline, start, end); break; - case Spline::Type::NURBS: + case CURVE_TYPE_NURBS: spline = std::make_unique<PolySpline>(trim_nurbs_spline(*spline, start, end)); break; } @@ -477,13 +477,13 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look static void to_single_point_spline(SplinePtr &spline, const Spline::LookupResult &lookup) { switch (spline->type()) { - case Spline::Type::Bezier: + case CURVE_TYPE_BEZIER: to_single_point_bezier(*spline, lookup); break; - case Spline::Type::Poly: + case CURVE_TYPE_POLY: to_single_point_poly(*spline, lookup); break; - case Spline::Type::NURBS: + case CURVE_TYPE_NURBS: spline = std::make_unique<PolySpline>(to_single_point_nurbs(*spline, lookup)); break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 2eeb957c123..60aabc7ce37 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -332,9 +332,9 @@ static void spline_copy_builtin_attributes(const Spline &spline, copy_data_based_on_mask(spline.radii(), r_spline.radii(), mask); copy_data_based_on_mask(spline.tilts(), r_spline.tilts(), mask); switch (spline.type()) { - case Spline::Type::Poly: + case CURVE_TYPE_POLY: break; - case Spline::Type::Bezier: { + case CURVE_TYPE_BEZIER: { const BezierSpline &src = static_cast<const BezierSpline &>(spline); BezierSpline &dst = static_cast<BezierSpline &>(r_spline); copy_data_based_on_mask(src.handle_positions_left(), dst.handle_positions_left(), mask); @@ -343,7 +343,7 @@ static void spline_copy_builtin_attributes(const Spline &spline, copy_data_based_on_mask(src.handle_types_right(), dst.handle_types_right(), mask); break; } - case Spline::Type::NURBS: { + case CURVE_TYPE_NURBS: { const NURBSpline &src = static_cast<const NURBSpline &>(spline); NURBSpline &dst = static_cast<NURBSpline &>(r_spline); copy_data_based_on_mask(src.weights(), dst.weights(), mask); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc index 9ae99b4d83e..ca10b640653 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc @@ -52,15 +52,15 @@ static Array<float3> curve_tangent_point_domain(const CurveEval &curve) const Spline &spline = *splines[i]; MutableSpan spline_tangents{tangents.as_mutable_span().slice(offsets[i], spline.size())}; switch (splines[i]->type()) { - case Spline::Type::Bezier: { + case CURVE_TYPE_BEZIER: { calculate_bezier_tangents(static_cast<const BezierSpline &>(spline), spline_tangents); break; } - case Spline::Type::Poly: { + case CURVE_TYPE_POLY: { calculate_poly_tangents(static_cast<const PolySpline &>(spline), spline_tangents); break; } - case Spline::Type::NURBS: { + case CURVE_TYPE_NURBS: { calculate_nurbs_tangents(static_cast<const NURBSpline &>(spline), spline_tangents); break; } @@ -83,7 +83,7 @@ static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &comp /* Use a reference to evaluated tangents if possible to avoid an allocation and a copy. * This is only possible when there is only one poly spline. */ - if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) { + if (splines.size() == 1 && splines.first()->type() == CURVE_TYPE_POLY) { const PolySpline &spline = static_cast<PolySpline &>(*splines.first()); return VArray<float3>::ForSpan(spline.evaluated_tangents()); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc index 4223356397e..3ccb9b79d1f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc @@ -62,7 +62,7 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode, int current_mask = 0; for (const SplinePtr &spline : curve->splines()) { - if (spline->type() == Spline::Type::Bezier) { + if (spline->type() == CURVE_TYPE_BEZIER) { BezierSpline &bezier = static_cast<BezierSpline &>(*spline); for (int i : bezier.positions().index_range()) { if (current_mask < selection.size() && selection[current_mask] == current_point) { @@ -128,7 +128,7 @@ static void node_geo_exec(GeoNodeExecParams params) bool has_bezier = false; geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { if (geometry_set.has_curve() && - geometry_set.get_curve_for_read()->has_spline_with_type(Spline::Type::Bezier)) { + geometry_set.get_curve_for_read()->has_spline_with_type(CURVE_TYPE_BEZIER)) { has_bezier = true; set_position_in_component(mode, geometry_set.get_component_for_write<CurveComponent>(), diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc index e4702035eec..f1353bda9ce 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc @@ -46,7 +46,7 @@ static void node_geo_exec(GeoNodeExecParams params) if (geometry_set.has_curve()) { if (only_poly) { for (const SplinePtr &spline : geometry_set.get_curve_for_read()->splines()) { - if (ELEM(spline->type(), Spline::Type::Bezier, Spline::Type::NURBS)) { + if (ELEM(spline->type(), CURVE_TYPE_BEZIER, CURVE_TYPE_NURBS)) { only_poly = false; break; } |