diff options
author | Jacques Lucke <jacques@blender.org> | 2021-08-30 17:02:58 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-08-30 17:02:58 +0300 |
commit | fb0d5124f28c639ebd49deeb461e9bb5fc8accc2 (patch) | |
tree | d48675472c0572b2eba205b2ca7382e71f5b1012 | |
parent | 6146a679c954b9847e3775add51af4a351bc8aaf (diff) |
support anonymous attributes in foreach_attributetemp-geometry-nodes-fields--anonymous-attributes
27 files changed, 371 insertions, 287 deletions
diff --git a/source/blender/blenkernel/BKE_anonymous_attribute.h b/source/blender/blenkernel/BKE_anonymous_attribute.h index cc9604dd99d..6ac9a514ec9 100644 --- a/source/blender/blenkernel/BKE_anonymous_attribute.h +++ b/source/blender/blenkernel/BKE_anonymous_attribute.h @@ -30,6 +30,7 @@ void BKE_anonymous_attribute_id_increment_strong(const AnonymousAttributeID *ano void BKE_anonymous_attribute_id_decrement_weak(const AnonymousAttributeID *anonymous_id); void BKE_anonymous_attribute_id_decrement_strong(const AnonymousAttributeID *anonymous_id); const char *BKE_anonymous_attribute_id_debug_name(const AnonymousAttributeID *anonymous_id); +const char *BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_anonymous_attribute.hh b/source/blender/blenkernel/BKE_anonymous_attribute.hh index 3366455ad89..ee7aaa2d4d5 100644 --- a/source/blender/blenkernel/BKE_anonymous_attribute.hh +++ b/source/blender/blenkernel/BKE_anonymous_attribute.hh @@ -19,6 +19,7 @@ #include <atomic> #include <string> +#include "BLI_hash.hh" #include "BLI_string_ref.hh" #include "BKE_anonymous_attribute.h" @@ -186,6 +187,16 @@ class AttributeIDRef { return this->is_named() || this->is_anonymous(); } + friend bool operator==(const AttributeIDRef &a, const AttributeIDRef &b) + { + return a.anonymous_id_ == b.anonymous_id_ && a.name_ == b.name_; + } + + uint64_t hash() const + { + return get_default_hash_2(name_, anonymous_id_); + } + bool is_named() const { return !name_.is_empty(); diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh index 7d90fedd99d..6f5567b1aa5 100644 --- a/source/blender/blenkernel/BKE_attribute_access.hh +++ b/source/blender/blenkernel/BKE_attribute_access.hh @@ -105,8 +105,8 @@ struct AttributeInitMove : public AttributeInit { }; /* Returns false when the iteration should be stopped. */ -using AttributeForeachCallback = blender::FunctionRef<bool(blender::StringRefNull attribute_name, - const AttributeMetaData &meta_data)>; +using AttributeForeachCallback = blender::FunctionRef<bool( + const blender::bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data)>; namespace blender::bke { diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 7a44553c565..0732f1e5190 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -33,6 +33,7 @@ extern "C" { #endif +struct AnonymousAttributeID; struct BMesh; struct BlendDataReader; struct BlendWriter; @@ -193,6 +194,12 @@ void *CustomData_add_layer_named(struct CustomData *data, void *layer, int totelem, const char *name); +void *CustomData_add_layer_anonymous(struct CustomData *data, + int type, + eCDAllocType alloctype, + void *layer, + int totelem, + const struct AnonymousAttributeID *anonymous_id); /* frees the active or first data layer with the give type. * returns 1 on success, 0 if no layer with the given type is found @@ -231,6 +238,11 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, const int type, const char *name, const int totelem); +void *CustomData_duplicate_referenced_layer_anonymous( + CustomData *data, + const int type, + const struct AnonymousAttributeID *anonymous_id, + const int totelem); bool CustomData_is_referenced_layer(struct CustomData *data, int type); /* Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers. */ diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index cf9d213384c..45e8ab92e41 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -134,7 +134,7 @@ class GeometryComponent { bool attribute_try_create_builtin(const blender::StringRef attribute_name, const AttributeInit &initializer); - blender::Set<std::string> attribute_names() const; + blender::Set<blender::bke::AttributeIDRef> attribute_ids() const; bool attribute_foreach(const AttributeForeachCallback callback) const; virtual bool is_empty() const; diff --git a/source/blender/blenkernel/BKE_geometry_set_instances.hh b/source/blender/blenkernel/BKE_geometry_set_instances.hh index 25876296a47..44a0ee30c4c 100644 --- a/source/blender/blenkernel/BKE_geometry_set_instances.hh +++ b/source/blender/blenkernel/BKE_geometry_set_instances.hh @@ -59,9 +59,10 @@ struct AttributeKind { * will contain the highest complexity data type and the highest priority domain among every * attribute with the given name on all of the input components. */ -void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> set_groups, - Span<GeometryComponentType> component_types, - const Set<std::string> &ignored_attributes, - Map<std::string, AttributeKind> &r_attributes); +void geometry_set_gather_instances_attribute_info( + Span<GeometryInstanceGroup> set_groups, + Span<GeometryComponentType> component_types, + const Set<std::string> &ignored_attributes, + Map<AttributeIDRef, AttributeKind> &r_attributes); } // namespace blender::bke diff --git a/source/blender/blenkernel/intern/anonymous_attribute.cc b/source/blender/blenkernel/intern/anonymous_attribute.cc index 8d9cddcbcb4..7088dff3db9 100644 --- a/source/blender/blenkernel/intern/anonymous_attribute.cc +++ b/source/blender/blenkernel/intern/anonymous_attribute.cc @@ -19,15 +19,24 @@ using namespace blender::bke; struct AnonymousAttributeID { - mutable std::atomic<int> refcount_weak; - mutable std::atomic<int> refcount_strong; + mutable std::atomic<int> refcount_weak = 0; + mutable std::atomic<int> refcount_strong = 0; std::string debug_name; + std::string internal_name; }; +static std::string get_new_internal_name() +{ + static std::atomic<int> index = 0; + const int next_index = index.fetch_add(1); + return "anonymous_attribute_" + std::to_string(next_index); +} + AnonymousAttributeID *BKE_anonymous_attribute_id_new_weak(const char *debug_name) { AnonymousAttributeID *anonymous_id = new AnonymousAttributeID(); anonymous_id->debug_name = debug_name; + anonymous_id->internal_name = get_new_internal_name(); anonymous_id->refcount_weak.store(1); return anonymous_id; } @@ -36,6 +45,7 @@ AnonymousAttributeID *BKE_anonymous_attribute_id_new_strong(const char *debug_na { AnonymousAttributeID *anonymous_id = new AnonymousAttributeID(); anonymous_id->debug_name = debug_name; + anonymous_id->internal_name = get_new_internal_name(); anonymous_id->refcount_weak.store(1); anonymous_id->refcount_strong.store(1); return anonymous_id; @@ -75,3 +85,8 @@ const char *BKE_anonymous_attribute_id_debug_name(const AnonymousAttributeID *an { return anonymous_id->debug_name.c_str(); } + +const char *BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id) +{ + return anonymous_id->internal_name.c_str(); +} diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index fbe5b664ad9..941bfebcc60 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -391,8 +391,14 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write( if (!custom_data_layer_matches_attribute_id(layer, attribute_id)) { continue; } - /* TODO: Properly handle anonymous attribute. */ - CustomData_duplicate_referenced_layer_named(custom_data, layer.type, layer.name, domain_size); + if (attribute_id.is_named()) { + CustomData_duplicate_referenced_layer_named( + custom_data, layer.type, layer.name, domain_size); + } + else { + CustomData_duplicate_referenced_layer_anonymous( + custom_data, layer.type, &attribute_id.anonymous_id(), domain_size); + } const CustomDataType data_type = (CustomDataType)layer.type; switch (data_type) { case CD_PROP_FLOAT: @@ -433,11 +439,22 @@ bool CustomDataAttributeProvider::try_delete(GeometryComponent &component, return false; } -static std::string get_anonymous_attribute_name() +static void *add_generic_custom_data_layer(CustomData &custom_data, + const CustomDataType data_type, + const eCDAllocType alloctype, + void *layer_data, + const int domain_size, + const AttributeIDRef &attribute_id) { - static std::atomic<int> index = 0; - const int next_index = index.fetch_add(1); - return "anonymous_attribute_" + std::to_string(next_index); + if (attribute_id.is_named()) { + char attribute_name_c[MAX_NAME]; + attribute_id.name().copy(attribute_name_c); + return CustomData_add_layer_named( + &custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c); + } + const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id(); + return CustomData_add_layer_anonymous( + &custom_data, data_type, alloctype, layer_data, domain_size, &anonymous_id); } static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id, @@ -446,62 +463,36 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr const int domain_size, const AttributeInit &initializer) { - char attribute_name_c[MAX_NAME]; - if (attribute_id.is_named()) { - attribute_id.name().copy(attribute_name_c); - } - else { - const std::string name = get_anonymous_attribute_name(); - STRNCPY(attribute_name_c, name.c_str()); - } - - bool success = false; - switch (initializer.type) { case AttributeInit::Type::Default: { - void *data = CustomData_add_layer_named( - &custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c); - success = data != nullptr; - break; + void *data = add_generic_custom_data_layer( + custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_id); + return data != nullptr; } case AttributeInit::Type::VArray: { - void *data = CustomData_add_layer_named( - &custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c); - if (data != nullptr) { - success = true; - const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; - varray->materialize_to_uninitialized(IndexRange(varray->size()), data); + void *data = add_generic_custom_data_layer( + custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_id); + if (data == nullptr) { + return false; } - break; + const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray->materialize_to_uninitialized(IndexRange(varray->size()), data); + return true; } case AttributeInit::Type::MoveArray: { void *source_data = static_cast<const AttributeInitMove &>(initializer).data; - void *data = CustomData_add_layer_named( - &custom_data, data_type, CD_ASSIGN, source_data, domain_size, attribute_name_c); + void *data = add_generic_custom_data_layer( + custom_data, data_type, CD_ASSIGN, source_data, domain_size, attribute_id); if (data == nullptr) { MEM_freeN(source_data); + return false; } - else { - success = true; - } - break; - } - } - - if (!success) { - return false; - } - - if (attribute_id.is_anonymous()) { - for (CustomDataLayer &layer : MutableSpan(custom_data.layers, custom_data.totlayer)) { - if (STREQ(layer.name, attribute_name_c)) { - layer.anonymous_id = &attribute_id.anonymous_id(); - BKE_anonymous_attribute_id_increment_weak(layer.anonymous_id); - } + return true; } } - return true; + BLI_assert_unreachable(); + return false; } bool CustomDataAttributeProvider::try_create(GeometryComponent &component, @@ -542,7 +533,14 @@ bool CustomDataAttributeProvider::foreach_attribute(const GeometryComponent &com const CustomDataType data_type = (CustomDataType)layer.type; if (this->type_is_supported(data_type)) { AttributeMetaData meta_data{domain_, data_type}; - if (!callback(layer.name, meta_data)) { + AttributeIDRef attribute_id; + if (layer.anonymous_id != nullptr) { + attribute_id = layer.anonymous_id; + } + else { + attribute_id = layer.name; + } + if (!callback(attribute_id, meta_data)) { return false; } } @@ -727,13 +725,8 @@ std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeI bool CustomDataAttributes::create(const AttributeIDRef &attribute_id, const CustomDataType data_type) { - /* TODO: Support anonymous attributes. */ - if (!attribute_id.is_named()) { - return false; - } - char name_c[MAX_NAME]; - attribute_id.name().copy(name_c); - void *result = CustomData_add_layer_named(&data, data_type, CD_DEFAULT, nullptr, size_, name_c); + void *result = add_generic_custom_data_layer( + data, data_type, CD_DEFAULT, nullptr, size_, attribute_id); return result != nullptr; } @@ -741,13 +734,8 @@ bool CustomDataAttributes::create_by_move(const blender::bke::AttributeIDRef &at const CustomDataType data_type, void *buffer) { - /* TODO: Support anonymous attributes. */ - if (!attribute_id.is_named()) { - return false; - } - char name_c[MAX_NAME]; - attribute_id.name().copy(name_c); - void *result = CustomData_add_layer_named(&data, data_type, CD_ASSIGN, buffer, size_, name_c); + void *result = add_generic_custom_data_layer( + data, data_type, CD_ASSIGN, buffer, size_, attribute_id); return result != nullptr; } @@ -775,7 +763,14 @@ bool CustomDataAttributes::foreach_attribute(const AttributeForeachCallback call { for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) { AttributeMetaData meta_data{domain, (CustomDataType)layer.type}; - if (!callback(layer.name, meta_data)) { + AttributeIDRef attribute_id; + if (layer.anonymous_id != nullptr) { + attribute_id = layer.anonymous_id; + } + else { + attribute_id = layer.name; + } + if (!callback(attribute_id, meta_data)) { return false; } } @@ -955,11 +950,12 @@ bool GeometryComponent::attribute_try_create_builtin(const blender::StringRef at return builtin_provider->try_create(*this, initializer); } -Set<std::string> GeometryComponent::attribute_names() const +Set<blender::bke::AttributeIDRef> GeometryComponent::attribute_ids() const { - Set<std::string> attributes; - this->attribute_foreach([&](StringRefNull name, const AttributeMetaData &UNUSED(meta_data)) { - attributes.add(name); + Set<blender::bke::AttributeIDRef> attributes; + this->attribute_foreach([&](const blender::bke::AttributeIDRef &attribute_id, + const AttributeMetaData &UNUSED(meta_data)) { + attributes.add(attribute_id); return true; }); return attributes; @@ -992,9 +988,9 @@ bool GeometryComponent::attribute_foreach(const AttributeForeachCallback callbac } for (const DynamicAttributesProvider *provider : providers->dynamic_attribute_providers()) { const bool continue_loop = provider->foreach_attribute( - *this, [&](StringRefNull name, const AttributeMetaData &meta_data) { - if (handled_attribute_names.add(name)) { - return callback(name, meta_data); + *this, [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (attribute_id.is_anonymous() || handled_attribute_names.add(attribute_id.name())) { + return callback(attribute_id, meta_data); } return true; }); @@ -1018,13 +1014,10 @@ bool GeometryComponent::attribute_exists(const blender::bke::AttributeIDRef &att std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data( const blender::bke::AttributeIDRef &attribute_id) const { - /* TODO: Support anonymous attributes. */ - if (!attribute_id.is_named()) { - return {}; - } std::optional<AttributeMetaData> result{std::nullopt}; - this->attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { - if (attribute_id.name() == name) { + this->attribute_foreach([&](const blender::bke::AttributeIDRef ¤t_attribute_id, + const AttributeMetaData &meta_data) { + if (attribute_id == current_attribute_id) { result = meta_data; return false; } diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc index 5c18f6f3807..7d945fc111f 100644 --- a/source/blender/blenkernel/intern/curve_eval.cc +++ b/source/blender/blenkernel/intern/curve_eval.cc @@ -25,6 +25,7 @@ #include "DNA_curve_types.h" +#include "BKE_anonymous_attribute.hh" #include "BKE_curve.h" #include "BKE_spline.hh" @@ -330,13 +331,13 @@ void CurveEval::assert_valid_point_attributes() const return; } const int layer_len = splines_.first()->attributes.data.totlayer; - Map<StringRefNull, AttributeMetaData> map; + Map<blender::bke::AttributeIDRef, AttributeMetaData> map; for (const SplinePtr &spline : splines_) { BLI_assert(spline->attributes.data.totlayer == layer_len); spline->attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { + [&](const blender::bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { map.add_or_modify( - name, + attribute_id, [&](AttributeMetaData *map_data) { /* All unique attribute names should be added on the first spline. */ BLI_assert(spline == splines_.first()); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 30fabe09602..a86d0a608d6 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2663,6 +2663,27 @@ void *CustomData_add_layer_named(CustomData *data, return NULL; } +void *CustomData_add_layer_anonymous(struct CustomData *data, + int type, + eCDAllocType alloctype, + void *layerdata, + int totelem, + const AnonymousAttributeID *anonymous_id) +{ + const char *name = BKE_anonymous_attribute_id_internal_name(anonymous_id); + CustomDataLayer *layer = customData_add_layer__internal( + data, type, alloctype, layerdata, totelem, name); + CustomData_update_typemap(data); + + if (layer == NULL) { + return NULL; + } + + BKE_anonymous_attribute_id_increment_weak(anonymous_id); + layer->anonymous_id = anonymous_id; + return layer->data; +} + bool CustomData_free_layer(CustomData *data, int type, int totelem, int index) { const int index_first = CustomData_get_layer_index(data, type); @@ -2826,6 +2847,20 @@ void *CustomData_duplicate_referenced_layer_named(CustomData *data, return customData_duplicate_referenced_layer_index(data, layer_index, totelem); } +void *CustomData_duplicate_referenced_layer_anonymous(CustomData *data, + const int type, + const AnonymousAttributeID *anonymous_id, + const int totelem) +{ + for (int i = 0; i < data->totlayer; i++) { + if (data->layers[i].anonymous_id == anonymous_id) { + return customData_duplicate_referenced_layer_index(data, i, totelem); + } + } + BLI_assert_unreachable(); + return NULL; +} + void CustomData_duplicate_referenced_layers(CustomData *data, int totelem) { for (int i = 0; i < data->totlayer; i++) { diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 32a65ab47bf..d281407dd5a 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -319,7 +319,7 @@ void geometry_set_instances_attribute_foreach(const GeometrySet &geometry_set, void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> set_groups, Span<GeometryComponentType> component_types, const Set<std::string> &ignored_attributes, - Map<std::string, AttributeKind> &r_attributes) + Map<AttributeIDRef, AttributeKind> &r_attributes) { for (const GeometryInstanceGroup &set_group : set_groups) { const GeometrySet &set = set_group.geometry_set; @@ -329,23 +329,24 @@ void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> se } const GeometryComponent &component = *set.get_component_for_read(component_type); - component.attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { - if (ignored_attributes.contains(name)) { - return true; - } - auto add_info = [&](AttributeKind *attribute_kind) { - attribute_kind->domain = meta_data.domain; - attribute_kind->data_type = meta_data.data_type; - }; - auto modify_info = [&](AttributeKind *attribute_kind) { - attribute_kind->domain = meta_data.domain; /* TODO: Use highest priority domain. */ - attribute_kind->data_type = bke::attribute_data_type_highest_complexity( - {attribute_kind->data_type, meta_data.data_type}); - }; - - r_attributes.add_or_modify(name, add_info, modify_info); - return true; - }); + component.attribute_foreach( + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (attribute_id.is_named() && ignored_attributes.contains(attribute_id.name())) { + return true; + } + auto add_info = [&](AttributeKind *attribute_kind) { + attribute_kind->domain = meta_data.domain; + attribute_kind->data_type = meta_data.data_type; + }; + auto modify_info = [&](AttributeKind *attribute_kind) { + attribute_kind->domain = meta_data.domain; /* TODO: Use highest priority domain. */ + attribute_kind->data_type = bke::attribute_data_type_highest_complexity( + {attribute_kind->data_type, meta_data.data_type}); + }; + + r_attributes.add_or_modify(attribute_id, add_info, modify_info); + return true; + }); } } } @@ -500,11 +501,11 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou static void join_attributes(Span<GeometryInstanceGroup> set_groups, Span<GeometryComponentType> component_types, - const Map<std::string, AttributeKind> &attribute_info, + const Map<AttributeIDRef, AttributeKind> &attribute_info, GeometryComponent &result) { - for (Map<std::string, AttributeKind>::Item entry : attribute_info.items()) { - StringRef name = entry.key; + for (Map<AttributeIDRef, AttributeKind>::Item entry : attribute_info.items()) { + const AttributeIDRef attribute_id = entry.key; const AttributeDomain domain_output = entry.value.domain; const CustomDataType data_type_output = entry.value.data_type; const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type_output); @@ -512,7 +513,7 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups, result.attribute_try_create( entry.key, domain_output, data_type_output, AttributeInitDefault()); - WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(name); + WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(attribute_id); if (!write_attribute || &write_attribute.varray->type() != cpp_type || write_attribute.domain != domain_output) { continue; @@ -531,7 +532,7 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups, continue; /* Domain size is 0, so no need to increment the offset. */ } GVArrayPtr source_attribute = component.attribute_try_get_for_read( - name, domain_output, data_type_output); + attribute_id, domain_output, data_type_output); if (source_attribute) { fn::GVArray_GSpan src_span{*source_attribute}; @@ -641,7 +642,7 @@ static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups, } /* Don't copy attributes that are stored directly in the mesh data structs. */ - Map<std::string, AttributeKind> attributes; + Map<AttributeIDRef, AttributeKind> attributes; geometry_set_gather_instances_attribute_info( set_groups, component_types, @@ -662,7 +663,7 @@ static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_grou PointCloudComponent &dst_component = result.get_component_for_write<PointCloudComponent>(); dst_component.replace(new_pointcloud); - Map<std::string, AttributeKind> attributes; + Map<AttributeIDRef, AttributeKind> attributes; geometry_set_gather_instances_attribute_info( set_groups, {GEO_COMPONENT_TYPE_POINT_CLOUD}, {"position"}, attributes); join_attributes(set_groups, @@ -696,7 +697,7 @@ static void join_instance_groups_curve(Span<GeometryInstanceGroup> set_groups, G CurveComponent &dst_component = result.get_component_for_write<CurveComponent>(); dst_component.replace(curve); - Map<std::string, AttributeKind> attributes; + Map<AttributeIDRef, AttributeKind> attributes; geometry_set_gather_instances_attribute_info( set_groups, {GEO_COMPONENT_TYPE_CURVE}, diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index e38c70afd0f..f3ca246c78c 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -45,15 +45,20 @@ namespace blender::ed::spreadsheet { void GeometryDataSource::foreach_default_column_ids( FunctionRef<void(const SpreadsheetColumnID &)> fn) const { - component_->attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { - if (meta_data.domain != domain_) { - return true; - } - SpreadsheetColumnID column_id; - column_id.name = (char *)name.c_str(); - fn(column_id); - return true; - }); + component_->attribute_foreach( + [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (meta_data.domain != domain_) { + return true; + } + if (attribute_id.is_anonymous()) { + return true; + } + SpreadsheetColumnID column_id; + std::string name = attribute_id.name(); + column_id.name = (char *)name.c_str(); + fn(column_id); + return true; + }); } std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 18ed8800d49..c078e15fa55 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -32,6 +32,7 @@ struct ModifierData; namespace blender::nodes { +using bke::AttributeIDRef; using bke::geometry_set_realize_instances; using bke::OutputAttribute; using bke::OutputAttribute_Typed; diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 956b7b8a005..7833dbf26f4 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -76,7 +76,7 @@ struct CurveToPointsResults { MutableSpan<float> radii; MutableSpan<float> tilts; - Map<std::string, GMutableSpan> point_attributes; + Map<AttributeIDRef, GMutableSpan> point_attributes; MutableSpan<float3> tangents; MutableSpan<float3> normals; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc index 1f878259f30..8e5ae7435b4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc @@ -60,25 +60,26 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component, Span<int> offsets, PointCloudComponent &points) { - curve_component.attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { - if (meta_data.domain != ATTR_DOMAIN_CURVE) { - return true; - } - GVArrayPtr spline_attribute = curve_component.attribute_get_for_read( - name, ATTR_DOMAIN_CURVE, meta_data.data_type); - - OutputAttribute result_attribute = points.attribute_try_get_for_output_only( - name, ATTR_DOMAIN_POINT, meta_data.data_type); - GMutableSpan result = result_attribute.as_span(); - - /* Only copy the attributes of splines in the offsets. */ - for (const int i : offsets.index_range()) { - spline_attribute->get(offsets[i], result[i]); - } - - result_attribute.save(); - return true; - }); + curve_component.attribute_foreach( + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (meta_data.domain != ATTR_DOMAIN_CURVE) { + return true; + } + GVArrayPtr spline_attribute = curve_component.attribute_get_for_read( + attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type); + + OutputAttribute result_attribute = points.attribute_try_get_for_output_only( + attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type); + GMutableSpan result = result_attribute.as_span(); + + /* Only copy the attributes of splines in the offsets. */ + for (const int i : offsets.index_range()) { + spline_attribute->get(offsets[i], result[i]); + } + + result_attribute.save(); + return true; + }); } /** @@ -128,20 +129,20 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines, /* Copy the point attribute data over. */ for (const auto &item : start_data.point_attributes.items()) { - const StringRef name = item.key; + const AttributeIDRef attribute_id = item.key; GMutableSpan point_span = item.value; - BLI_assert(spline.attributes.get_for_read(name)); - GSpan spline_span = *spline.attributes.get_for_read(name); + BLI_assert(spline.attributes.get_for_read(attribute_id)); + GSpan spline_span = *spline.attributes.get_for_read(attribute_id); blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]); } for (const auto &item : end_data.point_attributes.items()) { - const StringRef name = item.key; + const AttributeIDRef attribute_id = item.key; GMutableSpan point_span = item.value; - BLI_assert(spline.attributes.get_for_read(name)); - GSpan spline_span = *spline.attributes.get_for_read(name); + BLI_assert(spline.attributes.get_for_read(attribute_id)); + GSpan spline_span = *spline.attributes.get_for_read(attribute_id); blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc index ad0c453c2af..081839ec903 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -88,14 +88,14 @@ static SplinePtr resample_spline(const Spline &input_spline, const int count) input_spline.radii().first()); output_spline->attributes.reallocate(1); input_spline.attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { - std::optional<GSpan> src = input_spline.attributes.get_for_read(name); + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + std::optional<GSpan> src = input_spline.attributes.get_for_read(attribute_id); BLI_assert(src); - if (!output_spline->attributes.create(name, meta_data.data_type)) { + if (!output_spline->attributes.create(attribute_id, meta_data.data_type)) { BLI_assert_unreachable(); return false; } - std::optional<GMutableSpan> dst = output_spline->attributes.get_for_write(name); + std::optional<GMutableSpan> dst = output_spline->attributes.get_for_write(attribute_id); if (!dst) { BLI_assert_unreachable(); return false; @@ -126,15 +126,15 @@ static SplinePtr resample_spline(const Spline &input_spline, const int count) output_spline->attributes.reallocate(count); input_spline.attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { - std::optional<GSpan> input_attribute = input_spline.attributes.get_for_read(name); + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + std::optional<GSpan> input_attribute = input_spline.attributes.get_for_read(attribute_id); BLI_assert(input_attribute); - if (!output_spline->attributes.create(name, meta_data.data_type)) { + if (!output_spline->attributes.create(attribute_id, meta_data.data_type)) { BLI_assert_unreachable(); return false; } std::optional<GMutableSpan> output_attribute = output_spline->attributes.get_for_write( - name); + attribute_id); if (!output_attribute) { BLI_assert_unreachable(); return false; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc index e92d22a6064..b6c3a4adddf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc @@ -87,9 +87,9 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params) reverse_data<float>(splines[i]->tilts()); splines[i]->attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { std::optional<blender::fn::GMutableSpan> output_attribute = - splines[i]->attributes.get_for_write(name); + splines[i]->attributes.get_for_write(attribute_id); if (!output_attribute) { BLI_assert_unreachable(); return false; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc index fe3f42625ae..5c1f7fc97ab 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc @@ -78,14 +78,14 @@ template<typename CopyFn> static void copy_attributes(const Spline &input_spline, Spline &output_spline, CopyFn copy_fn) { input_spline.attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { - std::optional<GSpan> src = input_spline.attributes.get_for_read(name); + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + std::optional<GSpan> src = input_spline.attributes.get_for_read(attribute_id); BLI_assert(src); - if (!output_spline.attributes.create(name, meta_data.data_type)) { + if (!output_spline.attributes.create(attribute_id, meta_data.data_type)) { BLI_assert_unreachable(); return false; } - std::optional<GMutableSpan> dst = output_spline.attributes.get_for_write(name); + std::optional<GMutableSpan> dst = output_spline.attributes.get_for_write(attribute_id); if (!dst) { BLI_assert_unreachable(); return false; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc index 7908c26e2dc..7d197558bcc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc @@ -287,16 +287,16 @@ static void subdivide_dynamic_attributes(const Spline &src_spline, { const bool is_cyclic = src_spline.is_cyclic(); src_spline.attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { - std::optional<GSpan> src = src_spline.attributes.get_for_read(name); + [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + std::optional<GSpan> src = src_spline.attributes.get_for_read(attribute_id); BLI_assert(src); - if (!dst_spline.attributes.create(name, meta_data.data_type)) { + if (!dst_spline.attributes.create(attribute_id, meta_data.data_type)) { /* Since the source spline of the same type had the attribute, adding it should work. */ BLI_assert_unreachable(); } - std::optional<GMutableSpan> dst = dst_spline.attributes.get_for_write(name); + std::optional<GMutableSpan> dst = dst_spline.attributes.get_for_write(attribute_id); BLI_assert(dst); attribute_math::convert_to_static_type(dst->type(), [&](auto dummy) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index bb8f560f92d..7821479af2b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -119,21 +119,21 @@ static Array<int> calculate_spline_point_offsets(GeoNodeExecParams ¶ms, } static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &points, - const StringRef name, + const AttributeIDRef &attribute_id, const CustomDataType data_type) { - points.attribute_try_create(name, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault()); - WriteAttributeLookup attribute = points.attribute_try_get_for_write(name); + points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault()); + WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id); BLI_assert(attribute); return attribute.varray->get_internal_span(); } template<typename T> static MutableSpan<T> create_attribute_and_retrieve_span(PointCloudComponent &points, - const StringRef name) + const AttributeIDRef &attribute_id) { GMutableSpan attribute = create_attribute_and_retrieve_span( - points, name, bke::cpp_type_to_custom_data_type(CPPType::get<T>())); + points, attribute_id, bke::cpp_type_to_custom_data_type(CPPType::get<T>())); return attribute.typed<T>(); } @@ -151,9 +151,10 @@ CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponen /* Because of the invariants of the curve component, we use the attributes of the * first spline as a representative for the attribute meta data all splines. */ curve.splines().first()->attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { attributes.point_attributes.add_new( - name, create_attribute_and_retrieve_span(points, name, meta_data.data_type)); + attribute_id, + create_attribute_and_retrieve_span(points, attribute_id, meta_data.data_type)); return true; }, ATTR_DOMAIN_POINT); @@ -183,12 +184,12 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines, spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size)); spline.interpolate_to_evaluated(spline.tilts())->materialize(data.tilts.slice(offset, size)); - for (const Map<std::string, GMutableSpan>::Item &item : data.point_attributes.items()) { - const StringRef name = item.key; + for (const Map<AttributeIDRef, GMutableSpan>::Item &item : data.point_attributes.items()) { + const AttributeIDRef attribute_id = item.key; GMutableSpan point_span = item.value; - BLI_assert(spline.attributes.get_for_read(name)); - GSpan spline_span = *spline.attributes.get_for_read(name); + BLI_assert(spline.attributes.get_for_read(attribute_id)); + GSpan spline_span = *spline.attributes.get_for_read(attribute_id); spline.interpolate_to_evaluated(spline_span) ->materialize(point_span.slice(offset, size).data()); @@ -226,12 +227,12 @@ static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines, uniform_samples, data.tilts.slice(offset, size)); - for (const Map<std::string, GMutableSpan>::Item &item : data.point_attributes.items()) { - const StringRef name = item.key; + for (const Map<AttributeIDRef, GMutableSpan>::Item &item : data.point_attributes.items()) { + const AttributeIDRef attribute_id = item.key; GMutableSpan point_span = item.value; - BLI_assert(spline.attributes.get_for_read(name)); - GSpan spline_span = *spline.attributes.get_for_read(name); + BLI_assert(spline.attributes.get_for_read(attribute_id)); + GSpan spline_span = *spline.attributes.get_for_read(attribute_id); spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span), uniform_samples, @@ -261,31 +262,32 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component, Span<int> offsets, PointCloudComponent &points) { - curve_component.attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { - if (meta_data.domain != ATTR_DOMAIN_CURVE) { - return true; - } - GVArrayPtr spline_attribute = curve_component.attribute_get_for_read( - name, ATTR_DOMAIN_CURVE, meta_data.data_type); - const CPPType &type = spline_attribute->type(); - - OutputAttribute result_attribute = points.attribute_try_get_for_output_only( - name, ATTR_DOMAIN_POINT, meta_data.data_type); - GMutableSpan result = result_attribute.as_span(); - - for (const int i : IndexRange(spline_attribute->size())) { - const int offset = offsets[i]; - const int size = offsets[i + 1] - offsets[i]; - if (size != 0) { - BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); - spline_attribute->get(i, buffer); - type.fill_assign_n(buffer, result[offset], size); - } - } - - result_attribute.save(); - return true; - }); + curve_component.attribute_foreach( + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (meta_data.domain != ATTR_DOMAIN_CURVE) { + return true; + } + GVArrayPtr spline_attribute = curve_component.attribute_get_for_read( + attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type); + const CPPType &type = spline_attribute->type(); + + OutputAttribute result_attribute = points.attribute_try_get_for_output_only( + attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type); + GMutableSpan result = result_attribute.as_span(); + + for (const int i : IndexRange(spline_attribute->size())) { + const int offset = offsets[i]; + const int size = offsets[i + 1] - offsets[i]; + if (size != 0) { + BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); + spline_attribute->get(i, buffer); + type.fill_assign_n(buffer, result[offset], size); + } + } + + result_attribute.save(); + return true; + }); } void curve_create_default_rotation_attribute(Span<float3> tangents, diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc index f9415c6d27b..ae7c67d8816 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -162,8 +162,8 @@ static void trim_poly_spline(Spline &spline, linear_trim_data<float>(start, end, spline.tilts()); spline.attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &UNUSED(meta_data)) { - std::optional<GMutableSpan> src = spline.attributes.get_for_write(name); + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &UNUSED(meta_data)) { + std::optional<GMutableSpan> src = spline.attributes.get_for_write(attribute_id); BLI_assert(src); attribute_math::convert_to_static_type(src->type(), [&](auto dummy) { using T = decltype(dummy); @@ -197,14 +197,14 @@ static PolySpline trim_nurbs_spline(const Spline &spline, /* Copy generic attribute data. */ spline.attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { - std::optional<GSpan> src = spline.attributes.get_for_read(name); + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + std::optional<GSpan> src = spline.attributes.get_for_read(attribute_id); BLI_assert(src); - if (!new_spline.attributes.create(name, meta_data.data_type)) { + if (!new_spline.attributes.create(attribute_id, meta_data.data_type)) { BLI_assert_unreachable(); return false; } - std::optional<GMutableSpan> dst = new_spline.attributes.get_for_write(name); + std::optional<GMutableSpan> dst = new_spline.attributes.get_for_write(attribute_id); BLI_assert(dst); attribute_math::convert_to_static_type(src->type(), [&](auto dummy) { @@ -253,8 +253,8 @@ static void trim_bezier_spline(Spline &spline, linear_trim_data<float>(start, end, bezier_spline.radii()); linear_trim_data<float>(start, end, bezier_spline.tilts()); spline.attributes.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &UNUSED(meta_data)) { - std::optional<GMutableSpan> src = spline.attributes.get_for_write(name); + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &UNUSED(meta_data)) { + std::optional<GMutableSpan> src = spline.attributes.get_for_write(attribute_id); BLI_assert(src); attribute_math::convert_to_static_type(src->type(), [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 8c697275f88..f77329826f8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -97,16 +97,16 @@ static void copy_dynamic_attributes(const CustomDataAttributes &src, const IndexMask mask) { src.foreach_attribute( - [&](StringRefNull name, const AttributeMetaData &meta_data) { - std::optional<GSpan> src_attribute = src.get_for_read(name); + [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + std::optional<GSpan> src_attribute = src.get_for_read(attribute_id); BLI_assert(src_attribute); - if (!dst.create(name, meta_data.data_type)) { + if (!dst.create(attribute_id, meta_data.data_type)) { /* Since the source spline of the same type had the attribute, adding it should work. */ BLI_assert_unreachable(); } - std::optional<GMutableSpan> new_attribute = dst.get_for_write(name); + std::optional<GMutableSpan> new_attribute = dst.get_for_write(attribute_id); BLI_assert(new_attribute); attribute_math::convert_to_static_type(new_attribute->type(), [&](auto dummy) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 730cf08feaa..5792ee1485a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -161,34 +161,35 @@ static Array<const GeometryComponent *> to_base_components(Span<const Component return components; } -static Map<std::string, AttributeMetaData> get_final_attribute_info( +static Map<AttributeIDRef, AttributeMetaData> get_final_attribute_info( Span<const GeometryComponent *> components, Span<StringRef> ignored_attributes) { - Map<std::string, AttributeMetaData> info; + Map<AttributeIDRef, AttributeMetaData> info; for (const GeometryComponent *component : components) { - component->attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { - if (ignored_attributes.contains(name)) { - return true; - } - 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; - }); + component->attribute_foreach( + [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (attribute_id.is_named() && ignored_attributes.contains(attribute_id.name())) { + return true; + } + info.add_or_modify( + attribute_id, + [&](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; + }); } return info; } static void fill_new_attribute(Span<const GeometryComponent *> src_components, - StringRef attribute_name, + const AttributeIDRef &attribute_id, const CustomDataType data_type, const AttributeDomain domain, GMutableSpan dst_span) @@ -203,7 +204,7 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components, continue; } GVArrayPtr read_attribute = component->attribute_get_for_read( - attribute_name, domain, data_type, nullptr); + attribute_id, domain, data_type, nullptr); GVArray_GSpan src_span{*read_attribute}; const void *src_buffer = src_span.data(); @@ -218,20 +219,21 @@ static void join_attributes(Span<const GeometryComponent *> src_components, GeometryComponent &result, Span<StringRef> ignored_attributes = {}) { - const Map<std::string, AttributeMetaData> info = get_final_attribute_info(src_components, - ignored_attributes); + const Map<AttributeIDRef, AttributeMetaData> info = get_final_attribute_info(src_components, + ignored_attributes); - for (const Map<std::string, AttributeMetaData>::Item &item : info.items()) { - const StringRef name = item.key; + for (const Map<AttributeIDRef, AttributeMetaData>::Item &item : info.items()) { + const AttributeIDRef attribute_id = item.key; const AttributeMetaData &meta_data = item.value; OutputAttribute write_attribute = result.attribute_try_get_for_output_only( - name, meta_data.domain, meta_data.data_type); + attribute_id, meta_data.domain, meta_data.data_type); if (!write_attribute) { continue; } GMutableSpan dst_span = write_attribute.as_span(); - fill_new_attribute(src_components, name, meta_data.data_type, meta_data.domain, dst_span); + fill_new_attribute( + src_components, attribute_id, meta_data.data_type, meta_data.domain, dst_span); write_attribute.save(); } } @@ -306,7 +308,7 @@ static void join_components(Span<const VolumeComponent *> src_components, Geomet * \note This takes advantage of the fact that creating attributes on joined curves never * changes a point attribute into a spline attribute; it is always the other way around. */ -static void ensure_control_point_attribute(const StringRef name, +static void ensure_control_point_attribute(const AttributeIDRef &attribute_id, const CustomDataType data_type, Span<CurveComponent *> src_components, CurveEval &result) @@ -321,7 +323,7 @@ static void ensure_control_point_attribute(const StringRef name, const CurveEval *current_curve = src_components[src_component_index]->get_for_read(); for (SplinePtr &spline : splines) { - std::optional<GSpan> attribute = spline->attributes.get_for_read(name); + std::optional<GSpan> attribute = spline->attributes.get_for_read(attribute_id); if (attribute) { if (attribute->type() != type) { @@ -334,22 +336,22 @@ static void ensure_control_point_attribute(const StringRef name, conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), type) ->materialize(converted_buffer); - spline->attributes.remove(name); - spline->attributes.create_by_move(name, data_type, converted_buffer); + spline->attributes.remove(attribute_id); + spline->attributes.create_by_move(attribute_id, data_type, converted_buffer); } } else { - spline->attributes.create(name, data_type); + spline->attributes.create(attribute_id, data_type); - if (current_curve->attributes.get_for_read(name)) { + if (current_curve->attributes.get_for_read(attribute_id)) { /* In this case the attribute did not exist, but there is a spline domain attribute * we can retrieve a value from, as a spline to point domain conversion. So fill the * new attribute with the value for this spline. */ GVArrayPtr current_curve_attribute = current_curve->attributes.get_for_read( - name, data_type, nullptr); + attribute_id, data_type, nullptr); - BLI_assert(spline->attributes.get_for_read(name)); - std::optional<GMutableSpan> new_attribute = spline->attributes.get_for_write(name); + BLI_assert(spline->attributes.get_for_read(attribute_id)); + std::optional<GMutableSpan> new_attribute = spline->attributes.get_for_write(attribute_id); BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); current_curve_attribute->get(spline_index_in_component, buffer); @@ -371,15 +373,15 @@ static void ensure_control_point_attribute(const StringRef name, /** * Fill data for an attribute on the new curve based on all source curves. */ -static void ensure_spline_attribute(const StringRef name, +static void ensure_spline_attribute(const AttributeIDRef &attribute_id, const CustomDataType data_type, Span<CurveComponent *> src_components, CurveEval &result) { const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type); - result.attributes.create(name, data_type); - GMutableSpan result_attribute = *result.attributes.get_for_write(name); + result.attributes.create(attribute_id, data_type); + GMutableSpan result_attribute = *result.attributes.get_for_write(attribute_id); int offset = 0; for (const CurveComponent *component : src_components) { @@ -388,7 +390,7 @@ static void ensure_spline_attribute(const StringRef name, if (size == 0) { continue; } - GVArrayPtr read_attribute = curve.attributes.get_for_read(name, data_type, nullptr); + GVArrayPtr read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr); GVArray_GSpan src_span{*read_attribute}; const void *src_buffer = src_span.data(); @@ -406,19 +408,19 @@ static void ensure_spline_attribute(const StringRef name, * \warning Splines have been moved out of the source components at this point, so it * is important to only read curve-level data (spline domain attributes) from them. */ -static void join_curve_attributes(const Map<std::string, AttributeMetaData> &info, +static void join_curve_attributes(const Map<AttributeIDRef, AttributeMetaData> &info, Span<CurveComponent *> src_components, CurveEval &result) { - for (const Map<std::string, AttributeMetaData>::Item &item : info.items()) { - const StringRef name = item.key; + for (const Map<AttributeIDRef, AttributeMetaData>::Item &item : info.items()) { + const AttributeIDRef attribute_id = item.key; const AttributeMetaData meta_data = item.value; if (meta_data.domain == ATTR_DOMAIN_CURVE) { - ensure_spline_attribute(name, meta_data.data_type, src_components, result); + ensure_spline_attribute(attribute_id, meta_data.data_type, src_components, result); } else { - ensure_control_point_attribute(name, meta_data.data_type, src_components, result); + ensure_control_point_attribute(attribute_id, meta_data.data_type, src_components, result); } } } @@ -446,7 +448,7 @@ static void join_curve_components(MutableSpan<GeometrySet> src_geometry_sets, Ge } /* Retrieve attribute info before moving the splines out of the input components. */ - const Map<std::string, AttributeMetaData> info = get_final_attribute_info( + const Map<AttributeIDRef, AttributeMetaData> info = get_final_attribute_info( {(const GeometryComponent **)src_components.data(), src_components.size()}, {"position", "radius", "tilt", "cyclic", "resolution"}); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc index 637003a46c7..9d8c49a2a10 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc @@ -56,10 +56,10 @@ static void copy_attributes_to_points(CurveEval &curve, Span<Vector<int>> point_to_vert_maps) { MutableSpan<SplinePtr> splines = curve.splines(); - Set<std::string> source_attribute_names = mesh_component.attribute_names(); + Set<AttributeIDRef> source_attribute_ids = mesh_component.attribute_ids(); /* Copy builtin control point attributes. */ - if (source_attribute_names.contains_as("tilt")) { + if (source_attribute_ids.contains("tilt")) { const GVArray_Typed<float> tilt_attribute = mesh_component.attribute_get_for_read<float>( "tilt", ATTR_DOMAIN_POINT, 0.0f); threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) { @@ -68,9 +68,9 @@ static void copy_attributes_to_points(CurveEval &curve, *tilt_attribute, point_to_vert_maps[i], splines[i]->tilts()); } }); - source_attribute_names.remove_contained_as("tilt"); + source_attribute_ids.remove_contained("tilt"); } - if (source_attribute_names.contains_as("radius")) { + if (source_attribute_ids.contains("radius")) { const GVArray_Typed<float> radius_attribute = mesh_component.attribute_get_for_read<float>( "radius", ATTR_DOMAIN_POINT, 1.0f); threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) { @@ -79,15 +79,15 @@ static void copy_attributes_to_points(CurveEval &curve, *radius_attribute, point_to_vert_maps[i], splines[i]->radii()); } }); - source_attribute_names.remove_contained_as("radius"); + source_attribute_ids.remove_contained("radius"); } /* Don't copy other builtin control point attributes. */ - source_attribute_names.remove_as("position"); + source_attribute_ids.remove("position"); /* Copy dynamic control point attributes. */ - for (const StringRef name : source_attribute_names) { - const GVArrayPtr mesh_attribute = mesh_component.attribute_try_get_for_read(name, + for (const AttributeIDRef &attribute_id : source_attribute_ids) { + const GVArrayPtr mesh_attribute = mesh_component.attribute_try_get_for_read(attribute_id, ATTR_DOMAIN_POINT); /* Some attributes might not exist if they were builtin attribute on domains that don't * have any elements, i.e. a face attribute on the output of the line primitive node. */ @@ -100,8 +100,9 @@ static void copy_attributes_to_points(CurveEval &curve, threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { for (const int i : range) { /* Create attribute on the spline points. */ - splines[i]->attributes.create(name, data_type); - std::optional<GMutableSpan> spline_attribute = splines[i]->attributes.get_for_write(name); + splines[i]->attributes.create(attribute_id, data_type); + std::optional<GMutableSpan> spline_attribute = splines[i]->attributes.get_for_write( + attribute_id); BLI_assert(spline_attribute); /* Copy attribute based on the map for this spline. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index 99930b5ae46..19da1189987 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -277,17 +277,17 @@ BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh, BLI_NOINLINE static void interpolate_existing_attributes( Span<GeometryInstanceGroup> set_groups, Span<int> instance_start_offsets, - const Map<std::string, AttributeKind> &attributes, + const Map<AttributeIDRef, AttributeKind> &attributes, GeometryComponent &component, Span<Vector<float3>> bary_coords_array, Span<Vector<int>> looptri_indices_array) { - for (Map<std::string, AttributeKind>::Item entry : attributes.items()) { - StringRef attribute_name = entry.key; + for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { + const AttributeIDRef attribute_id = entry.key; const CustomDataType output_data_type = entry.value.data_type; /* The output domain is always #ATTR_DOMAIN_POINT, since we are creating a point cloud. */ OutputAttribute attribute_out = component.attribute_try_get_for_output_only( - attribute_name, ATTR_DOMAIN_POINT, output_data_type); + attribute_id, ATTR_DOMAIN_POINT, output_data_type); if (!attribute_out) { continue; } @@ -301,7 +301,7 @@ BLI_NOINLINE static void interpolate_existing_attributes( const Mesh &mesh = *source_component.get_for_read(); std::optional<AttributeMetaData> attribute_info = component.attribute_get_meta_data( - attribute_name); + attribute_id); if (!attribute_info) { i_instance += set_group.transforms.size(); continue; @@ -309,7 +309,7 @@ BLI_NOINLINE static void interpolate_existing_attributes( const AttributeDomain source_domain = attribute_info->domain; GVArrayPtr source_attribute = source_component.attribute_get_for_read( - attribute_name, source_domain, output_data_type, nullptr); + attribute_id, source_domain, output_data_type, nullptr); if (!source_attribute) { i_instance += set_group.transforms.size(); continue; @@ -406,7 +406,7 @@ BLI_NOINLINE static void compute_special_attributes(Span<GeometryInstanceGroup> BLI_NOINLINE static void add_remaining_point_attributes( Span<GeometryInstanceGroup> set_groups, Span<int> instance_start_offsets, - const Map<std::string, AttributeKind> &attributes, + const Map<AttributeIDRef, AttributeKind> &attributes, GeometryComponent &component, Span<Vector<float3>> bary_coords_array, Span<Vector<int>> looptri_indices_array) @@ -629,7 +629,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) PointCloudComponent &point_component = geometry_set_out.get_component_for_write<PointCloudComponent>(); - Map<std::string, AttributeKind> attributes; + Map<AttributeIDRef, AttributeKind> attributes; bke::geometry_set_gather_instances_attribute_info( set_groups, {GEO_COMPONENT_TYPE_MESH}, {"position", "normal", "id"}, attributes); add_remaining_point_attributes(set_groups, diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc index fc04d1e275f..5e9b040f973 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc @@ -57,8 +57,8 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, Span<bool> masks, const bool invert) { - for (const std::string &name : in_component.attribute_names()) { - ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(name); + for (const AttributeIDRef &attribute_id : in_component.attribute_ids()) { + ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type()); /* Only copy point attributes. Theoretically this could interpolate attributes on other @@ -69,7 +69,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, } OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( - name, ATTR_DOMAIN_POINT, data_type); + attribute_id, ATTR_DOMAIN_POINT, data_type); attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc index 7487f11d77d..3b3b643d0ae 100644 --- a/source/blender/nodes/intern/geometry_nodes_eval_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc @@ -161,8 +161,10 @@ GeometryValueLog::GeometryValueLog(const GeometrySet &geometry_set, bool log_ful { bke::geometry_set_instances_attribute_foreach( geometry_set, - [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) { - this->attributes_.append({attribute_name, meta_data.domain, meta_data.data_type}); + [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (attribute_id.is_named()) { + this->attributes_.append({attribute_id.name(), meta_data.domain, meta_data.data_type}); + } return true; }, 8); |