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);
96 visited[index] =
true;
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;
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;
129 if (visited[index]) {
132 visited[index] =
true;
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;
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;
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,
228 transform_data.
positions.as_mutable_span().slice(data_offset, selection.
size()));
245 for (
const int i : trans_data_contrainers.
index_range()) {
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];
262 curves.curve_type_counts(),
265 curves_transform_data->
memory);
268 curves.points_by_curve(), bezier_curves[
i], curves_transform_data->
memory);
275 selection_per_attribute[1], selection_per_attribute[0], memory);
277 selection_per_attribute[2], selection_per_attribute[0], memory);
284 selected_left, selected_right, bezier_points, handle_types_left, handle_types_right);
285 curves.tag_topology_changed();
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);
339 std::optional<MutableSpan<float>> value_attribute;
347 value_attribute = attribute_writer.
span;
353 value_attribute = attribute_writer.
span;
359 object->object_to_world(),
362 points_to_transform_per_attribute[
i],
369 attribute_writer.
finish();
387 transform_data.
aligned_with_left, positions, handle_positions_left, handle_positions_right);
389 transform_data.
aligned_with_right, positions, handle_positions_right, handle_positions_left);
400 Curves *curves_id =
static_cast<Curves *
>(tc.obedit->data);
403 curves.tag_radii_changed();
406 curves.tag_normals_changed();
411 for (
const int i : positions_per_selection_attr.
index_range()) {
413 tc.custom.type,
i, positions_per_selection_attr[
i]);
415 curves.tag_positions_changed();
416 curves.calculate_bezier_auto_handles();
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;
466 custom_data.
data = transform_data;
470 custom_data->
data =
nullptr;
472 return transform_data;
496 bool use_connected_only,
500 const std::array<Span<float3>, 3> src_positions_per_selection_attr = {
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],
527 for (
const StringRef selection_name : selection_attribute_names) {
530 selection_attrs.
append(selection_attr);
538 if (use_individual_origin) {
540 const IndexRange points = points_by_curve[curve_i];
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();
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();
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 ||
659 if (!has_any_selected) {
660 for (
const int i : map) {
669 mapped_curve_positions[
i] = td.
loc;
671 closest_distances[
i] = 0.0f;
675 if (cyclic[curve_i]) {
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.
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 int64_t size() const
constexpr IndexRange index_range() const
static VArray ForSingle(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
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)
IndexMask slice_content(IndexRange range) 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