38 "The number of duplicates to create for each element");
42 .
description(
"The duplicated geometry, not including the original geometry");
45 .
description(
"The indices of the duplicates for each element");
51 data->domain = int8_t(AttrDomain::Point);
96 for (const int i : range) {
97 MutableSpan<int> dst = all_dst.slice(offsets[i]);
101 dst.first() = src[i];
102 for (const int i_duplicate : dst.index_range().drop_front(1)) {
103 dst[i_duplicate] = noise::hash(src[i], i_duplicate);
120 for (
const int i :
indices.index_range()) {
124 duplicate_indices.
finish();
136 if (!src_attribute) {
141 if (!dst_attribute) {
176 switch (attribute.meta_data.domain) {
177 case AttrDomain::Curve:
179 curve_offsets, selection, attribute.src, attribute.dst.span);
181 case AttrDomain::Point:
183 using T = decltype(dummy);
184 const Span<T> src = attribute.src.typed<T>();
185 MutableSpan<T> dst = attribute.dst.span.typed<T>();
186 selection.foreach_index(
187 GrainSize(512), [&](const int64_t index, const int64_t i_selection) {
188 const Span<T> curve_src = src.slice(src_points_by_curve[index]);
189 for (const int dst_curve_index : curve_offsets[i_selection]) {
190 dst.slice(dst_points_by_curve[dst_curve_index]).copy_from(curve_src);
199 attribute.dst.finish();
215 if (!src_attribute) {
221 if (!dst_attribute) {
233 const Span<int> curve_src = src.
slice(src_points_by_curve[i_src_curve]);
234 const IndexRange duplicates_range = offsets[i_selection];
235 for (
const int i_duplicate :
IndexRange(offsets[i_selection].
size()).drop_front(1)) {
236 const int i_dst_curve = duplicates_range[i_duplicate];
252 evaluator.
add(count_field);
261 Array<int> curve_offset_data(selection.size() + 1);
262 Array<int> point_offset_data(selection.size() + 1);
264 int dst_curves_num = 0;
265 int dst_points_num = 0;
267 selection.foreach_index_optimized<
int>([&](
const int index,
const int i_curve) {
268 const int count = counts[index];
269 curve_offset_data[i_curve] = dst_curves_num;
270 point_offset_data[i_curve] = dst_points_num;
271 dst_curves_num +=
count;
272 dst_points_num +=
count * points_by_curve[index].
size();
275 if (dst_points_num == 0) {
279 curve_offset_data.
last() = dst_curves_num;
280 point_offset_data.
last() = dst_points_num;
289 const IndexRange src_curve_range = points_by_curve[i_src_curve];
290 const IndexRange dst_curves_range = curve_offsets[i_selection];
292 for (
const int i_duplicate :
IndexRange(dst_curves_range.
size())) {
293 dst_offsets[i_duplicate] = point_offsets[i_selection].start() +
294 src_curve_range.
size() * i_duplicate;
297 all_dst_offsets.
last() = dst_points_num;
321 {GeometryComponent::Type::Curve, GeometryComponent::Type::GreasePencil});
338 grease_pencil->layers().index_range(), 16, [&](
const IndexRange layers_range) {
339 for (const int layer_i : layers_range) {
340 Layer &layer = grease_pencil->layer(layer_i);
341 Drawing *drawing = grease_pencil->get_eval_drawing(layer);
345 bke::CurvesGeometry &curves = drawing->strokes_for_write();
346 const bke::GreasePencilLayerFieldContext field_context{
347 *grease_pencil, AttrDomain::Curve, layer_i};
348 curves = duplicate_curves_CurveGeometry(curves,
354 drawing->tag_topology_changed();
384 attribute_filter, {
"id",
".corner_vert",
".corner_edge",
".edge_verts"})))
386 switch (attribute.meta_data.domain) {
387 case AttrDomain::Point:
390 case AttrDomain::Edge:
393 case AttrDomain::Face:
395 offsets, selection, attribute.src, attribute.dst.span);
397 case AttrDomain::Corner:
404 attribute.dst.finish();
423 if (!src_attribute) {
428 if (!dst_attribute) {
438 const IndexRange range = face_offsets[i_face];
443 for ([[maybe_unused]]
const int i_duplicate :
IndexRange(range.
size())) {
444 for ([[maybe_unused]]
const int i_loops :
IndexRange(source.
size())) {
445 if (i_duplicate == 0) {
446 dst[loop_index] = src[vert_mapping[loop_index]];
449 dst[loop_index] =
noise::hash(src[vert_mapping[loop_index]], i_duplicate);
473 const Span<int> corner_verts = mesh.corner_verts();
474 const Span<int> corner_edges = mesh.corner_edges();
478 evaluator.
add(count_field);
488 const int count = counts[index];
489 offset_data[i_selection] = total_faces;
490 total_faces +=
count;
493 offset_data[selection.
size()] = total_faces;
510 const IndexRange face_range = duplicates[i_selection];
512 for ([[maybe_unused]]
const int i_duplicate : face_range.
index_range()) {
513 new_face_offsets[face_index] = loop_index;
514 for (
const int src_corner : source) {
515 loop_mapping[loop_index] = src_corner;
516 vert_mapping[loop_index] = corner_verts[src_corner];
517 edge_mapping[loop_index] = corner_edges[src_corner];
518 new_edges[loop_index][0] = loop_index;
519 if (src_corner != source.last()) {
520 new_edges[loop_index][1] = loop_index + 1;
523 new_edges[loop_index][1] = new_face_offsets[face_index];
533 new_mesh->tag_loose_verts_none();
534 new_mesh->tag_loose_edges_none();
535 new_mesh->tag_overlapping_none();
544 new_mesh->attributes_for_write());
551 new_mesh->attributes_for_write());
587 switch (attribute.meta_data.domain) {
588 case AttrDomain::Edge:
590 offsets, selection, attribute.src, attribute.dst.span);
592 case AttrDomain::Point:
599 attribute.dst.finish();
614 if (!src_attribute) {
619 if (!dst_attribute) {
628 const IndexRange edge_range = offsets[i_selection];
632 const int2 &edge = edges[index];
635 dst[vert_range[0]] = src[edge[0]];
636 dst[vert_range[1]] = src[edge[1]];
637 for (
const int i_duplicate :
IndexRange(1, edge_range.
size() - 1)) {
638 dst[vert_range[i_duplicate * 2]] =
noise::hash(src[edge[0]], i_duplicate);
639 dst[vert_range[i_duplicate * 2 + 1]] =
noise::hash(src[edge[1]], i_duplicate);
660 evaluator.
add(count_field);
668 selection, counts, offset_data);
669 const int output_edges_num = duplicates.
total_size();
674 Array<int> vert_orig_indices(output_edges_num * 2);
676 const int2 &edge = edges[index];
677 const IndexRange edge_range = duplicates[i_selection];
681 vert_orig_indices[vert_range[i_duplicate * 2]] = edge[0];
682 vert_orig_indices[vert_range[i_duplicate * 2 + 1]] = edge[1];
687 for (const int i_selection : range) {
688 const IndexRange edge_range = duplicates[i_selection];
689 const IndexRange vert_range(edge_range.start() * 2, edge_range.size() * 2);
690 for (const int i_duplicate : IndexRange(edge_range.size())) {
691 int2 &new_edge = new_edges[edge_range[i_duplicate]];
692 new_edge[0] = vert_range[i_duplicate * 2];
693 new_edge[1] = vert_range[i_duplicate * 2] + 1;
698 copy_edge_attributes_without_id(vert_orig_indices,
703 new_mesh->attributes_for_write());
705 copy_stable_id_edges(
706 mesh, selection, duplicates, mesh.attributes(), new_mesh->attributes_for_write());
708 if (attribute_outputs.duplicate_index) {
709 create_duplicate_index_attribute(new_mesh->attributes_for_write(),
716 new_mesh->tag_overlapping_none();
718 geometry_set.replace_mesh(new_mesh);
740 evaluator.
add(count_field);
748 selection, counts, offset_data);
771 using T = decltype(dummy);
772 const Span<T> src = attribute.src.typed<T>();
773 MutableSpan<T> dst = attribute.dst.span.typed<T>();
774 selection.foreach_index(GrainSize(512), [&](const int64_t index, const int64_t i_selection) {
775 const T &src_value = src[point_to_curve_map[index]];
776 dst.slice(duplicates[i_selection]).fill(src_value);
779 attribute.dst.finish();
782 copy_stable_id_point(duplicates, src_curves.attributes(), new_curves.attributes_for_write());
784 if (attribute_outputs.duplicate_index) {
785 create_duplicate_index_attribute(new_curves.attributes_for_write(),
832 grease_pencil.layers().index_range(), 16, [&](
const IndexRange layers_range) {
833 for (const int layer_i : layers_range) {
834 Layer &layer = grease_pencil.layer(layer_i);
835 Drawing *drawing = grease_pencil.get_eval_drawing(layer);
839 bke::CurvesGeometry &curves = drawing->strokes_for_write();
840 const bke::GreasePencilLayerFieldContext field_context{
841 grease_pencil, AttrDomain::Point, layer_i};
842 curves = duplicate_points_CurvesGeometry(curves,
848 drawing->tag_topology_changed();
869 evaluator.
add(count_field);
877 selection, counts, offset_data);
887 new_mesh->attributes_for_write());
899 new_mesh->tag_overlapping_none();
920 evaluator.
add(count_field);
928 selection, counts, offset_data);
938 pointcloud->attributes_for_write());
967 switch (component_type) {
968 case GeometryComponent::Type::PointCloud:
971 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
974 case GeometryComponent::Type::Mesh:
977 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
980 case GeometryComponent::Type::Curve:
983 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
986 case GeometryComponent::Type::GreasePencil: {
989 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
997 component_types.
append(GeometryComponent::Type::Instance);
1015 geometry_set.
clear();
1023 FieldEvaluator evaluator{field_context, src_grease_pencil.layers().size()};
1024 evaluator.
add(count_field);
1032 selection, counts, offset_data);
1033 const int new_layers_num = duplicates.
total_size();
1034 if (new_layers_num == 0) {
1035 geometry_set.
clear();
1042 new_grease_pencil->add_layers_with_empty_drawings_for_eval(new_layers_num);
1049 const Layer &src_layer = src_grease_pencil.layer(src_layer_i);
1050 const Drawing *src_drawing = src_grease_pencil.get_eval_drawing(src_layer);
1052 static_empty_curves;
1054 for (
Layer *new_layer : new_grease_pencil->layers_for_write().slice(range)) {
1056 new_layer->set_name(src_layer_name);
1057 Drawing *new_drawing = new_grease_pencil->get_eval_drawing(*new_layer);
1068 new_grease_pencil->attributes_for_write());
1094 geometry_set.
clear();
1102 evaluator.
add(count_field);
1110 selection, counts, offset_data);
1112 geometry_set.
clear();
1116 std::unique_ptr<bke::Instances> dst_instances = std::make_unique<bke::Instances>();
1118 dst_instances->resize(duplicates.
total_size());
1119 selection.
foreach_index([&](
const int i_src,
const int i_dst) {
1126 const int new_handle = dst_instances->add_reference(reference);
1127 dst_instances->reference_handles_for_write().slice(range).fill(new_handle);
1132 AttrDomain::Instance,
1133 AttrDomain::Instance,
1137 dst_instances->attributes_for_write());
1141 AttrDomain::Instance,
1163 static auto max_zero_fn = mf::build::SI1_SO<int, int>(
1165 [](
int value) {
return std::max(0, value); },
1166 mf::build::exec_presets::AllSpanOrSingle());
1172 attribute_outputs.duplicate_index =
params.get_output_anonymous_attribute_id_if_needed(
1177 if (duplicate_domain == AttrDomain::Instance) {
1179 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1183 switch (duplicate_domain) {
1184 case AttrDomain::Curve:
1186 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1188 case AttrDomain::Face:
1190 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1192 case AttrDomain::Edge:
1194 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1196 case AttrDomain::Point:
1198 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1200 case AttrDomain::Layer:
1202 geometry_set, count_field, selection_field, attribute_outputs, attribute_filter);
1212 params.set_default_remaining_outputs();
1216 params.set_output(
"Geometry", std::move(geometry_set));
1224 {int(AttrDomain::Point),
"POINT", 0,
"Point",
""},
1225 {int(AttrDomain::Edge),
"EDGE", 0,
"Edge",
""},
1226 {int(AttrDomain::Face),
"FACE", 0,
"Face",
""},
1227 {int(AttrDomain::Curve),
"SPLINE", 0,
"Spline",
""},
1228 {int(AttrDomain::Layer),
"LAYER", 0,
"Layer",
""},
1229 {int(AttrDomain::Instance),
"INSTANCE", 0,
"Instance",
""},
1230 {0,
nullptr, 0,
nullptr,
nullptr},
1236 "Which domain to duplicate",
1239 int(AttrDomain::Point),
1248 ntype.
ui_name =
"Duplicate Elements";
1249 ntype.
ui_description =
"Generate an arbitrary number copies of each selected input element";
1253 "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
#define GEO_NODE_DUPLICATE_ELEMENTS
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)
BMesh const char void * data
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 size() const
constexpr bool is_empty() 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 T & last(const int64_t n=0) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr 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
void update_curve_types()
MutableAttributeAccessor attributes_for_write()
AttributeAccessor attributes() const
MutableSpan< int > offsets_for_write()
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
void foreach_index_optimized(Fn &&fn) const
IndexRange index_range() const
void foreach_index(Fn &&fn) const
static std::shared_ptr< FieldOperation > Create(std::shared_ptr< const mf::MultiFunction > function, Vector< GField > inputs={})
static void remember_deformed_positions_if_necessary(GeometrySet &geometry)
IndexRange index_range() const
void * MEM_callocN(size_t len, const char *str)
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)
void gather(GSpan src, Span< int > map, GMutableSpan dst)
void gather_to_groups(OffsetIndices< int > dst_offsets, const IndexMask &src_selection, GSpan src, GMutableSpan dst)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
void curves_copy_parameters(const Curves &src, Curves &dst)
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const AttributeAccessor src_attributes, MutableAttributeAccessor dst_attributes, AttrDomainMask domain_mask, const AttributeFilter &attribute_filter={})
void gather_attributes_to_groups(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > dst_offsets, const IndexMask &src_selection, MutableAttributeAccessor dst_attributes)
void node_register_type(bNodeType &ntype)
auto attribute_filter_with_skip_ref(AttributeFilter filter, const Span< StringRef > skip)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Curves * curves_new_nomain(int points_num, int curves_num)
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 duplicate_curves(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 duplicate_points(GeometrySet &geometry_set, const Field< int > &count_field, const Field< bool > &selection_field, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter)
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))
VecBase< int32_t, 2 > int2
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
static GeometrySet from_instances(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
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
std::string ui_description
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
std::optional< std::string > duplicate_index
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)