diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 7c01a9205fc..76558b9ba28 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -41,6 +41,7 @@ typedef enum eAttrDomainMask { ATTR_DOMAIN_MASK_CURVE = (1 << 4), ATTR_DOMAIN_MASK_ALL = (1 << 5) - 1 } eAttrDomainMask; +ENUM_OPERATORS(eAttrDomainMask, ATTR_DOMAIN_MASK_ALL); #define ATTR_DOMAIN_AS_MASK(domain) ((eAttrDomainMask)((1 << (int)(domain)))) diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 8a6e1486701..e6721e96ab8 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -905,8 +905,10 @@ Vector retrieve_attributes_for_transfer( BLI_assert(src); bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span( id, meta_data.domain, meta_data.data_type); - BLI_assert(dst); - attributes.append({std::move(src), meta_data, std::move(dst)}); + if (dst) { + /* Writing the the legacy "normal" attribute will fail. */ + attributes.append({std::move(src), meta_data, std::move(dst)}); + } return true; }); 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 5b260a818a1..c61bb8b4d8a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -64,18 +64,6 @@ struct IndexAttributes { /** \name Utility Functions * \{ */ -static Map gather_attributes_without_id( - const GeometrySet &geometry_set, - const GeometryComponentType component_type, - const AnonymousAttributePropagationInfo &propagation_info) -{ - Map attributes; - geometry_set.gather_attributes_for_propagation( - {component_type}, component_type, false, propagation_info, attributes); - attributes.remove("id"); - return attributes; -}; - static OffsetIndices accumulate_counts_to_offsets(const IndexMask selection, const VArray &counts, Array &r_offset_data) @@ -183,39 +171,25 @@ static void copy_stable_id_point(const OffsetIndices offsets, dst_attribute.finish(); } -static void copy_attributes_without_id(GeometrySet &geometry_set, - const GeometryComponentType component_type, - const eAttrDomain domain, - const OffsetIndices offsets, +static void copy_attributes_without_id(const OffsetIndices offsets, const IndexMask selection, const AnonymousAttributePropagationInfo &propagation_info, + const eAttrDomain domain, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes) { - const Map attributes = gather_attributes_without_id( - geometry_set, component_type, propagation_info); - - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_attributes.lookup(attribute_id); - if (!src_attribute || src_attribute.domain != domain) { - continue; - } - eAttrDomain out_domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - 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) { + for (auto &attribute : bke::retrieve_attributes_for_transfer(src_attributes, + dst_attributes, + ATTR_DOMAIN_AS_MASK(domain), + propagation_info, + {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src = src_attribute.varray.typed(); - MutableSpan dst = dst_attribute.span.typed(); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); threaded_slice_fill(offsets, selection, src, dst); }); - dst_attribute.finish(); + attribute.dst.finish(); } } @@ -230,42 +204,26 @@ static void copy_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 bke::CurvesGeometry &src_curves, const IndexMask selection, const OffsetIndices curve_offsets, const AnonymousAttributePropagationInfo &propagation_info, bke::CurvesGeometry &dst_curves) { - Map attributes = gather_attributes_without_id( - geometry_set, GEO_COMPONENT_TYPE_CURVE, propagation_info); - const OffsetIndices src_points_by_curve = src_curves.points_by_curve(); const OffsetIndices dst_points_by_curve = dst_curves.points_by_curve(); - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_curves.attributes().lookup(attribute_id); - if (!src_attribute) { - continue; - } - - eAttrDomain out_domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.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) { + for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(), + dst_curves.attributes_for_write(), + ATTR_DOMAIN_MASK_ALL, + propagation_info, + {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src{src_attribute.varray.typed()}; - MutableSpan dst = dst_attribute.span.typed(); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); - switch (out_domain) { + switch (attribute.meta_data.domain) { case ATTR_DOMAIN_CURVE: threaded_slice_fill(curve_offsets, selection, src, dst); break; @@ -281,10 +239,11 @@ static void copy_curve_attributes_without_id( }); break; default: + BLI_assert_unreachable(); break; } }); - dst_attribute.finish(); + attribute.dst.finish(); } } @@ -394,8 +353,7 @@ static void duplicate_curves(GeometrySet &geometry_set, }); all_dst_offsets.last() = dst_points_num; - copy_curve_attributes_without_id( - geometry_set, curves, selection, curve_offsets, propagation_info, new_curves); + copy_curve_attributes_without_id(curves, selection, curve_offsets, propagation_info, new_curves); copy_stable_id_curves(curves, selection, curve_offsets, new_curves); @@ -422,7 +380,6 @@ static void duplicate_curves(GeometrySet &geometry_set, * copied with an offset fill, otherwise a mapping is used. */ static void copy_face_attributes_without_id( - GeometrySet &geometry_set, const Span edge_mapping, const Span vert_mapping, const Span loop_mapping, @@ -432,31 +389,14 @@ static void copy_face_attributes_without_id( const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes) { - Map attributes = gather_attributes_without_id( - geometry_set, GEO_COMPONENT_TYPE_MESH, propagation_info); - - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_attributes.lookup(attribute_id); - if (!src_attribute) { - continue; - } - - eAttrDomain out_domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - 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) { + for (auto &attribute : bke::retrieve_attributes_for_transfer( + src_attributes, dst_attributes, ATTR_DOMAIN_MASK_ALL, propagation_info, {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src{src_attribute.varray.typed()}; - MutableSpan dst = dst_attribute.span.typed(); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); - switch (out_domain) { + switch (attribute.meta_data.domain) { case ATTR_DOMAIN_POINT: array_utils::gather(src, vert_mapping, dst); break; @@ -470,10 +410,11 @@ static void copy_face_attributes_without_id( array_utils::gather(src, loop_mapping, dst); break; default: + BLI_assert_unreachable(); break; } }); - dst_attribute.finish(); + attribute.dst.finish(); } } @@ -607,8 +548,7 @@ static void duplicate_faces(GeometrySet &geometry_set, new_mesh->loose_edges_tag_none(); - copy_face_attributes_without_id(geometry_set, - edge_mapping, + copy_face_attributes_without_id(edge_mapping, vert_mapping, loop_mapping, duplicates, @@ -646,7 +586,6 @@ static void duplicate_faces(GeometrySet &geometry_set, * copied with an offset fill, for point domain a mapping is used. */ static void copy_edge_attributes_without_id( - GeometrySet &geometry_set, const Span point_mapping, const OffsetIndices offsets, const IndexMask selection, @@ -654,30 +593,18 @@ static void copy_edge_attributes_without_id( const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes) { - Map attributes = gather_attributes_without_id( - geometry_set, GEO_COMPONENT_TYPE_MESH, propagation_info); - - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_attributes.lookup(attribute_id); - if (!src_attribute) { - continue; - } - - const eAttrDomain out_domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - 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) { + for (auto &attribute : + bke::retrieve_attributes_for_transfer(src_attributes, + dst_attributes, + ATTR_DOMAIN_MASK_POINT | ATTR_DOMAIN_MASK_EDGE, + propagation_info, + {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src{src_attribute.varray.typed()}; - MutableSpan dst = dst_attribute.span.typed(); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); - switch (out_domain) { + switch (attribute.meta_data.domain) { case ATTR_DOMAIN_EDGE: threaded_slice_fill(offsets, selection, src, dst); break; @@ -685,10 +612,11 @@ static void copy_edge_attributes_without_id( array_utils::gather(src, point_mapping, dst); break; default: + BLI_assert_unreachable(); break; } }); - dst_attribute.finish(); + attribute.dst.finish(); } } @@ -791,8 +719,7 @@ static void duplicate_edges(GeometrySet &geometry_set, } }); - copy_edge_attributes_without_id(geometry_set, - vert_orig_indices, + copy_edge_attributes_without_id(vert_orig_indices, duplicates, selection, propagation_info, @@ -855,32 +782,16 @@ static void duplicate_points_curve(GeometrySet &geometry_set, } new_curve_offsets.last() = dst_num; - Map attributes = gather_attributes_without_id( - geometry_set, GEO_COMPONENT_TYPE_CURVE, propagation_info); - - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_curves.attributes().lookup(attribute_id); - if (!src_attribute) { - continue; - } - - eAttrDomain domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.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) { + for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(), + new_curves.attributes_for_write(), + ATTR_DOMAIN_MASK_ALL, + propagation_info, + {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src{src_attribute.varray.typed()}; - MutableSpan dst = dst_attribute.span.typed(); - - switch (domain) { + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); + switch (attribute.meta_data.domain) { case ATTR_DOMAIN_CURVE: threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) { for (const int i_selection : range) { @@ -893,10 +804,11 @@ static void duplicate_points_curve(GeometrySet &geometry_set, threaded_slice_fill(duplicates, selection, src, dst); break; default: + BLI_assert_unreachable(); break; } }); - dst_attribute.finish(); + attribute.dst.finish(); } copy_stable_id_point(duplicates, src_curves.attributes(), new_curves.attributes_for_write()); @@ -940,12 +852,10 @@ static void duplicate_points_mesh(GeometrySet &geometry_set, Mesh *new_mesh = BKE_mesh_new_nomain(duplicates.total_size(), 0, 0, 0, 0); - copy_attributes_without_id(geometry_set, - GEO_COMPONENT_TYPE_MESH, - ATTR_DOMAIN_POINT, - duplicates, + copy_attributes_without_id(duplicates, selection, propagation_info, + ATTR_DOMAIN_POINT, mesh.attributes(), new_mesh->attributes_for_write()); @@ -990,12 +900,10 @@ static void duplicate_points_pointcloud(GeometrySet &geometry_set, PointCloud *pointcloud = BKE_pointcloud_new_nomain(duplicates.total_size()); - copy_attributes_without_id(geometry_set, - GEO_COMPONENT_TYPE_POINT_CLOUD, - ATTR_DOMAIN_POINT, - duplicates, + copy_attributes_without_id(duplicates, selection, propagation_info, + ATTR_DOMAIN_POINT, src_points.attributes(), pointcloud->attributes_for_write()); @@ -1103,12 +1011,10 @@ static void duplicate_instances(GeometrySet &geometry_set, dst_instances->reference_handles().slice(range).fill(new_handle); } - copy_attributes_without_id(geometry_set, - GEO_COMPONENT_TYPE_INSTANCES, - ATTR_DOMAIN_INSTANCE, - duplicates, + copy_attributes_without_id(duplicates, selection, propagation_info, + ATTR_DOMAIN_INSTANCE, src_instances.attributes(), dst_instances->attributes_for_write());