22 const VArray<bool> selection = *attributes.lookup_or_default<
bool>(
23 ".selection", selection_domain,
true);
24 const int domain_size_orig = attributes.domain_size(selection_domain);
27 switch (selection_domain) {
29 curves.remove_points(mask, {});
32 curves.remove_curves(mask, {});
38 return attributes.domain_size(selection_domain) != domain_size_orig;
46 Array<bool> points_to_duplicate(curves.points_num());
48 const int num_points_to_add = mask.size();
50 int curr_dst_point_start = 0;
51 Array<int> dst_to_src_point(num_points_to_add);
57 for (
const int curve_i : curves.curves_range()) {
58 const IndexRange points = points_by_curve[curve_i];
59 const Span<bool> curve_points_to_duplicate = points_to_duplicate.
as_span().slice(points);
60 const bool curve_cyclic = src_cyclic[curve_i];
64 curve_points_to_duplicate,
true);
66 if (ranges_to_duplicate.
is_empty()) {
70 const bool is_last_segment_selected = curve_cyclic &&
71 ranges_to_duplicate.
first().first() == 0 &&
72 ranges_to_duplicate.
last().last() == points.size() - 1;
73 const bool is_curve_self_joined = is_last_segment_selected && ranges_to_duplicate.
size() != 1;
74 const bool is_cyclic = ranges_to_duplicate.
size() == 1 && is_last_segment_selected;
79 const IndexRange range = ranges_to_duplicate[range_i];
82 dst_to_src_point.
as_mutable_span().slice(curr_dst_point_start, range.size()),
83 range.start() + points.first());
84 curr_dst_point_start += range.size();
86 dst_curve_counts.
append(range.size());
87 dst_to_src_curve.
append(curve_i);
92 if (is_curve_self_joined) {
96 first_range.
start() + points.first());
97 curr_dst_point_start += first_range.
size();
98 dst_curve_counts[dst_curve_counts.
size() - 1] += first_range.
size();
102 const int old_curves_num = curves.curves_num();
103 const int old_points_num = curves.points_num();
104 const int num_curves_to_add = dst_to_src_curve.
size();
111 curves.resize(old_points_num + num_points_to_add, old_curves_num + num_curves_to_add);
128 if (iter.
name ==
"cyclic") {
135 attribute.span.slice(
IndexRange(old_curves_num, num_curves_to_add)));
142 attribute.span.slice(
IndexRange(old_points_num, num_points_to_add)));
159 curves.update_curve_types();
160 curves.tag_topology_changed();
165 selection.
span.take_back(num_points_to_add).fill(
true);
172 const int orig_points_num = curves.points_num();
173 const int orig_curves_num = curves.curves_num();
180 curves.resize(curves.points_num(), orig_curves_num + mask.size());
193 curves.resize(points_by_curve.
total_size(), curves.curves_num());
200 points_by_curve.
slice(new_curves_range),
215 curves.update_curve_types();
216 curves.tag_topology_changed();
221 selection.
span.take_back(mask.size()).fill(
true);
228 const int orig_points_num = curves.points_num();
229 const int orig_curves_num = curves.curves_num();
230 curves.resize(orig_points_num, orig_curves_num + new_sizes.
size());
237 curves.resize(curves.offsets().last(), curves.curves_num());
246 curves.update_curve_types();
261 std::optional<IndexRange> range = curves_to_resize.
to_range();
263 if (range && curves.curves_range() == *range) {
268 curves_to_copy = curves_to_resize.
complement(curves.curves_range(), memory);
290 const CPPType &type = src.type();
298 const IndexRange src_points = src_offsets[curve_i];
299 const IndexRange dst_points = dst_offsets[curve_i];
300 if (dst_points.
size() < src_points.
size()) {
301 const int src_excees = src_points.size() - dst_points.size();
302 dst.span.slice(dst_points).copy_from(src.slice(src_points.drop_back(src_excees)));
305 const int dst_excees = dst_points.size() - src_points.size();
306 dst.span.slice(dst_points.drop_back(dst_excees)).copy_from(src.slice(src_points));
307 GMutableSpan dst_end_slice = dst.span.slice(dst_points.take_back(dst_excees));
308 type.value_initialize_n(dst_end_slice.data(), dst_end_slice.size());
318 curves = std::move(dst_curves);
319 curves.tag_topology_changed();
Low-level operations for curves.
Low-level operations for curves.
#define BLI_assert_unreachable()
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
constexpr int64_t first() const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr IndexRange take_front(int64_t n) const
constexpr IndexRange drop_front(int64_t n) const
constexpr MutableSpan drop_back(const int64_t n) const
constexpr MutableSpan drop_front(const int64_t n) const
constexpr void copy_from(Span< T > values) const
constexpr MutableSpan take_front(const int64_t n) const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
T get_internal_single() const
void append(const T &value)
const T & last(const int64_t n=0) const
IndexRange index_range() const
Span< T > as_span() const
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
eCustomDataType data_type
GAttributeReader get() const
OffsetIndices< int > points_by_curve() const
void update_curve_types()
MutableAttributeAccessor attributes_for_write()
Span< int > offsets() const
void resize(int points_num, int curves_num)
MutableSpan< int > offsets_for_write()
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
std::optional< IndexRange > to_range() const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
void foreach_index(Fn &&fn) const
OffsetIndices slice(const IndexRange range) const
static bool is_cyclic(const Nurb *nu)
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
void scatter(const Span< T > src, const Span< IndexT > indices, MutableSpan< T > dst, const int64_t grain_size=4096)
void copy_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
Vector< IndexRange > find_all_ranges(const Span< T > span, const T &value)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void fill_index_range(MutableSpan< T > span, const T start=0)
void gather(GSpan src, Span< int > map, GMutableSpan dst)
void gather_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
bool attribute_name_is_anonymous(const StringRef name)
void fill_attribute_range_default(MutableAttributeAccessor dst_attributes, AttrDomain domain, const AttributeFilter &attribute_filter, IndexRange range)
bool remove_selection(bke::CurvesGeometry &curves, const bke::AttrDomain selection_domain)
void resize_curves(bke::CurvesGeometry &curves, const IndexMask &curves_to_resize, const Span< int > new_sizes)
void remove_selection_attributes(bke::MutableAttributeAccessor &attributes, Span< StringRef > selection_attribute_names)
void duplicate_curves(bke::CurvesGeometry &curves, const IndexMask &mask)
void duplicate_points(bke::CurvesGeometry &curves, const IndexMask &mask)
void add_curves(bke::CurvesGeometry &curves, const Span< int > new_sizes)
Span< StringRef > get_curves_selection_attribute_names(const bke::CurvesGeometry &curves)
void copy_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask, MutableSpan< int > sizes)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
OffsetIndices< int > gather_selected_offsets(OffsetIndices< int > src_offsets, const IndexMask &selection, int start_offset, MutableSpan< int > dst_offsets)
MutableVArraySpan< T > span