diff options
Diffstat (limited to 'source/blender/blenkernel/intern/geometry_component_curve.cc')
-rw-r--r-- | source/blender/blenkernel/intern/geometry_component_curve.cc | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc index 0b6ba966974..7d0537178ef 100644 --- a/source/blender/blenkernel/intern/geometry_component_curve.cc +++ b/source/blender/blenkernel/intern/geometry_component_curve.cc @@ -64,6 +64,8 @@ void CurveComponent::clear() delete curve_; } 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; } @@ -220,6 +222,37 @@ static void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve, mixer.finalize(); } +/** + * A spline is selected if all of its control points were selected. + * + * \note Theoretically this interpolation does not need to compute all values at once. + * However, doing that makes the implementation simpler, and this can be optimized in the future if + * only some values are required. + */ +template<> +void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + const int splines_len = curve.splines().size(); + Array<int> offsets = curve.control_point_offsets(); + BLI_assert(r_values.size() == splines_len); + + r_values.fill(true); + + for (const int i_spline : IndexRange(splines_len)) { + const int spline_offset = offsets[i_spline]; + const int spline_point_len = offsets[i_spline + 1] - spline_offset; + + for (const int i_point : IndexRange(spline_point_len)) { + if (!old_values[spline_offset + i_point]) { + r_values[i_spline] = false; + break; + } + } + } +} + static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -892,7 +925,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { public: ReadAttributeLookup try_get_for_read(const GeometryComponent &component, - const StringRef attribute_name) const final + const AttributeIDRef &attribute_id) const final { const CurveEval *curve = get_curve_from_component_for_read(component); if (curve == nullptr || curve->splines().size() == 0) { @@ -902,13 +935,13 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { Span<SplinePtr> splines = curve->splines(); Vector<GSpan> spans; /* GSpan has no default constructor. */ spans.reserve(splines.size()); - std::optional<GSpan> first_span = splines[0]->attributes.get_for_read(attribute_name); + std::optional<GSpan> first_span = splines[0]->attributes.get_for_read(attribute_id); if (!first_span) { return {}; } spans.append(*first_span); for (const int i : IndexRange(1, splines.size() - 1)) { - std::optional<GSpan> span = splines[i]->attributes.get_for_read(attribute_name); + std::optional<GSpan> span = splines[i]->attributes.get_for_read(attribute_id); if (!span) { /* All splines should have the same set of data layers. It would be possible to recover * here and return partial data instead, but that would add a lot of complexity for a @@ -945,7 +978,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { /* This function is almost the same as #try_get_for_read, but without const. */ WriteAttributeLookup try_get_for_write(GeometryComponent &component, - const StringRef attribute_name) const final + const AttributeIDRef &attribute_id) const final { CurveEval *curve = get_curve_from_component_for_write(component); if (curve == nullptr || curve->splines().size() == 0) { @@ -955,13 +988,13 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { MutableSpan<SplinePtr> splines = curve->splines(); Vector<GMutableSpan> spans; /* GMutableSpan has no default constructor. */ spans.reserve(splines.size()); - std::optional<GMutableSpan> first_span = splines[0]->attributes.get_for_write(attribute_name); + std::optional<GMutableSpan> first_span = splines[0]->attributes.get_for_write(attribute_id); if (!first_span) { return {}; } spans.append(*first_span); for (const int i : IndexRange(1, splines.size() - 1)) { - std::optional<GMutableSpan> span = splines[i]->attributes.get_for_write(attribute_name); + std::optional<GMutableSpan> span = splines[i]->attributes.get_for_write(attribute_id); if (!span) { /* All splines should have the same set of data layers. It would be possible to recover * here and return partial data instead, but that would add a lot of complexity for a @@ -996,7 +1029,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { return attribute; } - bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final + bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final { CurveEval *curve = get_curve_from_component_for_write(component); if (curve == nullptr) { @@ -1006,7 +1039,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { /* Reuse the boolean for all splines; we expect all splines to have the same attributes. */ bool layer_freed = false; for (SplinePtr &spline : curve->splines()) { - layer_freed = spline->attributes.remove(attribute_name); + layer_freed = spline->attributes.remove(attribute_id); } return layer_freed; } @@ -1034,7 +1067,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { } bool try_create(GeometryComponent &component, - const StringRef attribute_name, + const AttributeIDRef &attribute_id, const AttributeDomain domain, const CustomDataType data_type, const AttributeInit &initializer) const final @@ -1053,7 +1086,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { /* First check the one case that allows us to avoid copying the input data. */ if (splines.size() == 1 && initializer.type == AttributeInit::Type::MoveArray) { void *source_data = static_cast<const AttributeInitMove &>(initializer).data; - if (!splines[0]->attributes.create_by_move(attribute_name, data_type, source_data)) { + if (!splines[0]->attributes.create_by_move(attribute_id, data_type, source_data)) { MEM_freeN(source_data); return false; } @@ -1062,7 +1095,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { /* Otherwise just create a custom data layer on each of the splines. */ for (const int i : splines.index_range()) { - if (!splines[i]->attributes.create(attribute_name, data_type)) { + if (!splines[i]->attributes.create(attribute_id, data_type)) { /* If attribute creation fails on one of the splines, we cannot leave the custom data * layers in the previous splines around, so delete them before returning. However, * this is not an expected case. */ @@ -1076,7 +1109,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { return true; } - WriteAttributeLookup write_attribute = this->try_get_for_write(component, attribute_name); + WriteAttributeLookup write_attribute = this->try_get_for_write(component, attribute_id); /* We just created the attribute, it should exist. */ BLI_assert(write_attribute); |