41 const int curve_index,
44 if (points_to_transform_per_attr.
size() == 1) {
54 const IndexMask &selected_points = points_to_transform_per_attr[0];
56 points_to_transform_per_attr[1], selected_points, memory);
59 const IndexMask selected_right_handles = evaluate_expression(
60 builder.
subtract({&points_to_transform_per_attr[2]},
61 {&selected_left_handles, &selected_points}),
65 selected_left_handles, selected_right_handles, memory);
75 aligned_handles_to_selection(handle_types_left),
76 aligned_handles_to_selection(handle_types_right),
80 selected_left_handles, both_aligned, transform_data.
memory);
82 selected_right_handles, both_aligned, transform_data.
memory);
97 visited[index] =
true;
99 const int left_i = index - 1;
100 if (left_i >= 0 && !visited[left_i]) {
101 const float left_dist = r_distances[index] +
103 if (left_dist < r_distances[left_i]) {
104 r_distances[left_i] = left_dist;
109 const int right_i = index + 1;
110 if (right_i < positions.
size() && !visited[right_i]) {
111 const float right_dist = r_distances[index] +
113 if (right_dist < r_distances[right_i]) {
114 r_distances[right_i] = right_dist;
130 if (visited[index]) {
133 visited[index] =
true;
136 const float left_dist = r_distances[index] +
138 if (left_dist < r_distances[left_i] && !visited[left_i]) {
139 r_distances[left_i] = left_dist;
144 const float right_dist = r_distances[index] +
146 if (right_dist < r_distances[right_i] && !visited[right_i]) {
147 r_distances[right_i] = right_dist;
158 if (
const std::optional<int8_t> single_type =
types.get_if_single()) {
170 const IndexMask &selected_handles_opposite,
175 const IndexMask convert_to_align = evaluate_expression(
178 &builder.intersect({&selected_handles, &auto_handles}),
181 &builder.
intersect({&selected_handles_opposite, &auto_handles_opposite, &auto_handles}),
184 if (convert_to_align.is_empty()) {
219 const std::array<IndexMask, 3> &selection_per_attribute,
226 selection_per_attribute[1], selection_per_attribute[0], memory);
228 selection_per_attribute[2], selection_per_attribute[0], memory);
235 bool changed =
false;
240 const int64_t selected_point = selection_per_attribute[0].first();
241 if (auto_left.
contains(selected_point)) {
245 if (auto_right.
contains(selected_point)) {
252 curves, auto_left, auto_right, selected_left, selected_right,
"handle_type_left", memory);
254 curves, auto_right, auto_left, selected_right, selected_left,
"handle_type_right", memory);
261 curves.tag_topology_changed();
278 transform_data.
positions.as_mutable_span().slice(data_offset, selection.
size()));
295 for (
const int i : trans_data_contrainers.
index_range()) {
303 std::array<IndexMask, 3> selection_per_attribute;
306 curves.curve_type_counts(),
309 curves_transform_data->
memory);
312 curves.points_by_curve(), bezier_curves[
i], curves_transform_data->
memory);
314 for (
const int attribute_i : selection_attribute_names.
index_range()) {
315 const StringRef &selection_name = selection_attribute_names[attribute_i];
317 curves, selection_name, bezier_points, curves_transform_data->
memory);
326 {&bezier_points, selection_per_attribute.data()});
330 selection_per_attribute[1] = evaluate_expression(
331 builder.
merge({&selection_per_attribute[1], &selected_bezier_points}),
332 curves_transform_data->
memory);
333 selection_per_attribute[2] = evaluate_expression(
334 builder.
merge({&selection_per_attribute[2], &selected_bezier_points}),
335 curves_transform_data->
memory);
338 if (use_proportional_edit) {
340 points_to_transform_per_attribute[
i].append(
curves.points_range());
342 if (selection_attribute_names.
size() > 1) {
343 points_to_transform_per_attribute[
i].append(bezier_points);
344 points_to_transform_per_attribute[
i].append(bezier_points);
349 for (
const int selection_i : selection_attribute_names.
index_range()) {
350 points_to_transform_per_attribute[
i].append(selection_per_attribute[selection_i]);
351 tc.
data_len += points_to_transform_per_attribute[
i][selection_i].
size();
365 for (
const int i : trans_data_contrainers.
index_range()) {
371 Curves *curves_id =
static_cast<Curves *
>(
object->data);
376 std::optional<MutableSpan<float>> value_attribute;
384 value_attribute = attribute_writer.
span;
390 value_attribute = attribute_writer.
span;
400 object->object_to_world(),
403 points_to_transform_per_attribute[
i],
410 attribute_writer.
finish();
416 const int curve_index)
430 handle_positions_left,
431 handle_positions_right);
434 handle_positions_right,
435 handle_positions_left);
446 Curves *curves_id =
static_cast<Curves *
>(tc.obedit->data);
449 curves.tag_radii_changed();
452 curves.tag_normals_changed();
457 for (
const int i : positions_per_selection_attr.
index_range()) {
459 tc.custom.type,
i, positions_per_selection_attr[
i]);
461 curves.tag_positions_changed();
462 curves.calculate_bezier_auto_handles();
487 const int handles_offset,
490 const int position_index = curve_points.
start() + position_offsets_in_td[0].start();
492 const int left_handle_index = handles_offset + position_offsets_in_td[1].start();
493 const int right_handle_index = handles_offset + position_offsets_in_td[2].start();
494 std::array<int, 3> first_per_attr = {left_handle_index, position_index, right_handle_index};
496 for (const int i : range) {
497 for (const int attr : IndexRange(3)) {
498 map[i * 3 + attr] = first_per_attr[attr] + i;
512 custom_data.
data = transform_data;
516 custom_data->
data =
nullptr;
518 return transform_data;
542 bool use_connected_only,
546 const std::array<Span<float3>, 3> src_positions_per_selection_attr = {
560 std::array<MutableSpan<float3>, 3> positions_per_selection_attr;
561 for (
const int selection_i : points_to_transform_per_attr.
index_range()) {
563 points_to_transform_per_attr[selection_i],
564 src_positions_per_selection_attr[selection_i],
575 for (
const StringRef selection_name : selection_attribute_names) {
578 selection_attrs.
append(selection_attr);
586 if (use_individual_origin) {
588 const IndexRange points = points_by_curve[curve_i];
600 center /= selection.
size();
601 mean_center_point_per_curve[curve_i] = center;
606 for (
const int selection_i : position_offsets_in_td.
index_range()) {
607 if (position_offsets_in_td[selection_i].is_empty()) {
612 const IndexMask points_to_transform = points_to_transform_per_attr[selection_i];
613 const VArray<bool> selection = selection_attrs[selection_i];
617 const int curve_i = point_to_curve_map[domain_i];
620 float3 *elem = &positions[transform_i];
623 const bool use_local_center = hide_handles || use_individual_origin ||
624 point_selection[domain_i];
625 const bool use_mean_center = use_individual_origin &&
627 if (use_mean_center) {
628 center = mean_center_point_per_curve[curve_i];
630 else if (use_local_center) {
631 center = point_positions[domain_i];
642 if (selection[domain_i]) {
648 if (value_attribute) {
649 float *value = &((*value_attribute)[domain_i]);
669 if (points_to_transform_per_attr.
size() > 1 && points_to_transform_per_attr.
first().is_empty()) {
670 auto update_handle_center = [&](
const int handle_selection_attr,
671 const int opposite_handle_selection_attr) {
672 const IndexMask &handles_to_transform = points_to_transform_per_attr[handle_selection_attr];
673 const IndexMask &opposite_handles_to_transform =
674 points_to_transform_per_attr[opposite_handle_selection_attr];
676 if (handles_to_transform.
size() == 1 && opposite_handles_to_transform.
size() <= 1) {
678 position_offsets_in_td[handle_selection_attr]);
679 copy_v3_v3(tc_data[0].center, point_positions[handles_to_transform.
first()]);
682 update_handle_center(1, 2);
683 update_handle_center(2, 1);
686 if (use_connected_only) {
689 curves_offsets_in_td_buffer[curve] =
690 points_to_transform_per_attr[0].slice_content(points_by_curve[curve]).
size();
704 for (
const int curve_i : segment) {
705 const int selection_attrs_num = curve_types[curve_i] ==
CURVE_TYPE_BEZIER ? 3 : 1;
706 const IndexRange curve_points = points_by_curve[curve_i];
707 const IndexRange editable_curve_points = curves_offsets_in_td[curve_i];
708 const int total_curve_points = selection_attrs_num * editable_curve_points.
size();
711 closest_distances.
fill(std::numeric_limits<float>::max());
712 mapped_curve_positions.
reinitialize(total_curve_points);
715 editable_curve_points,
716 position_offsets_in_td,
717 bezier_offsets_in_td[curve_i],
720 bool has_any_selected =
false;
721 for (
const int selection_attr_i :
IndexRange(selection_attrs_num)) {
722 has_any_selected = has_any_selected ||
726 if (!has_any_selected) {
727 for (
const int i : map) {
736 mapped_curve_positions[
i] = td.
loc;
738 closest_distances[
i] = 0.0f;
742 if (cyclic[curve_i]) {
753 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.
BMesh const char void * data
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
static IndexMask from_difference(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
constexpr Span slice(int64_t start, int64_t size) const
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)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
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)
static IndexMask from_difference(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
constexpr int64_t size() const
constexpr int64_t start() const
constexpr IndexRange index_range() const
void priority_increased(const int64_t index)
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr IndexRange index_range() const
constexpr const T & first() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
static VArray from_single(T value, const int64_t size)
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, AttrType data_type, const void *default_value=nullptr) const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType 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)
IndexMask slice_content(IndexRange range) const
bool contains(int64_t query_index) const
void foreach_index(Fn &&fn) const
void foreach_segment(Fn &&fn) const
IndexRange index_range() const
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void scatter(const Span< T > src, const Span< IndexT > indices, MutableSpan< T > dst, const int64_t grain_size=4096)
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)
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig)
void calculate_aligned_handles(const IndexMask &selection, Span< float3 > positions, Span< float3 > align_by, MutableSpan< float3 > align)
IndexMask indices_for_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, const CurveType type, const IndexMask &selection, IndexMaskMemory &memory)
IndexMask curve_to_point_selection(OffsetIndices< int > points_by_curve, const IndexMask &curve_selection, IndexMaskMemory &memory)
static bool has_anything_selected(const Span< Curves * > curves_ids)
Vector< MutableSpan< float3 > > get_curves_positions_for_write(bke::CurvesGeometry &curves)
Span< StringRef > get_curves_selection_attribute_names(const bke::CurvesGeometry &curves)
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
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)
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)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
MatBase< float, 4, 4 > float4x4
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
const c_style_mat & ptr() const
MutableVArraySpan< T > span