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:
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user