Cleanup: Replace "foreach" lambdas with attribute storage iterator

Use the iterator added in 3929b27af6

Pull Request: https://projects.blender.org/blender/blender/pulls/153222
This commit is contained in:
Hans Goudey 2026-01-22 21:10:43 +01:00 • committed by Hans Goudey
parent 2d76c0615a
commit 0b422e45b1
20 changed files with 115 additions and 156 deletions

View file

@ -139,15 +139,6 @@ class AttributeStorage : public blender::AttributeStorage {
AttributeStorage &operator=(AttributeStorage &&other);
~AttributeStorage();
/**
* Iterate over all attributes, with the order defined by the order of insertion. It is not safe
* to add or remove attributes while iterating.
*/
void foreach(FunctionRef<void(Attribute &)> fn);
void foreach(FunctionRef<void(const Attribute &)> fn) const;
void foreach_with_stop(FunctionRef<bool(Attribute &)> fn);
void foreach_with_stop(FunctionRef<bool(const Attribute &)> fn) const;
/** Return the number of attributes. */
int count() const;

View file

@ -588,20 +588,18 @@ int BKE_attributes_length(const AttributeOwner &owner,
if (include_anonymous && domain_mask == ATTR_DOMAIN_MASK_ALL && mask == CD_MASK_PROP_ALL) {
return storage.count();
}
int length = 0;
storage.foreach([&](const bke::Attribute &attr) {
return std::count_if(storage.begin(), storage.end(), [&](const bke::Attribute &attr) {
if (!(ATTR_DOMAIN_AS_MASK(attr.domain()) & domain_mask)) {
return;
return false;
}
if (!(CD_TYPE_AS_MASK(*bke::attr_type_to_custom_data_type(attr.data_type())) & mask)) {
return;
return false;
}
if (!include_anonymous && bke::attribute_name_is_anonymous(attr.name())) {
return;
return false;
}
length++;
return true;
});
return length;
}
AttrDomain BKE_attribute_domain(const Mesh &mesh, const BMesh &bm, const CustomDataLayer *layer)
@ -782,25 +780,22 @@ std::optional<StringRef> BKE_attribute_from_index(AttributeOwner &owner,
return storage.at_index(lookup_index).name();
}
int index = 0;
std::optional<StringRef> result;
storage.foreach_with_stop([&](const bke::Attribute &attr) {
for (const bke::Attribute &attr : storage) {
if (!(ATTR_DOMAIN_AS_MASK(attr.domain()) & domain_mask)) {
return true;
continue;
}
if (!(CD_TYPE_AS_MASK(*bke::attr_type_to_custom_data_type(attr.data_type())) & layer_mask)) {
return true;
continue;
}
if (!include_anonymous && bke::attribute_name_is_anonymous(attr.name())) {
return true;
continue;
}
if (index == lookup_index) {
result = attr.name();
return false;
return attr.name();
}
index++;
return true;
});
return result;
}
return std::nullopt;
}
int BKE_attribute_to_index(const AttributeOwner &owner,
@ -841,25 +836,22 @@ int BKE_attribute_to_index(const AttributeOwner &owner,
return storage.index_of(name);
}
int index = 0;
bool found = false;
storage.foreach_with_stop([&](const bke::Attribute &attr) {
for (const bke::Attribute &attr : storage) {
if (!(ATTR_DOMAIN_AS_MASK(attr.domain()) & domain_mask)) {
return true;
continue;
}
if (!(CD_TYPE_AS_MASK(*bke::attr_type_to_custom_data_type(attr.data_type())) & layer_mask)) {
return true;
continue;
}
if (!include_anonymous && bke::attribute_name_is_anonymous(attr.name())) {
return true;
continue;
}
if (attr.name() == name) {
found = true;
return false;
return index;
}
index++;
return true;
});
return found ? index : -1;
}
return -1;
}
std::optional<StringRef> BKE_id_attributes_active_color_name(const ID *id)

View file

@ -304,22 +304,22 @@ LegacyMeshInterpolator::LegacyMeshInterpolator(const Mesh &src, Mesh &dst, const
AttributeStorage &dst_attributes = dst.attribute_storage.wrap();
const int src_domain_size = get_domain_size(src, domain);
const int dst_domain_size = get_domain_size(dst, domain);
src_attributes.foreach([&](const Attribute &src_attr) {
for (const Attribute &src_attr : src_attributes) {
if (src_attr.domain() != domain) {
return;
continue;
}
Attribute *dst_attr = dst_attributes.lookup(src_attr.name());
if (!dst_attr) {
return;
continue;
}
if (dst_attr->domain() != domain) {
return;
continue;
}
if (dst_attr->data_type() != src_attr.data_type()) {
return;
continue;
}
if (dst_attr->storage_type() != AttrStorageType::Array) {
return;
continue;
}
const CPPType &cpp_type = attribute_type_to_cpp_type(src_attr.data_type());
switch (src_attr.storage_type()) {
@ -336,7 +336,7 @@ LegacyMeshInterpolator::LegacyMeshInterpolator(const Mesh &src, Mesh &dst, const
}
auto &value = std::get<Attribute::ArrayData>(dst_attr->data_for_write());
attrs_dst_.append({cpp_type, value.data, dst_domain_size});
});
}
}
void LegacyMeshInterpolator::copy(const int src_index, const int dst_index, const int count) const

View file

@ -134,36 +134,6 @@ Attribute::SingleData Attribute::SingleData::from_default_value(const CPPType &t
return from_value(GPointer(type, type.default_value()));
}
void AttributeStorage::foreach(FunctionRef<void(Attribute &)> fn)
{
for (const std::unique_ptr<Attribute> &attribute : this->runtime->attributes) {
fn(*attribute);
}
}
void AttributeStorage::foreach(FunctionRef<void(const Attribute &)> fn) const
{
for (const std::unique_ptr<Attribute> &attribute : this->runtime->attributes) {
fn(*attribute);
}
}
void AttributeStorage::foreach_with_stop(FunctionRef<bool(Attribute &)> fn)
{
for (const std::unique_ptr<Attribute> &attribute : this->runtime->attributes) {
if (!fn(*attribute)) {
break;
}
}
}
void AttributeStorage::foreach_with_stop(FunctionRef<bool(const Attribute &)> fn) const
{
for (const std::unique_ptr<Attribute> &attribute : this->runtime->attributes) {
if (!fn(*attribute)) {
break;
}
}
}
AttrStorageType Attribute::storage_type() const
{
if (std::get_if<Attribute::ArrayData>(&data_)) {
@ -218,9 +188,9 @@ AttributeStorage::AttributeStorage(const AttributeStorage &other)
this->dna_attributes_num = 0;
this->runtime = MEM_new<AttributeStorageRuntime>(__func__);
this->runtime->attributes.reserve(other.runtime->attributes.size());
other.foreach([&](const Attribute &attribute) {
for (const Attribute &attribute : other) {
this->runtime->attributes.add_new(std::make_unique<Attribute>(attribute));
});
}
}
AttributeStorage &AttributeStorage::operator=(const AttributeStorage &other)
@ -336,9 +306,9 @@ void AttributeStorage::rename(const StringRef old_name, std::string new_name)
void AttributeStorage::resize(const AttrDomain domain, const int64_t new_size)
{
this->foreach([&](Attribute &attr) {
for (Attribute &attr : *this) {
if (attr.domain() != domain) {
return;
continue;
}
const CPPType &type = attribute_type_to_cpp_type(attr.data_type());
switch (attr.storage_type()) {
@ -354,12 +324,13 @@ void AttributeStorage::resize(const AttrDomain domain, const int64_t new_size)
}
attr.assign_data(std::move(new_data));
break;
}
case bke::AttrStorageType::Single: {
return;
break;
}
}
});
}
}
static void read_array_data(BlendDataReader &reader,
@ -585,7 +556,7 @@ static void write_array_data(BlendWriter &writer,
void attribute_storage_blend_write_prepare(AttributeStorage &data,
AttributeStorage::BlendWriteData &write_data)
{
data.foreach([&](Attribute &attr) {
for (Attribute &attr : data) {
blender::Attribute attribute_dna{};
attribute_dna.name = attr.name().c_str();
attribute_dna.data_type = int16_t(attr.data_type());
@ -614,7 +585,7 @@ void attribute_storage_blend_write_prepare(AttributeStorage &data,
}
write_data.attributes.append(attribute_dna);
});
}
data.runtime = nullptr;
}

View file

@ -12,8 +12,7 @@ namespace blender::bke::tests {
TEST(attribute_storage, Empty)
{
AttributeStorage storage;
int count = 0;
storage.foreach([&](const Attribute & /*attribute*/) { count++; });
const int count = std::distance(storage.begin(), storage.end());
EXPECT_EQ(count, 0);
}
@ -36,8 +35,7 @@ TEST(attribute_storage, Single)
EXPECT_EQ(data.data, sharing_info->data.data());
}
int count = 0;
storage.foreach([&](const Attribute & /*attribute*/) { count++; });
const int count = std::distance(storage.begin(), storage.end());
EXPECT_EQ(count, 1);
}
@ -133,8 +131,7 @@ TEST(attribute_storage, MultipleShared)
EXPECT_EQ(data_ptr[3], 1.0f);
}
int count = 0;
storage.foreach([&](const Attribute & /*attribute*/) { count++; });
const int count = std::distance(storage.begin(), storage.end());
EXPECT_EQ(count, 5);
}
@ -208,8 +205,7 @@ TEST(attribute_storage, UniqueNames)
storage.add(
storage.unique_name_calc("foo_2"), AttrDomain::Point, AttrType::Float, create_array_data());
int count = 0;
storage.foreach([&](const Attribute & /*attribute*/) { count++; });
const int count = std::distance(storage.begin(), storage.end());
EXPECT_EQ(count, 6);
}

View file

@ -357,7 +357,7 @@ static AttributeAccessorFunctions get_curves_accessor_functions()
}
const AttributeStorage &storage = curves.attribute_storage.wrap();
storage.foreach_with_stop([&](const Attribute &attr) {
for (const Attribute &attr : storage) {
const auto get_fn = [&]() {
const int domain_size = get_domain_size(owner, attr.domain());
return attribute_to_reader(attr, attr.domain(), domain_size);
@ -366,8 +366,10 @@ static AttributeAccessorFunctions get_curves_accessor_functions()
iter.is_builtin = builtin_attributes().contains(attr.name());
iter.accessor = &accessor;
fn(iter);
return !iter.is_stopped();
});
if (iter.is_stopped()) {
break;
}
}
};
fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);

View file

@ -3806,9 +3806,9 @@ static void reorder_attribute_domain(bke::AttributeStorage &data,
const bke::AttrDomain domain,
const Span<int> new_by_old_map)
{
data.foreach([&](bke::Attribute &attr) {
for (bke::Attribute &attr : data) {
if (attr.domain() != domain) {
return;
continue;
}
const CPPType &type = bke::attribute_type_to_cpp_type(attr.data_type());
switch (attr.storage_type()) {
@ -3819,12 +3819,13 @@ static void reorder_attribute_domain(bke::AttributeStorage &data,
new_by_old_map,
GMutableSpan(type, new_data.data, new_data.size));
attr.assign_data(std::move(new_data));
break;
}
case bke::AttrStorageType::Single: {
return;
break;
}
}
});
}
}
static void reorder_layer_data(GreasePencil &grease_pencil,
@ -4137,7 +4138,7 @@ static void shrink_attribute_storage(bke::AttributeStorage &storage,
const IndexRange range_before(index_to_remove);
const IndexRange range_after(index_to_remove + 1, size - index_to_remove - 1);
storage.foreach([&](bke::Attribute &attr) {
for (bke::Attribute &attr : storage) {
const CPPType &type = bke::attribute_type_to_cpp_type(attr.data_type());
switch (attr.storage_type()) {
case bke::AttrStorageType::Array: {
@ -4150,12 +4151,13 @@ static void shrink_attribute_storage(bke::AttributeStorage &storage,
range_after.size());
attr.assign_data(std::move(new_data));
break;
}
case bke::AttrStorageType::Single: {
return;
break;
}
}
});
}
}
static void update_active_node_from_node_to_remove(GreasePencil &grease_pencil,

View file

@ -78,7 +78,7 @@ static AttributeAccessorFunctions get_grease_pencil_accessor_functions()
const AttributeAccessor &accessor) {
const GreasePencil &grease_pencil = *static_cast<const GreasePencil *>(owner);
const AttributeStorage &storage = grease_pencil.attribute_storage.wrap();
storage.foreach_with_stop([&](const Attribute &attribute) {
for (const Attribute &attribute : storage) {
const auto get_fn = [&]() {
const int domain_size = get_domain_size(owner, AttrDomain::Layer);
return attribute_to_reader(attribute, AttrDomain::Layer, domain_size);
@ -87,8 +87,10 @@ static AttributeAccessorFunctions get_grease_pencil_accessor_functions()
iter.is_builtin = builtin_attributes().contains(attribute.name());
iter.accessor = &accessor;
fn(iter);
return !iter.is_stopped();
});
if (iter.is_stopped()) {
break;
}
}
};
fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);

View file

@ -96,7 +96,7 @@ static constexpr AttributeAccessorFunctions get_instances_accessor_functions()
const AttributeAccessor &accessor) {
const Instances &instances = *static_cast<const Instances *>(owner);
const AttributeStorage &storage = instances.attribute_storage();
storage.foreach_with_stop([&](const Attribute &attribute) {
for (const Attribute &attribute : storage) {
const auto get_fn = [&]() {
return attribute_to_reader(attribute, AttrDomain::Instance, instances.instances_num());
};
@ -104,8 +104,10 @@ static constexpr AttributeAccessorFunctions get_instances_accessor_functions()
iter.is_builtin = builtin_attributes().contains(attribute.name());
iter.accessor = &accessor;
fn(iter);
return !iter.is_stopped();
});
if (iter.is_stopped()) {
break;
}
}
};
fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);

