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");
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);
119 for (
const int i :
indices.index_range()) {
123 duplicate_indices.
finish();
135 if (!src_attribute) {
140 if (!dst_attribute) {
176 case AttrDomain::Curve:
180 case AttrDomain::Point:
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);
214 if (!src_attribute) {
220 if (!dst_attribute) {
232 const Span<int> curve_src = src.
slice(src_points_by_curve[i_src_curve]);
233 const IndexRange duplicates_range = offsets[i_selection];
234 for (
const int i_duplicate :
IndexRange(offsets[i_selection].
size()).drop_front(1)) {
235 const int i_dst_curve = duplicates_range[i_duplicate];
251 evaluator.
add(count_field);
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;
320 {GeometryComponent::Type::Curve, GeometryComponent::Type::GreasePencil});
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();
383 attribute_filter, {
"id",
".corner_vert",
".corner_edge",
".edge_verts"})))
386 case AttrDomain::Point:
389 case AttrDomain::Edge:
392 case AttrDomain::Face:
396 case AttrDomain::Corner:
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];
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;
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];
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());
587 case AttrDomain::Edge:
591 case AttrDomain::Point:
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);
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];
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);
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);
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(),
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);
886 new_mesh->attributes_for_write());
898 new_mesh->tag_overlapping_none();
919 evaluator.
add(count_field);
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);
1014 geometry_set.
clear();
1022 FieldEvaluator evaluator{field_context, src_grease_pencil.layers().size()};
1023 evaluator.
add(count_field);
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) {
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);
1067 new_grease_pencil->attributes_for_write());
1093 geometry_set.
clear();
1101 evaluator.
add(count_field);
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];
1125 const int new_handle = dst_instances->add_reference(reference);
1126 dst_instances->reference_handles_for_write().slice(range).fill(new_handle);
1131 AttrDomain::Instance,
1132 AttrDomain::Instance,
1136 dst_instances->attributes_for_write());
1140 AttrDomain::Instance,
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());
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
#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)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
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 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
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
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 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)
auto attribute_filter_with_skip_ref(AttributeFilter filter, const Span< StringRef > skip)
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)
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, 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)
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
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
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