helper: make to_entity also work for stable types (close #768)

This commit is contained in:
Michele Caini
2021-11-23 12:53:50 +01:00
parent e4d36e4982
commit 5b8dcff2a4
4 changed files with 53 additions and 5 deletions

View File

@@ -138,11 +138,12 @@ void invoke(basic_registry<Entity> &reg, const Entity entt) {
*/
template<typename Entity, typename Component>
Entity to_entity(const basic_registry<Entity> &reg, const Component &instance) {
const auto view = reg.template view<const Component>();
const auto &storage = reg.template storage<const Component>();
const typename std::remove_const_t<std::remove_reference_t<decltype(storage)>>::base_type &base = storage;
const auto *addr = std::addressof(instance);
for(auto it = view.rbegin(), last = view.rend(); it < last; it += ENTT_PACKED_PAGE) {
if(const auto dist = (addr - std::addressof(view.template get<const Component>(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) {
for(auto it = base.rbegin(), last = base.rend(); it < last; it += ENTT_PACKED_PAGE) {
if(const auto dist = (addr - std::addressof(storage.get(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) {
return *(it + dist);
}
}

View File

@@ -13,6 +13,15 @@ struct clazz {
entt::entity entt{entt::null};
};
struct stable_type {
int value;
};
template<>
struct entt::component_traits<stable_type>: basic_component_traits {
using in_place_delete = std::true_type;
};
TEST(Helper, AsView) {
entt::registry registry;
const entt::registry cregistry;
@@ -79,3 +88,41 @@ TEST(Helper, ToEntity) {
ASSERT_EQ(entt::to_entity(registry, 42), null);
ASSERT_EQ(entt::to_entity(registry, value), null);
}
TEST(Helper, ToEntityStableType) {
entt::registry registry;
const entt::entity null = entt::null;
const stable_type value{42};
ASSERT_EQ(entt::to_entity(registry, stable_type{42}), null);
ASSERT_EQ(entt::to_entity(registry, value), null);
const auto entity = registry.create();
registry.emplace<stable_type>(entity);
while(registry.size<stable_type>() < (ENTT_PACKED_PAGE - 2u)) {
registry.emplace<stable_type>(registry.create(), value);
}
const auto other = registry.create();
const auto next = registry.create();
registry.emplace<stable_type>(other);
registry.emplace<stable_type>(next);
ASSERT_EQ(entt::to_entity(registry, registry.get<stable_type>(entity)), entity);
ASSERT_EQ(entt::to_entity(registry, registry.get<stable_type>(other)), other);
ASSERT_EQ(entt::to_entity(registry, registry.get<stable_type>(next)), next);
ASSERT_EQ(&registry.get<stable_type>(entity) + ENTT_PACKED_PAGE - 2u, &registry.get<stable_type>(other));
registry.destroy(other);
ASSERT_EQ(entt::to_entity(registry, registry.get<stable_type>(entity)), entity);
ASSERT_EQ(entt::to_entity(registry, registry.get<stable_type>(next)), next);
ASSERT_EQ(&registry.get<stable_type>(entity) + ENTT_PACKED_PAGE - 1u, &registry.get<stable_type>(next));
ASSERT_EQ(entt::to_entity(registry, stable_type{42}), null);
ASSERT_EQ(entt::to_entity(registry, value), null);
}

View File

@@ -11,7 +11,7 @@ ENTT_API void update_position(entt::registry &registry) {
ENTT_API void emplace_velocity(entt::registry &registry) {
// forces the creation of the pool for the velocity component
registry.storage<velocity>();
static_cast<void>(registry.storage<velocity>());
for(auto entity: registry.view<position>()) {
registry.emplace<velocity>(entity, 1., 1.);

View File

@@ -9,7 +9,7 @@ CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
auto &registry = *static_cast<entt::registry *>(ctx->userdata);
// forces the creation of the pool for the velocity component
registry.storage<velocity>();
static_cast<void>(registry.storage<velocity>());
const auto view = registry.view<position>();
registry.insert(view.begin(), view.end(), velocity{1., 1.});