View file

@ -1449,12 +1449,12 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
}
bke::MutableAttributeAccessor dst_attrs = me_dst->attributes_for_write();
me_src->attribute_storage.wrap().foreach([&](const bke::Attribute &attr) {
for (const bke::Attribute &attr : me_src->attribute_storage.wrap()) {
if (dst_attrs.contains(attr.name())) {
return;
continue;
}
dst_attrs.add(attr.name(), attr.domain(), attr.data_type(), bke::AttributeInitDefaultValue());
});
}
return me_dst;
}

View file

@ -958,7 +958,7 @@ static AttributeAccessorFunctions get_mesh_accessor_functions()
}
const AttributeStorage &storage = mesh.attribute_storage.wrap();
storage.foreach_with_stop([&](const Attribute &attr) {
for (const Attribute &attr : storage) {
const auto get_fn = [&]() {
const int domain_size = get_domain_size(owner, attr.domain());
return attribute_to_reader(attr, attr.domain(), domain_size);
@ -967,8 +967,10 @@ static AttributeAccessorFunctions get_mesh_accessor_functions()
iter.is_builtin = builtin_attributes().contains(attr.name());
iter.accessor = &accessor;
fn(iter);
return !iter.is_stopped();
});
if (iter.is_stopped()) {
break;
}
}
};
fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);

