Cleanup: Refactor join geometry node attribute gathering

Instead of building a set and then determining the final domain and
type for every attribute separately in the loop, construct a map with
the necessary data in the first place. This is simpler and should be
slightly more efficient.

Split from D11491
This commit is contained in:
2021-06-14 13:58:02 -05:00
parent 4a540b9b48
commit fe0fa7cec6

View File

@@ -157,35 +157,30 @@ static Array<const GeometryComponent *> to_base_components(Span<const Component
return components; return components;
} }
static Set<std::string> find_all_attribute_names(Span<const GeometryComponent *> components) static Map<std::string, AttributeMetaData> get_final_attribute_info(
Span<const GeometryComponent *> components, Span<StringRef> ignored_attributes)
{ {
Set<std::string> attribute_names; Map<std::string, AttributeMetaData> info;
for (const GeometryComponent *component : components) {
Set<std::string> names = component->attribute_names();
for (const std::string &name : names) {
attribute_names.add(name);
}
}
return attribute_names;
}
static void determine_final_data_type_and_domain(Span<const GeometryComponent *> components,
StringRef attribute_name,
CustomDataType *r_type,
AttributeDomain *r_domain)
{
Vector<CustomDataType> data_types;
Vector<AttributeDomain> domains;
for (const GeometryComponent *component : components) { for (const GeometryComponent *component : components) {
ReadAttributeLookup attribute = component->attribute_try_get_for_read(attribute_name); component->attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) {
if (attribute) { if (ignored_attributes.contains(name)) {
data_types.append(bke::cpp_type_to_custom_data_type(attribute.varray->type())); return true;
domains.append(attribute.domain); }
} info.add_or_modify(
name,
[&](AttributeMetaData *meta_data_final) { *meta_data_final = meta_data; },
[&](AttributeMetaData *meta_data_final) {
meta_data_final->data_type = blender::bke::attribute_data_type_highest_complexity(
{meta_data_final->data_type, meta_data.data_type});
meta_data_final->domain = blender::bke::attribute_domain_highest_priority(
{meta_data_final->domain, meta_data.domain});
});
return true;
});
} }
*r_type = bke::attribute_data_type_highest_complexity(data_types); return info;
*r_domain = bke::attribute_domain_highest_priority(domains);
} }
static void fill_new_attribute(Span<const GeometryComponent *> src_components, static void fill_new_attribute(Span<const GeometryComponent *> src_components,
@@ -219,23 +214,20 @@ static void join_attributes(Span<const GeometryComponent *> src_components,
GeometryComponent &result, GeometryComponent &result,
Span<StringRef> ignored_attributes = {}) Span<StringRef> ignored_attributes = {})
{ {
Set<std::string> attribute_names = find_all_attribute_names(src_components); const Map<std::string, AttributeMetaData> info = get_final_attribute_info(src_components,
for (StringRef name : ignored_attributes) { ignored_attributes);
attribute_names.remove(name);
}
for (const std::string &attribute_name : attribute_names) { for (const Map<std::string, AttributeMetaData>::Item &item : info.items()) {
CustomDataType data_type; const StringRef name = item.key;
AttributeDomain domain; const AttributeMetaData &meta_data = item.value;
determine_final_data_type_and_domain(src_components, attribute_name, &data_type, &domain);
OutputAttribute write_attribute = result.attribute_try_get_for_output_only( OutputAttribute write_attribute = result.attribute_try_get_for_output_only(
attribute_name, domain, data_type); name, meta_data.domain, meta_data.data_type);
if (!write_attribute) { if (!write_attribute) {
continue; continue;
} }
GMutableSpan dst_span = write_attribute.as_span(); GMutableSpan dst_span = write_attribute.as_span();
fill_new_attribute(src_components, attribute_name, data_type, domain, dst_span); fill_new_attribute(src_components, name, meta_data.data_type, meta_data.domain, dst_span);
write_attribute.save(); write_attribute.save();
} }
} }