Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc')
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc375
1 files changed, 206 insertions, 169 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
index 90837486186..679a8ba4f8c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
@@ -61,13 +61,11 @@ struct IndexAttributes {
* \{ */
static Map<AttributeIDRef, AttributeKind> gather_attributes_without_id(
- const GeometrySet &geometry_set,
- const GeometryComponentType component_type,
- const bool include_instances)
+ const GeometrySet &geometry_set, const GeometryComponentType component_type)
{
Map<AttributeIDRef, AttributeKind> attributes;
geometry_set.gather_attributes_for_propagation(
- {component_type}, component_type, include_instances, attributes);
+ {component_type}, component_type, false, attributes);
attributes.remove("id");
return attributes;
};
@@ -92,12 +90,16 @@ static Array<int> accumulate_counts_to_offsets(const IndexMask selection,
/* Utility functions for threaded copying of attribute data where possible. */
template<typename T>
-static void threaded_slice_fill(Span<int> offsets, Span<T> src, MutableSpan<T> dst)
+static void threaded_slice_fill(Span<int> offsets,
+ const IndexMask selection,
+ Span<T> src,
+ MutableSpan<T> dst)
{
BLI_assert(offsets.last() == dst.size());
+ BLI_assert(selection.size() == offsets.size() - 1);
threading::parallel_for(IndexRange(offsets.size() - 1), 512, [&](IndexRange range) {
for (const int i : range) {
- dst.slice(range_for_offsets_index(offsets, i)).fill(src[i]);
+ dst.slice(range_for_offsets_index(offsets, i)).fill(src[selection[i]]);
}
});
}
@@ -128,6 +130,9 @@ static void threaded_id_offset_copy(const Span<int> offsets,
for (const int i : range) {
dst[offsets[i]] = src[i];
const int count = offsets[i + 1] - offsets[i];
+ if (count == 0) {
+ continue;
+ }
for (const int i_duplicate : IndexRange(1, count - 1)) {
dst[offsets[i] + i_duplicate] = noise::hash(src[i], i_duplicate);
}
@@ -136,23 +141,22 @@ static void threaded_id_offset_copy(const Span<int> offsets,
}
/** Create the copy indices for the duplication domain. */
-static void create_duplicate_index_attribute(GeometryComponent &component,
- const AttributeDomain output_domain,
+static void create_duplicate_index_attribute(bke::MutableAttributeAccessor attributes,
+ const eAttrDomain output_domain,
const IndexMask selection,
const IndexAttributes &attribute_outputs,
const Span<int> offsets)
{
- OutputAttribute_Typed<int> copy_attribute = component.attribute_try_get_for_output_only<int>(
+ SpanAttributeWriter<int> duplicate_indices = attributes.lookup_or_add_for_write_only_span<int>(
attribute_outputs.duplicate_index.get(), output_domain);
- MutableSpan<int> duplicate_indices = copy_attribute.as_span();
for (const int i : IndexRange(selection.size())) {
const IndexRange range = range_for_offsets_index(offsets, i);
- MutableSpan<int> indices = duplicate_indices.slice(range);
+ MutableSpan<int> indices = duplicate_indices.span.slice(range);
for (const int i : indices.index_range()) {
indices[i] = i;
}
}
- copy_attribute.save();
+ duplicate_indices.finish();
}
/**
@@ -160,61 +164,57 @@ static void create_duplicate_index_attribute(GeometryComponent &component,
* and the duplicate number. This function is used for the point domain elements.
*/
static void copy_stable_id_point(const Span<int> offsets,
- const GeometryComponent &src_component,
- GeometryComponent &dst_component)
+ const bke::AttributeAccessor src_attributes,
+ bke::MutableAttributeAccessor dst_attributes)
{
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read("id");
+ GAttributeReader src_attribute = src_attributes.lookup("id");
if (!src_attribute) {
return;
}
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
if (!dst_attribute) {
return;
}
- VArray_Span<int> src{src_attribute.varray.typed<int>()};
- MutableSpan<int> dst = dst_attribute.as_span<int>();
+ VArraySpan<int> src{src_attribute.varray.typed<int>()};
+ MutableSpan<int> dst = dst_attribute.span.typed<int>();
threaded_id_offset_copy(offsets, src, dst);
- dst_attribute.save();
+ dst_attribute.finish();
}
-/* The attributes for the point (also instance) duplicated elements are stored sequentially
- * (1,1,1,2,2,2,3,3,3,etc) They can be copied by using a simple offset array. For each domain, if
- * elements are ordered differently a custom function is called to copy the attributes.
- */
-
-static void copy_point_attributes_without_id(GeometrySet &geometry_set,
- const GeometryComponentType component_type,
- const bool include_instances,
- const Span<int> offsets,
- const GeometryComponent &src_component,
- GeometryComponent &dst_component)
+static void copy_attributes_without_id(GeometrySet &geometry_set,
+ const GeometryComponentType component_type,
+ const eAttrDomain domain,
+ const Span<int> offsets,
+ const IndexMask selection,
+ const bke::AttributeAccessor src_attributes,
+ bke::MutableAttributeAccessor dst_attributes)
{
- Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
- geometry_set, component_type, include_instances);
+ const Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
+ geometry_set, component_type);
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id);
- if (!src_attribute || src_attribute.domain != ATTR_DOMAIN_POINT) {
+ GAttributeReader src_attribute = src_attributes.lookup(attribute_id);
+ if (!src_attribute || src_attribute.domain != domain) {
continue;
}
- AttributeDomain out_domain = src_attribute.domain;
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(
+ eAttrDomain out_domain = src_attribute.domain;
+ const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- VArray_Span<T> src = src_attribute.varray.typed<T>();
- MutableSpan<T> dst = dst_attribute.as_span<T>();
- threaded_slice_fill<T>(offsets, src, dst);
+ VArraySpan<T> src = src_attribute.varray.typed<T>();
+ MutableSpan<T> dst = dst_attribute.span.typed<T>();
+ threaded_slice_fill<T>(offsets, selection, src, dst);
});
- dst_attribute.save();
+ dst_attribute.finish();
}
}
@@ -229,40 +229,39 @@ static void copy_point_attributes_without_id(GeometrySet &geometry_set,
* copied with an offset fill, otherwise a mapping is used.
*/
static void copy_curve_attributes_without_id(const GeometrySet &geometry_set,
- const CurveComponent &src_component,
const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const Span<int> curve_offsets,
- bke::CurvesGeometry &dst_curves,
- CurveComponent &dst_component)
+ bke::CurvesGeometry &dst_curves)
{
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
- geometry_set, GEO_COMPONENT_TYPE_CURVE, false);
+ geometry_set, GEO_COMPONENT_TYPE_CURVE);
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id);
+ GAttributeReader src_attribute = src_curves.attributes().lookup(attribute_id);
if (!src_attribute) {
continue;
}
- AttributeDomain out_domain = src_attribute.domain;
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(
+ eAttrDomain out_domain = src_attribute.domain;
+ const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
- attribute_id, out_domain, data_type);
+ GSpanAttributeWriter dst_attribute =
+ dst_curves.attributes_for_write().lookup_or_add_for_write_only_span(
+ attribute_id, out_domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- VArray_Span<T> src{src_attribute.varray.typed<T>()};
- MutableSpan<T> dst = dst_attribute.as_span<T>();
+ VArraySpan<T> src{src_attribute.varray.typed<T>()};
+ MutableSpan<T> dst = dst_attribute.span.typed<T>();
switch (out_domain) {
case ATTR_DOMAIN_CURVE:
- threaded_slice_fill<T>(curve_offsets, src, dst);
+ threaded_slice_fill<T>(curve_offsets, selection, src, dst);
break;
case ATTR_DOMAIN_POINT:
threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) {
@@ -279,7 +278,7 @@ static void copy_curve_attributes_without_id(const GeometrySet &geometry_set,
break;
}
});
- dst_attribute.save();
+ dst_attribute.finish();
}
}
@@ -292,22 +291,21 @@ static void copy_curve_attributes_without_id(const GeometrySet &geometry_set,
static void copy_stable_id_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const Span<int> curve_offsets,
- const CurveComponent &src_component,
- bke::CurvesGeometry &dst_curves,
- CurveComponent &dst_component)
+ bke::CurvesGeometry &dst_curves)
{
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read("id");
+ GAttributeReader src_attribute = src_curves.attributes().lookup("id");
if (!src_attribute) {
return;
}
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
- "id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
+ GSpanAttributeWriter dst_attribute =
+ dst_curves.attributes_for_write().lookup_or_add_for_write_only_span(
+ "id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
if (!dst_attribute) {
return;
}
- VArray_Span<int> src{src_attribute.varray.typed<int>()};
- MutableSpan<int> dst = dst_attribute.as_span<int>();
+ VArraySpan<int> src{src_attribute.varray.typed<int>()};
+ MutableSpan<int> dst = dst_attribute.span.typed<int>();
threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) {
for (const int i_selection : range) {
@@ -321,7 +319,7 @@ static void copy_stable_id_curves(const bke::CurvesGeometry &src_curves,
}
}
});
- dst_attribute.save();
+ dst_attribute.finish();
}
static void duplicate_curves(GeometrySet &geometry_set,
@@ -364,6 +362,7 @@ static void duplicate_curves(GeometrySet &geometry_set,
point_offsets.last() = dst_points_num;
Curves *new_curves_id = bke::curves_new_nomain(dst_points_num, dst_curves_num);
+ bke::curves_copy_parameters(curves_id, *new_curves_id);
bke::CurvesGeometry &new_curves = bke::CurvesGeometry::wrap(new_curves_id->geometry);
MutableSpan<int> all_dst_offsets = new_curves.offsets_for_write();
@@ -381,18 +380,16 @@ static void duplicate_curves(GeometrySet &geometry_set,
});
all_dst_offsets.last() = dst_points_num;
- CurveComponent dst_component;
- dst_component.replace(new_curves_id, GeometryOwnershipType::Editable);
+ copy_curve_attributes_without_id(geometry_set, curves, selection, curve_offsets, new_curves);
- copy_curve_attributes_without_id(
- geometry_set, src_component, curves, selection, curve_offsets, new_curves, dst_component);
-
- copy_stable_id_curves(
- curves, selection, curve_offsets, src_component, new_curves, dst_component);
+ copy_stable_id_curves(curves, selection, curve_offsets, new_curves);
if (attribute_outputs.duplicate_index) {
- create_duplicate_index_attribute(
- dst_component, ATTR_DOMAIN_CURVE, selection, attribute_outputs, curve_offsets);
+ create_duplicate_index_attribute(new_curves.attributes_for_write(),
+ ATTR_DOMAIN_CURVE,
+ selection,
+ attribute_outputs,
+ curve_offsets);
}
geometry_set.replace_curves(new_curves_id);
@@ -413,23 +410,24 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set,
const Span<int> vert_mapping,
const Span<int> loop_mapping,
const Span<int> offsets,
- const GeometryComponent &src_component,
- GeometryComponent &dst_component)
+ const IndexMask selection,
+ const bke::AttributeAccessor src_attributes,
+ bke::MutableAttributeAccessor dst_attributes)
{
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
- geometry_set, GEO_COMPONENT_TYPE_MESH, false);
+ geometry_set, GEO_COMPONENT_TYPE_MESH);
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id);
+ GAttributeReader src_attribute = src_attributes.lookup(attribute_id);
if (!src_attribute) {
continue;
}
- AttributeDomain out_domain = src_attribute.domain;
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(
+ eAttrDomain out_domain = src_attribute.domain;
+ const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
if (!dst_attribute) {
continue;
@@ -437,12 +435,12 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set,
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- VArray_Span<T> src{src_attribute.varray.typed<T>()};
- MutableSpan<T> dst = dst_attribute.as_span<T>();
+ VArraySpan<T> src{src_attribute.varray.typed<T>()};
+ MutableSpan<T> dst = dst_attribute.span.typed<T>();
switch (out_domain) {
case ATTR_DOMAIN_FACE:
- threaded_slice_fill<T>(offsets, src, dst);
+ threaded_slice_fill<T>(offsets, selection, src, dst);
break;
case ATTR_DOMAIN_EDGE:
threaded_mapped_copy<T>(edge_mapping, src, dst);
@@ -457,7 +455,7 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set,
break;
}
});
- dst_attribute.save();
+ dst_attribute.finish();
}
}
@@ -472,21 +470,21 @@ static void copy_stable_id_faces(const Mesh &mesh,
const IndexMask selection,
const Span<int> poly_offsets,
const Span<int> vert_mapping,
- const MeshComponent &src_component,
- MeshComponent &dst_component)
+ const bke::AttributeAccessor src_attributes,
+ bke::MutableAttributeAccessor dst_attributes)
{
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read("id");
+ GAttributeReader src_attribute = src_attributes.lookup("id");
if (!src_attribute) {
return;
}
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
if (!dst_attribute) {
return;
}
- VArray_Span<int> src{src_attribute.varray.typed<int>()};
- MutableSpan<int> dst = dst_attribute.as_span<int>();
+ VArraySpan<int> src{src_attribute.varray.typed<int>()};
+ MutableSpan<int> dst = dst_attribute.span.typed<int>();
Span<MPoly> polys(mesh.mpoly, mesh.totpoly);
int loop_index = 0;
@@ -509,7 +507,7 @@ static void copy_stable_id_faces(const Mesh &mesh,
}
}
- dst_attribute.save();
+ dst_attribute.finish();
}
static void duplicate_faces(GeometrySet &geometry_set,
@@ -590,22 +588,28 @@ static void duplicate_faces(GeometrySet &geometry_set,
}
}
- MeshComponent dst_component;
- dst_component.replace(new_mesh, GeometryOwnershipType::Editable);
-
copy_face_attributes_without_id(geometry_set,
edge_mapping,
vert_mapping,
loop_mapping,
offsets,
- src_component,
- dst_component);
+ selection,
+ bke::mesh_attributes(mesh),
+ bke::mesh_attributes_for_write(*new_mesh));
- copy_stable_id_faces(mesh, selection, offsets, vert_mapping, src_component, dst_component);
+ copy_stable_id_faces(mesh,
+ selection,
+ offsets,
+ vert_mapping,
+ bke::mesh_attributes(mesh),
+ bke::mesh_attributes_for_write(*new_mesh));
if (attribute_outputs.duplicate_index) {
- create_duplicate_index_attribute(
- dst_component, ATTR_DOMAIN_FACE, selection, attribute_outputs, offsets);
+ create_duplicate_index_attribute(bke::mesh_attributes_for_write(*new_mesh),
+ ATTR_DOMAIN_FACE,
+ selection,
+ attribute_outputs,
+ offsets);
}
geometry_set.replace_mesh(new_mesh);
@@ -624,35 +628,36 @@ static void duplicate_faces(GeometrySet &geometry_set,
static void copy_edge_attributes_without_id(GeometrySet &geometry_set,
const Span<int> point_mapping,
const Span<int> offsets,
- const GeometryComponent &src_component,
- GeometryComponent &dst_component)
+ const IndexMask selection,
+ const bke::AttributeAccessor src_attributes,
+ bke::MutableAttributeAccessor dst_attributes)
{
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
- geometry_set, GEO_COMPONENT_TYPE_MESH, false);
+ geometry_set, GEO_COMPONENT_TYPE_MESH);
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id);
+ GAttributeReader src_attribute = src_attributes.lookup(attribute_id);
if (!src_attribute) {
continue;
}
- const AttributeDomain out_domain = src_attribute.domain;
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(
+ const eAttrDomain out_domain = src_attribute.domain;
+ const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- VArray_Span<T> src{src_attribute.varray.typed<T>()};
- MutableSpan<T> dst = dst_attribute.as_span<T>();
+ VArraySpan<T> src{src_attribute.varray.typed<T>()};
+ MutableSpan<T> dst = dst_attribute.span.typed<T>();
switch (out_domain) {
case ATTR_DOMAIN_EDGE:
- threaded_slice_fill<T>(offsets, src, dst);
+ threaded_slice_fill<T>(offsets, selection, src, dst);
break;
case ATTR_DOMAIN_POINT:
threaded_mapped_copy<T>(point_mapping, src, dst);
@@ -661,7 +666,7 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set,
break;
}
});
- dst_attribute.save();
+ dst_attribute.finish();
}
}
@@ -672,14 +677,14 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set,
static void copy_stable_id_edges(const Mesh &mesh,
const IndexMask selection,
const Span<int> edge_offsets,
- const MeshComponent &src_component,
- MeshComponent &dst_component)
+ const bke::AttributeAccessor src_attributes,
+ bke::MutableAttributeAccessor dst_attributes)
{
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read("id");
+ GAttributeReader src_attribute = src_attributes.lookup("id");
if (!src_attribute) {
return;
}
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
if (!dst_attribute) {
return;
@@ -687,15 +692,15 @@ static void copy_stable_id_edges(const Mesh &mesh,
Span<MEdge> edges(mesh.medge, mesh.totedge);
- VArray_Span<int> src{src_attribute.varray.typed<int>()};
- MutableSpan<int> dst = dst_attribute.as_span<int>();
+ VArraySpan<int> src{src_attribute.varray.typed<int>()};
+ MutableSpan<int> dst = dst_attribute.span.typed<int>();
threading::parallel_for(IndexRange(selection.size()), 1024, [&](IndexRange range) {
- for (const int i_edge : range) {
- const IndexRange edge_range = range_for_offsets_index(edge_offsets, i_edge);
+ for (const int i_selection : range) {
+ const IndexRange edge_range = range_for_offsets_index(edge_offsets, i_selection);
if (edge_range.size() == 0) {
continue;
}
- const MEdge &edge = edges[i_edge];
+ const MEdge &edge = edges[selection[i_selection]];
const IndexRange vert_range = {edge_range.start() * 2, edge_range.size() * 2};
dst[vert_range[0]] = src[edge.v1];
@@ -706,7 +711,7 @@ static void copy_stable_id_edges(const Mesh &mesh,
}
}
});
- dst_attribute.save();
+ dst_attribute.finish();
}
static void duplicate_edges(GeometrySet &geometry_set,
@@ -739,9 +744,9 @@ static void duplicate_edges(GeometrySet &geometry_set,
Array<int> vert_orig_indices(edge_offsets.last() * 2);
threading::parallel_for(selection.index_range(), 1024, [&](IndexRange range) {
- for (const int i_edge : range) {
- const MEdge &edge = edges[i_edge];
- const IndexRange edge_range = range_for_offsets_index(edge_offsets, i_edge);
+ for (const int i_selection : range) {
+ const MEdge &edge = edges[selection[i_selection]];
+ const IndexRange edge_range = range_for_offsets_index(edge_offsets, i_selection);
const IndexRange vert_range(edge_range.start() * 2, edge_range.size() * 2);
for (const int i_duplicate : IndexRange(edge_range.size())) {
@@ -752,8 +757,8 @@ static void duplicate_edges(GeometrySet &geometry_set,
});
threading::parallel_for(selection.index_range(), 1024, [&](IndexRange range) {
- for (const int i_edge : range) {
- const IndexRange edge_range = range_for_offsets_index(edge_offsets, i_edge);
+ for (const int i_selection : range) {
+ const IndexRange edge_range = range_for_offsets_index(edge_offsets, i_selection);
const IndexRange vert_range(edge_range.start() * 2, edge_range.size() * 2);
for (const int i_duplicate : IndexRange(edge_range.size())) {
MEdge &new_edge = new_edges[edge_range[i_duplicate]];
@@ -764,17 +769,25 @@ static void duplicate_edges(GeometrySet &geometry_set,
}
});
- MeshComponent dst_component;
- dst_component.replace(new_mesh, GeometryOwnershipType::Editable);
-
- copy_edge_attributes_without_id(
- geometry_set, vert_orig_indices, edge_offsets, src_component, dst_component);
+ copy_edge_attributes_without_id(geometry_set,
+ vert_orig_indices,
+ edge_offsets,
+ selection,
+ bke::mesh_attributes(mesh),
+ bke::mesh_attributes_for_write(*new_mesh));
- copy_stable_id_edges(mesh, selection, edge_offsets, src_component, dst_component);
+ copy_stable_id_edges(mesh,
+ selection,
+ edge_offsets,
+ bke::mesh_attributes(mesh),
+ bke::mesh_attributes_for_write(*new_mesh));
if (attribute_outputs.duplicate_index) {
- create_duplicate_index_attribute(
- dst_component, ATTR_DOMAIN_EDGE, selection, attribute_outputs, edge_offsets);
+ create_duplicate_index_attribute(bke::mesh_attributes_for_write(*new_mesh),
+ ATTR_DOMAIN_EDGE,
+ selection,
+ attribute_outputs,
+ edge_offsets);
}
geometry_set.replace_mesh(new_mesh);
@@ -818,6 +831,7 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
});
Curves *new_curves_id = bke::curves_new_nomain(dst_num, dst_num);
+ bke::curves_copy_parameters(src_curves_id, *new_curves_id);
bke::CurvesGeometry &new_curves = bke::CurvesGeometry::wrap(new_curves_id->geometry);
MutableSpan<int> new_curve_offsets = new_curves.offsets_for_write();
for (const int i : new_curves.curves_range()) {
@@ -825,32 +839,30 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
}
new_curve_offsets.last() = dst_num;
- CurveComponent dst_component;
- dst_component.replace(new_curves_id, GeometryOwnershipType::Editable);
-
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
- geometry_set, GEO_COMPONENT_TYPE_CURVE, false);
+ geometry_set, GEO_COMPONENT_TYPE_CURVE);
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
- ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id);
+ GAttributeReader src_attribute = src_component.attributes()->lookup(attribute_id);
if (!src_attribute) {
continue;
}
- AttributeDomain domain = src_attribute.domain;
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(
+ eAttrDomain domain = src_attribute.domain;
+ const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
- attribute_id, domain, data_type);
+ GSpanAttributeWriter dst_attribute =
+ new_curves.attributes_for_write().lookup_or_add_for_write_only_span(
+ attribute_id, domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- VArray_Span<T> src{src_attribute.varray.typed<T>()};
- MutableSpan<T> dst = dst_attribute.as_span<T>();
+ VArraySpan<T> src{src_attribute.varray.typed<T>()};
+ MutableSpan<T> dst = dst_attribute.span.typed<T>();
switch (domain) {
case ATTR_DOMAIN_CURVE:
@@ -863,20 +875,23 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
});
break;
case ATTR_DOMAIN_POINT:
- threaded_slice_fill(offsets, src, dst);
+ threaded_slice_fill(offsets, selection, src, dst);
break;
default:
break;
}
});
- dst_attribute.save();
+ dst_attribute.finish();
}
- copy_stable_id_point(offsets, src_component, dst_component);
+ copy_stable_id_point(offsets, src_curves.attributes(), new_curves.attributes_for_write());
if (attribute_outputs.duplicate_index) {
- create_duplicate_index_attribute(
- dst_component, ATTR_DOMAIN_POINT, selection, attribute_outputs, offsets.as_span());
+ create_duplicate_index_attribute(new_curves.attributes_for_write(),
+ ATTR_DOMAIN_POINT,
+ selection,
+ attribute_outputs,
+ offsets.as_span());
}
geometry_set.replace_curves(new_curves_id);
@@ -910,18 +925,25 @@ static void duplicate_points_mesh(GeometrySet &geometry_set,
Mesh *new_mesh = BKE_mesh_new_nomain(offsets.last(), 0, 0, 0, 0);
MutableSpan<MVert> dst_verts(new_mesh->mvert, new_mesh->totvert);
- threaded_slice_fill(offsets.as_span(), src_verts, dst_verts);
+ threaded_slice_fill(offsets.as_span(), selection, src_verts, dst_verts);
- MeshComponent dst_component;
- dst_component.replace(new_mesh, GeometryOwnershipType::Editable);
- copy_point_attributes_without_id(
- geometry_set, GEO_COMPONENT_TYPE_MESH, false, offsets, src_component, dst_component);
+ copy_attributes_without_id(geometry_set,
+ GEO_COMPONENT_TYPE_MESH,
+ ATTR_DOMAIN_POINT,
+ offsets,
+ selection,
+ bke::mesh_attributes(mesh),
+ bke::mesh_attributes_for_write(*new_mesh));
- copy_stable_id_point(offsets, src_component, dst_component);
+ copy_stable_id_point(
+ offsets, bke::mesh_attributes(mesh), bke::mesh_attributes_for_write(*new_mesh));
if (attribute_outputs.duplicate_index) {
- create_duplicate_index_attribute(
- dst_component, ATTR_DOMAIN_POINT, selection, attribute_outputs, offsets.as_span());
+ create_duplicate_index_attribute(bke::mesh_attributes_for_write(*new_mesh),
+ ATTR_DOMAIN_POINT,
+ selection,
+ attribute_outputs,
+ offsets.as_span());
}
geometry_set.replace_mesh(new_mesh);
@@ -940,7 +962,7 @@ static void duplicate_points_pointcloud(GeometrySet &geometry_set,
{
const PointCloudComponent &src_points =
*geometry_set.get_component_for_read<PointCloudComponent>();
- const int point_num = src_points.attribute_domain_num(ATTR_DOMAIN_POINT);
+ const int point_num = src_points.attribute_domain_size(ATTR_DOMAIN_POINT);
GeometryComponentFieldContext field_context{src_points, ATTR_DOMAIN_POINT};
FieldEvaluator evaluator{field_context, point_num};
@@ -953,17 +975,24 @@ static void duplicate_points_pointcloud(GeometrySet &geometry_set,
Array<int> offsets = accumulate_counts_to_offsets(selection, counts);
PointCloud *pointcloud = BKE_pointcloud_new_nomain(offsets.last());
- PointCloudComponent dst_component;
- dst_component.replace(pointcloud, GeometryOwnershipType::Editable);
- copy_point_attributes_without_id(
- geometry_set, GEO_COMPONENT_TYPE_POINT_CLOUD, false, offsets, src_points, dst_component);
+ copy_attributes_without_id(geometry_set,
+ GEO_COMPONENT_TYPE_POINT_CLOUD,
+ ATTR_DOMAIN_POINT,
+ offsets,
+ selection,
+ *src_points.attributes(),
+ bke::pointcloud_attributes_for_write(*pointcloud));
- copy_stable_id_point(offsets, src_points, dst_component);
+ copy_stable_id_point(
+ offsets, *src_points.attributes(), bke::pointcloud_attributes_for_write(*pointcloud));
if (attribute_outputs.duplicate_index) {
- create_duplicate_index_attribute(
- dst_component, ATTR_DOMAIN_POINT, selection, attribute_outputs, offsets);
+ create_duplicate_index_attribute(bke::pointcloud_attributes_for_write(*pointcloud),
+ ATTR_DOMAIN_POINT,
+ selection,
+ attribute_outputs,
+ offsets);
}
geometry_set.replace_pointcloud(pointcloud);
}
@@ -1055,12 +1084,20 @@ static void duplicate_instances(GeometrySet &geometry_set,
dst_instances.instance_reference_handles().slice(range).fill(new_handle);
}
- copy_point_attributes_without_id(
- geometry_set, GEO_COMPONENT_TYPE_INSTANCES, true, offsets, src_instances, dst_instances);
+ copy_attributes_without_id(geometry_set,
+ GEO_COMPONENT_TYPE_INSTANCES,
+ ATTR_DOMAIN_INSTANCE,
+ offsets,
+ selection,
+ *src_instances.attributes(),
+ *dst_instances.attributes_for_write());
if (attribute_outputs.duplicate_index) {
- create_duplicate_index_attribute(
- dst_instances, ATTR_DOMAIN_INSTANCE, selection, attribute_outputs, offsets);
+ create_duplicate_index_attribute(*dst_instances.attributes_for_write(),
+ ATTR_DOMAIN_INSTANCE,
+ selection,
+ attribute_outputs,
+ offsets);
}
geometry_set = std::move(dst_geometry);
@@ -1077,7 +1114,7 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
const NodeGeometryDuplicateElements &storage = node_storage(params.node());
- const AttributeDomain duplicate_domain = AttributeDomain(storage.domain);
+ const eAttrDomain duplicate_domain = eAttrDomain(storage.domain);
Field<int> count_field = params.extract_input<Field<int>>("Amount");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");