View file

@ -498,9 +498,9 @@ void mesh_calc_edges(Mesh &mesh,
}
mesh.attribute_storage.wrap().remove(".edge_verts");
mesh.attribute_storage.wrap().foreach([&](bke::Attribute &attr) {
for (bke::Attribute &attr : mesh.attribute_storage.wrap()) {
if (attr.domain() != bke::AttrDomain::Edge) {
return;
continue;
}
switch (attr.storage_type()) {
case AttrStorageType::Single: {
@ -520,7 +520,7 @@ void mesh_calc_edges(Mesh &mesh,
break;
}
}
});
}
{
const int orig_index_layer = CustomData_get_layer_index(&mesh.edge_data, CD_ORIGINDEX);

View file

@ -2675,11 +2675,11 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh)
/* free old CustomData and assign new one */
CustomData_free(&mesh->edge_data);
Set<StringRef> edge_attributes;
mesh->attribute_storage.wrap().foreach([&](const bke::Attribute &attr) {
for (const bke::Attribute &attr : mesh->attribute_storage.wrap()) {
if (attr.domain() == bke::AttrDomain::Edge) {
edge_attributes.add(attr.name());
}
});
}
for (const StringRef name : edge_attributes) {
mesh->attribute_storage.wrap().remove(name);
}

View file

@ -370,7 +370,7 @@ static void remove_invalid_faces(Mesh &mesh, const IndexMask &valid_faces)
const OffsetIndices new_faces = offset_indices::gather_selected_offsets(
old_faces, valid_faces, new_face_offsets);
mesh.attribute_storage.wrap().foreach([&](bke::Attribute &attr) {
for (bke::Attribute &attr : mesh.attribute_storage.wrap()) {
const CPPType &type = attribute_type_to_cpp_type(attr.data_type());
switch (attr.domain()) {
case AttrDomain::Face: {
@ -411,7 +411,7 @@ static void remove_invalid_faces(Mesh &mesh, const IndexMask &valid_faces)
default:
break;
}
});
}
for (CustomDataLayer &layer : MutableSpan(mesh.face_data.layers, mesh.face_data.totlayer)) {
if (layer.type == CD_ORIGINDEX) {
@ -469,9 +469,9 @@ static void remove_invalid_edges(Mesh &mesh, const IndexMask &valid_edges)
{
const int valid_edges_num = valid_edges.size();
mesh.attribute_storage.wrap().foreach([&](bke::Attribute &attr) {
for (bke::Attribute &attr : mesh.attribute_storage.wrap()) {
if (attr.domain() != AttrDomain::Edge) {
return;
continue;
}
const CPPType &type = attribute_type_to_cpp_type(attr.data_type());
switch (attr.storage_type()) {
@ -487,7 +487,7 @@ static void remove_invalid_edges(Mesh &mesh, const IndexMask &valid_edges)
case AttrStorageType::Single:
break;
}
});
}
for (CustomDataLayer &layer : MutableSpan(mesh.edge_data.layers, mesh.edge_data.totlayer)) {
if (layer.type == CD_ORIGINDEX) {

View file

@ -100,7 +100,7 @@ static constexpr AttributeAccessorFunctions get_pointcloud_accessor_functions()
const AttributeAccessor &accessor) {
const PointCloud &pointcloud = *static_cast<const PointCloud *>(owner);
const AttributeStorage &storage = pointcloud.attribute_storage.wrap();
storage.foreach_with_stop([&](const Attribute &attribute) {
for (const Attribute &attribute : storage) {
const auto get_fn = [&]() {
return attribute_to_reader(attribute, AttrDomain::Point, pointcloud.totpoint);
};
@ -108,8 +108,10 @@ static constexpr AttributeAccessorFunctions get_pointcloud_accessor_functions()
iter.is_builtin = builtin_attributes().contains(attribute.name());
iter.accessor = &accessor;
fn(iter);
return !iter.is_stopped();
});
if (iter.is_stopped()) {
break;
}
}
};
fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);

View file

@ -488,12 +488,12 @@ void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst,
bke::GeometrySet::GatheredAttributes attribute_info;
for (int i = 0; i < me_src_array_len; i++) {
const Mesh *me_src = me_src_array[i];
me_src->attribute_storage.wrap().foreach([&](const bke::Attribute &attr) {
for (const bke::Attribute &attr : me_src->attribute_storage.wrap()) {
if (BM_attribute_stored_in_bmesh_builtin(attr.name())) {
return;
continue;
}
attribute_info.add(attr.name(), {attr.domain(), attr.data_type()});
});
}
}
for (const int i : attribute_info.names.index_range()) {

View file

@ -279,19 +279,19 @@ static CustomData get_mesh_to_bm_custom_data(const Mesh &mesh,
{
CustomData custom_data;
CustomData_reset(&custom_data);
mesh.attribute_storage.wrap().foreach([&](const bke::Attribute &attr) {
for (const bke::Attribute &attr : mesh.attribute_storage.wrap()) {
if (attr.domain() != domain) {
return;
continue;
}
if (BM_attribute_stored_in_bmesh_builtin(attr.name())) {
return;
continue;
}
const eCustomDataType data_type = *bke::attr_type_to_custom_data_type(attr.data_type());
if ((CD_TYPE_AS_MASK(data_type) & cd_type_mask) == 0) {
return;
continue;
}
CustomData_add_layer_named(&custom_data, data_type, CD_SET_DEFAULT, 0, attr.name());
});
}
const CustomData &mesh_data = get_mesh_custom_data(mesh, domain);
for (const CustomDataLayer &layer : Span(mesh_data.layers, mesh_data.totlayer)) {
if ((CD_TYPE_AS_MASK(eCustomDataType(layer.type)) & cd_type_mask) == 0) {
@ -1212,18 +1212,18 @@ static Vector<BMeshToMeshLayerInfo> bm_to_mesh_copy_info_calc(const CustomData &
per_type_index[type]++;
}
storage.foreach([&](bke::Attribute &attr) {
for (bke::Attribute &attr : storage) {
if (attr.domain() != domain) {
return;
continue;
}
const eCustomDataType cd_type = *bke::attr_type_to_custom_data_type(attr.data_type());
const int bm_layer_index = CustomData_get_named_layer_index(&bm_data, cd_type, attr.name());
if (bm_layer_index == -1) {
return;
continue;
}
const CustomDataLayer &bm_layer = bm_data.layers[bm_layer_index];
if (bm_layer.flag & CD_FLAG_NOCOPY) {
return;
continue;
}
BMeshToMeshLayerInfo info{};
info.type = cd_type;
@ -1231,7 +1231,7 @@ static Vector<BMeshToMeshLayerInfo> bm_to_mesh_copy_info_calc(const CustomData &
info.mesh_data = std::get<bke::Attribute::ArrayData>(attr.data_for_write()).data;
info.elem_size = bke::attribute_type_to_cpp_type(attr.data_type()).size;
infos.append(info);
});
}
return infos;
}

View file

@ -495,8 +495,9 @@ static void um_arraystore_cd_free(BArrayCustomData *bcd, const int bs_index)
static MultiValueMap<bke::AttrDomain, bke::Attribute *> get_attributes_by_domain(Mesh &mesh)
{
MultiValueMap<bke::AttrDomain, bke::Attribute *> result;
mesh.attribute_storage.wrap().foreach(
[&](bke::Attribute &attr) { result.add(attr.domain(), &attr); });
for (bke::Attribute &attr : mesh.attribute_storage.wrap()) {
result.add(attr.domain(), &attr);
}
return result;
}
@ -628,7 +629,9 @@ static void um_arraystore_expand_clear(UndoMesh *um)
um_arraystore_cd_clear(&mesh->edge_data);
um_arraystore_cd_clear(&mesh->corner_data);
um_arraystore_cd_clear(&mesh->face_data);
mesh->attribute_storage.wrap().foreach([&](bke::Attribute &attr) { attr.assign_data({}); });
for (bke::Attribute &attr : mesh->attribute_storage.wrap()) {
attr.assign_data({});
}
if (mesh->face_offset_indices) {
implicit_sharing::free_shared_data(&mesh->face_offset_indices,
&mesh->runtime->face_offsets_sharing_info);

View file

@ -615,12 +615,12 @@ std::optional<Mesh *> mesh_triangulate(const Mesh &src_mesh,
* for original edges. New edges will be generated by #bke::mesh_calc_edges later.*/
CustomData_merge(&src_mesh.vert_data, &mesh->vert_data, CD_MASK_MESH.vmask, mesh->verts_num);
CustomData_merge(&src_mesh.edge_data, &mesh->edge_data, CD_MASK_MESH.emask, mesh->edges_num);
src_mesh.attribute_storage.wrap().foreach([&](const bke::Attribute &attr) {
for (const bke::Attribute &attr : src_mesh.attribute_storage.wrap()) {
if (!ELEM(attr.domain(), bke::AttrDomain::Point, bke::AttrDomain::Edge)) {
return;
continue;
}
mesh->attribute_storage.wrap().add(attr.name(), attr.domain(), attr.data_type(), attr.data());
});
}
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();

View file

@ -247,15 +247,9 @@ namespace blender {
static bool find_attr_with_pointer(const bke::AttributeStorage &storage,
const bke::Attribute &attr)
{
bool found_attr = false;
storage.foreach_with_stop([&](const bke::Attribute &attr_iter) {
if (&attr_iter == &attr) {
found_attr = true;
return false;
}
return true;
return std::any_of(storage.begin(), storage.end(), [&](const bke::Attribute &attr_iter) {
return &attr_iter == &attr;
});
return found_attr;
}
static AttributeOwner owner_from_attribute_pointer_rna(PointerRNA *ptr)
@ -847,18 +841,18 @@ void rna_AttributeGroup_iterator_begin(CollectionPropertyIterator *iter,
bke::AttributeStorage &storage = *owner.get_storage();
Vector<bke::Attribute *, 16> attributes;
storage.foreach([&](bke::Attribute &attr) {
for (bke::Attribute &attr : storage) {
if (!(ATTR_DOMAIN_AS_MASK(attr.domain()) & domain_mask)) {
return;
continue;
}
if (!(CD_TYPE_AS_MASK(*bke::attr_type_to_custom_data_type(attr.data_type())) & cd_type_mask)) {
return;
continue;
}
if (!include_anonymous && bke::attribute_name_is_anonymous(attr.name())) {
return;
continue;
}
attributes.append(&attr);
});
}
VectorData data = attributes.release();
rna_iterator_array_begin(
iter, ptr, data.data, sizeof(bke::Attribute *), data.size, true, nullptr);