diff --git a/include/geode/basic/attribute_manager.hpp b/include/geode/basic/attribute_manager.hpp index 5d8b23d3c..28c1eb444 100644 --- a/include/geode/basic/attribute_manager.hpp +++ b/include/geode/basic/attribute_manager.hpp @@ -260,9 +260,17 @@ namespace geode void import( const AttributeManager& attribute_manager, absl::Span< const index_t > old2new ); + void import( const AttributeManager& attribute_manager, + absl::Span< const index_t > old2new, + std::string_view attribute_name ); + void import( const AttributeManager& attribute_manager, const GenericMapping< index_t >& old2new_mapping ); + void import( const AttributeManager& attribute_manager, + const GenericMapping< index_t >& old2new_mapping, + std::string_view attribute_name ); + private: friend class bitsery::Access; template < typename Archive > diff --git a/src/geode/basic/attribute_manager.cpp b/src/geode/basic/attribute_manager.cpp index 03ca8b4f9..e596ea6b2 100644 --- a/src/geode/basic/attribute_manager.cpp +++ b/src/geode/basic/attribute_manager.cpp @@ -251,8 +251,9 @@ namespace geode } } + template < typename T > void import( const AttributeManager::Impl &attribute_manager, - absl::Span< const index_t > old2new, + const T &old2new_mapping, const AttributeBase::AttributeKey &key ) { for( const auto &[attribute_name, attribute_from] : @@ -270,43 +271,53 @@ namespace geode continue; } this->attributes_.at( attribute_name ) - ->import( old2new, attribute_from, key ); + ->import( old2new_mapping, attribute_from, key ); } else { attributes_.emplace( attribute_name, - attribute_from->extract( old2new, nb_elements_, key ) ); + attribute_from->extract( + old2new_mapping, nb_elements_, key ) ); } } } + template < typename T > void import( const AttributeManager::Impl &attribute_manager, - const GenericMapping< index_t > &old2new_mapping, + const T &old2new_mapping, + std::string_view attribute_name, const AttributeBase::AttributeKey &key ) { - for( const auto &[attribute_name, attribute_from] : - attribute_manager.attributes_ ) + auto it = attribute_manager.attributes_.find( attribute_name ); + OpenGeodeBasicException::check_exception( + it != attribute_manager.attributes_.end(), nullptr, + OpenGeodeException::TYPE::data, + "[AttributeManager::import] Could not import attribute '", + attribute_name, + "'. No attribute with this name exists in the source " + "AttributeManager." ); + OpenGeodeBasicException::check_exception( + it->second->properties().transferable, nullptr, + OpenGeodeException::TYPE::data, + "[AttributeManager::import] Could not import attribute '", + attribute_name, "'. The attribute is not transferable." ); + if( attribute_exists( attribute_name ) ) { - if( !attribute_from->properties().transferable ) - { - continue; - } - if( attribute_exists( attribute_name ) ) - { - if( attribute_from->type() - != this->attributes_.at( attribute_name )->type() ) - { - continue; - } - this->attributes_.at( attribute_name ) - ->import( old2new_mapping, attribute_from, key ); - } - else - { - attributes_.emplace( attribute_name, - attribute_from->extract( - old2new_mapping, nb_elements_, key ) ); - } + OpenGeodeBasicException::check_exception( + it->second->type() + == this->attributes_.at( attribute_name )->type(), + nullptr, OpenGeodeException::TYPE::data, + "[AttributeManager::import] Could not import attribute '", + attribute_name, + "'. An attribute with the same name but a different type " + "already exists in the destination AttributeManager." ); + this->attributes_.at( attribute_name ) + ->import( old2new_mapping, it->second, key ); + } + else + { + attributes_.emplace( attribute_name, + it->second->extract( old2new_mapping, nb_elements_, key ) ); } } @@ -511,12 +522,27 @@ namespace geode impl_->import( *attribute_manager.impl_, old2new, {} ); } + void AttributeManager::import( const AttributeManager &attribute_manager, + absl::Span< const index_t > old2new, + std::string_view attribute_name ) + { + impl_->import( *attribute_manager.impl_, old2new, attribute_name, {} ); + } + void AttributeManager::import( const AttributeManager &attribute_manager, const GenericMapping< index_t > &old2new_mapping ) { impl_->import( *attribute_manager.impl_, old2new_mapping, {} ); } + void AttributeManager::import( const AttributeManager &attribute_manager, + const GenericMapping< index_t > &old2new_mapping, + std::string_view attribute_name ) + { + impl_->import( + *attribute_manager.impl_, old2new_mapping, attribute_name, {} ); + } + void AttributeManager::rename_attribute( std::string_view old_name, std::string_view new_name ) {