1 #include <map>
2 #include <tuple>
3 #include <queue>
4 #include <vector>
5 #include <type_traits>
6 #include <gtest/gtest.h>
7 #include <entt/entity/registry.hpp>
8 #include <entt/entity/snapshot.hpp>
9 #include <entt/entity/entity.hpp>
10 
11 struct noncopyable_component {
noncopyable_componentnoncopyable_component12     noncopyable_component(): value{} {}
noncopyable_componentnoncopyable_component13     explicit noncopyable_component(int v): value{v} {}
14 
15     noncopyable_component(const noncopyable_component &) = delete;
16     noncopyable_component(noncopyable_component &&) = default;
17 
18     noncopyable_component& operator=(const noncopyable_component &) = delete;
19     noncopyable_component& operator=(noncopyable_component &&) = default;
20 
21     int value;
22 };
23 
24 template<typename Storage>
25 struct output_archive {
output_archiveoutput_archive26     output_archive(Storage &instance)
27         : storage{instance}
28     {}
29 
30     template<typename... Value>
operator ()output_archive31     void operator()(const Value &... value) {
32         (std::get<std::queue<Value>>(storage).push(value), ...);
33     }
34 
operator ()output_archive35     void operator()(const entt::entity &entity, const noncopyable_component &instance) {
36         (*this)(entity, instance.value);
37     }
38 
39 private:
40     Storage &storage;
41 };
42 
43 template<typename Storage>
44 struct input_archive {
input_archiveinput_archive45     input_archive(Storage &instance)
46         : storage{instance}
47     {}
48 
49     template<typename... Value>
operator ()input_archive50     void operator()(Value &... value) {
51         auto assign = [this](auto &val) {
52             auto &queue = std::get<std::queue<std::decay_t<decltype(val)>>>(storage);
53             val = queue.front();
54             queue.pop();
55         };
56 
57         (assign(value), ...);
58     }
59 
operator ()input_archive60     void operator()(entt::entity &entity, noncopyable_component &instance) {
61         (*this)(entity, instance.value);
62     }
63 
64 private:
65     Storage &storage;
66 };
67 
68 struct a_component {};
69 
70 struct another_component {
71     int key;
72     int value;
73 };
74 
75 struct what_a_component {
76     entt::entity bar;
77     std::vector<entt::entity> quux;
78 };
79 
80 struct map_component {
81     std::map<entt::entity, int> keys;
82     std::map<int, entt::entity> values;
83     std::map<entt::entity, entt::entity> both;
84 };
85 
TEST(Snapshot,Dump)86 TEST(Snapshot, Dump) {
87     using traits_type = entt::entt_traits<entt::entity>;
88 
89     entt::registry registry;
90 
91     const auto e0 = registry.create();
92     registry.emplace<int>(e0, 42);
93     registry.emplace<char>(e0, 'c');
94     registry.emplace<double>(e0, .1);
95 
96     const auto e1 = registry.create();
97 
98     const auto e2 = registry.create();
99     registry.emplace<int>(e2, 3);
100 
101     const auto e3 = registry.create();
102     registry.emplace<a_component>(e3);
103     registry.emplace<char>(e3, '0');
104 
105     registry.destroy(e1);
106     auto v1 = registry.current(e1);
107 
108     using storage_type = std::tuple<
109         std::queue<typename traits_type::entity_type>,
110         std::queue<entt::entity>,
111         std::queue<int>,
112         std::queue<char>,
113         std::queue<double>,
114         std::queue<a_component>,
115         std::queue<another_component>
116     >;
117 
118     storage_type storage;
119     output_archive<storage_type> output{storage};
120     input_archive<storage_type> input{storage};
121 
122     entt::snapshot{registry}.entities(output).component<int, char, double, a_component, another_component>(output);
123     registry.clear();
124 
125     ASSERT_FALSE(registry.valid(e0));
126     ASSERT_FALSE(registry.valid(e1));
127     ASSERT_FALSE(registry.valid(e2));
128     ASSERT_FALSE(registry.valid(e3));
129 
130     entt::snapshot_loader{registry}.entities(input).component<int, char, double, a_component, another_component>(input).orphans();
131 
132     ASSERT_TRUE(registry.valid(e0));
133     ASSERT_FALSE(registry.valid(e1));
134     ASSERT_TRUE(registry.valid(e2));
135     ASSERT_TRUE(registry.valid(e3));
136 
137     ASSERT_FALSE(registry.orphan(e0));
138     ASSERT_FALSE(registry.orphan(e2));
139     ASSERT_FALSE(registry.orphan(e3));
140 
141     ASSERT_EQ(registry.get<int>(e0), 42);
142     ASSERT_EQ(registry.get<char>(e0), 'c');
143     ASSERT_EQ(registry.get<double>(e0), .1);
144     ASSERT_EQ(registry.current(e1), v1);
145     ASSERT_EQ(registry.get<int>(e2), 3);
146     ASSERT_EQ(registry.get<char>(e3), '0');
147     ASSERT_TRUE(registry.all_of<a_component>(e3));
148 
149     ASSERT_TRUE(registry.empty<another_component>());
150 }
151 
TEST(Snapshot,Partial)152 TEST(Snapshot, Partial) {
153     using traits_type = entt::entt_traits<entt::entity>;
154 
155     entt::registry registry;
156 
157     const auto e0 = registry.create();
158     registry.emplace<int>(e0, 42);
159     registry.emplace<char>(e0, 'c');
160     registry.emplace<double>(e0, .1);
161 
162     const auto e1 = registry.create();
163 
164     const auto e2 = registry.create();
165     registry.emplace<int>(e2, 3);
166 
167     const auto e3 = registry.create();
168     registry.emplace<char>(e3, '0');
169 
170     registry.destroy(e1);
171     auto v1 = registry.current(e1);
172 
173     using storage_type = std::tuple<
174         std::queue<typename traits_type::entity_type>,
175         std::queue<entt::entity>,
176         std::queue<int>,
177         std::queue<char>,
178         std::queue<double>
179     >;
180 
181     storage_type storage;
182     output_archive<storage_type> output{storage};
183     input_archive<storage_type> input{storage};
184 
185     entt::snapshot{registry}.entities(output).component<char, int>(output);
186     registry.clear();
187 
188     ASSERT_FALSE(registry.valid(e0));
189     ASSERT_FALSE(registry.valid(e1));
190     ASSERT_FALSE(registry.valid(e2));
191     ASSERT_FALSE(registry.valid(e3));
192 
193     entt::snapshot_loader{registry}.entities(input).component<char, int>(input);
194 
195     ASSERT_TRUE(registry.valid(e0));
196     ASSERT_FALSE(registry.valid(e1));
197     ASSERT_TRUE(registry.valid(e2));
198     ASSERT_TRUE(registry.valid(e3));
199 
200     ASSERT_EQ(registry.get<int>(e0), 42);
201     ASSERT_EQ(registry.get<char>(e0), 'c');
202     ASSERT_FALSE(registry.all_of<double>(e0));
203     ASSERT_EQ(registry.current(e1), v1);
204     ASSERT_EQ(registry.get<int>(e2), 3);
205     ASSERT_EQ(registry.get<char>(e3), '0');
206 
207     entt::snapshot{registry}.entities(output);
208     registry.clear();
209 
210     ASSERT_FALSE(registry.valid(e0));
211     ASSERT_FALSE(registry.valid(e1));
212     ASSERT_FALSE(registry.valid(e2));
213     ASSERT_FALSE(registry.valid(e3));
214 
215     entt::snapshot_loader{registry}.entities(input).orphans();
216 
217     ASSERT_FALSE(registry.valid(e0));
218     ASSERT_FALSE(registry.valid(e1));
219     ASSERT_FALSE(registry.valid(e2));
220     ASSERT_FALSE(registry.valid(e3));
221 }
222 
TEST(Snapshot,Iterator)223 TEST(Snapshot, Iterator) {
224     using traits_type = entt::entt_traits<entt::entity>;
225 
226     entt::registry registry;
227 
228     for(auto i = 0; i < 50; ++i) {
229         const auto entity = registry.create();
230         registry.emplace<another_component>(entity, i, i);
231         registry.emplace<noncopyable_component>(entity, i);
232 
233         if(i % 2) {
234             registry.emplace<a_component>(entity);
235         }
236     }
237 
238     using storage_type = std::tuple<
239         std::queue<typename traits_type::entity_type>,
240         std::queue<entt::entity>,
241         std::queue<another_component>,
242         std::queue<int>
243     >;
244 
245     storage_type storage;
246     output_archive<storage_type> output{storage};
247     input_archive<storage_type> input{storage};
248 
249     const auto view = registry.view<a_component>();
250     const auto size = view.size();
251 
252     entt::snapshot{registry}.component<another_component, noncopyable_component>(output, view.begin(), view.end());
253     registry.clear();
254     entt::snapshot_loader{registry}.component<another_component, noncopyable_component>(input);
255 
256     ASSERT_EQ(registry.view<another_component>().size(), size);
257 
258     registry.view<another_component>().each([](const auto entity, const auto &) {
259         ASSERT_NE(entt::to_integral(entity) % 2u, 0u);
260     });
261 }
262 
TEST(Snapshot,Continuous)263 TEST(Snapshot, Continuous) {
264     using traits_type = entt::entt_traits<entt::entity>;
265 
266     entt::registry src;
267     entt::registry dst;
268 
269     entt::continuous_loader loader{dst};
270 
271     std::vector<entt::entity> entities;
272     entt::entity entity;
273 
274     using storage_type = std::tuple<
275         std::queue<typename traits_type::entity_type>,
276         std::queue<entt::entity>,
277         std::queue<another_component>,
278         std::queue<what_a_component>,
279         std::queue<map_component>,
280         std::queue<int>,
281         std::queue<double>
282     >;
283 
284     storage_type storage;
285     output_archive<storage_type> output{storage};
286     input_archive<storage_type> input{storage};
287 
288     for(int i = 0; i < 10; ++i) {
289         static_cast<void>(src.create());
290     }
291 
292     src.clear();
293 
294     for(int i = 0; i < 5; ++i) {
295         entity = src.create();
296         entities.push_back(entity);
297 
298         src.emplace<a_component>(entity);
299         src.emplace<another_component>(entity, i, i);
300         src.emplace<noncopyable_component>(entity, i);
301 
302         if(i % 2) {
303             src.emplace<what_a_component>(entity, entity);
304         } else {
305             src.emplace<map_component>(entity);
306         }
307     }
308 
309     src.view<what_a_component>().each([&entities](auto, auto &what_a_component) {
310         what_a_component.quux.insert(what_a_component.quux.begin(), entities.begin(), entities.end());
311     });
312 
313     src.view<map_component>().each([&entities](auto, auto &map_component) {
314         for(size_t i = 0; i < entities.size(); ++i) {
315             map_component.keys.insert({entities[i], int(i)});
316             map_component.values.insert({int(i), entities[i]});
317             map_component.both.insert({entities[entities.size() - i - 1], entities[i]});
318         }
319     });
320 
321     entity = dst.create();
322     dst.emplace<a_component>(entity);
323     dst.emplace<another_component>(entity, -1, -1);
324     dst.emplace<noncopyable_component>(entity, -1);
325 
326     entt::snapshot{src}.entities(output).component<a_component, another_component, what_a_component, map_component, noncopyable_component>(output);
327 
328     loader.entities(input)
329         .component<a_component, another_component, what_a_component, map_component, noncopyable_component>(
330             input,
331             &what_a_component::bar,
332             &what_a_component::quux,
333             &map_component::keys,
334             &map_component::values,
335             &map_component::both
336         ).orphans();
337 
338     decltype(dst.size()) a_component_cnt{};
339     decltype(dst.size()) another_component_cnt{};
340     decltype(dst.size()) what_a_component_cnt{};
341     decltype(dst.size()) map_component_cnt{};
342     decltype(dst.size()) noncopyable_component_cnt{};
343 
344     dst.each([&dst, &a_component_cnt](auto entt) {
345         ASSERT_TRUE(dst.all_of<a_component>(entt));
346         ++a_component_cnt;
347     });
348 
349     dst.view<another_component>().each([&another_component_cnt](auto, const auto &component) {
350         ASSERT_EQ(component.value, component.key < 0 ? -1 : component.key);
351         ++another_component_cnt;
352     });
353 
354     dst.view<what_a_component>().each([&dst, &what_a_component_cnt](auto entt, const auto &component) {
355         ASSERT_EQ(entt, component.bar);
356 
357         for(auto child: component.quux) {
358             ASSERT_TRUE(dst.valid(child));
359         }
360 
361         ++what_a_component_cnt;
362     });
363 
364     dst.view<map_component>().each([&dst, &map_component_cnt](const auto &component) {
365         for(auto child: component.keys) {
366             ASSERT_TRUE(dst.valid(child.first));
367         }
368 
369         for(auto child: component.values) {
370             ASSERT_TRUE(dst.valid(child.second));
371         }
372 
373         for(auto child: component.both) {
374             ASSERT_TRUE(dst.valid(child.first));
375             ASSERT_TRUE(dst.valid(child.second));
376         }
377 
378         ++map_component_cnt;
379     });
380 
381     dst.view<noncopyable_component>().each([&dst, &noncopyable_component_cnt](auto, const auto &component) {
382         ++noncopyable_component_cnt;
383         ASSERT_EQ(component.value, static_cast<int>(dst.size<noncopyable_component>() - noncopyable_component_cnt - 1u));
384     });
385 
386     src.view<another_component>().each([](auto, auto &component) {
387         component.value = 2 * component.key;
388     });
389 
390     auto size = dst.size();
391 
392     entt::snapshot{src}.entities(output).component<a_component, what_a_component, map_component, another_component>(output);
393 
394     loader.entities(input)
395         .component<a_component, what_a_component, map_component, another_component>(
396             input,
397             &what_a_component::bar,
398             &what_a_component::quux,
399             &map_component::keys,
400             &map_component::values,
401             &map_component::both
402         ).orphans();
403 
404     ASSERT_EQ(size, dst.size());
405 
406     ASSERT_EQ(dst.size<a_component>(), a_component_cnt);
407     ASSERT_EQ(dst.size<another_component>(), another_component_cnt);
408     ASSERT_EQ(dst.size<what_a_component>(), what_a_component_cnt);
409     ASSERT_EQ(dst.size<map_component>(), map_component_cnt);
410     ASSERT_EQ(dst.size<noncopyable_component>(), noncopyable_component_cnt);
411 
412     dst.view<another_component>().each([](auto, auto &component) {
413         ASSERT_EQ(component.value, component.key < 0 ? -1 : (2 * component.key));
414     });
415 
416     entity = src.create();
417 
418     src.view<what_a_component>().each([entity](auto, auto &component) {
419         component.bar = entity;
420     });
421 
422     entt::snapshot{src}.entities(output).component<what_a_component, map_component, a_component, another_component>(output);
423 
424     loader.entities(input)
425         .component<what_a_component, map_component, a_component, another_component>(
426             input,
427             &what_a_component::bar,
428             &what_a_component::quux,
429             &map_component::keys,
430             &map_component::values,
431             &map_component::both
432         ).orphans();
433 
434     dst.view<what_a_component>().each([&loader, entity](auto, auto &component) {
435         ASSERT_EQ(component.bar, loader.map(entity));
436     });
437 
438     entities.clear();
439     for(auto entt: src.view<a_component>()) {
440         entities.push_back(entt);
441     }
442 
443     src.destroy(entity);
444     loader.shrink();
445 
446     entt::snapshot{src}.entities(output).component<a_component, another_component, what_a_component, map_component>(output);
447 
448     loader.entities(input)
449         .component<a_component, another_component, what_a_component, map_component>(
450             input,
451             &what_a_component::bar,
452             &what_a_component::quux,
453             &map_component::keys,
454             &map_component::values,
455             &map_component::both
456         ).orphans().shrink();
457 
458     dst.view<what_a_component>().each([&dst](auto, auto &component) {
459         ASSERT_FALSE(dst.valid(component.bar));
460     });
461 
462     ASSERT_FALSE(loader.contains(entity));
463 
464     entity = src.create();
465 
466     src.view<what_a_component>().each([entity](auto, auto &component) {
467         component.bar = entity;
468     });
469 
470     dst.clear<a_component>();
471     a_component_cnt = src.size<a_component>();
472 
473     entt::snapshot{src}.entities(output).component<a_component, what_a_component, map_component, another_component>(output);
474 
475     loader.entities(input)
476         .component<a_component, what_a_component, map_component, another_component>(
477             input,
478             &what_a_component::bar,
479             &what_a_component::quux,
480             &map_component::keys,
481             &map_component::values,
482             &map_component::both
483         ).orphans();
484 
485     ASSERT_EQ(dst.size<a_component>(), a_component_cnt);
486 
487     src.clear<a_component>();
488     a_component_cnt = {};
489 
490     entt::snapshot{src}.entities(output).component<what_a_component, map_component, a_component, another_component>(output);
491 
492     loader.entities(input)
493         .component<what_a_component, map_component, a_component, another_component>(
494             input,
495             &what_a_component::bar,
496             &what_a_component::quux,
497             &map_component::keys,
498             &map_component::values,
499             &map_component::both
500         ).orphans();
501 
502     ASSERT_EQ(dst.size<a_component>(), a_component_cnt);
503 }
504 
TEST(Snapshot,MoreOnShrink)505 TEST(Snapshot, MoreOnShrink) {
506     using traits_type = entt::entt_traits<entt::entity>;
507 
508     entt::registry src;
509     entt::registry dst;
510 
511     entt::continuous_loader loader{dst};
512 
513     using storage_type = std::tuple<
514         std::queue<typename traits_type::entity_type>,
515         std::queue<entt::entity>
516         >;
517 
518     storage_type storage;
519     output_archive<storage_type> output{storage};
520     input_archive<storage_type> input{storage};
521 
522     auto entity = src.create();
523     entt::snapshot{src}.entities(output);
524     loader.entities(input).shrink();
525 
526     ASSERT_TRUE(dst.valid(entity));
527 
528     loader.shrink();
529 
530     ASSERT_FALSE(dst.valid(entity));
531 }
532 
TEST(Snapshot,SyncDataMembers)533 TEST(Snapshot, SyncDataMembers) {
534     using traits_type = entt::entt_traits<entt::entity>;
535 
536     entt::registry src;
537     entt::registry dst;
538 
539     entt::continuous_loader loader{dst};
540 
541     using storage_type = std::tuple<
542         std::queue<typename traits_type::entity_type>,
543         std::queue<entt::entity>,
544         std::queue<what_a_component>,
545         std::queue<map_component>
546     >;
547 
548     storage_type storage;
549     output_archive<storage_type> output{storage};
550     input_archive<storage_type> input{storage};
551 
552     static_cast<void>(src.create());
553     static_cast<void>(src.create());
554 
555     src.clear();
556 
557     auto parent = src.create();
558     auto child = src.create();
559 
560 
561     src.emplace<what_a_component>(parent, entt::null);
562     src.emplace<what_a_component>(child, parent).quux.push_back(child);
563 
564     src.emplace<map_component>(
565         child,
566         decltype(map_component::keys){{{ child, 10 }}},
567         decltype(map_component::values){{{ 10, child }}},
568         decltype(map_component::both){{{ child, child }}}
569     );
570 
571     entt::snapshot{src}.entities(output).component<what_a_component, map_component>(output);
572 
573     loader.entities(input).component<what_a_component, map_component>(
574         input,
575         &what_a_component::bar,
576         &what_a_component::quux,
577         &map_component::keys,
578         &map_component::values,
579         &map_component::both
580     );
581 
582     ASSERT_FALSE(dst.valid(parent));
583     ASSERT_FALSE(dst.valid(child));
584 
585     ASSERT_TRUE(dst.all_of<what_a_component>(loader.map(parent)));
586     ASSERT_TRUE(dst.all_of<what_a_component>(loader.map(child)));
587 
588     ASSERT_EQ(dst.get<what_a_component>(loader.map(parent)).bar, static_cast<entt::entity>(entt::null));
589 
590     const auto &component = dst.get<what_a_component>(loader.map(child));
591 
592     ASSERT_EQ(component.bar, loader.map(parent));
593     ASSERT_EQ(component.quux[0], loader.map(child));
594 
595     const auto &foobar = dst.get<map_component>(loader.map(child));
596     ASSERT_EQ(foobar.keys.at(loader.map(child)), 10);
597     ASSERT_EQ(foobar.values.at(10), loader.map(child));
598     ASSERT_EQ(foobar.both.at(loader.map(child)), loader.map(child));
599 }
600