27 ".selection", selection_domain,
true);
28 const int domain_size_orig = attributes.
domain_size(selection_domain);
31 switch (selection_domain) {
42 return attributes.
domain_size(selection_domain) != domain_size_orig;
58 const bool merge_loop = cyclic && selected_points.
first().size() < points.
size() &&
59 selected_points.
first().first() == points.
first() &&
60 selected_points.
last().last() == points.
last();
62 int last_dst_offset = r_dst_offsets.
last();
63 int last_curve_offset = r_new_curve_offsets.
last();
65 r_src_ranges.
append(range);
66 last_dst_offset += range.size();
67 r_dst_offsets.
append(last_dst_offset);
68 last_curve_offset += range.size();
69 r_new_curve_offsets.
append(last_curve_offset);
73 r_src_ranges.
append(merge_to_end);
74 r_dst_offsets.
append(last_dst_offset + merge_to_end.
size());
75 r_new_curve_offsets.
last() += merge_to_end.
size();
77 const int curves_added = selected_points.
size() - merge_loop;
89 curves.nurbs_custom_knots_update_size();
103 const int old_curves_num =
curves.curves_num() - dst_to_src_curve.
size();
106 for (
const int appended_curve : dst_to_src_curve.
index_range()) {
107 const int dst_curve = appended_curve + old_curves_num;
112 const int src_curve = dst_to_src_curve[appended_curve];
113 const int order = src_orders[src_curve];
114 const int first_curve_point = src_points_by_curve[src_curve];
115 const int first_curve_knot = src_knots_by_curve[src_curve];
116 const int point_to_knot = -first_curve_point + first_curve_knot;
117 const IndexRange src_range = src_ranges[range];
119 src_range.
first() + point_to_knot, src_range.
size() + order);
120 const IndexRange dst_knot_range = knots_by_curve[dst_curve];
123 if (dst_offsets[range].
size() != points_by_curve[dst_curve].
size()) {
125 const IndexRange merged_tail = src_ranges[range];
126 const IndexRange src_tail_knots = merged_tail.
shift(point_to_knot + order);
131 dst_knots[dst_tail_knots[
i]] = src_knots[src_tail_knots[
i]] + knot_shift;
152 new_curve_offsets.reserve(
curves.curves_num() + 1);
154 dst_offsets.reserve(
curves.curves_num() + 1);
173 const int old_curves_num =
curves.curves_num();
174 const int old_points_num =
curves.points_num();
175 const int num_curves_to_add = dst_to_src_curve.
size();
176 const int num_points_to_add =
mask.size();
183 curves.resize(old_points_num + num_points_to_add, old_curves_num + num_curves_to_add);
186 curves.offsets_for_write().drop_front(old_curves_num));
197 if (iter.
name ==
"cyclic") {
210 dst_offsets.as_span(),
229 curves.update_curve_types();
230 curves.tag_topology_changed();
232 if (
curves.nurbs_has_custom_knots()) {
239 selection.
span.take_back(num_points_to_add).fill(
true);
246 curves.nurbs_custom_knots_update_size();
247 const int old_curves_num =
curves.curves_num() -
mask.size();
253 const int orig_points_num =
curves.points_num();
254 const int orig_curves_num =
curves.curves_num();
262 const IndexRange orig_curves_range =
curves.curves_range().take_front(orig_curves_num);
263 const IndexRange new_curves_range =
curves.curves_range().drop_front(orig_curves_num);
281 points_by_curve.
slice(new_curves_range),
296 curves.update_curve_types();
297 curves.tag_topology_changed();
299 if (
curves.nurbs_has_custom_knots()) {
306 selection.
span.take_back(
mask.size()).fill(
true);
315 const bool contains_first = ranges.
first().first() == universe.
first();
316 const bool contains_last = ranges.
last().last() == universe.
last();
317 inverted.
reinitialize(ranges.
size() - 1 + !contains_first + !contains_last);
319 int64_t start = contains_first ? ranges.
first().one_after_last() : universe.
first();
323 start = range.one_after_last();
325 if (!contains_last) {
345 extended_ranges.
clear();
350 const bool first_match = ranges.
first().first() == universe.
first();
351 const bool last_match = ranges.
last().last() == universe.
last();
352 const bool add_first = cyclic && last_match && !first_match;
353 const bool add_last = cyclic && first_match && !last_match;
359 if (extended.
first() <= current.
last()) {
363 extended_ranges.
append(current);
367 extended_ranges.
append(current);
406 src_ranges, dst_offsets, attribute.src, attribute.dst.span);
407 attribute.dst.finish();
413 append_point_knots(src_ranges, dst_offsets, dst_to_src_curve, src_curves, dst_curves);
450 invert_ranges(points, selected_curve_points, unselected_curve_points);
454 points, cyclic[curve], unselected_curve_points, curve_points_to_preserve);
455 const int size_before = curve_map.
size();
459 const bool can_merge_loop = !unselected_curve_points.
is_empty() &&
460 (unselected_curve_points.
first().first() == points.
first() ||
461 unselected_curve_points.
last().last() == points.
last());
465 cyclic[curve] && can_merge_loop,
475 int last_offset = new_offsets.last();
476 int last_dst_offset = dst_offsets.last();
477 for (
const int curve :
curves) {
481 const IndexRange points = points_by_curve[curve];
482 src_ranges.
append(points);
483 last_dst_offset += points.
size();
484 dst_offsets.append(last_dst_offset);
486 last_offset += points.
size();
487 new_offsets.append(last_offset);
489 new_cyclic.
append(cyclic[curve]);
494 curves, curve_map, new_offsets, new_cyclic, src_ranges, dst_offsets.
as_span());
500 for (
const int curve :
curves) {
542 separated_src_ranges,
543 separated_dst_offsets,
544 separated_curve_map);
546 invert_ranges(points, selected_curve_points, unselected_curve_points);
550 points, cyclic[curve], unselected_curve_points, curve_points_to_retain);
554 const bool can_merge_loop = !unselected_curve_points.
is_empty() &&
555 (unselected_curve_points.
first().first() == points.
first() ||
556 unselected_curve_points.
last().last() == points.
last());
560 cyclic[curve] && can_merge_loop,
564 retained_dst_offsets,
568 int last_offset = retained_offsets.last();
569 int last_dst_offset = retained_dst_offsets.last();
570 for (
const int curve :
curves) {
574 const IndexRange points = points_by_curve[curve];
575 retained_src_ranges.
append(points);
576 last_dst_offset += points.
size();
577 retained_dst_offsets.append(last_dst_offset);
579 last_offset += points.
size();
580 retained_offsets.append(last_offset);
581 retained_curve_map.
append(curve);
582 retained_cyclic.
append(cyclic[curve]);
593 separated_src_ranges,
594 separated_dst_offsets.
as_span());
605 retained_dst_offsets.
as_span());
616 const int orig_points_num =
curves.points_num();
617 const int orig_curves_num =
curves.curves_num();
618 curves.resize(orig_points_num, orig_curves_num + new_sizes.
size());
634 curves.update_curve_types();
649 std::optional<IndexRange> range = curves_to_resize.
to_range();
651 if (range &&
curves.curves_range() == *range) {
656 curves_to_copy = curves_to_resize.
complement(
curves.curves_range(), memory);
686 const IndexRange src_points = src_offsets[curve_i];
687 const IndexRange dst_points = dst_offsets[curve_i];
688 if (dst_points.
size() < src_points.
size()) {
689 const int src_excees = src_points.
size() - dst_points.
size();
693 const int dst_excees = dst_points.
size() - src_points.
size();
710 curves = std::move(dst_curves);
711 curves.tag_topology_changed();
Low-level operations for curves.
Low-level operations for curves.
#define BLI_assert_unreachable()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr MutableSpan drop_back(const int64_t n) const
constexpr void copy_from(Span< T > values) const
constexpr const T & last(const int64_t n=0) const
const T & last(const int64_t n=0) const
void reinitialize(const int64_t new_size)
void value_initialize_n(void *ptr, int64_t n) const
void copy_from(GSpan values)
GMutableSpan take_back(const int64_t n) const
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
GSpan slice(const int64_t start, int64_t size) const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr int64_t one_before_start() const
constexpr int64_t first() const
constexpr int64_t one_after_last() const
constexpr IndexRange shift(int64_t n) const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
static constexpr IndexRange from_begin_end(const int64_t begin, const int64_t end)
static constexpr IndexRange from_begin_size(const int64_t begin, const int64_t size)
constexpr int64_t start() const
constexpr IndexRange take_back(int64_t n) const
static constexpr IndexRange from_single(const int64_t index)
constexpr IndexRange index_range() const
constexpr IndexRange take_front(int64_t n) const
static constexpr IndexRange from_begin_end_inclusive(const int64_t begin, const int64_t last)
constexpr MutableSpan slice(const int64_t start, const int64_t size) 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 Span drop_front(int64_t n) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T & first() const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
T get_internal_single() const
void append(const T &value)
const T & last(const int64_t n=0) const
void reserve(const int64_t min_capacity)
Span< T > as_span() const
void append_n_times(const T &value, const int64_t n)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
int domain_size(const AttrDomain domain) const
GAttributeReader get() const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
void update_curve_types()
MutableAttributeAccessor attributes_for_write()
Span< float > nurbs_custom_knots() const
Span< int > offsets() const
void resize(int points_num, int curves_num)
AttributeAccessor attributes() const
MutableSpan< int > offsets_for_write()
bool nurbs_has_custom_knots() const
OffsetIndices< int > nurbs_custom_knots_by_curve() const
MutableSpan< bool > cyclic_for_write()
VArray< int8_t > nurbs_orders() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
std::optional< IndexRange > to_range() const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void foreach_index(Fn &&fn) const
OffsetIndices slice(const IndexRange range) const
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
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)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void gather(GSpan src, Span< int > map, GMutableSpan dst)
void gather_ranges_to_groups(Span< IndexRange > src_ranges, OffsetIndices< int > dst_offsets, GSpan src, GMutableSpan dst)
void gather_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
void gather_custom_knots(const bke::CurvesGeometry &src, const IndexMask &src_curves, int dst_curve_offset, bke::CurvesGeometry &dst)
void update_custom_knot_modes(const IndexMask &mask, const KnotsMode mode_for_regular, const KnotsMode mode_for_cyclic, bke::CurvesGeometry &curves)
void foreach_selected_point_ranges_per_curve(const IndexMask &mask, OffsetIndices< int > points_by_curve, SelectedCallback selected_fn)
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
bool attribute_name_is_anonymous(const StringRef name)
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const AttributeAccessor src_attributes, MutableAttributeAccessor dst_attributes, AttrDomainMask domain_mask, const AttributeFilter &attribute_filter={})
auto attribute_filter_from_skip_ref(const Span< StringRef > skip)
void fill_attribute_range_default(MutableAttributeAccessor dst_attributes, AttrDomain domain, const AttributeFilter &attribute_filter, IndexRange range)
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
bool remove_selection(bke::CurvesGeometry &curves, const bke::AttrDomain selection_domain)
static bke::CurvesGeometry copy_data_to_geometry(const bke::CurvesGeometry &src_curves, const Span< int > dst_to_src_curve, const Span< int > offsets, const Span< bool > cyclic, const Span< IndexRange > src_ranges, const OffsetIndices< int > dst_offsets)
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)
static void append_point_knots(const Span< IndexRange > src_ranges, const OffsetIndices< int > dst_offsets, const Span< int > dst_to_src_curve, const bke::CurvesGeometry &src_curves, bke::CurvesGeometry &curves)
void duplicate_curves(bke::CurvesGeometry &curves, const IndexMask &mask)
void duplicate_points(bke::CurvesGeometry &curves, const IndexMask &mask)
static IndexRange extend_range(const IndexRange range, const IndexRange universe)
static void curve_offsets_from_selection(const Span< IndexRange > selected_points, const IndexRange points, const int curve, const bool cyclic, Vector< int > &r_new_curve_offsets, Vector< bool > &r_new_cyclic, Vector< IndexRange > &r_src_ranges, Vector< int > &r_dst_offsets, Vector< int > &r_dst_to_src_curve)
void foreach_selection_attribute_writer(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, blender::FunctionRef< void(bke::GSpanAttributeWriter &selection)> fn)
void separate_points(const bke::CurvesGeometry &curves, const IndexMask &points_to_separate, bke::CurvesGeometry &separated, bke::CurvesGeometry &retained)
bke::CurvesGeometry split_points(const bke::CurvesGeometry &curves, const IndexMask &points_to_split)
void fill_selection_false(GMutableSpan selection)
void add_curves(bke::CurvesGeometry &curves, const Span< int > new_sizes)
static void invert_ranges(const IndexRange universe, const Span< IndexRange > ranges, Array< IndexRange > &inverted)
Span< StringRef > get_curves_selection_attribute_names(const bke::CurvesGeometry &curves)
static void append_curve_knots(const IndexMask &mask, bke::CurvesGeometry &curves)
static void extend_range_by_1_within_bounds(const IndexRange universe, const bool cyclic, const Span< IndexRange > ranges, Vector< IndexRange > &extended_ranges)
void reorder_curves(bke::CurvesGeometry &curves, const Span< int > old_by_new_indices_map)
bke::CurvesGeometry reorder_curves_geometry(const bke::CurvesGeometry &src_curves, Span< int > old_by_new_map, const bke::AttributeFilter &attribute_filter)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
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)
ListBase vertex_group_names
MutableVArraySpan< T > span