Skip to content

Instantly share code, notes, and snippets.

@danielytics
Created June 8, 2021 15:49
Show Gist options
  • Save danielytics/d43902a9f43bd4d974d26cacc8b29a11 to your computer and use it in GitHub Desktop.
Save danielytics/d43902a9f43bd4d974d26cacc8b29a11 to your computer and use it in GitHub Desktop.
EnTT poly_storage registry copying
#include <iostream>
#include <entt/entity/registry.hpp>
struct A {
};
struct B {
int x;
};
int main (int argc, char* argv[])
{
entt::registry registry;
entt::registry other;
entt::entity entities[10u];
registry.create(std::begin(entities), std::end(entities));
registry.insert<int>(std::begin(entities), std::end(entities), 42);
registry.insert<char>(std::begin(entities), std::end(entities), 'c');
registry.insert<B>(std::begin(entities), std::end(entities), {2});
// insert A, an empty component:
registry.insert<A>(std::begin(entities), std::end(entities));
for(const auto entity: registry.view<B>()) {
std::cout << entt::to_integral(entity);
if (registry.any_of<B>(entity)) {
std::cout << " registry: " << registry.get<B>(entity).x;
}
if (other.valid(entity)) {
std::cout << " other: ";
if (other.any_of<B>(entity)) {
std::cout << other.get<B>(entity).x;
}
}
std::cout << "\n";
}
}
main.cpp:52:20: error: cannot take the address of an rvalue of type 'void'
return &self.get(entity);
^~~~~~~~~~~~~~~~~
main.cpp:67:29: note: in instantiation of member function 'PolyStorage<entt::entity>::members<entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>>>::get' requested here
&members<Type>::get,
^
entt/src/entt/entity/../poly/poly.hpp:274:17: note: in instantiation of function template specialization 'entt::basic_poly<PolyStorage<entt::entity>, 16, 16>::basic_poly<entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>> &, entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>> &>' requested here
*this = basic_poly{std::in_place_type<Type>, std::forward<Args>(args)...};
^
entt/src/entt/entity/registry.hpp:115:33: note: in instantiation of function template specialization 'entt::basic_poly<PolyStorage<entt::entity>, 16, 16>::emplace<entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>> &, entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>> &>' requested here
pdata.poly.template emplace<storage_type<Component> &>(*static_cast<storage_type<Component> *>(pdata.pool.get()));
^
entt/src/entt/entity/registry.hpp:566:9: note: in instantiation of function template specialization 'entt::basic_registry<entt::entity>::assure<A>' requested here
assure<Component>()->insert(*this, first, last, value);
^
main.cpp:98:14: note: in instantiation of function template specialization 'entt::basic_registry<entt::entity>::insert<A, entt::entity *>' requested here
registry.insert<A>(std::begin(entities), std::end(entities));
^
main.cpp:57:28: error: no matching member function for call to 'insert'
other.template insert<typename Type::value_type>(base.rbegin(), base.rend(), self.rbegin());
~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:68:29: note: in instantiation of member function 'PolyStorage<entt::entity>::members<entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>>>::copy_to' requested here
&members<Type>::copy_to
^
entt/src/entt/entity/../poly/poly.hpp:274:17: note: in instantiation of function template specialization 'entt::basic_poly<PolyStorage<entt::entity>, 16, 16>::basic_poly<entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>> &, entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>> &>' requested here
*this = basic_poly{std::in_place_type<Type>, std::forward<Args>(args)...};
^
entt/src/entt/entity/registry.hpp:115:33: note: in instantiation of function template specialization 'entt::basic_poly<PolyStorage<entt::entity>, 16, 16>::emplace<entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>> &, entt::sigh_storage_mixin<entt::basic_storage<entt::entity, A, std::allocator<A>, void>> &>' requested here
pdata.poly.template emplace<storage_type<Component> &>(*static_cast<storage_type<Component> *>(pdata.pool.get()));
^
entt/src/entt/entity/registry.hpp:566:9: note: in instantiation of function template specialization 'entt::basic_registry<entt::entity>::assure<A>' requested here
assure<Component>()->insert(*this, first, last, value);
^
main.cpp:98:14: note: in instantiation of function template specialization 'entt::basic_registry<entt::entity>::insert<A, entt::entity *>' requested here
registry.insert<A>(std::begin(entities), std::end(entities));
^
entt/src/entt/entity/registry.hpp:564:10: note: candidate function template not viable: no known conversion from 'entt::basic_sparse_set<entt::entity, std::allocator<entt::entity>>::reverse_iterator' (aka 'const entt::entity *') to 'const A' for 3rd argument
void insert(It first, It last, const Component &value = {}) {
^
entt/src/entt/entity/registry.hpp:582:10: note: candidate template ignored: requirement 'std::is_same_v<entt::entity, A>' was not satisfied [with Component = A, EIt = const entt::entity *, CIt = const entt::entity *]
void insert(EIt first, EIt last, CIt from) {
^
2 errors generated.
#include <iostream>
#include <entt/core/utility.hpp>
#include <entt/entity/poly_storage.hpp>
#include <entt/entity/registry.hpp>
template<typename... Type>
entt::type_list<Type...> as_type_list(const entt::type_list<Type...> &);
template<typename Entity>
struct PolyStorage: entt::type_list_cat_t<
decltype(as_type_list(std::declval<entt::Storage<Entity>>())),
entt::type_list<
void(const Entity *, const Entity *, void *),
void(entt::basic_registry<Entity> &, const Entity, const void *),
const void *(const Entity) const,
void(entt::basic_registry<Entity> &) const
>
> {
using entity_type = Entity;
using size_type = std::size_t;
template<typename Base>
struct type: entt::Storage<Entity>::template type<Base> {
static constexpr auto base = decltype(as_type_list(std::declval<entt::Storage<Entity>>()))::size;
void erase(entt::basic_registry<Entity> &owner, const entity_type *first, const entity_type *last) {
entt::poly_call<base + 0>(*this, first, last, &owner);
}
void emplace(entt::basic_registry<Entity> &owner, const entity_type entity, const void *instance) {
entt::poly_call<base + 1>(*this, owner, entity, instance);
}
const void * get(const entity_type entity) const {
return entt::poly_call<base + 2>(*this, entity);
}
void copy_to(entt::basic_registry<Entity> &other) const {
entt::poly_call<base + 3>(*this, other);
}
};
template<typename Type>
struct members {
static void emplace(Type &self, entt::basic_registry<Entity> &owner, const entity_type entity, const void *instance) {
self.emplace(owner, entity, *static_cast<const typename Type::value_type *>(instance));
}
static const typename Type::value_type * get(const Type &self, const entity_type entity) {
return &self.get(entity);
}
static void copy_to(const Type &self, entt::basic_registry<entity_type> &other) {
const entt::sparse_set &base = self;
other.template insert<typename Type::value_type>(base.rbegin(), base.rend(), self.rbegin());
}
};
template<typename Type>
using impl = entt::value_list_cat_t<
typename entt::Storage<Entity>::template impl<Type>,
entt::value_list<
&Type::template erase<const entity_type *>,
&members<Type>::emplace,
&members<Type>::get,
&members<Type>::copy_to
>
>;
};
template<typename Entity>
struct entt::poly_storage_traits<Entity> {
using storage_type = entt::poly<PolyStorage<Entity>>;
};
struct A {
};
struct B {
int x;
};
int main (int argc, char* argv[])
{
entt::registry registry;
entt::registry other;
entt::entity entities[10u];
registry.create(std::begin(entities), std::end(entities));
registry.insert<int>(std::begin(entities), std::end(entities), 42);
registry.insert<char>(std::begin(entities), std::end(entities), 'c');
registry.insert<B>(std::begin(entities), std::end(entities), {2});
// insert A, an empty component:
registry.insert<A>(std::begin(entities), std::end(entities));
other.assign(registry.data(), registry.data() + registry.size(), registry.destroyed());
registry.visit([&](const auto info) {
std::as_const(registry).storage(info)->copy_to(other);
});
for(const auto entity: registry.view<B>()) {
std::cout << entt::to_integral(entity);
if (registry.any_of<B>(entity)) {
std::cout << " registry: " << registry.get<B>(entity).x;
}
if (other.valid(entity)) {
std::cout << " other: ";
if (other.any_of<B>(entity)) {
std::cout << other.get<B>(entity).x;
}
}
std::cout << "\n";
}
}
#include <iostream>
#include <entt/core/utility.hpp>
#include <entt/entity/poly_storage.hpp>
#include <entt/entity/registry.hpp>
template<typename... Type>
entt::type_list<Type...> as_type_list(const entt::type_list<Type...> &);
template<typename Entity>
struct PolyStorage: entt::type_list_cat_t<
decltype(as_type_list(std::declval<entt::Storage<Entity>>())),
entt::type_list<
void(const Entity *, const Entity *, void *),
void(entt::basic_registry<Entity> &, const Entity, const void *),
const void *(const Entity) const,
void(entt::basic_registry<Entity> &) const
>
> {
using entity_type = Entity;
using size_type = std::size_t;
template<typename Base>
struct type: entt::Storage<Entity>::template type<Base> {
static constexpr auto base = decltype(as_type_list(std::declval<entt::Storage<Entity>>()))::size;
void erase(entt::basic_registry<Entity> &owner, const entity_type *first, const entity_type *last) {
entt::poly_call<base + 0>(*this, first, last, &owner);
}
void emplace(entt::basic_registry<Entity> &owner, const entity_type entity, const void *instance) {
entt::poly_call<base + 1>(*this, owner, entity, instance);
}
const void * get(const entity_type entity) const {
return entt::poly_call<base + 2>(*this, entity);
}
void copy_to(entt::basic_registry<Entity> &other) const {
entt::poly_call<base + 3>(*this, other);
}
};
template<typename Type>
struct members {
static void emplace(Type &self, entt::basic_registry<Entity> &owner, const entity_type entity, const void *instance) {
self.emplace(owner, entity, *static_cast<const typename Type::value_type *>(instance));
}
static const typename Type::value_type * get(const Type &self, const entity_type entity) {
return &self.get(entity);
}
static void copy_to(const Type &self, entt::basic_registry<entity_type> &other) {
const entt::sparse_set &base = self;
other.template insert<typename Type::value_type>(base.rbegin(), base.rend(), self.rbegin());
}
};
template<typename Type>
using impl = entt::value_list_cat_t<
typename entt::Storage<Entity>::template impl<Type>,
entt::value_list<
&Type::template erase<const entity_type *>,
&members<Type>::emplace,
&members<Type>::get,
&members<Type>::copy_to
>
>;
};
template<typename Entity>
struct entt::poly_storage_traits<Entity> {
using storage_type = entt::poly<PolyStorage<Entity>>;
};
struct A {
};
struct B {
int x;
};
int main (int argc, char* argv[])
{
entt::registry registry;
entt::registry other;
entt::entity entities[10u];
registry.create(std::begin(entities), std::end(entities));
registry.insert<int>(std::begin(entities), std::end(entities), 42);
registry.insert<char>(std::begin(entities), std::end(entities), 'c');
registry.insert<B>(std::begin(entities), std::end(entities), {2});
other.assign(registry.data(), registry.data() + registry.size(), registry.destroyed());
registry.visit([&](const auto info) {
std::as_const(registry).storage(info)->copy_to(other);
});
for(const auto entity: registry.view<B>()) {
std::cout << entt::to_integral(entity);
if (registry.any_of<B>(entity)) {
std::cout << " registry: " << registry.get<B>(entity).x;
}
if (other.valid(entity)) {
std::cout << " other: ";
if (other.any_of<B>(entity)) {
std::cout << other.get<B>(entity).x;
}
}
std::cout << "\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment