37 "The number of duplicates to create for each element");
41 .
description(
"The duplicated geometry, not including the original geometry");
44 .
description(
"The indices of the duplicates for each element");
50 data->domain =
int8_t(AttrDomain::Point);
95 for (const int i : range) {
96 MutableSpan<int> dst = all_dst.slice(offsets[i]);
100 dst.first() = src[i];
101 for (const int i_duplicate : dst.index_range().drop_front(1)) {
102 dst[i_duplicate] = noise::hash(src[i], i_duplicate);
110 const AttrDomain output_domain,
117 for (
const int i :
IndexRange(selection.size())) {
119 for (
const int i : indices.index_range()) {
123 duplicate_indices.
finish();
135 if (!src_attribute) {
140 if (!dst_attribute) {
169 for (
auto &attribute : bke::retrieve_attributes_for_transfer(
173 bke::attribute_filter_with_skip_ref(attribute_filter, {
"id"})))
175 switch (attribute.meta_data.domain) {
176 case AttrDomain::Curve:
177 bke::attribute_math::gather_to_groups(
178 curve_offsets, selection, attribute.src, attribute.dst.span);
180 case AttrDomain::Point:
181 bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](
auto dummy) {
182 using T = decltype(dummy);
183 const Span<T> src = attribute.src.typed<T>();
184 MutableSpan<T> dst = attribute.dst.span.typed<T>();
185 selection.foreach_index(
186 GrainSize(512), [&](const int64_t index, const int64_t i_selection) {
187 const Span<T> curve_src = src.slice(src_points_by_curve[index]);
188 for (const int dst_curve_index : curve_offsets[i_selection]) {
189 dst.slice(dst_points_by_curve[dst_curve_index]).copy_from(curve_src);
198 attribute.dst.finish();
214 if (!src_attribute) {
220 if (!dst_attribute) {
230 selection.foreach_index(
232 const Span<int> curve_src = src.
slice(src_points_by_curve[i_src_curve]);
233 const IndexRange duplicates_range = offsets[i_selection];
235 const int i_dst_curve = duplicates_range[i_duplicate];
251 evaluator.add(count_field);
252 evaluator.set_selection(selection_field);
253 evaluator.evaluate();
254 const VArray<int> counts = evaluator.get_evaluated<
int>(0);
255 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
257 const OffsetIndices points_by_curve = curves.points_by_curve();
260 Array<int> curve_offset_data(selection.size() + 1);
261 Array<int> point_offset_data(selection.size() + 1);
263 int dst_curves_num = 0;
264 int dst_points_num = 0;
266 selection.foreach_index_optimized<
int>([&](
const int index,
const int i_curve) {
267 const int count = counts[index];
268 curve_offset_data[i_curve] = dst_curves_num;
269 point_offset_data[i_curve] = dst_points_num;
270 dst_curves_num +=
count;
271 dst_points_num +=
count * points_by_curve[index].
size();
274 if (dst_points_num == 0) {
278 curve_offset_data.
last() = dst_curves_num;
279 point_offset_data.
last() = dst_points_num;
288 const IndexRange src_curve_range = points_by_curve[i_src_curve];
289 const IndexRange dst_curves_range = curve_offsets[i_selection];
291 for (
const int i_duplicate :
IndexRange(dst_curves_range.
size())) {
292 dst_offsets[i_duplicate] = point_offsets[i_selection].start() +
293 src_curve_range.
size() * i_duplicate;
296 all_dst_offsets.
last() = dst_points_num;
309 new_curves.update_curve_types();
320 {GeometryComponent::Type::Curve, GeometryComponent::Type::GreasePencil});
321 GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry_set);
330 Curves *new_curves_id = bke::curves_new_nomain(std::move(new_curves));
331 bke::curves_copy_parameters(*curves_id, *new_curves_id);
335 using namespace bke::greasepencil;
336 threading::parallel_for(
337 grease_pencil->layers().index_range(), 16, [&](
const IndexRange layers_range) {
338 for (const int layer_i : layers_range) {
339 Layer &layer = grease_pencil->layer(layer_i);
340 Drawing *drawing = grease_pencil->get_eval_drawing(layer);
344 bke::CurvesGeometry &curves = drawing->strokes_for_write();
345 const bke::GreasePencilLayerFieldContext field_context{
346 *grease_pencil, AttrDomain::Curve, layer_i};
347 curves = duplicate_curves_CurveGeometry(curves,
353 drawing->tag_topology_changed();
378 for (
auto &attribute : bke::retrieve_attributes_for_transfer(
382 bke::attribute_filter_with_skip_ref(
383 attribute_filter, {
"id",
".corner_vert",
".corner_edge",
".edge_verts"})))
385 switch (attribute.meta_data.domain) {
386 case AttrDomain::Point:
387 bke::attribute_math::gather(attribute.src, vert_mapping, attribute.dst.span);
389 case AttrDomain::Edge:
390 bke::attribute_math::gather(attribute.src, edge_mapping, attribute.dst.span);
392 case AttrDomain::Face:
393 bke::attribute_math::gather_to_groups(
394 offsets, selection, attribute.src, attribute.dst.span);
396 case AttrDomain::Corner:
397 bke::attribute_math::gather(attribute.src, loop_mapping, attribute.dst.span);
403 attribute.dst.finish();
422 if (!src_attribute) {
427 if (!dst_attribute) {
436 for (
const int i_face : selection.index_range()) {
437 const IndexRange range = face_offsets[i_face];
438 if (range.is_empty()) {
442 for ([[maybe_unused]]
const int i_duplicate :
IndexRange(range.size())) {
443 for ([[maybe_unused]]
const int i_loops :
IndexRange(source.
size())) {
444 if (i_duplicate == 0) {
445 dst[loop_index] = src[vert_mapping[loop_index]];
448 dst[loop_index] = noise::hash(src[vert_mapping[loop_index]], i_duplicate);
472 const Span<int> corner_verts = mesh.corner_verts();
473 const Span<int> corner_edges = mesh.corner_edges();
477 evaluator.
add(count_field);
486 selection.foreach_index_optimized<
int>([&](
const int index,
const int i_selection) {
487 const int count = counts[index];
488 offset_data[i_selection] = total_faces;
489 total_faces +=
count;
490 total_loops +=
count * faces[index].
size();
492 offset_data[selection.size()] = total_faces;
508 selection.foreach_index_optimized<
int>([&](
const int index,
const int i_selection) {
509 const IndexRange face_range = duplicates[i_selection];
511 for ([[maybe_unused]]
const int i_duplicate : face_range.
index_range()) {
512 new_face_offsets[face_index] = loop_index;
513 for (
const int src_corner : source) {
514 loop_mapping[loop_index] = src_corner;
515 vert_mapping[loop_index] = corner_verts[src_corner];
516 edge_mapping[loop_index] = corner_edges[src_corner];
517 new_edges[loop_index][0] = loop_index;
518 if (src_corner != source.
last()) {
519 new_edges[loop_index][1] = loop_index + 1;
522 new_edges[loop_index][1] = new_face_offsets[face_index];
529 array_utils::fill_index_range<int>(new_corner_verts);
530 array_utils::fill_index_range<int>(new_corner_edges);
532 new_mesh->tag_loose_verts_none();
533 new_mesh->tag_loose_edges_none();
534 new_mesh->tag_overlapping_none();
543 new_mesh->attributes_for_write());
550 new_mesh->attributes_for_write());
580 for (
auto &attribute : bke::retrieve_attributes_for_transfer(
584 bke::attribute_filter_with_skip_ref(attribute_filter, {
"id",
".edge_verts"})))
586 switch (attribute.meta_data.domain) {
587 case AttrDomain::Edge:
588 bke::attribute_math::gather_to_groups(
589 offsets, selection, attribute.src, attribute.dst.span);
591 case AttrDomain::Point:
592 bke::attribute_math::gather(attribute.src, point_mapping, attribute.dst.span);
598 attribute.dst.finish();
613 if (!src_attribute) {
618 if (!dst_attribute) {
627 const IndexRange edge_range = offsets[i_selection];
631 const int2 &edge = edges[index];
634 dst[vert_range[0]] = src[edge[0]];
635 dst[vert_range[1]] = src[edge[1]];
636 for (
const int i_duplicate :
IndexRange(1, edge_range.
size() - 1)) {
637 dst[vert_range[i_duplicate * 2]] = noise::hash(src[edge[0]], i_duplicate);
638 dst[vert_range[i_duplicate * 2 + 1]] = noise::hash(src[edge[1]], i_duplicate);
659 evaluator.
add(count_field);
660 evaluator.set_selection(selection_field);
661 evaluator.evaluate();
662 const VArray<int> counts = evaluator.get_evaluated<
int>(0);
663 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
667 selection, counts, offset_data);
668 const int output_edges_num = duplicates.
total_size();
673 Array<int> vert_orig_indices(output_edges_num * 2);
675 const int2 &edge = edges[index];
676 const IndexRange edge_range = duplicates[i_selection];
680 vert_orig_indices[vert_range[i_duplicate * 2]] = edge[0];
681 vert_orig_indices[vert_range[i_duplicate * 2 + 1]] = edge[1];
685 threading::parallel_for(selection.index_range(), 1024, [&](
IndexRange range) {
686 for (const int i_selection : range) {
687 const IndexRange edge_range = duplicates[i_selection];
688 const IndexRange vert_range(edge_range.start() * 2, edge_range.size() * 2);
689 for (const int i_duplicate : IndexRange(edge_range.size())) {
690 int2 &new_edge = new_edges[edge_range[i_duplicate]];
691 new_edge[0] = vert_range[i_duplicate * 2];
692 new_edge[1] = vert_range[i_duplicate * 2] + 1;
697 copy_edge_attributes_without_id(vert_orig_indices,
702 new_mesh->attributes_for_write());
704 copy_stable_id_edges(
705 mesh, selection, duplicates, mesh.attributes(), new_mesh->attributes_for_write());
707 if (attribute_outputs.duplicate_index) {
708 create_duplicate_index_attribute(new_mesh->attributes_for_write(),
715 new_mesh->tag_overlapping_none();
717 geometry_set.replace_mesh(new_mesh);
739 evaluator.add(count_field);
740 evaluator.set_selection(selection_field);
741 evaluator.evaluate();
742 const VArray<int> counts = evaluator.get_evaluated<
int>(0);
743 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
747 selection, counts, offset_data);
753 offset_indices::fill_constant_group_size(1, 0, new_curves.offsets_for_write());
755 bke::gather_attributes_to_groups(src_curves.
attributes(),
761 new_curves.attributes_for_write());
763 for (
auto &attribute : bke::retrieve_attributes_for_transfer(
765 new_curves.attributes_for_write(),
767 bke::attribute_filter_with_skip_ref(attribute_filter, {
"id"})))
769 bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](
auto dummy) {
770 using T = decltype(dummy);
771 const Span<T> src = attribute.src.typed<T>();
772 MutableSpan<T> dst = attribute.dst.span.typed<T>();
773 selection.foreach_index(GrainSize(512), [&](const int64_t index, const int64_t i_selection) {
774 const T &src_value = src[point_to_curve_map[index]];
775 dst.slice(duplicates[i_selection]).fill(src_value);
778 attribute.dst.finish();
781 copy_stable_id_point(duplicates, src_curves.attributes(), new_curves.attributes_for_write());
783 if (attribute_outputs.duplicate_index) {
784 create_duplicate_index_attribute(new_curves.attributes_for_write(),
811 Curves *new_curves_id = bke::curves_new_nomain(std::move(new_curves));
812 bke::curves_copy_parameters(src_curves_id, *new_curves_id);
828 using namespace bke::greasepencil;
830 threading::parallel_for(
831 grease_pencil.layers().index_range(), 16, [&](
const IndexRange layers_range) {
832 for (const int layer_i : layers_range) {
833 Layer &layer = grease_pencil.layer(layer_i);
834 Drawing *drawing = grease_pencil.get_eval_drawing(layer);
838 bke::CurvesGeometry &curves = drawing->strokes_for_write();
839 const bke::GreasePencilLayerFieldContext field_context{
840 grease_pencil, AttrDomain::Point, layer_i};
841 curves = duplicate_points_CurvesGeometry(curves,
847 drawing->tag_topology_changed();
868 evaluator.
add(count_field);
869 evaluator.set_selection(selection_field);
870 evaluator.evaluate();
871 const VArray<int> counts = evaluator.get_evaluated<
int>(0);
872 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
876 selection, counts, offset_data);
880 bke::gather_attributes_to_groups(mesh.attributes(),
883 bke::attribute_filter_with_skip_ref(attribute_filter, {
"id"}),
886 new_mesh->attributes_for_write());
898 new_mesh->tag_overlapping_none();
919 evaluator.add(count_field);
920 evaluator.set_selection(selection_field);
921 evaluator.evaluate();
922 const VArray<int> counts = evaluator.get_evaluated<
int>(0);
923 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
927 selection, counts, offset_data);
931 bke::gather_attributes_to_groups(src_points.
attributes(),
934 bke::attribute_filter_with_skip_ref(attribute_filter, {
"id"}),
937 pointcloud->attributes_for_write());
966 switch (component_type) {
967 case GeometryComponent::Type::PointCloud:
970 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
973 case GeometryComponent::Type::Mesh:
976 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
979 case GeometryComponent::Type::Curve:
982 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
985 case GeometryComponent::Type::GreasePencil: {
988 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
996 component_types.
append(GeometryComponent::Type::Instance);
1012 using namespace bke::greasepencil;
1014 geometry_set.
clear();
1018 GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry_set);
1022 FieldEvaluator evaluator{field_context, src_grease_pencil.layers().size()};
1023 evaluator.add(count_field);
1024 evaluator.set_selection(selection_field);
1025 evaluator.evaluate();
1026 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
1027 const VArray<int> counts = evaluator.get_evaluated<
int>(0);
1031 selection, counts, offset_data);
1032 const int new_layers_num = duplicates.
total_size();
1033 if (new_layers_num == 0) {
1034 geometry_set.
clear();
1041 new_grease_pencil->add_layers_with_empty_drawings_for_eval(new_layers_num);
1043 selection.foreach_index([&](
const int src_layer_i,
const int pos) {
1045 if (range.is_empty()) {
1048 const Layer &src_layer = src_grease_pencil.layer(src_layer_i);
1049 const Drawing *src_drawing = src_grease_pencil.get_eval_drawing(src_layer);
1051 static_empty_curves;
1053 for (
Layer *new_layer : new_grease_pencil->layers_for_write().slice(range)) {
1055 new_layer->set_name(src_layer_name);
1056 Drawing *new_drawing = new_grease_pencil->get_eval_drawing(*new_layer);
1061 bke::gather_attributes_to_groups(src_grease_pencil.attributes(),
1067 new_grease_pencil->attributes_for_write());
1093 geometry_set.
clear();
1101 evaluator.add(count_field);
1102 evaluator.set_selection(selection_field);
1103 evaluator.evaluate();
1104 IndexMask selection = evaluator.get_evaluated_selection_as_mask();
1105 const VArray<int> counts = evaluator.get_evaluated<
int>(0);
1109 selection, counts, offset_data);
1111 geometry_set.
clear();
1115 std::unique_ptr<bke::Instances> dst_instances = std::make_unique<bke::Instances>();
1117 dst_instances->resize(duplicates.
total_size());
1118 for (
const int i_selection : selection.index_range()) {
1119 const IndexRange range = duplicates[i_selection];
1120 if (range.is_empty()) {
1125 const int new_handle = dst_instances->add_reference(reference);
1126 dst_instances->reference_handles_for_write().slice(range).fill(new_handle);
1129 bke::gather_attributes_to_groups(
1131 AttrDomain::Instance,
1132 AttrDomain::Instance,
1133 bke::attribute_filter_with_skip_ref(attribute_filter, {
"id",
".reference_index"}),
1136 dst_instances->attributes_for_write());
1140 AttrDomain::Instance,
1146 geometry_set = GeometrySet::from_instances(dst_instances.release());
1160 const AttrDomain duplicate_domain = AttrDomain(storage.domain);
1162 static auto max_zero_fn = mf::build::SI1_SO<int, int>(
1164 [](
int value) {
return std::max(0, value); },
1165 mf::build::exec_presets::AllSpanOrSingle());
1167 FieldOperation::Create(max_zero_fn, {
params.extract_input<
Field<int>>(
"Amount")}));
1171 attribute_outputs.duplicate_index =
params.get_output_anonymous_attribute_id_if_needed(
1176 if (duplicate_domain == AttrDomain::Instance) {
1178 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1182 switch (duplicate_domain) {
1183 case AttrDomain::Curve:
1185 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1187 case AttrDomain::Face:
1189 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1191 case AttrDomain::Edge:
1193 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1195 case AttrDomain::Point:
1197 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1199 case AttrDomain::Layer:
1201 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1211 params.set_default_remaining_outputs();
1215 params.set_output(
"Geometry", std::move(geometry_set));
1223 {
int(AttrDomain::Point),
"POINT", 0,
"Point",
""},
1224 {
int(AttrDomain::Edge),
"EDGE", 0,
"Edge",
""},
1225 {
int(AttrDomain::Face),
"FACE", 0,
"Face",
""},
1226 {
int(AttrDomain::Curve),
"SPLINE", 0,
"Spline",
""},
1227 {
int(AttrDomain::Layer),
"LAYER", 0,
"Layer",
""},
1228 {
int(AttrDomain::Instance),
"INSTANCE", 0,
"Instance",
""},
1229 {0,
nullptr, 0,
nullptr,
nullptr},
1235 "Which domain to duplicate",
1238 int(AttrDomain::Point),
1250 "NodeGeometryDuplicateElements",
Low-level operations for curves.
Low-level operations for grease pencil.
void BKE_grease_pencil_copy_parameters(const GreasePencil &src, GreasePencil &dst)
GreasePencil * BKE_grease_pencil_new_nomain()
void BKE_grease_pencil_copy_layer_parameters(const blender::bke::greasepencil::Layer &src, blender::bke::greasepencil::Layer &dst)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_GEOMETRY
General operations for point clouds.
PointCloud * BKE_pointcloud_new_nomain(int totpoint)
#define BLI_assert_unreachable()
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_storage_enum_accessors(member)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
MutableSpan< T > as_mutable_span()
const T & last(const int64_t n=0) const
void reinitialize(const int64_t new_size)
MutableSpan< T > typed() const
VArray< T > typed() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr int64_t start() const
constexpr IndexRange index_range() const
constexpr IndexRange drop_front(int64_t n) const
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr T & last(const int64_t n=0) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr IndexRange index_range() const
std::optional< T > get_if_single() const
void append(const T &value)
GAttributeReader lookup(const StringRef attribute_id) const
Array< int > point_to_curve_map() const
OffsetIndices< int > points_by_curve() const
MutableAttributeAccessor attributes_for_write()
AttributeAccessor attributes() const
Span< int > reference_handles() const
Span< InstanceReference > references() const
bke::AttributeAccessor attributes() const
int instances_num() const
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void set_selection(Field< bool > selection)
int add(GField field, GVArray *varray_ptr)
IndexMask get_evaluated_selection_as_mask() const
const GVArray & get_evaluated(const int field_index) const
IndexRange index_range() const
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
void node_register_type(bNodeType *ntype)
static void copy_stable_id_curves(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const OffsetIndices< int > offsets, bke::CurvesGeometry &dst_curves)
static void duplicate_points_grease_pencil(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static void duplicate_points_pointcloud(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static void duplicate_faces(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static OffsetIndices< int > accumulate_counts_to_offsets(const IndexMask &selection, const VArray< int > &counts, Array< int > &r_offset_data)
static void node_rna(StructRNA *srna)
static void node_init(bNodeTree *, bNode *node)
static void copy_edge_attributes_without_id(const Span< int > point_mapping, const OffsetIndices< int > offsets, const IndexMask &selection, const AttributeFilter &attribute_filter, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes)
static void duplicate_instances(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static bke::CurvesGeometry duplicate_curves_CurveGeometry(const bke::CurvesGeometry &curves, const FieldContext &field_context, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static void copy_stable_id_faces(const Mesh &mesh, const IndexMask &selection, const OffsetIndices< int > face_offsets, const Span< int > vert_mapping, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void copy_hashed_ids(const Span< int > src, const int hash, MutableSpan< int > dst)
static void duplicate_layers(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static void copy_stable_id_edges(const Mesh &mesh, const IndexMask &selection, const OffsetIndices< int > offsets, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes)
static void copy_face_attributes_without_id(const Span< int > edge_mapping, const Span< int > vert_mapping, const Span< int > loop_mapping, const OffsetIndices< int > offsets, const IndexMask &selection, const AttributeFilter &attribute_filter, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes)
static void node_declare(NodeDeclarationBuilder &b)
static void duplicate_points_curve(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static bke::CurvesGeometry duplicate_points_CurvesGeometry(const bke::CurvesGeometry &src_curves, const FieldContext &field_context, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static void duplicate_points_mesh(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static void copy_curve_attributes_without_id(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const OffsetIndices< int > curve_offsets, const AttributeFilter &attribute_filter, bke::CurvesGeometry &dst_curves)
static void node_geo_exec(GeoNodeExecParams params)
static void create_duplicate_index_attribute(bke::MutableAttributeAccessor attributes, const AttrDomain output_domain, const IndexMask &selection, const IndexAttributes &attribute_outputs, const OffsetIndices< int > offsets)
static void duplicate_edges(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
static void threaded_id_offset_copy(const OffsetIndices< int > offsets, const Span< int > src, MutableSpan< int > all_dst)
static void copy_stable_id_point(const OffsetIndices< int > offsets, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes)
static void node_register()
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
uint32_t hash(uint32_t kx)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void fill_constant_group_size(int size, int start_offset, MutableSpan< int > offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
const GreasePencil * get_grease_pencil() const
bool has_pointcloud() const
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void keep_only_during_modify(Span< GeometryComponent::Type > component_types)
const Curves * get_curves() const
const Instances * get_instances() const
bool has_grease_pencil() const
bool has_instances() const
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const PointCloud * get_pointcloud() const
const Mesh * get_mesh() const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GreasePencil * get_grease_pencil_for_write()
Vector< GeometryComponent::Type > gather_component_types(bool include_instances, bool ignore_empty) const
void remove_geometry_during_modify()
void replace_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
MutableVArraySpan< T > span
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGeometryExecFunction geometry_node_execute
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
std::optional< std::string > duplicate_index