43 if (points_to_transform_per_attr.
size() == 1) {
53 const IndexMask &selected_points = points_to_transform_per_attr[0];
55 points_to_transform_per_attr[1], selected_points, memory);
58 const IndexMask selected_right_handles = evaluate_expression(
59 builder.
subtract({&points_to_transform_per_attr[2]},
60 {&selected_left_handles, &selected_points}),
64 selected_left_handles, selected_right_handles, memory);
74 aligned_handles_to_selection(handle_types_left),
75 aligned_handles_to_selection(handle_types_right),
79 selected_left_handles, both_aligned, transform_data.
memory);
81 selected_right_handles, both_aligned, transform_data.
memory);
91 while (!queue.is_empty()) {
92 int64_t index = queue.pop_index();
98 const int left_i = index - 1;
99 if (left_i >= 0 && !
visited[left_i]) {
100 const float left_dist = r_distances[index] +
102 if (left_dist < r_distances[left_i]) {
103 r_distances[left_i] = left_dist;
104 queue.priority_increased(left_i);
108 const int right_i = index + 1;
109 if (right_i < positions.
size() && !
visited[right_i]) {
110 const float right_dist = r_distances[index] +
112 if (right_dist < r_distances[right_i]) {
113 r_distances[right_i] = right_dist;
114 queue.priority_increased(right_i);
127 while (!queue.is_empty()) {
128 int64_t index = queue.pop_index();
135 const float left_dist = r_distances[index] +
137 if (left_dist < r_distances[left_i] && !
visited[left_i]) {
138 r_distances[left_i] = left_dist;
139 queue.priority_increased(left_i);
143 const float right_dist = r_distances[index] +
145 if (right_dist < r_distances[right_i] && !
visited[right_i]) {
146 r_distances[right_i] = right_dist;
147 queue.priority_increased(right_i);
174 const IndexMask &selected_handles_opposite,
179 const IndexMask &convert_to_align = evaluate_expression(
182 &builder.intersect({&selected_handles, &auto_handles}),
185 &builder.
intersect({&selected_handles_opposite, &auto_handles_opposite, &auto_handles}),
205 selected_handles_left,
206 selected_handles_right,
211 selected_handles_right,
212 selected_handles_left,
245 for (
const int i : trans_data_contrainers.
index_range()) {
251 Span<StringRef> selection_attribute_names = ed::curves::get_curves_selection_attribute_names(
253 std::array<IndexMask, 3> selection_per_attribute;
255 for (
const int attribute_i : selection_attribute_names.
index_range()) {
256 const StringRef &selection_name = selection_attribute_names[attribute_i];
257 selection_per_attribute[attribute_i] = ed::curves::retrieve_selected_points(
258 curves, selection_name, curves_transform_data->
memory);
261 bezier_curves[i] = bke::curves::indices_for_type(curves.
curve_types(),
265 curves_transform_data->
memory);
267 const IndexMask bezier_points = bke::curves::curve_to_point_selection(
274 const IndexMask selected_left = IndexMask::from_difference(
275 selection_per_attribute[1], selection_per_attribute[0], memory);
276 const IndexMask selected_right = IndexMask::from_difference(
277 selection_per_attribute[2], selection_per_attribute[0], memory);
284 selected_left, selected_right, bezier_points, handle_types_left, handle_types_right);
289 {&bezier_points, selection_per_attribute.data()});
293 selection_per_attribute[1] = evaluate_expression(
294 builder.
merge({&selection_per_attribute[1], &selected_bezier_points}),
295 curves_transform_data->
memory);
296 selection_per_attribute[2] = evaluate_expression(
297 builder.
merge({&selection_per_attribute[2], &selected_bezier_points}),
298 curves_transform_data->
memory);
301 if (use_proportional_edit) {
303 points_to_transform_per_attribute[i].append(curves.
points_range());
305 if (selection_attribute_names.
size() > 1) {
306 points_to_transform_per_attribute[i].append(bezier_points);
307 points_to_transform_per_attribute[i].append(bezier_points);
312 for (
const int selection_i : selection_attribute_names.
index_range()) {
313 points_to_transform_per_attribute[i].append(selection_per_attribute[selection_i]);
314 tc.
data_len += points_to_transform_per_attribute[i][selection_i].
size();
328 for (
const int i : trans_data_contrainers.
index_range()) {
334 Curves *curves_id =
static_cast<Curves *
>(
object->data);
337 bke::crazyspace::get_evaluated_curves_deformation(*
depsgraph, *
object);
339 std::optional<MutableSpan<float>> value_attribute;
345 bke::AttrDomain::Point,
347 value_attribute = attribute_writer.
span;
352 bke::AttrDomain::Point);
353 value_attribute = attribute_writer.
span;
359 object->object_to_world(),
362 points_to_transform_per_attribute[i],
369 attribute_writer.
finish();
376 if (ed::curves::get_curves_selection_attribute_names(curves).
size() == 1) {
386 bke::curves::bezier::calculate_aligned_handles(
387 transform_data.
aligned_with_left, positions, handle_positions_left, handle_positions_right);
388 bke::curves::bezier::calculate_aligned_handles(
389 transform_data.
aligned_with_right, positions, handle_positions_right, handle_positions_left);
400 Curves *curves_id =
static_cast<Curves *
>(tc.obedit->data);
410 ed::curves::get_curves_positions_for_write(curves);
411 for (
const int i : positions_per_selection_attr.
index_range()) {
413 tc.custom.type, i, positions_per_selection_attr[i]);
417 calculate_aligned_handles(tc.custom.type, curves);
441 const int handles_offset,
444 const int position_index = curve_points.
start() + position_offsets_in_td[0].start();
446 const int left_handle_index = handles_offset + position_offsets_in_td[1].start();
447 const int right_handle_index = handles_offset + position_offsets_in_td[2].start();
448 std::array<int, 3> first_per_attr = {left_handle_index, position_index, right_handle_index};
450 for (const int i : range) {
451 for (const int attr : IndexRange(3)) {
452 map[i * 3 + attr] = first_per_attr[attr] + i;
458 array_utils::fill_index_range(map, position_index);
466 custom_data.
data = transform_data;
470 custom_data->
data =
nullptr;
472 return transform_data;
485 array_utils::scatter(positions, selection, positions_dst);
496 bool use_connected_only,
500 const std::array<Span<float3>, 3> src_positions_per_selection_attr = {
509 ".selection", bke::AttrDomain::Point,
true);
512 std::array<MutableSpan<float3>, 3> positions_per_selection_attr;
513 for (
const int selection_i : points_to_transform_per_attr.
index_range()) {
515 points_to_transform_per_attr[selection_i],
516 src_positions_per_selection_attr[selection_i],
525 Span<StringRef> selection_attribute_names = ed::curves::get_curves_selection_attribute_names(
527 for (
const StringRef selection_name : selection_attribute_names) {
529 selection_name, bke::AttrDomain::Point,
true);
530 selection_attrs.
append(selection_attr);
538 if (use_individual_origin) {
540 const IndexRange points = points_by_curve[curve_i];
543 IndexMask::from_bools(point_selection, memory).
slice_content(points);
552 center /= selection.
size();
553 mean_center_point_per_curve[curve_i] = center;
558 for (
const int selection_i : position_offsets_in_td.
index_range()) {
559 if (position_offsets_in_td[selection_i].is_empty()) {
564 const IndexMask points_to_transform = points_to_transform_per_attr[selection_i];
565 const VArray<bool> selection = selection_attrs[selection_i];
569 const int curve_i = point_to_curve_map[domain_i];
572 float3 *elem = &positions[transform_i];
575 const bool use_local_center = hide_handles || use_individual_origin ||
576 point_selection[domain_i];
577 const bool use_mean_center = use_individual_origin &&
579 if (use_mean_center) {
580 center = mean_center_point_per_curve[curve_i];
582 else if (use_local_center) {
583 center = point_positions[domain_i];
594 if (selection[domain_i]) {
600 if (value_attribute) {
601 float *
value = &((*value_attribute)[domain_i]);
619 if (use_connected_only) {
622 curves_offsets_in_td_buffer[
curve] =
623 points_to_transform_per_attr[0].slice_content(points_by_curve[
curve]).
size();
625 offset_indices::accumulate_counts_to_offsets(curves_offsets_in_td_buffer);
629 offset_indices::copy_group_sizes(points_by_curve, bezier_curves, bezier_offsets_in_td);
630 offset_indices::accumulate_counts_to_offsets(bezier_offsets_in_td);
637 for (
const int curve_i : segment) {
638 const int selection_attrs_num = curve_types[curve_i] ==
CURVE_TYPE_BEZIER ? 3 : 1;
639 const IndexRange curve_points = points_by_curve[curve_i];
640 const IndexRange editable_curve_points = curves_offsets_in_td[curve_i];
641 const int total_curve_points = selection_attrs_num * editable_curve_points.
size();
642 map.reinitialize(total_curve_points);
644 closest_distances.
fill(std::numeric_limits<float>::max());
645 mapped_curve_positions.
reinitialize(total_curve_points);
648 editable_curve_points,
649 position_offsets_in_td,
650 bezier_offsets_in_td[curve_i],
653 bool has_any_selected =
false;
654 for (
const int selection_attr_i :
IndexRange(selection_attrs_num)) {
655 has_any_selected = has_any_selected ||
656 ed::curves::has_anything_selected(selection_attrs[selection_attr_i],
659 if (!has_any_selected) {
660 for (
const int i : map) {
667 for (
const int i : closest_distances.
index_range()) {
669 mapped_curve_positions[i] = td.
loc;
671 closest_distances[i] = 0.0f;
675 if (cyclic[curve_i]) {
684 for (
const int i : closest_distances.
index_range()) {
686 td.
dist = closest_distances[i];
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Low-level operations for curves.
Low-level operations for curves.
void copy_m3_m3(float m1[3][3], const float m2[3][3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
ATTR_WARN_UNUSED_RESULT const size_t num
void DEG_id_tag_update(ID *id, unsigned int flags)
@ V3D_AROUND_LOCAL_ORIGINS
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
IndexRange index_range() const
void fill(const T &value) const
void reinitialize(const int64_t new_size)
constexpr int64_t size() const
constexpr int64_t start() const
constexpr IndexRange index_range() const
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr IndexRange index_range() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
void append(const T &value)
const T & last(const int64_t n=0) const
IndexRange index_range() const
Span< T > as_span() const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
VArray< int8_t > handle_types_left() const
Array< int > point_to_curve_map() const
OffsetIndices< int > points_by_curve() const
MutableSpan< int8_t > handle_types_right_for_write()
VArray< int8_t > handle_types_right() const
IndexRange curves_range() const
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
MutableSpan< float3 > handle_positions_left_for_write()
MutableAttributeAccessor attributes_for_write()
MutableSpan< float3 > handle_positions_right_for_write()
void tag_normals_changed()
Span< float3 > handle_positions_left() const
IndexRange points_range() const
Span< float3 > positions() const
void tag_topology_changed()
Span< float3 > handle_positions_right() const
void tag_positions_changed()
AttributeAccessor attributes() const
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
void calculate_bezier_auto_handles()
MutableSpan< int8_t > handle_types_left_for_write()
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
const IntersectionExpr & intersect(const Span< Term > terms)
const UnionExpr & merge(const Span< Term > terms)
const DifferenceExpr & subtract(const Term &main_term, const Span< Term > subtract_terms)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
IndexMask slice_content(IndexRange range) const
static IndexMask from_union(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
static IndexMask from_intersection(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
void foreach_index(Fn &&fn) const
static IndexMask from_difference(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
void foreach_segment(Fn &&fn) const
IndexRange index_range() const
const Depsgraph * depsgraph
Set< ComponentNode * > visited
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void masked_fill(MutableSpan< T > data, const T &value, const IndexMask &mask)
T distance(const T &a, const T &b)
MatBase< T, Size, Size > pseudo_invert(const MatBase< T, Size, Size > &mat, T epsilon=1e-8)
T mod_periodic(const T &a, const T &b)
const c_style_mat & ptr() const
MutableVArraySpan< T > span