| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- #include <tuple>
- #include <queue>
- #include <vector>
- #include <gtest/gtest.h>
- #include <entt/entity/registry.hpp>
- template<typename Storage>
- struct OutputArchive {
- OutputArchive(Storage &storage)
- : storage{storage}
- {}
- template<typename Value>
- void operator()(const Value &value) {
- std::get<std::queue<Value>>(storage).push(value);
- }
- private:
- Storage &storage;
- };
- template<typename Storage>
- struct InputArchive {
- InputArchive(Storage &storage)
- : storage{storage}
- {}
- template<typename Value>
- void operator()(Value &value) {
- auto &queue = std::get<std::queue<Value>>(storage);
- value = queue.front();
- queue.pop();
- }
- private:
- Storage &storage;
- };
- struct AComponent {};
- struct AnotherComponent {
- int key;
- int value;
- };
- struct WhatAComponent {
- entt::DefaultRegistry::entity_type bar;
- std::vector<entt::DefaultRegistry::entity_type> quux;
- };
- TEST(Snapshot, Dump) {
- entt::DefaultRegistry registry;
- const auto e0 = registry.create();
- registry.assign<int>(e0, 42);
- registry.assign<char>(e0, 'c');
- registry.assign<double>(e0, .1);
- const auto e1 = registry.create();
- const auto e2 = registry.create();
- registry.assign<int>(e2, 3);
- const auto e3 = registry.create();
- registry.assign<char>(e3, '0');
- registry.assign<float>(entt::tag_type_t{}, e3, .3f);
- const auto e4 = registry.create();
- registry.assign<AComponent>(entt::tag_type_t{}, e4);
- registry.destroy(e1);
- auto v1 = registry.current(e1);
- using storage_type = std::tuple<
- std::queue<entt::DefaultRegistry::entity_type>,
- std::queue<int>,
- std::queue<char>,
- std::queue<double>,
- std::queue<float>,
- std::queue<bool>,
- std::queue<AComponent>,
- std::queue<AnotherComponent>,
- std::queue<WhatAComponent>
- >;
- storage_type storage;
- OutputArchive<storage_type> output{storage};
- InputArchive<storage_type> input{storage};
- registry.snapshot()
- .entities(output)
- .destroyed(output)
- .component<int, char, AnotherComponent, double>(output)
- .tag<float, bool, AComponent>(output);
- registry.reset();
- ASSERT_FALSE(registry.valid(e0));
- ASSERT_FALSE(registry.valid(e1));
- ASSERT_FALSE(registry.valid(e2));
- ASSERT_FALSE(registry.valid(e3));
- ASSERT_FALSE(registry.valid(e4));
- registry.restore()
- .entities(input)
- .destroyed(input)
- .component<int, char, AnotherComponent, double>(input)
- .tag<float, bool, AComponent>(input)
- .orphans();
- ASSERT_TRUE(registry.valid(e0));
- ASSERT_FALSE(registry.valid(e1));
- ASSERT_TRUE(registry.valid(e2));
- ASSERT_TRUE(registry.valid(e3));
- ASSERT_TRUE(registry.valid(e4));
- ASSERT_FALSE(registry.orphan(e0));
- ASSERT_FALSE(registry.orphan(e2));
- ASSERT_FALSE(registry.orphan(e3));
- ASSERT_FALSE(registry.orphan(e4));
- ASSERT_EQ(registry.get<int>(e0), 42);
- ASSERT_EQ(registry.get<char>(e0), 'c');
- ASSERT_EQ(registry.get<double>(e0), .1);
- ASSERT_EQ(registry.current(e1), v1);
- ASSERT_EQ(registry.get<int>(e2), 3);
- ASSERT_EQ(registry.get<char>(e3), '0');
- ASSERT_TRUE(registry.has<float>());
- ASSERT_EQ(registry.attachee<float>(), e3);
- ASSERT_EQ(registry.get<float>(), .3f);
- ASSERT_TRUE(registry.has<AComponent>());
- ASSERT_EQ(registry.attachee<AComponent>(), e4);
- ASSERT_TRUE(registry.empty<AnotherComponent>());
- ASSERT_FALSE(registry.has<long int>());
- }
- TEST(Snapshot, Partial) {
- entt::DefaultRegistry registry;
- const auto e0 = registry.create();
- registry.assign<int>(e0, 42);
- registry.assign<char>(e0, 'c');
- registry.assign<double>(e0, .1);
- const auto e1 = registry.create();
- const auto e2 = registry.create();
- registry.assign<int>(e2, 3);
- const auto e3 = registry.create();
- registry.assign<char>(e3, '0');
- registry.assign<float>(entt::tag_type_t{}, e3, .3f);
- const auto e4 = registry.create();
- registry.assign<AComponent>(entt::tag_type_t{}, e4);
- registry.destroy(e1);
- auto v1 = registry.current(e1);
- using storage_type = std::tuple<
- std::queue<entt::DefaultRegistry::entity_type>,
- std::queue<int>,
- std::queue<char>,
- std::queue<double>,
- std::queue<float>,
- std::queue<bool>,
- std::queue<AComponent>,
- std::queue<WhatAComponent>
- >;
- storage_type storage;
- OutputArchive<storage_type> output{storage};
- InputArchive<storage_type> input{storage};
- registry.snapshot()
- .entities(output)
- .destroyed(output)
- .component<char, int>(output)
- .tag<bool, float>(output);
- registry.reset();
- ASSERT_FALSE(registry.valid(e0));
- ASSERT_FALSE(registry.valid(e1));
- ASSERT_FALSE(registry.valid(e2));
- ASSERT_FALSE(registry.valid(e3));
- ASSERT_FALSE(registry.valid(e4));
- registry.restore()
- .entities(input)
- .destroyed(input)
- .component<char, int>(input)
- .tag<bool, float>(input);
- ASSERT_TRUE(registry.valid(e0));
- ASSERT_FALSE(registry.valid(e1));
- ASSERT_TRUE(registry.valid(e2));
- ASSERT_TRUE(registry.valid(e3));
- ASSERT_TRUE(registry.valid(e4));
- ASSERT_EQ(registry.get<int>(e0), 42);
- ASSERT_EQ(registry.get<char>(e0), 'c');
- ASSERT_FALSE(registry.has<double>(e0));
- ASSERT_EQ(registry.current(e1), v1);
- ASSERT_EQ(registry.get<int>(e2), 3);
- ASSERT_EQ(registry.get<char>(e3), '0');
- ASSERT_TRUE(registry.orphan(e4));
- ASSERT_TRUE(registry.has<float>());
- ASSERT_EQ(registry.attachee<float>(), e3);
- ASSERT_EQ(registry.get<float>(), .3f);
- ASSERT_FALSE(registry.has<long int>());
- registry.snapshot()
- .tag<float>(output)
- .destroyed(output)
- .entities(output);
- registry.reset();
- ASSERT_FALSE(registry.valid(e0));
- ASSERT_FALSE(registry.valid(e1));
- ASSERT_FALSE(registry.valid(e2));
- ASSERT_FALSE(registry.valid(e3));
- ASSERT_FALSE(registry.valid(e4));
- registry.restore()
- .tag<float>(input)
- .destroyed(input)
- .entities(input)
- .orphans();
- ASSERT_FALSE(registry.valid(e0));
- ASSERT_FALSE(registry.valid(e1));
- ASSERT_FALSE(registry.valid(e2));
- ASSERT_TRUE(registry.valid(e3));
- ASSERT_FALSE(registry.valid(e4));
- }
- TEST(Snapshot, Continuous) {
- using entity_type = entt::DefaultRegistry::entity_type;
- entt::DefaultRegistry src;
- entt::DefaultRegistry dst;
- entt::ContinuousLoader<entity_type> loader{dst};
- std::vector<entity_type> entities;
- entity_type entity;
- using storage_type = std::tuple<
- std::queue<entity_type>,
- std::queue<AComponent>,
- std::queue<AnotherComponent>,
- std::queue<WhatAComponent>,
- std::queue<double>
- >;
- storage_type storage;
- OutputArchive<storage_type> output{storage};
- InputArchive<storage_type> input{storage};
- for(int i = 0; i < 10; ++i) {
- src.create();
- }
- src.each([&src](auto entity) {
- src.destroy(entity);
- });
- for(int i = 0; i < 5; ++i) {
- entity = src.create();
- entities.push_back(entity);
- src.assign<AComponent>(entity);
- src.assign<AnotherComponent>(entity, i, i);
- if(i % 2) {
- src.assign<WhatAComponent>(entity, entity);
- } else if(i == 2) {
- src.assign<double>(entt::tag_type_t{}, entity, .3);
- }
- }
- src.view<WhatAComponent>().each([&entities](auto, auto &whatAComponent) {
- whatAComponent.quux.insert(whatAComponent.quux.begin(), entities.begin(), entities.end());
- });
- entity = dst.create();
- dst.assign<AComponent>(entity);
- dst.assign<AnotherComponent>(entity, -1, -1);
- src.snapshot()
- .entities(output)
- .destroyed(output)
- .component<AComponent, AnotherComponent, WhatAComponent>(output)
- .tag<double>(output);
- loader.entities(input)
- .destroyed(input)
- .component<AComponent, AnotherComponent>(input)
- .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
- .tag<double>(input)
- .orphans();
- decltype(dst.size()) aComponentCnt{};
- decltype(dst.size()) anotherComponentCnt{};
- decltype(dst.size()) whatAComponentCnt{};
- dst.each([&dst, &aComponentCnt](auto entity) {
- ASSERT_TRUE(dst.has<AComponent>(entity));
- ++aComponentCnt;
- });
- dst.view<AnotherComponent>().each([&anotherComponentCnt](auto, const auto &component) {
- ASSERT_EQ(component.value, component.key < 0 ? -1 : component.key);
- ++anotherComponentCnt;
- });
- dst.view<WhatAComponent>().each([&dst, &whatAComponentCnt](auto entity, const auto &component) {
- ASSERT_EQ(entity, component.bar);
- for(auto entity: component.quux) {
- ASSERT_TRUE(dst.valid(entity));
- }
- ++whatAComponentCnt;
- });
- ASSERT_TRUE(dst.has<double>());
- ASSERT_EQ(dst.get<double>(), .3);
- src.view<AnotherComponent>().each([](auto, auto &component) {
- component.value = 2 * component.key;
- });
- auto size = dst.size();
- src.snapshot()
- .entities(output)
- .destroyed(output)
- .component<AComponent, AnotherComponent, WhatAComponent>(output)
- .tag<double>(output);
- loader.entities(input)
- .destroyed(input)
- .component<AComponent, AnotherComponent>(input)
- .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
- .tag<double>(input)
- .orphans();
- ASSERT_EQ(size, dst.size());
- ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
- ASSERT_EQ(dst.size<AnotherComponent>(), anotherComponentCnt);
- ASSERT_EQ(dst.size<WhatAComponent>(), whatAComponentCnt);
- ASSERT_TRUE(dst.has<double>());
- dst.view<AnotherComponent>().each([](auto, auto &component) {
- ASSERT_EQ(component.value, component.key < 0 ? -1 : (2 * component.key));
- });
- entity = src.create();
- src.view<WhatAComponent>().each([entity](auto, auto &component) {
- component.bar = entity;
- });
- src.snapshot()
- .entities(output)
- .destroyed(output)
- .component<AComponent, AnotherComponent, WhatAComponent>(output)
- .tag<double>(output);
- loader.entities(input)
- .destroyed(input)
- .component<AComponent, AnotherComponent>(input)
- .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
- .tag<double>(input)
- .orphans();
- dst.view<WhatAComponent>().each([&loader, entity](auto, auto &component) {
- ASSERT_EQ(component.bar, loader.map(entity));
- });
- entities.clear();
- for(auto entity: src.view<AComponent>()) {
- entities.push_back(entity);
- }
- src.destroy(entity);
- loader.shrink();
- src.snapshot()
- .entities(output)
- .destroyed(output)
- .component<AComponent, AnotherComponent, WhatAComponent>(output)
- .tag<double>(output);
- loader.entities(input)
- .destroyed(input)
- .component<AComponent, AnotherComponent>(input)
- .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
- .tag<double>(input)
- .orphans()
- .shrink();
- dst.view<WhatAComponent>().each([&dst, &loader, entity](auto, auto &component) {
- ASSERT_FALSE(dst.valid(component.bar));
- });
- ASSERT_FALSE(loader.has(entity));
- entity = src.create();
- src.view<WhatAComponent>().each([entity](auto, auto &component) {
- component.bar = entity;
- });
- dst.reset<AComponent>();
- aComponentCnt = src.size<AComponent>();
- src.snapshot()
- .entities(output)
- .destroyed(output)
- .component<AComponent, AnotherComponent, WhatAComponent>(output)
- .tag<double>(output);
- loader.entities(input)
- .destroyed(input)
- .component<AComponent, AnotherComponent>(input)
- .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
- .tag<double>(input)
- .orphans();
- ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
- ASSERT_TRUE(dst.has<double>());
- src.reset<AComponent>();
- src.remove<double>();
- aComponentCnt = {};
- src.snapshot()
- .entities(output)
- .destroyed(output)
- .component<AComponent, AnotherComponent, WhatAComponent>(output)
- .tag<double>(output);
- loader.entities(input)
- .destroyed(input)
- .component<AComponent, AnotherComponent>(input)
- .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
- .tag<double>(input)
- .orphans();
- ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
- ASSERT_FALSE(dst.has<double>());
- }
- TEST(Snapshot, ContinuousMoreOnShrink) {
- using entity_type = entt::DefaultRegistry::entity_type;
- entt::DefaultRegistry src;
- entt::DefaultRegistry dst;
- entt::ContinuousLoader<entity_type> loader{dst};
- using storage_type = std::tuple<
- std::queue<entity_type>,
- std::queue<AComponent>
- >;
- storage_type storage;
- OutputArchive<storage_type> output{storage};
- InputArchive<storage_type> input{storage};
- auto entity = src.create();
- src.snapshot().entities(output);
- loader.entities(input).shrink();
- ASSERT_TRUE(dst.valid(entity));
- loader.shrink();
- ASSERT_FALSE(dst.valid(entity));
- }
|