diff --git a/source/blender/blenkernel/BKE_anonymous_attribute_id.hh b/source/blender/blenkernel/BKE_anonymous_attribute_id.hh index 1f6ee0cf271..8c2e76eac45 100644 --- a/source/blender/blenkernel/BKE_anonymous_attribute_id.hh +++ b/source/blender/blenkernel/BKE_anonymous_attribute_id.hh @@ -12,52 +12,6 @@ namespace blender::bke { -/** - * An #AnonymousAttributeID contains information about a specific anonymous attribute. - * Like normal attributes, anonymous attributes are also identified by their name, so one should - * not have to compare #AnonymousAttributeID pointers. - * - * Anonymous attributes don't need additional information besides their name, with a few - * exceptions: - * - The name of anonymous attributes is generated automatically, so it is generally not human - * readable (just random characters). #AnonymousAttributeID can provide more context as where a - * specific anonymous attribute was created which can simplify debugging. - * - [Not yet supported.] When anonymous attributes are contained in on-disk caches, we have to map - * those back to anonymous attributes at run-time. The issue is that (for various reasons) we - * might change how anonymous attribute names are generated in the future, which would lead to a - * mis-match between stored and new attribute names. To work around it, we should cache - * additional information for anonymous attributes on disk (like which node created it). This - * information can then be used to map stored attributes to their run-time counterpart. - * - * Once created, #AnonymousAttributeID is immutable. Also it is intrinsically reference counted so - * that it can have shared ownership. `std::shared_ptr` can't be used for that purpose here, - * because that is not available in C code. If possible, the #AnonymousAttributeIDPtr wrapper - * should be used to avoid manual reference counting in C++ code. - */ -class AnonymousAttributeID : public ImplicitSharingMixin { - protected: - std::string name_; - - public: - virtual ~AnonymousAttributeID() = default; - - StringRefNull name() const - { - return name_; - } - - virtual std::string user_name() const; - - private: - void delete_self() override - { - MEM_delete(this); - } -}; - -/** Wrapper for #AnonymousAttributeID that avoids manual reference counting. */ -using AnonymousAttributeIDPtr = ImplicitSharingPtr; - /** * A set of anonymous attribute names that is passed around in geometry nodes. */ @@ -91,7 +45,7 @@ class AnonymousAttributePropagationInfo { /** * Return true when the anonymous attribute should be propagated and false otherwise. */ - bool propagate(const AnonymousAttributeID &anonymous_id) const; + bool propagate(StringRef anonymous_id) const; }; } // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_anonymous_attribute_make.hh b/source/blender/blenkernel/BKE_anonymous_attribute_make.hh new file mode 100644 index 00000000000..1fd96b8790c --- /dev/null +++ b/source/blender/blenkernel/BKE_anonymous_attribute_make.hh @@ -0,0 +1,20 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include + +namespace blender::bke { + +template inline std::string hash_to_anonymous_attribute_name(Args &&...args) +{ + std::stringstream ss; + ((ss << args), ...); + const std::string long_name = ss.str(); + const XXH128_hash_t hash = XXH3_128bits(long_name.c_str(), long_name.size()); + return fmt::format(".a_{:x}{:x}", hash.low64, hash.high64); +} + +} // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_attribute.hh b/source/blender/blenkernel/BKE_attribute.hh index 575b84a492f..d5b2d08b05e 100644 --- a/source/blender/blenkernel/BKE_attribute.hh +++ b/source/blender/blenkernel/BKE_attribute.hh @@ -55,7 +55,6 @@ enum class AttrDomain : int8_t { class AttributeIDRef { private: StringRef name_; - const AnonymousAttributeID *anonymous_id_ = nullptr; public: AttributeIDRef(); @@ -63,20 +62,29 @@ class AttributeIDRef { AttributeIDRef(StringRefNull name); AttributeIDRef(const char *name); AttributeIDRef(const std::string &name); - AttributeIDRef(const AnonymousAttributeID &anonymous_id); - AttributeIDRef(const AnonymousAttributeID *anonymous_id); operator bool() const; uint64_t hash() const; bool is_anonymous() const; StringRef name() const; - const AnonymousAttributeID &anonymous_id() const; BLI_STRUCT_EQUALITY_OPERATORS_1(AttributeIDRef, name_) friend std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_id); }; +/** + * Checks if the attribute name has the `.a_` prefix which indicates that it is an anonymous + * attribute. I.e. it is just internally used by Blender and the name should not be exposed to the + * user. + * + * Use #hash_to_anonymous_attribute_name to generate names for anonymous attributes. + */ +inline bool attribute_name_is_anonymous(const StringRef name) +{ + return name.startswith(".a_"); +} + const CPPType *custom_data_type_to_cpp_type(eCustomDataType type); eCustomDataType cpp_type_to_custom_data_type(const CPPType &type); @@ -862,19 +870,6 @@ inline AttributeIDRef::AttributeIDRef(const char *name) : name_(name) {} inline AttributeIDRef::AttributeIDRef(const std::string &name) : name_(name) {} -/* The anonymous id is only borrowed, the caller has to keep a reference to it. */ -inline AttributeIDRef::AttributeIDRef(const AnonymousAttributeID &anonymous_id) - : AttributeIDRef(anonymous_id.name()) -{ - anonymous_id_ = &anonymous_id; -} - -inline AttributeIDRef::AttributeIDRef(const AnonymousAttributeID *anonymous_id) - : AttributeIDRef(anonymous_id ? anonymous_id->name() : "") -{ - anonymous_id_ = anonymous_id; -} - inline AttributeIDRef::operator bool() const { return !name_.is_empty(); @@ -887,7 +882,7 @@ inline uint64_t AttributeIDRef::hash() const inline bool AttributeIDRef::is_anonymous() const { - return anonymous_id_ != nullptr; + return attribute_name_is_anonymous(name_); } inline StringRef AttributeIDRef::name() const @@ -895,12 +890,6 @@ inline StringRef AttributeIDRef::name() const return name_; } -inline const AnonymousAttributeID &AttributeIDRef::anonymous_id() const -{ - BLI_assert(this->is_anonymous()); - return *anonymous_id_; -} - void gather_attributes(AttributeAccessor src_attributes, AttrDomain domain, const AnonymousAttributePropagationInfo &propagation_info, diff --git a/source/blender/blenkernel/BKE_bake_items_socket.hh b/source/blender/blenkernel/BKE_bake_items_socket.hh index 0f6277c4595..22ea080548d 100644 --- a/source/blender/blenkernel/BKE_bake_items_socket.hh +++ b/source/blender/blenkernel/BKE_bake_items_socket.hh @@ -55,7 +55,7 @@ void move_bake_items_to_socket_values( Span bake_items, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map, - FunctionRef(int socket_index, const CPPType &)> + FunctionRef(int socket_index, const CPPType &)> make_attribute_field, Span r_socket_values); @@ -67,8 +67,7 @@ void copy_bake_items_to_socket_values( Span bake_items, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map, - FunctionRef(int, const CPPType &)> - make_attribute_field, + FunctionRef(int, const CPPType &)> make_attribute_field, Span r_socket_values); } // namespace blender::bke::bake diff --git a/source/blender/blenkernel/BKE_customdata.hh b/source/blender/blenkernel/BKE_customdata.hh index f62c9301759..12a3f322ddb 100644 --- a/source/blender/blenkernel/BKE_customdata.hh +++ b/source/blender/blenkernel/BKE_customdata.hh @@ -282,19 +282,6 @@ const void *CustomData_add_layer_named_with_data(CustomData *data, blender::StringRef name, const blender::ImplicitSharingInfo *sharing_info); -void *CustomData_add_layer_anonymous(CustomData *data, - eCustomDataType type, - eCDAllocType alloctype, - int totelem, - const AnonymousAttributeIDHandle *anonymous_id); -const void *CustomData_add_layer_anonymous_with_data( - CustomData *data, - eCustomDataType type, - const AnonymousAttributeIDHandle *anonymous_id, - int totelem, - void *layer_data, - const blender::ImplicitSharingInfo *sharing_info); - /** * 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 diff --git a/source/blender/blenkernel/BKE_geometry_fields.hh b/source/blender/blenkernel/BKE_geometry_fields.hh index df3ef47b07d..f8f2c671587 100644 --- a/source/blender/blenkernel/BKE_geometry_fields.hh +++ b/source/blender/blenkernel/BKE_geometry_fields.hh @@ -261,22 +261,34 @@ class InstancesFieldInput : public fn::FieldInput { class AttributeFieldInput : public GeometryFieldInput { private: std::string name_; + std::optional socket_inspection_name_; public: - AttributeFieldInput(std::string name, const CPPType &type) - : GeometryFieldInput(type, name), name_(std::move(name)) + AttributeFieldInput(std::string name, + const CPPType &type, + std::optional socket_inspection_name = std::nullopt) + : GeometryFieldInput(type, name), + name_(std::move(name)), + socket_inspection_name_(std::move(socket_inspection_name)) { - category_ = Category::NamedAttribute; + category_ = attribute_name_is_anonymous(name_) ? Category::AnonymousAttribute : + Category::NamedAttribute; } - static fn::GField Create(std::string name, const CPPType &type) + static fn::GField Create(std::string name, + const CPPType &type, + std::optional socket_inspection_name = std::nullopt) { - auto field_input = std::make_shared(std::move(name), type); + auto field_input = std::make_shared( + std::move(name), type, std::move(socket_inspection_name)); return fn::GField(field_input); } - template static fn::Field Create(std::string name) + template + static fn::Field Create(std::string name, + std::optional socket_inspection_name = std::nullopt) { - return fn::Field(Create(std::move(name), CPPType::get())); + return fn::Field( + Create(std::move(name), CPPType::get(), std::move(socket_inspection_name))); } StringRefNull attribute_name() const @@ -371,46 +383,6 @@ class NormalFieldInput : public GeometryFieldInput { bool is_equal_to(const fn::FieldNode &other) const override; }; -class AnonymousAttributeFieldInput : public GeometryFieldInput { - private: - AnonymousAttributeIDPtr anonymous_id_; - std::string producer_name_; - - public: - AnonymousAttributeFieldInput(AnonymousAttributeIDPtr anonymous_id, - const CPPType &type, - std::string producer_name) - : GeometryFieldInput(type, anonymous_id->user_name()), - anonymous_id_(std::move(anonymous_id)), - producer_name_(std::move(producer_name)) - { - category_ = Category::AnonymousAttribute; - } - - template - static fn::Field Create(AnonymousAttributeIDPtr anonymous_id, std::string producer_name) - { - const CPPType &type = CPPType::get(); - auto field_input = std::make_shared( - std::move(anonymous_id), type, std::move(producer_name)); - return fn::Field{field_input}; - } - - const AnonymousAttributeIDPtr &anonymous_id() const - { - return anonymous_id_; - } - - GVArray get_varray_for_context(const GeometryFieldContext &context, - const IndexMask &mask) const override; - - std::string socket_inspection_name() const override; - - uint64_t hash() const override; - bool is_equal_to(const fn::FieldNode &other) const override; - std::optional preferred_domain(const GeometryComponent &component) const override; -}; - class CurveLengthFieldInput final : public CurvesFieldInput { public: CurveLengthFieldInput(); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b5baed9a440..12c8554e156 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -328,6 +328,7 @@ set(SRC BKE_anim_visualization.h BKE_animsys.h BKE_anonymous_attribute_id.hh + BKE_anonymous_attribute_make.hh BKE_appdir.hh BKE_armature.hh BKE_asset.hh diff --git a/source/blender/blenkernel/intern/anonymous_attribute_id.cc b/source/blender/blenkernel/intern/anonymous_attribute_id.cc index 8080c131dd9..58fdeb6375a 100644 --- a/source/blender/blenkernel/intern/anonymous_attribute_id.cc +++ b/source/blender/blenkernel/intern/anonymous_attribute_id.cc @@ -6,12 +6,7 @@ namespace blender::bke { -std::string AnonymousAttributeID::user_name() const -{ - return this->name(); -} - -bool AnonymousAttributePropagationInfo::propagate(const AnonymousAttributeID &anonymous_id) const +bool AnonymousAttributePropagationInfo::propagate(const StringRef attribute) const { if (this->propagate_all) { return true; @@ -19,7 +14,7 @@ bool AnonymousAttributePropagationInfo::propagate(const AnonymousAttributeID &an if (!this->names) { return false; } - return this->names->contains_as(anonymous_id.name()); + return this->names->contains_as(attribute); } } // namespace blender::bke diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 8a10a378eac..90bccfcb222 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -252,9 +252,6 @@ AttrDomain attribute_domain_highest_priority(Span domains) static AttributeIDRef attribute_id_from_custom_data_layer(const CustomDataLayer &layer) { - if (layer.anonymous_id != nullptr) { - return *layer.anonymous_id; - } return layer.name; } @@ -264,15 +261,10 @@ static void *add_generic_custom_data_layer(CustomData &custom_data, const int domain_size, const AttributeIDRef &attribute_id) { - if (!attribute_id.is_anonymous()) { - char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME]; - attribute_id.name().copy(attribute_name_c); - return CustomData_add_layer_named( - &custom_data, data_type, alloctype, domain_size, attribute_name_c); - } - const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id(); - return CustomData_add_layer_anonymous( - &custom_data, data_type, alloctype, domain_size, &anonymous_id); + char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME]; + attribute_id.name().copy(attribute_name_c); + return CustomData_add_layer_named( + &custom_data, data_type, alloctype, domain_size, attribute_name_c); } static const void *add_generic_custom_data_layer_with_existing_data( @@ -283,11 +275,6 @@ static const void *add_generic_custom_data_layer_with_existing_data( void *layer_data, const ImplicitSharingInfo *sharing_info) { - if (attribute_id.is_anonymous()) { - const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id(); - return CustomData_add_layer_anonymous_with_data( - &custom_data, data_type, &anonymous_id, domain_size, layer_data, sharing_info); - } return CustomData_add_layer_named_with_data( &custom_data, data_type, layer_data, domain_size, attribute_id.name(), sharing_info); } @@ -673,15 +660,15 @@ Set AttributeAccessor::all_ids() const void MutableAttributeAccessor::remove_anonymous() { - Vector anonymous_ids; + Vector anonymous_ids; for (const AttributeIDRef &id : this->all_ids()) { if (id.is_anonymous()) { - anonymous_ids.append(&id.anonymous_id()); + anonymous_ids.append(id.name()); } } while (!anonymous_ids.is_empty()) { - this->remove(*anonymous_ids.pop_last()); + this->remove(anonymous_ids.pop_last()); } } @@ -835,7 +822,7 @@ Vector retrieve_attributes_for_transfer( if (!(ATTR_DOMAIN_AS_MASK(meta_data.domain) & domain_mask)) { return true; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } if (skip.contains(id.name())) { @@ -869,7 +856,7 @@ void gather_attributes(const AttributeAccessor src_attributes, if (meta_data.data_type == CD_PROP_STRING) { return true; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } if (skip.contains(id.name())) { @@ -911,7 +898,7 @@ void gather_attributes(const AttributeAccessor src_attributes, if (meta_data.data_type == CD_PROP_STRING) { return true; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } if (skip.contains(id.name())) { @@ -946,7 +933,7 @@ void gather_attributes_group_to_group(const AttributeAccessor src_attributes, if (meta_data.data_type == CD_PROP_STRING) { return true; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } if (skip.contains(id.name())) { @@ -979,7 +966,7 @@ void gather_attributes_to_groups(const AttributeAccessor src_attributes, if (meta_data.data_type == CD_PROP_STRING) { return true; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } if (skip.contains(id.name())) { @@ -1031,7 +1018,7 @@ void copy_attributes_group_to_group(const AttributeAccessor src_attributes, if (meta_data.data_type == CD_PROP_STRING) { return true; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } if (skip.contains(id.name())) { diff --git a/source/blender/blenkernel/intern/bake_items_socket.cc b/source/blender/blenkernel/intern/bake_items_socket.cc index 59a4b2dc6d5..082f0f36081 100644 --- a/source/blender/blenkernel/intern/bake_items_socket.cc +++ b/source/blender/blenkernel/intern/bake_items_socket.cc @@ -128,9 +128,9 @@ Array> move_socket_values_to_bake_items(const Span(const CPPType &type)> + const FunctionRef(const CPPType &type)> make_attribute_field, - Map &r_attribute_map, + Map &r_attribute_map, void *r_value) { switch (socket_type) { @@ -158,12 +158,10 @@ Array> move_socket_values_to_bake_items(const Span(&bake_item)) { - std::shared_ptr attribute_field = make_attribute_field( - base_type); - const AnonymousAttributeIDPtr &attribute_id = attribute_field->anonymous_id(); + std::shared_ptr attribute_field = make_attribute_field(base_type); + r_attribute_map.add(item->name(), attribute_field->attribute_name()); fn::GField field{attribute_field}; new (r_value) SocketValueVariant(std::move(field)); - r_attribute_map.add(item->name(), attribute_id); return true; } #ifdef WITH_OPENVDB @@ -198,7 +196,7 @@ Array> move_socket_values_to_bake_items(const Span geometries, - const Map &attribute_map) + const Map &attribute_map) { for (GeometrySet *geometry : geometries) { for (const GeometryComponent::Type type : {GeometryComponent::Type::Mesh, @@ -221,10 +219,8 @@ static void rename_attributes(const Span geometries, GeometryComponent &component = geometry->get_component_for_write(type); MutableAttributeAccessor attributes = *component.attributes_for_write(); - for (const MapItem &attribute_item : - attribute_map.items()) - { - attributes.rename(attribute_item.key, *attribute_item.value); + for (const MapItem &attribute_item : attribute_map.items()) { + attributes.rename(attribute_item.key, attribute_item.value); } } } @@ -255,11 +251,10 @@ void move_bake_items_to_socket_values( const Span bake_items, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map, - FunctionRef(int, const CPPType &)> - make_attribute_field, + FunctionRef(int, const CPPType &)> make_attribute_field, const Span r_socket_values) { - Map attribute_map; + Map attribute_map; Vector geometries; @@ -296,11 +291,10 @@ void copy_bake_items_to_socket_values( const Span bake_items, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map, - FunctionRef(int, const CPPType &)> - make_attribute_field, + FunctionRef(int, const CPPType &)> make_attribute_field, const Span r_socket_values) { - Map attribute_map; + Map attribute_map; Vector geometries; for (const int i : bake_items.index_range()) { diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index 8887506b04b..23036ff5e02 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -376,7 +376,7 @@ static bool should_add_attribute_to_mesh(const AttributeAccessor &curve_attribut if (curve_attributes.is_builtin(id) && !mesh_attributes.is_builtin(id)) { return false; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return false; } if (meta_data.data_type == CD_PROP_STRING) { diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 95ecd1b5816..750f8f36772 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2487,11 +2487,6 @@ static bool customdata_merge_internal(const CustomData *source, new_layer->active_clone = last_clone; new_layer->active_mask = last_mask; changed = true; - - if (src_layer.anonymous_id != nullptr) { - new_layer->anonymous_id = src_layer.anonymous_id; - new_layer->anonymous_id->add_user(); - } } CustomData_update_typemap(dest); @@ -2718,10 +2713,6 @@ void CustomData_init_layout_from(const CustomData *source, static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem) { - if (layer->anonymous_id != nullptr) { - layer->anonymous_id->remove_user_and_delete_if_last(); - layer->anonymous_id = nullptr; - } const eCustomDataType type = eCustomDataType(layer->type); if (layer->sharing_info == nullptr) { if (layer->data) { @@ -3081,7 +3072,7 @@ bool CustomData_layer_is_anonymous(const CustomData *data, eCustomDataType type, BLI_assert(layer_index >= 0); - return data->layers[layer_index].anonymous_id != nullptr; + return blender::bke::attribute_name_is_anonymous(data->layers[layer_index].name); } static void customData_resize(CustomData *data, const int grow_amount) @@ -3283,47 +3274,6 @@ const void *CustomData_add_layer_named_with_data(CustomData *data, return nullptr; } -void *CustomData_add_layer_anonymous(CustomData *data, - const eCustomDataType type, - const eCDAllocType alloctype, - const int totelem, - const AnonymousAttributeIDHandle *anonymous_id) -{ - const StringRef name = anonymous_id->name().c_str(); - CustomDataLayer *layer = customData_add_layer__internal( - data, type, alloctype, nullptr, nullptr, totelem, name); - CustomData_update_typemap(data); - - if (layer == nullptr) { - return nullptr; - } - - anonymous_id->add_user(); - layer->anonymous_id = anonymous_id; - return layer->data; -} - -const void *CustomData_add_layer_anonymous_with_data( - CustomData *data, - const eCustomDataType type, - const AnonymousAttributeIDHandle *anonymous_id, - const int totelem, - void *layer_data, - const ImplicitSharingInfo *sharing_info) -{ - const StringRef name = anonymous_id->name().c_str(); - CustomDataLayer *layer = customData_add_layer__internal( - data, type, std::nullopt, layer_data, sharing_info, totelem, name); - CustomData_update_typemap(data); - - if (layer == nullptr) { - return nullptr; - } - anonymous_id->add_user(); - layer->anonymous_id = anonymous_id; - return layer->data; -} - bool CustomData_free_layer(CustomData *data, const eCustomDataType type, const int totelem, @@ -3438,7 +3388,9 @@ int CustomData_number_of_anonymous_layers(const CustomData *data, const eCustomD int number = 0; for (int i = 0; i < data->totlayer; i++) { - if (data->layers[i].type == type && data->layers[i].anonymous_id != nullptr) { + if (data->layers[i].type == type && + blender::bke::attribute_name_is_anonymous(data->layers[i].name)) + { number++; } } @@ -4475,7 +4427,7 @@ void CustomData_blend_write_prepare(CustomData &data, if (layer.flag & CD_FLAG_NOCOPY) { continue; } - if (layer.anonymous_id != nullptr) { + if (blender::bke::attribute_name_is_anonymous(layer.name)) { continue; } if (skip_names.contains(layer.name)) { diff --git a/source/blender/blenkernel/intern/geometry_fields.cc b/source/blender/blenkernel/intern/geometry_fields.cc index da06f6c4501..73aa6b78346 100644 --- a/source/blender/blenkernel/intern/geometry_fields.cc +++ b/source/blender/blenkernel/intern/geometry_fields.cc @@ -430,6 +430,9 @@ GVArray AttributeExistsFieldInput::get_varray_for_context(const bke::GeometryFie std::string AttributeFieldInput::socket_inspection_name() const { + if (socket_inspection_name_) { + return *socket_inspection_name_; + } return fmt::format(TIP_("\"{}\" attribute from geometry"), name_); } @@ -503,47 +506,6 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const return dynamic_cast(&other) != nullptr; } -GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryFieldContext &context, - const IndexMask & /*mask*/) const -{ - const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_); - return *context.attributes()->lookup(*anonymous_id_, context.domain(), data_type); -} - -std::string AnonymousAttributeFieldInput::socket_inspection_name() const -{ - return fmt::format(TIP_("\"{}\" from {}"), TIP_(debug_name_.c_str()), producer_name_); -} - -uint64_t AnonymousAttributeFieldInput::hash() const -{ - return get_default_hash(anonymous_id_.get(), type_); -} - -bool AnonymousAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const -{ - if (const AnonymousAttributeFieldInput *other_typed = - dynamic_cast(&other)) - { - return anonymous_id_.get() == other_typed->anonymous_id_.get() && type_ == other_typed->type_; - } - return false; -} - -std::optional AnonymousAttributeFieldInput::preferred_domain( - const GeometryComponent &component) const -{ - const std::optional attributes = component.attributes(); - if (!attributes.has_value()) { - return std::nullopt; - } - const std::optional meta_data = attributes->lookup_meta_data(*anonymous_id_); - if (!meta_data.has_value()) { - return std::nullopt; - } - return meta_data->domain; -} - GVArray NamedLayerSelectionFieldInput::get_varray_for_context( const bke::GeometryFieldContext &context, const IndexMask &mask) const { @@ -764,9 +726,6 @@ static std::optional try_get_field_direct_attribute_id(const fn: if (const auto *field = dynamic_cast(&any_field.node())) { return field->attribute_name(); } - if (const auto *field = dynamic_cast(&any_field.node())) { - return *field->anonymous_id(); - } return {}; } diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 433edc655c7..52932469496 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -635,7 +635,7 @@ void GeometrySet::propagate_attributes_from_layer_to_instances( const AnonymousAttributePropagationInfo &propagation_info) { src_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } const GAttributeReader src = src_attributes.lookup(id, AttrDomain::Layer); @@ -683,8 +683,7 @@ void GeometrySet::gather_attributes_for_propagation( /* Propagating string attributes is not supported yet. */ return; } - if (attribute_id.is_anonymous() && - !propagation_info.propagate(attribute_id.anonymous_id())) { + if (attribute_id.is_anonymous() && !propagation_info.propagate(attribute_id.name())) { return; } diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt index 5325406ed6f..5c998a4fc6e 100644 --- a/source/blender/editors/armature/CMakeLists.txt +++ b/source/blender/editors/armature/CMakeLists.txt @@ -49,6 +49,7 @@ set(LIB PRIVATE bf::blenlib PRIVATE bf::depsgraph PRIVATE bf::dna + PRIVATE bf::extern::fmtlib PRIVATE bf::intern::clog PRIVATE bf::intern::guardedalloc ) diff --git a/source/blender/editors/curves/CMakeLists.txt b/source/blender/editors/curves/CMakeLists.txt index 4f942712d51..c71d693ba3b 100644 --- a/source/blender/editors/curves/CMakeLists.txt +++ b/source/blender/editors/curves/CMakeLists.txt @@ -39,6 +39,7 @@ set(LIB PRIVATE bf::depsgraph PRIVATE bf::dna PRIVATE bf::extern::curve_fit_nd + PRIVATE bf::extern::fmtlib PRIVATE bf::intern::clog PRIVATE bf::intern::guardedalloc ) diff --git a/source/blender/editors/geometry/CMakeLists.txt b/source/blender/editors/geometry/CMakeLists.txt index 17631417061..06f27aaf60e 100644 --- a/source/blender/editors/geometry/CMakeLists.txt +++ b/source/blender/editors/geometry/CMakeLists.txt @@ -35,6 +35,7 @@ set(LIB PRIVATE bf::depsgraph PRIVATE bf::dna bf_editor_object + PRIVATE bf::extern::fmtlib PRIVATE bf::intern::guardedalloc bf_windowmanager ) diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_geom.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_geom.cc index 2088c4ab323..565c97c490b 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_geom.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_geom.cc @@ -305,7 +305,7 @@ blender::bke::CurvesGeometry curves_merge_by_distance( bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write(); src_attributes.for_all([&](const bke::AttributeIDRef &id, const bke::AttributeMetaData &meta_data) { - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } if (meta_data.domain != bke::AttrDomain::Point) { diff --git a/source/blender/geometry/GEO_mesh_primitive_cuboid.hh b/source/blender/geometry/GEO_mesh_primitive_cuboid.hh index bf1e0960772..a90bbbc43ee 100644 --- a/source/blender/geometry/GEO_mesh_primitive_cuboid.hh +++ b/source/blender/geometry/GEO_mesh_primitive_cuboid.hh @@ -15,8 +15,11 @@ class AttributeIDRef; namespace blender::geometry { -Mesh *create_cuboid_mesh( - const float3 &size, int verts_x, int verts_y, int verts_z, const bke::AttributeIDRef &uv_id); +Mesh *create_cuboid_mesh(const float3 &size, + int verts_x, + int verts_y, + int verts_z, + const std::optional &uv_id); Mesh *create_cuboid_mesh(const float3 &size, int verts_x, int verts_y, int verts_z); diff --git a/source/blender/geometry/GEO_mesh_primitive_cylinder_cone.hh b/source/blender/geometry/GEO_mesh_primitive_cylinder_cone.hh index 5afaf96f045..0a1d8bc5e2b 100644 --- a/source/blender/geometry/GEO_mesh_primitive_cylinder_cone.hh +++ b/source/blender/geometry/GEO_mesh_primitive_cylinder_cone.hh @@ -11,10 +11,10 @@ struct Mesh; namespace blender::geometry { struct ConeAttributeOutputs { - bke::AnonymousAttributeIDPtr top_id; - bke::AnonymousAttributeIDPtr bottom_id; - bke::AnonymousAttributeIDPtr side_id; - bke::AnonymousAttributeIDPtr uv_map_id; + std::optional top_id; + std::optional bottom_id; + std::optional side_id; + std::optional uv_map_id; }; enum class ConeFillType { diff --git a/source/blender/geometry/GEO_mesh_primitive_grid.hh b/source/blender/geometry/GEO_mesh_primitive_grid.hh index ca42f3ec28e..aa76cb70d49 100644 --- a/source/blender/geometry/GEO_mesh_primitive_grid.hh +++ b/source/blender/geometry/GEO_mesh_primitive_grid.hh @@ -11,7 +11,10 @@ class AttributeIDRef; namespace blender::geometry { -Mesh *create_grid_mesh( - int verts_x, int verts_y, float size_x, float size_y, const bke::AttributeIDRef &uv_map_id); +Mesh *create_grid_mesh(int verts_x, + int verts_y, + float size_x, + float size_y, + const std::optional &uv_map_id); } // namespace blender::geometry diff --git a/source/blender/geometry/GEO_mesh_primitive_uv_sphere.hh b/source/blender/geometry/GEO_mesh_primitive_uv_sphere.hh index 7e74c60128f..5279961497a 100644 --- a/source/blender/geometry/GEO_mesh_primitive_uv_sphere.hh +++ b/source/blender/geometry/GEO_mesh_primitive_uv_sphere.hh @@ -26,6 +26,6 @@ Bounds calculate_bounds_radial_primitive(float radius_top, Mesh *create_uv_sphere_mesh(float radius, int segments, int rings, - const bke::AttributeIDRef &uv_map_id); + const std::optional &uv_map_id); } // namespace blender::geometry diff --git a/source/blender/geometry/GEO_resample_curves.hh b/source/blender/geometry/GEO_resample_curves.hh index 4320947dd48..349a23b6682 100644 --- a/source/blender/geometry/GEO_resample_curves.hh +++ b/source/blender/geometry/GEO_resample_curves.hh @@ -14,8 +14,8 @@ namespace blender::geometry { using bke::CurvesGeometry; struct ResampleCurvesOutputAttributeIDs { - bke::AttributeIDRef tangent_id; - bke::AttributeIDRef normal_id; + std::optional tangent_id; + std::optional normal_id; }; /** diff --git a/source/blender/geometry/intern/mesh_primitive_cuboid.cc b/source/blender/geometry/intern/mesh_primitive_cuboid.cc index cc9d43a16b7..81de447af51 100644 --- a/source/blender/geometry/intern/mesh_primitive_cuboid.cc +++ b/source/blender/geometry/intern/mesh_primitive_cuboid.cc @@ -289,7 +289,7 @@ static void calculate_corner_verts(const CuboidConfig &config, MutableSpan } } -static void calculate_uvs(const CuboidConfig &config, Mesh *mesh, const bke::AttributeIDRef &uv_id) +static void calculate_uvs(const CuboidConfig &config, Mesh *mesh, const std::string &uv_id) { bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); bke::SpanAttributeWriter uv_attribute = attributes.lookup_or_add_for_write_only_span( @@ -369,7 +369,7 @@ Mesh *create_cuboid_mesh(const float3 &size, const int verts_x, const int verts_y, const int verts_z, - const bke::AttributeIDRef &uv_id) + const std::optional &uv_id) { const CuboidConfig config(size, verts_x, verts_y, verts_z); @@ -384,7 +384,7 @@ Mesh *create_cuboid_mesh(const float3 &size, bke::mesh_calc_edges(*mesh, false, false); if (uv_id) { - calculate_uvs(config, mesh, uv_id); + calculate_uvs(config, mesh, *uv_id); } const float3 bounds = size * 0.5f; diff --git a/source/blender/geometry/intern/mesh_primitive_cylinder_cone.cc b/source/blender/geometry/intern/mesh_primitive_cylinder_cone.cc index 7be82245d75..55c3bb5e9b7 100644 --- a/source/blender/geometry/intern/mesh_primitive_cylinder_cone.cc +++ b/source/blender/geometry/intern/mesh_primitive_cylinder_cone.cc @@ -473,7 +473,7 @@ static void calculate_selection_outputs(const ConeConfig &config, if (attribute_outputs.top_id) { const bool face = !config.top_is_point && config.fill_type != ConeFillType::None; bke::SpanAttributeWriter selection = attributes.lookup_or_add_for_write_span( - attribute_outputs.top_id.get(), face ? bke::AttrDomain::Face : bke::AttrDomain::Point); + *attribute_outputs.top_id, face ? bke::AttrDomain::Face : bke::AttrDomain::Point); if (config.top_is_point) { selection.span[config.first_vert] = true; @@ -488,7 +488,7 @@ static void calculate_selection_outputs(const ConeConfig &config, if (attribute_outputs.bottom_id) { const bool face = !config.bottom_is_point && config.fill_type != ConeFillType::None; bke::SpanAttributeWriter selection = attributes.lookup_or_add_for_write_span( - attribute_outputs.bottom_id.get(), face ? bke::AttrDomain::Face : bke::AttrDomain::Point); + *attribute_outputs.bottom_id, face ? bke::AttrDomain::Face : bke::AttrDomain::Point); if (config.bottom_is_point) { selection.span[config.last_vert] = true; @@ -505,7 +505,7 @@ static void calculate_selection_outputs(const ConeConfig &config, /* Populate "Side" selection output. */ if (attribute_outputs.side_id) { bke::SpanAttributeWriter selection = attributes.lookup_or_add_for_write_span( - attribute_outputs.side_id.get(), bke::AttrDomain::Face); + *attribute_outputs.side_id, bke::AttrDomain::Face); selection.span.slice(config.side_faces_start, config.side_faces_len).fill(true); selection.finish(); @@ -693,7 +693,7 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top, calculate_cone_faces(config, corner_verts, corner_edges, face_offsets.drop_back(1)); offset_indices::accumulate_counts_to_offsets(face_offsets); if (attribute_outputs.uv_map_id) { - calculate_cone_uvs(config, mesh, attribute_outputs.uv_map_id.get()); + calculate_cone_uvs(config, mesh, *attribute_outputs.uv_map_id); } calculate_selection_outputs(config, attribute_outputs, mesh->attributes_for_write()); diff --git a/source/blender/geometry/intern/mesh_primitive_grid.cc b/source/blender/geometry/intern/mesh_primitive_grid.cc index f31938b0a13..1112eb7d4a7 100644 --- a/source/blender/geometry/intern/mesh_primitive_grid.cc +++ b/source/blender/geometry/intern/mesh_primitive_grid.cc @@ -41,7 +41,7 @@ Mesh *create_grid_mesh(const int verts_x, const int verts_y, const float size_x, const float size_y, - const bke::AttributeIDRef &uv_map_id) + const std::optional &uv_map_id) { BLI_assert(verts_x > 0 && verts_y > 0); const int edges_x = verts_x - 1; @@ -143,7 +143,7 @@ Mesh *create_grid_mesh(const int verts_x, }); if (uv_map_id && mesh->faces_num != 0) { - calculate_uvs(mesh, positions, corner_verts, size_x, size_y, uv_map_id); + calculate_uvs(mesh, positions, corner_verts, size_x, size_y, *uv_map_id); } if (verts_x > 1 || verts_y > 1) { diff --git a/source/blender/geometry/intern/mesh_primitive_uv_sphere.cc b/source/blender/geometry/intern/mesh_primitive_uv_sphere.cc index 97401b77a51..3eb5dc393a0 100644 --- a/source/blender/geometry/intern/mesh_primitive_uv_sphere.cc +++ b/source/blender/geometry/intern/mesh_primitive_uv_sphere.cc @@ -235,7 +235,7 @@ BLI_NOINLINE static void calculate_sphere_corners(MutableSpan corner_verts, BLI_NOINLINE static void calculate_sphere_uvs(Mesh *mesh, const float segments, const float rings, - const bke::AttributeIDRef &uv_map_id) + const StringRef uv_map_id) { bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); @@ -294,7 +294,7 @@ static Bounds calculate_bounds_uv_sphere(const float radius, Mesh *create_uv_sphere_mesh(const float radius, const int segments, const int rings, - const bke::AttributeIDRef &uv_map_id) + const std::optional &uv_map_id) { Mesh *mesh = BKE_mesh_new_nomain(sphere_vert_total(segments, rings), sphere_edge_total(segments, rings), @@ -319,7 +319,7 @@ Mesh *create_uv_sphere_mesh(const float radius, [&]() { calculate_sphere_corners(corner_verts, corner_edges, segments, rings); }, [&]() { if (uv_map_id) { - calculate_sphere_uvs(mesh, segments, rings, uv_map_id); + calculate_sphere_uvs(mesh, segments, rings, *uv_map_id); } }); diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc index 8085931b152..15fb2aa9810 100644 --- a/source/blender/geometry/intern/mesh_to_curve_convert.cc +++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc @@ -61,7 +61,7 @@ BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices( if (skip.contains(id.name())) { return true; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } diff --git a/source/blender/geometry/intern/point_merge_by_distance.cc b/source/blender/geometry/intern/point_merge_by_distance.cc index 955ce52e120..a327650d3d4 100644 --- a/source/blender/geometry/intern/point_merge_by_distance.cc +++ b/source/blender/geometry/intern/point_merge_by_distance.cc @@ -123,7 +123,7 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points, /* Transfer all other attributes. */ for (const bke::AttributeIDRef &id : attribute_ids) { - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { continue; } diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index a516b7c32b8..0934e784b48 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -869,7 +869,7 @@ static void gather_attributes_for_propagation( return; } if (attribute_id.is_anonymous() && - !propagation_info.propagate(attribute_id.anonymous_id())) { + !propagation_info.propagate(attribute_id.name())) { return; } diff --git a/source/blender/geometry/intern/reorder.cc b/source/blender/geometry/intern/reorder.cc index 12360b06238..6f534953b34 100644 --- a/source/blender/geometry/intern/reorder.cc +++ b/source/blender/geometry/intern/reorder.cc @@ -225,7 +225,7 @@ static void clean_unused_attributes(const bke::AnonymousAttributePropagationInfo if (meta_data.data_type == CD_PROP_STRING) { return true; } - if (propagation_info.propagate(id.anonymous_id())) { + if (propagation_info.propagate(id.name())) { return true; } unused_ids.append(id.name()); diff --git a/source/blender/geometry/intern/resample_curves.cc b/source/blender/geometry/intern/resample_curves.cc index f098eef9bd8..4ffdb76a2bd 100644 --- a/source/blender/geometry/intern/resample_curves.cc +++ b/source/blender/geometry/intern/resample_curves.cc @@ -183,14 +183,14 @@ static void gather_point_attributes_to_interpolate( if (output_ids.tangent_id) { result.src_evaluated_tangents = src_curves.evaluated_tangents(); bke::GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( - output_ids.tangent_id, bke::AttrDomain::Point, CD_PROP_FLOAT3); + *output_ids.tangent_id, bke::AttrDomain::Point, CD_PROP_FLOAT3); result.dst_tangents = dst_attribute.span.typed(); result.dst_attributes.append(std::move(dst_attribute)); } if (output_ids.normal_id) { result.src_evaluated_normals = src_curves.evaluated_normals(); bke::GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( - output_ids.normal_id, bke::AttrDomain::Point, CD_PROP_FLOAT3); + *output_ids.normal_id, bke::AttrDomain::Point, CD_PROP_FLOAT3); result.dst_normals = dst_attribute.span.typed(); result.dst_attributes.append(std::move(dst_attribute)); } diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index d45abd3bcc6..30ccbba77cd 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -14,16 +14,6 @@ #include "BLI_implicit_sharing.h" -/** Workaround to forward-declare C++ type in C header. */ -#ifdef __cplusplus -namespace blender::bke { -class AnonymousAttributeID; -} // namespace blender::bke -using AnonymousAttributeIDHandle = blender::bke::AnonymousAttributeID; -#else -typedef struct AnonymousAttributeIDHandle AnonymousAttributeIDHandle; -#endif - /** Descriptor and storage for a custom data layer. */ typedef struct CustomDataLayer { /** Type of data in layer. */ @@ -47,11 +37,6 @@ typedef struct CustomDataLayer { char _pad1[4]; /** Layer data. */ void *data; - /** - * Run-time identifier for this layer. Can be used to retrieve information about where this - * attribute was created. - */ - const AnonymousAttributeIDHandle *anonymous_id; /** * Run-time data that allows sharing `data` with other entities (mostly custom data layers on * other geometries). diff --git a/source/blender/makesrna/intern/rna_mesh_utils.hh b/source/blender/makesrna/intern/rna_mesh_utils.hh index 41bc4299143..ca9ecada679 100644 --- a/source/blender/makesrna/intern/rna_mesh_utils.hh +++ b/source/blender/makesrna/intern/rna_mesh_utils.hh @@ -17,7 +17,7 @@ void *data) \ { \ CustomDataLayer *layer = (CustomDataLayer *)data; \ - return (layer->anonymous_id != NULL || layer->type != layer_type); \ + return (blender::bke::attribute_name_is_anonymous(layer->name) || layer->type != layer_type); \ } \ /* begin */ \ [[maybe_unused]] static void rna_Mesh_##collection_name##s_begin( \ diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 36a4f93a674..462feacca0d 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -146,6 +146,7 @@ set(LIB bf_nodes_shader bf_nodes_texture PRIVATE bf::extern::fmtlib + PRIVATE bf::extern::xxhash ) if(WITH_BULLET) diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 6872457b914..e3a16c19b1b 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -24,9 +24,6 @@ namespace blender::nodes { -using bke::AnonymousAttributeFieldInput; -using bke::AnonymousAttributeID; -using bke::AnonymousAttributeIDPtr; using bke::AnonymousAttributePropagationInfo; using bke::AttrDomain; using bke::AttributeAccessor; @@ -67,7 +64,7 @@ class GeoNodeExecParams { const lf::Context &lf_context_; const Span lf_input_for_output_bsocket_usage_; const Span lf_input_for_attribute_propagation_to_output_; - const FunctionRef get_output_attribute_id_; + const FunctionRef get_output_attribute_id_; public: GeoNodeExecParams(const bNode &node, @@ -75,7 +72,7 @@ class GeoNodeExecParams { const lf::Context &lf_context, const Span lf_input_for_output_bsocket_usage, const Span lf_input_for_attribute_propagation_to_output, - const FunctionRef get_output_attribute_id) + const FunctionRef get_output_attribute_id) : node_(node), params_(params), lf_context_(lf_context), @@ -275,11 +272,11 @@ class GeoNodeExecParams { * Return a new anonymous attribute id for the given output. None is returned if the anonymous * attribute is not needed. */ - AnonymousAttributeIDPtr get_output_anonymous_attribute_id_if_needed( + std::optional get_output_anonymous_attribute_id_if_needed( const StringRef output_identifier, const bool force_create = false) { if (!this->anonymous_attribute_output_is_required(output_identifier) && !force_create) { - return {}; + return std::nullopt; } const bNodeSocket &output_socket = node_.output_by_identifier(output_identifier); return get_output_attribute_id_(output_socket.index()); diff --git a/source/blender/nodes/NOD_geometry_nodes_lazy_function.hh b/source/blender/nodes/NOD_geometry_nodes_lazy_function.hh index 0f0ecedd7bb..7b15bf42537 100644 --- a/source/blender/nodes/NOD_geometry_nodes_lazy_function.hh +++ b/source/blender/nodes/NOD_geometry_nodes_lazy_function.hh @@ -449,6 +449,10 @@ std::unique_ptr get_warning_node_lazy_function(const bNode &node); */ void set_default_remaining_node_outputs(lf::Params ¶ms, const bNode &node); +std::string make_anonymous_attribute_socket_inspection_string(const bNodeSocket &socket); +std::string make_anonymous_attribute_socket_inspection_string(StringRef node_name, + StringRef socket_name); + struct FoundNestedNodeID { int id; bool is_in_simulation = false; @@ -458,23 +462,6 @@ struct FoundNestedNodeID { std::optional find_nested_node_id(const GeoNodesLFUserData &user_data, const int node_id); -/** - * An anonymous attribute created by a node. - */ -class NodeAnonymousAttributeID : public bke::AnonymousAttributeID { - std::string long_name_; - std::string socket_name_; - - public: - NodeAnonymousAttributeID(const Object &object, - const ComputeContext &compute_context, - const bNode &bnode, - const StringRef identifier, - const StringRef name); - - std::string user_name() const override; -}; - /** * Main function that converts a #bNodeTree into a lazy-function graph. If the graph has been * generated already, nothing is done. Under some circumstances a valid graph cannot be created. In diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index e36165f859a..c76bd9e8cf4 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -252,6 +252,7 @@ set(LIB bf_nodes PRIVATE bf::intern::atomic PRIVATE bf::extern::fmtlib + PRIVATE bf::extern::xxhash ) if(WITH_IO_STL) diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc index d7a6dd1b1bd..b365592c339 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc @@ -186,7 +186,7 @@ static void clean_unused_attributes(const AnonymousAttributePropagationInfo &pro if (skip.contains(id)) { return true; } - if (propagation_info.propagate(id.anonymous_id())) { + if (propagation_info.propagate(id.name())) { return true; } unused_ids.append(id.name()); @@ -215,7 +215,7 @@ static void node_geo_exec(GeoNodeExecParams params) Vector used_items; Vector fields; - Vector attribute_id_ptrs; + Vector attribute_id_ptrs; Set used_attribute_ids_set; for (const NodeGeometryAttributeCaptureItem &item : Span{storage.capture_items, storage.capture_items_num}) @@ -224,14 +224,14 @@ static void node_geo_exec(GeoNodeExecParams params) CaptureAttributeItemsAccessor::input_socket_identifier_for_item(item); const std::string output_identifier = CaptureAttributeItemsAccessor::output_socket_identifier_for_item(item); - AnonymousAttributeIDPtr attribute_id = params.get_output_anonymous_attribute_id_if_needed( + std::optional attribute_id = params.get_output_anonymous_attribute_id_if_needed( output_identifier); if (!attribute_id) { continue; } used_attribute_ids_set.add(*attribute_id); fields.append(params.extract_input(input_identifier)); - attribute_id_ptrs.append(std::move(attribute_id)); + attribute_id_ptrs.append(std::move(*attribute_id)); used_items.append(&item); } @@ -243,7 +243,7 @@ static void node_geo_exec(GeoNodeExecParams params) Array attribute_ids(attribute_id_ptrs.size()); for (const int i : attribute_id_ptrs.index_range()) { - attribute_ids[i] = *attribute_id_ptrs[i]; + attribute_ids[i] = attribute_id_ptrs[i]; } const auto capture_on = [&](GeometryComponent &component) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_bake.cc b/source/blender/nodes/geometry/nodes/node_geo_bake.cc index a3648c6e2ed..8871e3630f4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_bake.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_bake.cc @@ -15,6 +15,7 @@ #include "BLI_string.h" +#include "BKE_anonymous_attribute_make.hh" #include "BKE_bake_geometry_nodes_modifier.hh" #include "BKE_bake_items_socket.hh" #include "BKE_context.hh" @@ -535,21 +536,17 @@ class LazyFunctionForBakeNode final : public LazyFunction { r_output_values); } - std::shared_ptr make_attribute_field( - const Object &self_object, - const ComputeContext &compute_context, - const NodeGeometryBakeItem &item, - const CPPType &type) const + std::shared_ptr make_attribute_field(const Object &self_object, + const ComputeContext &compute_context, + const NodeGeometryBakeItem &item, + const CPPType &type) const { - AnonymousAttributeIDPtr attribute_id = AnonymousAttributeIDPtr( - MEM_new(__func__, - self_object, - compute_context, - node_, - std::to_string(item.identifier), - item.name)); - return std::make_shared( - attribute_id, type, node_.label_or_name()); + std::string attribute_name = bke::hash_to_anonymous_attribute_name( + compute_context.hash(), self_object.id.name, node_.identifier, item.identifier); + std::string socket_inspection_name = make_anonymous_attribute_socket_inspection_string( + node_.label_or_name(), item.name); + return std::make_shared( + std::move(attribute_name), type, std::move(socket_inspection_name)); } }; diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index b12aedb2989..d9c3eb2b29e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -42,7 +42,7 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) } struct AttributeOutputs { - AnonymousAttributeIDPtr intersecting_edges_id; + std::optional intersecting_edges_id; }; static void node_update(bNodeTree *ntree, bNode *node) @@ -198,7 +198,7 @@ static void node_geo_exec(GeoNodeExecParams params) if (attribute_outputs.intersecting_edges_id) { MutableAttributeAccessor attributes = result->attributes_for_write(); SpanAttributeWriter selection = attributes.lookup_or_add_for_write_only_span( - attribute_outputs.intersecting_edges_id.get(), AttrDomain::Edge); + *attribute_outputs.intersecting_edges_id, AttrDomain::Edge); selection.span.fill(false); for (const int i : intersecting_edges) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc index 575da0349a7..b4ede42cf47 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc @@ -60,11 +60,10 @@ static Curves *create_star_curve(const float inner_radius, return curves_id; } -static void create_selection_output(CurveComponent &component, - AnonymousAttributeIDPtr &r_attribute) +static void create_selection_output(CurveComponent &component, const StringRef &r_attribute) { SpanAttributeWriter selection = - component.attributes_for_write()->lookup_or_add_for_write_only_span(*r_attribute, + component.attributes_for_write()->lookup_or_add_for_write_only_span(r_attribute, AttrDomain::Point); for (int i : selection.span.index_range()) { selection.span[i] = i % 2 == 0; @@ -80,10 +79,10 @@ static void node_geo_exec(GeoNodeExecParams params) std::max(params.extract_input("Points"), 3)); GeometrySet output = GeometrySet::from_curves(curves); - if (AnonymousAttributeIDPtr outer_points_id = params.get_output_anonymous_attribute_id_if_needed( - "Outer Points")) + if (std::optional outer_points_id = + params.get_output_anonymous_attribute_id_if_needed("Outer Points")) { - create_selection_output(output.get_component_for_write(), outer_points_id); + create_selection_output(output.get_component_for_write(), *outer_points_id); } params.set_output("Curve", std::move(output)); } 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 5809c1f78e8..fa3cbf7cc28 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 @@ -110,19 +110,19 @@ static void copy_curve_domain_attributes(const AttributeAccessor curve_attribute } static PointCloud *pointcloud_from_curves(bke::CurvesGeometry curves, - const AttributeIDRef &tangent_id, - const AttributeIDRef &normal_id, - const AttributeIDRef &rotation_id) + const std::optional &tangent_id, + const std::optional &normal_id, + const std::optional &rotation_id) { PointCloud *pointcloud = BKE_pointcloud_new_nomain(0); pointcloud->totpoint = curves.points_num(); if (rotation_id) { MutableAttributeAccessor attributes = curves.attributes_for_write(); - const VArraySpan tangents = *attributes.lookup(tangent_id, AttrDomain::Point); - const VArraySpan normals = *attributes.lookup(normal_id, AttrDomain::Point); + const VArraySpan tangents = *attributes.lookup(*tangent_id, AttrDomain::Point); + const VArraySpan normals = *attributes.lookup(*normal_id, AttrDomain::Point); SpanAttributeWriter rotations = - attributes.lookup_or_add_for_write_only_span(rotation_id, + attributes.lookup_or_add_for_write_only_span(*rotation_id, AttrDomain::Point); fill_rotation_attribute(tangents, normals, rotations.span); rotations.finish(); @@ -142,7 +142,7 @@ static void curve_to_points(GeometrySet &geometry_set, GeoNodeExecParams params, const GeometryNodeCurveResampleMode mode, geometry::ResampleCurvesOutputAttributeIDs resample_attributes, - AnonymousAttributeIDPtr rotation_anonymous_id) + std::optional rotation_anonymous_id) { switch (mode) { case GEO_NODE_CURVE_RESAMPLE_COUNT: { @@ -160,7 +160,7 @@ static void curve_to_points(GeometrySet &geometry_set, PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves), resample_attributes.tangent_id, resample_attributes.normal_id, - rotation_anonymous_id.get()); + rotation_anonymous_id); geometry.remove_geometry_during_modify(); geometry.replace_pointcloud(pointcloud); } @@ -182,7 +182,7 @@ static void curve_to_points(GeometrySet &geometry_set, PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves), resample_attributes.tangent_id, resample_attributes.normal_id, - rotation_anonymous_id.get()); + rotation_anonymous_id); geometry.remove_geometry_during_modify(); geometry.replace_pointcloud(pointcloud); } @@ -199,7 +199,7 @@ static void curve_to_points(GeometrySet &geometry_set, PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves), resample_attributes.tangent_id, resample_attributes.normal_id, - rotation_anonymous_id.get()); + rotation_anonymous_id); geometry.remove_geometry_during_modify(); geometry.replace_pointcloud(pointcloud); } @@ -213,7 +213,7 @@ static void grease_pencil_to_points(GeometrySet &geometry_set, GeoNodeExecParams params, const GeometryNodeCurveResampleMode mode, geometry::ResampleCurvesOutputAttributeIDs resample_attributes, - AnonymousAttributeIDPtr rotation_anonymous_id, + std::optional rotation_anonymous_id, const AnonymousAttributePropagationInfo &propagation_info) { Field count; @@ -273,7 +273,7 @@ static void grease_pencil_to_points(GeometrySet &geometry_set, pointcloud_by_layer[layer_index] = pointcloud_from_curves(std::move(dst_curves), resample_attributes.tangent_id, resample_attributes.normal_id, - rotation_anonymous_id.get()); + rotation_anonymous_id); } if (!pointcloud_by_layer.is_empty()) { InstancesComponent &instances_component = @@ -314,17 +314,17 @@ static void node_geo_exec(GeoNodeExecParams params) GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry_set); - AnonymousAttributeIDPtr rotation_anonymous_id = + std::optional rotation_anonymous_id = params.get_output_anonymous_attribute_id_if_needed("Rotation"); const bool need_tangent_and_normal = bool(rotation_anonymous_id); - AnonymousAttributeIDPtr tangent_anonymous_id = + std::optional tangent_anonymous_id = params.get_output_anonymous_attribute_id_if_needed("Tangent", need_tangent_and_normal); - AnonymousAttributeIDPtr normal_anonymous_id = params.get_output_anonymous_attribute_id_if_needed( - "Normal", need_tangent_and_normal); + std::optional normal_anonymous_id = + params.get_output_anonymous_attribute_id_if_needed("Normal", need_tangent_and_normal); geometry::ResampleCurvesOutputAttributeIDs resample_attributes; - resample_attributes.tangent_id = tangent_anonymous_id.get(); - resample_attributes.normal_id = normal_anonymous_id.get(); + resample_attributes.tangent_id = tangent_anonymous_id; + resample_attributes.normal_id = normal_anonymous_id; const AnonymousAttributePropagationInfo &propagation_info = params.get_output_propagation_info( "Points"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curves_to_grease_pencil.cc b/source/blender/nodes/geometry/nodes/node_geo_curves_to_grease_pencil.cc index 03293ac447d..a33f4aa1322 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curves_to_grease_pencil.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curves_to_grease_pencil.cc @@ -139,7 +139,7 @@ static GreasePencil *curve_instances_to_grease_pencil_layers( if (ELEM(attribute_id, "opacity")) { return true; } - if (attribute_id.is_anonymous() && !propagation_info.propagate(attribute_id.anonymous_id())) { + if (attribute_id.is_anonymous() && !propagation_info.propagate(attribute_id.name())) { return true; } const GAttributeReader src_attribute = instances_attributes.lookup(attribute_id); diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index b94ee68f872..03f106ef735 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -318,8 +318,8 @@ BLI_NOINLINE static void propagate_existing_attributes( namespace { struct AttributeOutputs { - AnonymousAttributeIDPtr normal_id; - AnonymousAttributeIDPtr rotation_id; + std::optional normal_id; + std::optional rotation_id; }; } // namespace @@ -413,11 +413,11 @@ BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh, if (attribute_outputs.normal_id) { normals = point_attributes.lookup_or_add_for_write_only_span( - attribute_outputs.normal_id.get(), AttrDomain::Point); + *attribute_outputs.normal_id, AttrDomain::Point); } if (attribute_outputs.rotation_id) { rotations = point_attributes.lookup_or_add_for_write_only_span( - attribute_outputs.rotation_id.get(), AttrDomain::Point); + *attribute_outputs.rotation_id, AttrDomain::Point); } threading::parallel_for(bary_coords.index_range(), 1024, [&](const IndexRange range) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 3ed18add842..d895c5ab601 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -146,7 +146,7 @@ static void transfer_attributes( attribute_ids.remove(".corner_edge"); attribute_ids.remove("sharp_face"); attribute_ids.remove_if([&](const AttributeIDRef &id) { - return id.is_anonymous() && !propagation_info.propagate(id.anonymous_id()); + return id.is_anonymous() && !propagation_info.propagate(id.name()); }); for (const AttributeIDRef &id : attribute_ids) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 88b5a27f777..f3e92db2d95 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -56,7 +56,7 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) } struct IndexAttributes { - AnonymousAttributeIDPtr duplicate_index; + std::optional duplicate_index; }; /* -------------------------------------------------------------------- */ @@ -112,7 +112,7 @@ static void create_duplicate_index_attribute(bke::MutableAttributeAccessor attri const OffsetIndices offsets) { SpanAttributeWriter duplicate_indices = attributes.lookup_or_add_for_write_only_span( - attribute_outputs.duplicate_index.get(), output_domain); + *attribute_outputs.duplicate_index, output_domain); for (const int i : IndexRange(selection.size())) { MutableSpan indices = duplicate_indices.span.slice(offsets[i]); for (const int i : indices.index_range()) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 302cdf4d9f6..0f90777b768 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -72,12 +72,12 @@ static void node_update(bNodeTree *ntree, bNode *node) } struct AttributeOutputs { - AnonymousAttributeIDPtr top_id; - AnonymousAttributeIDPtr side_id; + std::optional top_id; + std::optional side_id; }; static void save_selection_as_attribute(MutableAttributeAccessor attributes, - const AnonymousAttributeID *id, + const StringRef id, const AttrDomain domain, const IndexMask &selection) { @@ -99,7 +99,7 @@ static void remove_non_propagated_attributes( if (!id.is_anonymous()) { return true; } - if (propagation_info.propagate(id.anonymous_id())) { + if (propagation_info.propagate(id.name())) { return true; } return false; @@ -454,11 +454,11 @@ static void extrude_mesh_vertices(Mesh &mesh, if (attribute_outputs.top_id) { save_selection_as_attribute( - attributes, attribute_outputs.top_id.get(), AttrDomain::Point, new_vert_range); + attributes, *attribute_outputs.top_id, AttrDomain::Point, new_vert_range); } if (attribute_outputs.side_id) { save_selection_as_attribute( - attributes, attribute_outputs.side_id.get(), AttrDomain::Edge, new_edge_range); + attributes, *attribute_outputs.side_id, AttrDomain::Edge, new_edge_range); } const bool no_loose_vert_hint = mesh.runtime->loose_verts_cache.is_cached() && @@ -813,11 +813,11 @@ static void extrude_mesh_edges(Mesh &mesh, if (attribute_outputs.top_id) { save_selection_as_attribute( - attributes, attribute_outputs.top_id.get(), AttrDomain::Edge, duplicate_edge_range); + attributes, *attribute_outputs.top_id, AttrDomain::Edge, duplicate_edge_range); } if (attribute_outputs.side_id) { save_selection_as_attribute( - attributes, attribute_outputs.side_id.get(), AttrDomain::Face, new_face_range); + attributes, *attribute_outputs.side_id, AttrDomain::Face, new_face_range); } tag_mesh_added_faces(mesh); @@ -1209,11 +1209,11 @@ static void extrude_mesh_face_regions(Mesh &mesh, if (attribute_outputs.top_id) { save_selection_as_attribute( - attributes, attribute_outputs.top_id.get(), AttrDomain::Face, face_selection); + attributes, *attribute_outputs.top_id, AttrDomain::Face, face_selection); } if (attribute_outputs.side_id) { save_selection_as_attribute( - attributes, attribute_outputs.side_id.get(), AttrDomain::Face, side_face_range); + attributes, *attribute_outputs.side_id, AttrDomain::Face, side_face_range); } tag_mesh_added_faces(mesh); @@ -1457,11 +1457,11 @@ static void extrude_individual_mesh_faces( if (attribute_outputs.top_id) { save_selection_as_attribute( - attributes, attribute_outputs.top_id.get(), AttrDomain::Face, face_selection); + attributes, *attribute_outputs.top_id, AttrDomain::Face, face_selection); } if (attribute_outputs.side_id) { save_selection_as_attribute( - attributes, attribute_outputs.side_id.get(), AttrDomain::Face, side_face_range); + attributes, *attribute_outputs.side_id, AttrDomain::Face, side_face_range); } tag_mesh_added_faces(mesh); diff --git a/source/blender/nodes/geometry/nodes/node_geo_interpolate_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_interpolate_curves.cc index 95b96b2cba5..a6057f9e951 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_interpolate_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_interpolate_curves.cc @@ -463,7 +463,7 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves, * that they had on the guides. */ guide_curve_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData &meta_data) { - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } const eCustomDataType type = meta_data.data_type; @@ -602,7 +602,7 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves, if (guide_curve_attributes.contains(id)) { return true; } - if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) { + if (id.is_anonymous() && !propagation_info.propagate(id.name())) { return true; } if (meta_data.data_type == CD_PROP_STRING) { @@ -624,8 +624,8 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves, } static void store_output_attributes(bke::CurvesGeometry &child_curves, - const AnonymousAttributeIDPtr weight_attribute_id, - const AnonymousAttributeIDPtr index_attribute_id, + const std::optional weight_attribute_id, + const std::optional index_attribute_id, const int max_neighbors, const Span all_neighbor_counts, const Span all_neighbor_indices, @@ -689,8 +689,8 @@ static GeometrySet generate_interpolated_curves( const VArray &point_group_ids, const int max_neighbors, const AnonymousAttributePropagationInfo &propagation_info, - const AnonymousAttributeIDPtr &index_attribute_id, - const AnonymousAttributeIDPtr &weight_attribute_id) + const std::optional &index_attribute_id, + const std::optional &weight_attribute_id) { const bke::CurvesGeometry &guide_curves = guide_curves_id.geometry.wrap(); @@ -847,10 +847,10 @@ static void node_geo_exec(GeoNodeExecParams params) const AnonymousAttributePropagationInfo propagation_info = params.get_output_propagation_info( "Curves"); - AnonymousAttributeIDPtr index_attribute_id = params.get_output_anonymous_attribute_id_if_needed( - "Closest Index"); - AnonymousAttributeIDPtr weight_attribute_id = params.get_output_anonymous_attribute_id_if_needed( - "Closest Weight"); + std::optional index_attribute_id = + params.get_output_anonymous_attribute_id_if_needed("Closest Index"); + std::optional weight_attribute_id = + params.get_output_anonymous_attribute_id_if_needed("Closest Weight"); GeometrySet new_curves = generate_interpolated_curves(guide_curves_id, *points_component->attributes(), diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc index e693863e697..ca825327004 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc @@ -46,7 +46,7 @@ static Mesh *create_cube_mesh(const float3 size, const int verts_x, const int verts_y, const int verts_z, - const AttributeIDRef &uv_map_id) + const std::optional &uv_map_id) { const int dimensions = (verts_x - 1 > 0) + (verts_y - 1 > 0) + (verts_z - 1 > 0); if (dimensions == 0) { @@ -102,9 +102,10 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - AnonymousAttributeIDPtr uv_map_id = params.get_output_anonymous_attribute_id_if_needed("UV Map"); + std::optional uv_map_id = params.get_output_anonymous_attribute_id_if_needed( + "UV Map"); - Mesh *mesh = create_cube_mesh(size, verts_x, verts_y, verts_z, uv_map_id.get()); + Mesh *mesh = create_cube_mesh(size, verts_x, verts_y, verts_z, uv_map_id); BKE_id_material_eval_ensure_default_slot(&mesh->id); params.set_output("Mesh", GeometrySet::from_mesh(mesh)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc index 472acde4efc..e2fd403f474 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc @@ -47,9 +47,10 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - AnonymousAttributeIDPtr uv_map_id = params.get_output_anonymous_attribute_id_if_needed("UV Map"); + std::optional uv_map_id = params.get_output_anonymous_attribute_id_if_needed( + "UV Map"); - Mesh *mesh = geometry::create_grid_mesh(verts_x, verts_y, size_x, size_y, uv_map_id.get()); + Mesh *mesh = geometry::create_grid_mesh(verts_x, verts_y, size_x, size_y, uv_map_id); BKE_id_material_eval_ensure_default_slot(reinterpret_cast(mesh)); params.set_output("Mesh", GeometrySet::from_mesh(mesh)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc index a0ba15aec07..17edb9bc93a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc @@ -62,7 +62,7 @@ static Bounds calculate_bounds_ico_sphere(const float radius, const int static Mesh *create_ico_sphere_mesh(const int subdivisions, const float radius, - const AttributeIDRef &uv_map_id) + const std::optional &uv_map_id) { if (subdivisions >= 3) { /* Most nodes don't need this because they internally use multi-threading which triggers @@ -105,7 +105,7 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions, if (create_uv_map) { const VArraySpan orig_uv_map = *attributes.lookup("UVMap"); SpanAttributeWriter uv_map = attributes.lookup_or_add_for_write_only_span( - uv_map_id, AttrDomain::Corner); + *uv_map_id, AttrDomain::Corner); uv_map.span.copy_from(orig_uv_map); uv_map.finish(); } @@ -123,9 +123,10 @@ static void node_geo_exec(GeoNodeExecParams params) const int subdivisions = std::min(params.extract_input("Subdivisions"), 10); const float radius = params.extract_input("Radius"); - AnonymousAttributeIDPtr uv_map_id = params.get_output_anonymous_attribute_id_if_needed("UV Map"); + std::optional uv_map_id = params.get_output_anonymous_attribute_id_if_needed( + "UV Map"); - Mesh *mesh = create_ico_sphere_mesh(subdivisions, radius, uv_map_id.get()); + Mesh *mesh = create_ico_sphere_mesh(subdivisions, radius, uv_map_id); params.set_output("Mesh", GeometrySet::from_mesh(mesh)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index 0f3fbacd87c..4809cacb8f2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -45,9 +45,10 @@ static void node_geo_exec(GeoNodeExecParams params) const float radius = params.extract_input("Radius"); - AnonymousAttributeIDPtr uv_map_id = params.get_output_anonymous_attribute_id_if_needed("UV Map"); + std::optional uv_map_id = params.get_output_anonymous_attribute_id_if_needed( + "UV Map"); - Mesh *mesh = geometry::create_uv_sphere_mesh(radius, segments_num, rings_num, uv_map_id.get()); + Mesh *mesh = geometry::create_uv_sphere_mesh(radius, segments_num, rings_num, uv_map_id); BKE_id_material_eval_ensure_default_slot(reinterpret_cast(mesh)); params.set_output("Mesh", GeometrySet::from_mesh(mesh)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_simulation.cc b/source/blender/nodes/geometry/nodes/node_geo_simulation.cc index 1c703fe07a5..ec899360d4e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_simulation.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_simulation.cc @@ -8,6 +8,7 @@ #include "BLI_string_utils.hh" #include "BLI_task.hh" +#include "BKE_anonymous_attribute_make.hh" #include "BKE_attribute_math.hh" #include "BKE_bake_geometry_nodes_modifier.hh" #include "BKE_bake_items_socket.hh" @@ -101,16 +102,19 @@ static bke::bake::BakeSocketConfig make_bake_socket_config( return config; } -static std::shared_ptr make_attribute_field( +static std::shared_ptr make_attribute_field( const Object &self_object, const ComputeContext &compute_context, const bNode &node, const NodeSimulationItem &item, const CPPType &type) { - AnonymousAttributeIDPtr attribute_id = AnonymousAttributeIDPtr(MEM_new( - __func__, self_object, compute_context, node, std::to_string(item.identifier), item.name)); - return std::make_shared(attribute_id, type, node.label_or_name()); + std::string attribute_name = bke::hash_to_anonymous_attribute_name( + self_object.id.name, compute_context.hash(), node.identifier, item.identifier); + std::string socket_inspection_name = make_anonymous_attribute_socket_inspection_string( + node.label_or_name(), item.name); + return std::make_shared( + std::move(attribute_name), type, std::move(socket_inspection_name)); } static void move_simulation_state_to_values(const Span node_simulation_items, diff --git a/source/blender/nodes/geometry/nodes/node_geo_split_to_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_split_to_instances.cc index d81b6a21b56..297d250404a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_split_to_instances.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_split_to_instances.cc @@ -310,7 +310,7 @@ static void node_geo_exec(GeoNodeExecParams params) const int total_groups_num = geometry_by_group_id.size(); dst_instances->resize(total_groups_num); - AnonymousAttributeIDPtr dst_group_id_attribute_id = + std::optional dst_group_id_attribute_id = params.get_output_anonymous_attribute_id_if_needed("Group ID"); if (dst_group_id_attribute_id) { SpanAttributeWriter dst_group_id = diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc index da27232963d..ffa6d81211b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc @@ -335,7 +335,8 @@ static void create_attributes(GeoNodeExecParams ¶ms, { MutableAttributeAccessor attributes = instances.attributes_for_write(); - if (AnonymousAttributeIDPtr line_id = params.get_output_anonymous_attribute_id_if_needed("Line")) + if (std::optional line_id = params.get_output_anonymous_attribute_id_if_needed( + "Line")) { SpanAttributeWriter line_attribute = attributes.lookup_or_add_for_write_only_span( *line_id, AttrDomain::Instance); @@ -343,7 +344,7 @@ static void create_attributes(GeoNodeExecParams ¶ms, line_attribute.finish(); } - if (AnonymousAttributeIDPtr pivot_id = params.get_output_anonymous_attribute_id_if_needed( + if (std::optional pivot_id = params.get_output_anonymous_attribute_id_if_needed( "Pivot Point")) { SpanAttributeWriter pivot_attribute = diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index b65b2bea40c..0274a2401ee 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -37,6 +37,7 @@ #include "DNA_ID.h" +#include "BKE_anonymous_attribute_make.hh" #include "BKE_compute_contexts.hh" #include "BKE_geometry_nodes_gizmos_transforms.hh" #include "BKE_geometry_set.hh" @@ -122,34 +123,6 @@ static void lazy_function_interface_from_node(const bNode &node, } } -NodeAnonymousAttributeID::NodeAnonymousAttributeID(const Object &object, - const ComputeContext &compute_context, - const bNode &bnode, - const StringRef identifier, - const StringRef name) - : socket_name_(name) -{ - const ComputeContextHash &hash = compute_context.hash(); - { - std::stringstream ss; - ss << hash << "_" << object.id.name << "_" << bnode.identifier << "_" << identifier; - long_name_ = ss.str(); - } - { - uint64_t hash_result[2]; - BLI_hash_md5_buffer(long_name_.data(), long_name_.size(), hash_result); - std::stringstream ss; - ss << ".a_" << std::hex << hash_result[0] << hash_result[1]; - name_ = ss.str(); - BLI_assert(name_.size() < MAX_CUSTOMDATA_LAYER_NAME); - } -} - -std::string NodeAnonymousAttributeID::user_name() const -{ - return socket_name_; -} - /** * Used for most normal geometry nodes like Subdivision Surface and Set Position. */ @@ -164,15 +137,6 @@ class LazyFunctionForGeometryNode : public LazyFunction { */ Vector is_attribute_output_bsocket_; - struct OutputAttributeID { - int bsocket_index; - AnonymousAttributeIDPtr attribute_id; - }; - - struct Storage { - Vector attributes; - }; - public: LazyFunctionForGeometryNode(const bNode &node, GeometryNodesLazyFunctionGraphInfo &own_lf_graph_info) @@ -225,43 +189,12 @@ class LazyFunctionForGeometryNode : public LazyFunction { } } - void *init_storage(LinearAllocator<> &allocator) const override - { - return allocator.construct().release(); - } - - void destruct_storage(void *storage) const override - { - Storage *s = static_cast(storage); - std::destroy_at(s); - } - void execute_impl(lf::Params ¶ms, const lf::Context &context) const override { - Storage *storage = static_cast(context.storage); GeoNodesLFUserData *user_data = dynamic_cast(context.user_data); BLI_assert(user_data != nullptr); const auto &local_user_data = *static_cast(context.local_user_data); - /* Lazily create the required anonymous attribute ids. */ - auto get_output_attribute_id = [&](const int output_bsocket_index) -> AnonymousAttributeIDPtr { - for (const OutputAttributeID &node_output_attribute : storage->attributes) { - if (node_output_attribute.bsocket_index == output_bsocket_index) { - return node_output_attribute.attribute_id; - } - } - const bNodeSocket &bsocket = node_.output_socket(output_bsocket_index); - AnonymousAttributeIDPtr attribute_id = AnonymousAttributeIDPtr( - MEM_new(__func__, - *user_data->call_data->self_object(), - *user_data->compute_context, - node_, - bsocket.identifier, - bsocket.name)); - storage->attributes.append({output_bsocket_index, attribute_id}); - return attribute_id; - }; - bool used_non_attribute_output_exists = false; for (const int output_bsocket_index : node_.output_sockets().index_range()) { const bNodeSocket &output_bsocket = node_.output_socket(output_bsocket_index); @@ -278,8 +211,7 @@ class LazyFunctionForGeometryNode : public LazyFunction { if (params.output_was_set(lf_index)) { continue; } - this->output_anonymous_attribute_field( - params, lf_index, output_bsocket, get_output_attribute_id(output_bsocket_index)); + this->output_anonymous_attribute_field(params, *user_data, lf_index, output_bsocket); } else { if (output_usage == lf::ValueUsage::Used) { @@ -305,13 +237,17 @@ class LazyFunctionForGeometryNode : public LazyFunction { return; } + auto get_anonymous_attribute_name = [&](const int i) { + return this->anonymous_attribute_name_for_output(*user_data, i); + }; + GeoNodeExecParams geo_params{ node_, params, context, own_lf_graph_info_.mapping.lf_input_index_for_output_bsocket_usage, own_lf_graph_info_.mapping.lf_input_index_for_attribute_propagation_to_output, - get_output_attribute_id}; + get_anonymous_attribute_name}; geo_eval_log::TimePoint start_time = geo_eval_log::Clock::now(); node_.typeinfo->geometry_node_execute(geo_params); @@ -324,23 +260,6 @@ class LazyFunctionForGeometryNode : public LazyFunction { } } - /** - * Output the given anonymous attribute id as a field. - */ - void output_anonymous_attribute_field(lf::Params ¶ms, - const int lf_index, - const bNodeSocket &bsocket, - AnonymousAttributeIDPtr attribute_id) const - { - GField output_field{std::make_shared( - std::move(attribute_id), - *bsocket.typeinfo->base_cpp_type, - fmt::format(TIP_("{} node"), node_.label_or_name()))}; - void *r_value = params.get_output_data_ptr(lf_index); - new (r_value) SocketValueVariant(std::move(output_field)); - params.output_set(lf_index); - } - std::string input_name(const int index) const override { for (const bNodeSocket *bsocket : node_.output_sockets()) { @@ -368,6 +287,33 @@ class LazyFunctionForGeometryNode : public LazyFunction { { return outputs_[index].debug_name; } + + void output_anonymous_attribute_field(lf::Params ¶ms, + const GeoNodesLFUserData &user_data, + const int lf_index, + const bNodeSocket &socket) const + { + std::string attribute_name = this->anonymous_attribute_name_for_output(user_data, + socket.index()); + std::string socket_inspection_name = make_anonymous_attribute_socket_inspection_string(socket); + auto attribute_field = std::make_shared( + std::move(attribute_name), + *socket.typeinfo->base_cpp_type, + std::move(socket_inspection_name)); + + void *r_value = params.get_output_data_ptr(lf_index); + new (r_value) SocketValueVariant(GField(std::move(attribute_field))); + params.output_set(lf_index); + } + + std::string anonymous_attribute_name_for_output(const GeoNodesLFUserData &user_data, + const int output_index) const + { + return bke::hash_to_anonymous_attribute_name(user_data.call_data->self_object()->id.name, + user_data.compute_context->hash(), + node_.identifier, + node_.output_socket(output_index).identifier); + } }; /** @@ -502,6 +448,17 @@ void set_default_remaining_node_outputs(lf::Params ¶ms, const bNode &node) } } +std::string make_anonymous_attribute_socket_inspection_string(const bNodeSocket &socket) +{ + return make_anonymous_attribute_socket_inspection_string(socket.owner_node().label_or_name(), + socket.name); +} +std::string make_anonymous_attribute_socket_inspection_string(StringRef node_name, + StringRef socket_name) +{ + return fmt::format(TIP_("\"{}\" from {}"), socket_name, node_name); +} + static void execute_multi_function_on_value_variant__single( const MultiFunction &fn, const Span input_values, @@ -1384,13 +1341,15 @@ class LazyFunctionForAnonymousAttributeSetExtract : public lf::LazyFunction { if (value_variant->is_context_dependent_field()) { const GField &field = value_variant->get(); field.node().for_each_field_input_recursive([&](const FieldInput &field_input) { - if (const auto *attr_field_input = dynamic_cast( - &field_input)) + if (const auto *attr_field_input = dynamic_cast(&field_input)) { - if (!attributes.names) { - attributes.names = std::make_shared>(); + const StringRef name = attr_field_input->attribute_name(); + if (bke::attribute_name_is_anonymous(name)) { + if (!attributes.names) { + attributes.names = std::make_shared>(); + } + attributes.names->add_as(name); } - attributes.names->add_as(attr_field_input->anonymous_id()->name()); } }); }