diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/anonymous_attribute.cc | 19 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/attribute_access.cc | 147 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curve_eval.cc | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 35 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/geometry_set_instances.cc | 53 |
5 files changed, 153 insertions, 108 deletions
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}, |