Squashed 'external/entt/entt/' changes from fef921132..344e03ac6
344e03ac6 update single include file to v3.12.2 da56665b0 registry: make ::valid backward compatible f6f01ef1b snapshot: avoid warnings due to deprecated functions 0ed514628 now working on v3.12.2 a41421d86 update single include file to v3.12.1 c1f6b11f7 snapshot: reintroduce support to storage listeners b2233064a now working on version v3.12.1 cb974bf56 adjacency_matrix: fix in_edges() is off by 1 in some cases (close #1019) 7b7d82e6f doc: snapshot (close #984) 05c6898fc test: self-fixing archive example for snapshot classes 7ffa459a6 snapshot: drop ::get member template parameter 93e8e94e6 test: basic continuous loader c4e241662 snapshot: review basic_continuous_loader (and drop shrink) 9c25419b9 test: more on basic_snapshot_loader 1879830df snapshot: drop pointless assert 29298c0eb test: guarantee code coverage, we'll update the test later on 247abef1d test: rollback for code coverage purposes on the snapshot class 6994d98d2 test: typo 9a600ece2 test: snapshot f91226ef4 snapshot: share ::orphans implementation (to deprecate in future though) e366ffbd3 doc: snapshot 63b300d39 snapshot: again, dense_map::contains is a thing afb70d157 test: avoid warnings due to unused variables 49534eec0 snapshot: dense_map::contains is a thing fortunately 3f1277f7b snapshot: use the right allocator for the remote-local mapping 26fad4c38 test: basic snapshot loader 25b3afacf test: basic snapshot 2d25bbb09 snapshot: check registry type 0eb834582 snapshot: small cleanup 124a44052 test: use the new snapshot get functions in the test suite 5c704636e test: use the new snapshot get functions in the test suite 31fd94cc3 snapshot: cleanup to get ready to drop an internal function 573e43272 snapshot: reduce storage lookups 1d8943481 snapshot: drop useless function e0a1ef7c1 snapshot: check on member type class 48ac0e0eb snapshot: add basic_continuous_loader::get, deprecate ::entities and ::component bcb6234d9 snapshot: add basic_snapshot_loader::get, deprecate ::entities and ::component f96796326 snapshot: reject entity type in the range-get (now get instead of get_sparse) b22c55dd2 doc: typo 4ff5a536c snapshot: add basic_snapshot::get, deprecate ::entities and ::component fff5f578a test: avoid using deprecated functions in an example 0f44c8c92 doc: reflect recent changes 0b6ad0315 snapshot: * single element only archive functions required * avoid iterating elements more than once 2450b0bc6 test: minor changes (waiting for a rework) fc8eebf36 snapshot: use component_traits instead of is_empty_v e4f51f2b7 snapshot: avoid multiple lookups of the same storage 2c2216a89 doc: typo cafe85180 snapshot: deprecate multi-type component loading function 35e338cc9 snapshot: deprecate multi-type component loading function 8feeaaef7 doc: minor changes e7a3c4e37 snapshot: add missing [[deprecate(...)]] ea5c558bd snapshot: cleanup (waiting for further improvements) 94f0ed179 snapshot: deprecate multi-type component loading function 244c35949 snapshot: deprecate multi-type component loading function 1f24fea21 type_traits: formatting 8deaa09b2 test: perform static checks at compile-time 85bffb714 type_traits: std::tuple traits specialization for entt::type_list and entt::value_list (#1011) 325ca310d view: updated ::refresh d903e268f snapshot: minor changes f4b26756c snapshot: improved basic_snapshot::component fb3a34ee9 *: updated TODO 6902bb6c4 doc: typo 379819b2b test: cleanup 59abfbfb5 meta: refine policy check on value types for non-member data 6e2d87184 registry: avoid casting return types directly to better support empty storage 57ec3c85c registry: erase_if (close #977) 4afdf287f doc: minor changes 2810ac7cb registry: suppress a warning on msvc e0d27f9bf *: updated TODO de303c999 test: reverse-each for storage entity 1619e780f test: reverse each for plain storage classes a1e37eca6 storage: reverse-each c345e7456 doc: note on reverse iterations d166c026f snapshot: minor changes 5e639996d doc: minor changes dac2ef5a9 doc: typo 71d7888e8 snapshot: drop redundant check 84a4df9c4 doc: exclude-only views 95bc20319 doc: entity lifecycle 5a9f6d211 doc: cleanup a29302faa test: more on entity signals 75efa72c6 registry: cleanup ::erase 58a84665b registry: cleanup ::remove a5263384d doc: drop redundant comments c0e6759c6 doc: cleanup a little further d754f7431 doc: cleanup 1df539943 doc: drop pointless tags c284e6fee doc: minor changes 500239758 test: typo 319ecd808 organizer: fix organizer::vertex::prepare not creating component pools (#1014) d7891fabc doc: mention named pools support when registering listeners e287dd041 helper: minor changes 4dee9dde1 registry: named pools support for on_construct/on_update/on_destroy 9bae6e67b doc: update connection helper doc aa7a7ce25 doc: minor changes a969468c5 registry: de-deprecate :) on_construct/on_update/on_destroy a1e76fc63 doc: more about entity storage d8ed4ca35 registry: refine how entity storage is used internally 3248e3f91 helper: make sigh_helper work with named pools f00687e6f doc: updated registry documentation 5240c6b60 registry: deprecate on_construct/on_update/on_destroy 67604a88e natvis: update registry snippet 4242dfb8b registry: use entity storage directly as much as possible f96d8ee83 registry: prepare to split component storage and entity storage c147ec37c test: try to make gcc happy again 094ddbba3 meta: avoid shadow warnings 634630ca2 test: add missing template keywords (thanks msvc for ignoring them) d78c26f26 *: updated TODO fabc6c9bd test: full cross-registry entity-copy example with meta (not strictly required) b6e8ddd2a meta: fight against the small nuances of the language :) cf2bbae6e mixin: make it simpler to modify the underlying type 08799616d *: updated TODO 58bebf78d meta: reduce symbols and their sizes if possible d534fad3e doc: more about views 871dc7a40 doc: drop references to storage placeholders 1fe7c78f7 test: minor changes 22a65f80f test: cleanup 756ea8a38 *: updated TODO 12186cb40 registry: drop internal static storage variables from ::assure aa9ffb9ee registry: const ::storage<T>(...) returns a pointer to possibly null storage dcb5aed90 registry: lazily/partially initialize views in the ::view const function 34f6a747a registry: add support for non-existent pools to try_get 912cb2ad5 snapshot: constness review 885488b3d registry: any_of supports non-existing pools now 3d3d3ef2d registry: all_of supports non-existing pools now a7120b340 registry: coding style 51915205b test: cover stable multi-type model 4a3ee042e view: refine ::storage function 88a1b8d0d view: stable multi-type view ::each(cb) function 7e18a0f96 view: update ::use function c367082dd view: unchecked_refresh function 9f94b5306 view: double check on none_of 44ed10c50 view: stable multi type view ::find/::back/::front functions 1b2280941 view: stable multi type view ::begin/::end functions bdabbaa63 view: stable multi type view ::contains function c79c109b7 view: stable multi type view ::size_hint function f1a213382 registry: prepare to remove static storage from const assure 17dc06149 view: stable single type view ::each(cb) function 3b8d82330 view: drop unused return a20829e70 view: ::handle returns a pointer rather than a reference 5be2fdc15 view: stable single type view ::each() function 873b107e6 -: updated TODO 356bbbe53 view: stable single type view ::find function e3ce4e156 view: stable single type view ::front/::back functions e02050c51 view: stable single type view ::rbegin/::rend functions 26930633f view: stable single type view ::begin/::end functions b7a485767 view: stable single type view ::contains function f54cdccd4 view: stable single type view ::empty function 41c9a32f3 view: stable single type view ::size function 736ef3580 view: make operator bool work properly with partially initialized views 0128cbb4f test: minor changes ff0a40715 test: prepare test suite for safe invalid views 34f440386 view: avoid using storage, further prepare for empty safe views b1c78efb6 nativs: updated signal file 28f03ff9c meta: add missing checks on factory<...>::data a5fe61adb *: minor changes 457f5e59e view: rollback handle() usage and prepare to safe empty views 422fd284e group: refine group ::find function 6f3222573 view: refine single type view ::find function 366bbceb0 doc: use doxygen-awesome-css 7b7f81e08 doc: update reference.md cfe955f97 doc: update links.md 684ddc9de doc: minor changes f5d38a9ae doc: drop redundant doxy variable 447e3693f doc: updated doxy file (doxygen 1.9.6) 909490bf6 view: try to make g++ happy again d90363e4a view: make view pack also work with empty views ee5de744c view: add missing [[nodiscard]] d401c88a0 view: assert on null handles 80563b955 view: allow swapping storage elements of a view c74900057 sigh_mixin: avoid shadow warnings 78867d5c9 group: make msvc happy with constness on virtual functions d435fc779 basic_entt_traits: suppress a warning by gcc e6f76e0f9 view: try to make VS happy again :) 1c6b53360 test: minor changes 5c3d8360c view: turn ::use into a self-contained, non-const function 3882c7d9a view: turn ::refresh into a self contained, non-const function 15726218b view: doc 869bfc82c test: minor changes 0eb3d54b2 group: change signature of ::storage to return a (maybe null) pointer rather than a reference f83290f76 view: change signature of ::storage to return a (maybe null) pointer rather than a reference 686a3b9d7 registry: make storage_for_type available to the final user 4d57d5c32 registry: make ::storage<T> return type explicit 36c21cf7f registry: drop redundant traits usage 7ab10e193 test: minor changes 41467d35a -: updated TODO d351252a1 doc: entity storage c6cd4f701 doc: refine storage section 65889cca4 doc: brief mention of void storage f1914fd94 doc: rearrange a few things e53af7bef registry: minor changes b910cd261 *: updated TODO 58d331ca0 registry: minor changes 17f5b0a33 registry: avoid bumping version on destroy if not requested de386292b registry: deprecate ::each 88bf26a2f registry: deprecate ::assign 3caad4100 mixin: common internal owner_or_assert function 916203a24 test: stress assert on entity limit 62f1971f7 test: minor changes 4fde96357 natvis: updated registry snippet c3730b65f group: * unified model * drop group handler's size function (no longer required) 1ea072cd3 group: back to the unified model for group handlers bbe4582ee meta: minor changes 89ab5c328 meta: operator==/!= for meta_func 3a4672793 meta: operator==/!= for meta_prop 0a0446f35 meta: operator==/!= for meta_data (close #1002) fc58ff74b meta: operator==/!= for meta_handle (see #1002) fed6831cd locator: support to opaque structures (close #956) 1605c8d9d natvis: updated entity file d6641c7d8 -: updated TODO file 5079f38e9 storage: allow on_update signals on entity storage 1eab2a4a8 meta: fix constness detection for static functions in meta_type::invoke c33110765 test: cleanup 117b0bd67 test: more about storage<...>::patch 9b4a6f877 storage: use allocator_traits::destroy rather than destroy_at f4e6f2b37 group: suppress shadow warning 5971fb7aa -: updated TODO 10dfe7e93 sigh: allow disconnecting listeners during iterations (close #986) a9208a956 doc: fixed typo 1cc5b32ca test: cleanup f8a972a3c signal: drop sink::before 5b7cc2002 group: rollback some (no longer required) changes to the owning_group_descriptor bd34e7f2c group: drop nested groups support, prepare to the large group review and multi storage support 46fe29c3f group: make matching functions virtual for owning groups c50e2815c group: make owning_group_descriptor depend on the storage base type fbfee632d group: minor changes 77c59aabf group: group_handler::size function for owning groups ebb1e8a72 group: single check function for group handlers 1646217f0 group: make types explicit for the next/prev functions 645edfb2b group: decouple constructing and setting prev/next links 61f28298c group/registry: minor changes d19f97bf2 group: use ::handle() if possible 70c611a84 group: cleanup 286428c19 group: make common_type base of non-owning group handlers 6ec719bcf group: reduce the footprint of non-owning group handlers 11f9bb2d7 registry: use shared_ptr<void> for non-owning groups (prepare to drop the basic handler dependency) 5a1ba5ad7 regisrtry: decouple container types for groups cf094e7ef registry: finally split owning and non-owning groups as it ought to be 31808bd9a sigh: flip the last commit on its head and drop redundant functions rather than merging them 61a5173a7 sigh: merge a couple of functions ed6fe9e65 sigh/sink: refine internal definition e30fa8520 doc: cleanup ca1069e18 snapshot: avoid allocations if possible 70f73a094 snapshot: drop pointless checks 710fff0e3 entity: make get_t, exclude_t and owned_t constexpr constructible 660bc5843 entity: turn get_t, exclude_t and owned_t into proper classes (close #998) 13295a14e type_traits: v141 toolset workaround for value_list_diff 9ce07ff61 type_traits: value_list_diff[_t] b272e04ba type_traits: value_list_contains[_v] 28b11912a test: cleanup b9f096d12 type_traits: value_list_unique[_t] 8c60faa1d type_traits: value_list_index[_v] 1f93ea4ee snapshot: avoid unnecessary lookups 7ca77e53f snapshot: avoid unnecessary lookups 69397f365 snapshot: avoid unnecessary lookups f907bc066 snapshot: drop redundant checks and avoid unnecessary lookups bda52701f snapshot: avoid unnecessary lookups d26f7684c snapshot: minor changes 63d6c2bff snapshot: avoid unnecessary lookups cc45e7341 snapshot: also avoid using views if not required 5d092bcb1 snapshot: avoid unnecessary lookups 295c68841 snapshot: review ::orphans functions 2664b5255 observer: allocator support dd3632833 observer: configurable mask type c8c929e4a group: use type members properly d1ef7bf15 view: use type members properly 1ab23f17d group: early exit on signal races a72eb4693 group: minor changes 67579d062 -: updated TODO 766a233f3 view: base_type -> common_type 905671c23 runtime_view: base_type -> common_type 27c1383e4 group: base_type -> common_type 029ccc8f7 registry: base_type -> common_type cde40d586 group: drop unused using decl 6a16a8a20 group: auto init for owning groups 1a12dede6 group: auto init for non-owning groups 35a78b65e group: cleanup ada19432f group: support for index based sort 4998e9087 doc: minor changes 471c11c6d sparse_set: respect -> sort_as (naming is hard, you know) 3e13e0b59 group: sort/respect -> sort_as (also decoupled from group types) 53cd105f2 group: reuse pools as much as possible 24b31c379 group: reuse pools as much as possible def82b534 group: index based get a424f4ebf view: review get b8f0a8d8e doc: a couple of interesting articles/series (close #994) 7941226ef group: try to reuse pools when sorting and also please all compilers out there at the same time (aka me figthing ICEs again) 86bbb2f6b group: reuse pools when sorting 3c176f725 test: suppress warnings due to unused variables 3642c8a78 registry: drop [[nodiscard]] from ::group (close #991) 0e80d90a7 group: use storage<idx> as much as possible 4fdf2dccd group: update doc f8a997e6c group: minor changes 40f676ed1 test: drop unused include 5e346748e test: code coverage for groups and registry 3ef61fe01 meta: support meta member functions on primitive types 3885d280d test: cleanup f41b91419 meta: allow updating values on meta properties e0684f634 registry: cleanup/minor changes fb980a78c registry: further refine the group function(s) c2430ab48 doc: minor changes d36d9cb39 registry: further cleanup group functions 0017c08bb group: get pools from handlers e737ff747 group: get filter from handlers 945dc4093 group: split group handler functions 7ef008511 registry: drop group_data d2fa68813 registry/group: prepare to get rid of group_data f22a09a9a group: in-between change to simplify dropping group_data b0aba79a5 snapshot: minor changes 7c23e4a2f registry: minor changes 7fe035ce4 group: move group size from registry group_data to basic_group_handler 3e7160eda group: minor changes aaeb686ec group: common base class for group handlers 3fdf4884d group: prepare for group handler common base class 1b23ff4b9 registry: use common group handler types as keys for the group set 88dac318e group: wrap the len of owning groups to avoid changing it by mistake 520c2e660 group: make group handlers work with multiple storage of the same type f5d0d451b group: split pools and filter in the group handlers 8af6fc0cc group: use ::handle internally if possible c04b97a31 group: add ::handle function to all group types 1d85414dc doc: drop refs to registry::version (close #992) c6533827f group: fight with clang format from time to time :) b5803451b group: make owning groups work with their handlers 3417d66b2 group: make non-owning groups work with their handlers 1e61204e8 registry: deduce group handler type from group type 19c4857ef group: cleanup 66ea94898 registry/group: move group handler to group file as it ought to be ced6d21c3 registry: break dependency between registry and group handlers 429c7c45c registry: further cleanup things c03b1111a registry: small cleanup ebd7d3acd registry: storage based model with pools for groups 5aeec60cf registry: prepare to switch to storage based group handlers 620b4f751 registry: pass handlers to group callbacks 6d58004c1 registry: minor changes to simplify the implementation slightly df6d926de registry: prepare for a storage based group handler e63af24cb registry: turn the non-owning group handler in a storage 068d9f8ae registry: discard unused arguments from listeners if possible c19c848c4 test: suppress warnings due to unused variables 0bf0a0a8f doc: delegate 743e8678e delegate: also support functions that skip first elements (on second attempt only) a7ad1c06f delegate: prepare to support filtering on both sides b1af70e70 registry: avoid checking pools in the group handler if possible c87c3533e registry: avoid checking pools in the group handler if possible 4839a0ee6 registry: cleanup a0f0c44e6 registry: minor changes 74691dc1d group: just use meaningful names :) e4957badb registry: split group handler to further refine group management 46791c4c3 registry: turn group handler functions into static ones 56c391784 registry: prepare to rework groups 1fb13d3e9 doc: minor changes 535beb4e2 storage: drop unnecessary use of integral_constant 2d318b88c -: updated TODO b7f0b76ce entity/mixin: add missing include d30312f51 entity/helper: add missing include, drop unnecessary traits calls 30772848e meta: avoid unnecessary calls to std::move eca01a397 doc: add vcpkg badge and vcpkg.link (#985) 35ef0b7ac core: reduces the number of instantiations a bit 19ccba3a6 meta: reduces the number of instantiations a bit 207b7674a doc: fix typo 631c55ba9 storage: minor changes/tests e7b30fd36 storage: return iterator to elements rather than entities and only if it makes sense 3e959007b storage: ::insert returns an iterator to the range of inserted entities 07ec4ca23 -: updated TODO 6e4946b68 storage: uniform interface to simplify mixin implementation 47ea16f17 test: signals on entity creation/destruction 722857fc0 test: get rid of pointless template parameters 2125b3838 test: minor changes 289de7d57 test: exclude only views 25ecd8e79 test: minor changes 319dfdb07 test: filtered registry view 9dbbcac01 -: updated TODO f545c8e05 registry: deprecate ::release c68fa6a65 registry: make ::destroy work without ::release (the latter to be deprecated) d288ecd70 registry: make ::release use ::bump return value 312d3aba8 sparse_set: bump returns the version in use (for convenience) 4d2b2c6de registry: use traits_type::next if possible 80d55a226 test: increase code coverage d86a53935 test: suppress warnings due to unused variables 0f7098d0e -: updated TODO 8c96be1e9 registry: deprecate a bunch of functions because of the entity storage 37f396bfe registry: make entity storage storage as any other 75894dc40 storage: update traits_type for entity storage cdee000ce any: rollback a change that turns vs toolset v141 crazy 54ca62600 dispatcher: refine aggregate check 6f4280ed5 any: refine aggregate check ddf56b78c storage: backward compatibility on component requirements 53a854f54 any: just cleanup the code to make it easier to work with 4896acac7 storage: typo e3defeba2 test: suppress warnings due to unused variables 62079908c storage: use proper value type for entity storage e65a8f2e5 doc: add link to koala engine :) 9f27fb1e5 registry: further prepare to turn the entity storage into a plain pool 04d734e76 registry: prepare to turn the entity pool in a plain storage df50fa1b5 natvis: cleanup 051872b8c natvis: update registry definition 57ab9e7be registry: avoid using assure if not required 69d95ba75 test: more bench to stress a little an upcoming feature 9caf66d7c test: cleanup 74cb0d40c test: internal rework deac7f34b dispatcher: refine aggregate support a9883f27c storage: refine transparent aggregate support 85b1e57d8 sparse_set: drop fast_compact, expect full clear b7d8e0186 storage: make the entity storage perform a full clear rather than a fake one (still viable via erase) 390a56176 -: updated TODO file a1b888cce natvis: add optiona storage length item for entity storage 2107dd689 natvis: fix already existing errors due to renaming or design changes 1fca56afe storage: make it easier to refine the natvis file c0762a6a5 storage: add get/get_as_tuple to entity storage to make it suitable for use with views f48de1bac test: stress get/get_as_tuple for empty types c7dfce89e sigh_mixin: refine pop_all 822fafcd4 view: uniform implementation to simplify upcoming changes 1476d4ea9 sparse_set: refine ::respect c1c63777e -: updated TODO 2fab25ae8 registry: refine internal check 75d449152 -: updated TODO c7866fb21 storage: use entt traits next function if possible 87987bacd entity: added basic_entt_traits::next (with tests) bde0219fe snapshot: review basic_continuous_loader::entities ad64c849b storage: suppress warnings b808bb83b test: suppress warnings d0090d35f snapshot: try to make sizes an opaque value to the caller 7a1a06a24 sigh_mixin: avoid shadow warnings 000b17881 -: updated TODO 068b6ed49 registry: first (almost) backward compatible version with opaque hidden entity storage 0187fb48a test: sigh mixin for entity storage types 35a2b3844 sigh_mixin: also support entity storage types 4747c9a4c registry: extended checks to support swap-only entity storage types 7be8d8327 registry: make a couple of conditions opaque a5d6757d6 registry: prepare to get rid of the vector of entities 3f09d47c8 storage: remove redundant typename keyword 9c06d6ba0 registry: use type member names b7c819bf4 test: entity storage 9f31803ba storage: swap-only entity storage 1e7deff9c test: drop redundant checks 04ac15d8d test: minor changes 376218991 sigh_mixin: make pop_all use narrow view iterators if any 18d6e466d -: [[nodiscard]] as appropriate 095ecf314 group: extended_group_iterator::base to return the underlying iterator 433ed863e view: extended_view_iterator::base to return the underlying iterator 0dba68e75 storage: coding style/minor changes 1ab281582 storage: extended_storage_iterator::base to return the underlying iterator 2af5a725e doc: * updated copyright * udpated TODO list a86bf1332 test: try to make lcov happy 831054bff test: share as much as possible f94de1c06 test: rework lib stuff to share common files a3d9503a1 test: try to make lcov happy 3f2b15f9f test: try to make lcov happy e48817d51 test: try to make lcov happy d11cebe30 view: uniform design to also help natvis without having to poke into stl internals 77a5efb32 natvis: updated to_entity intrinsic 851006efe -: updated TODO 6fc6b2fb3 sigh_mixin: further improve ::pop_all ed17a2c48 sparse_set: ::contiguous function bd00e797a sparse_set: further refine pop_all to make it even faster e645c4928 -: updated TODO a425878e8 sparse_set/storage: clear is backward compatible now f3cd9d374 storage: fixed clear_all counter b3e93b084 registry: naming convention 314c189c4 test: minor changes 2bb2c5566 build: try to make lcov happy again d13c126e9 view: avoid name clashes 9b54ee37a flow: propagate allocator to generated graph + internal rework e1ead9d3e build: update coverage workflow cf61068dc mixin: suppress a warning with gcc11 82863f829 test: code coverage for range functionalities e4de59827 test: try to make lcov happy ccea4c920 memory: code coverage 89166f0e4 build: refine analyzer workflow 7a05a16c5 registry: slightly better destroy (yet not quite there though) d0854646c test: yet another test to stress the upcoming changes 1e9c9fe5f registry: better, faster range-remove + refine range-erase 80fac8d8e test: minor changes c774b9838 -: updated TODO 3fd0403cc registry: faster, better range-erase 6eb3347a3 test: a couple of extra functions to stress the upcoming changes 89bceaff7 -: updated TODO dc25c9c1a sparse_set: invoke release_sparse_pages before clearing the sparse array e68ba5870 sigh_mixin: add a missing include c68cb3375 entity: make deletion_policy publicly available via fwd.hpp 59f807fd0 sparse_set: suppress warnings due to unused expressions 232ffebc1 sparse_set: internal clear_all function 3cea845a0 sparse_set: sparse_set_iterator::data function 295f3b32e registry: a couple of extra move calls here and there 254da2c3c sparse_set: better, faster range remove ecd3b8d93 sparse_set: prevent rework errors as much as possible c673b9b17 sigh_mixin: slightly improved pop + review insert cd28de0d6 test: clear-stable bench 672f6a711 test: minor changes 3b50672b7 storage: restore storage_for/storage_type duality, it turned out to be very useful in practice f0613b1c6 sparse_set/storage: minor changes to reuse type members 2197e160e -: drop file pushed by mistake :) 2dccd9016 handle: discard entity on destruction 2f873f2dd -: storage_mixin.hpp -> mixin.hpp (non-storage mixins are also a thing) fde1a524e sparse_set: ::get -> ::value (to avoid hiding from derived classes) 055801047 doc: drop references to docsforge + minor changes 79a054a52 sigh_mixin: scope base_type properly d94e443a1 doc: drop outdated section 3862184e8 sigh_mixin: support self managed storage classes f40fa3c2f test: * use range destroy * avoid compiler optimizations 01bc93459 test (bench): the new entity storage enables the fast path in all cases 151bd0739 sparse_set: revert optmized range push, it prevents self-managed storage classes 935393aae sparse_set: better, faster range push fbfde4347 snapshot: avoid unused variable warnings 2ffbe115b component_traits: revert entity customization support 645973eb7 sparse_set: insert -> push 133230797 sparse_set: emplace -> push b700f5eb5 doc: typo e60dbdc52 sparse_set/storage: * rename swap_at in swap_or_move to capture the real purpose * define swap_at as a protected function to allow swapping from above c66623b33 sigh_mixin: avoid hiding basic_iterator type meber 62246d879 storage: avoid hiding basic_iterator type meber b35f13130 sparse_set: support swap-only mixins 3dd82633a -: drop storage_mixin.cpp, I forgot to do it a couple of commits ago :) 00231bf8a storage: make swap_at non-final to support checks on derived classes 58d392e81 -: minor changes 1d4d99d09 mixin: sigh_storage_mixin -> sigh_mixin fe3edf2c8 -: minor changes 0864ba042 -: drop useless typename 3a9698001 build: minor changes 423f7a555 is_equality_comparable: detect C-style arrays directly 5db8ad53a build: update gh workflow c2ab35780 view: make also VS toolset v141 happy 4fb558f14 view: further reduce instantiations 5762a8a08 view: reuse internal functions if possible ed4c67521 sparse_set/storage: drop move_element f15789846 config: ENTT_FAIL(msg) -> ENTT_ASSERT(false, msg) 6d20709e0 storage: minor changes a9a9853c0 sigh_storage_mixin: use entity_type from Type af14aa4c9 doc: more about signals (sigh_storage_mixin) 24d6b9881 test: minor changes 899f4baa6 storage: * drop storage_for]_t] * make storage_type[_t] deal with constness c1ab7ba02 sigh_storage_mixin: make all virtual member functions final 9d38f6020 registry: thanks MSVC for accepting invalid C++ code 0efa25cf6 sigh: cool, I keep doing the same error again and again apparently :) 6316b6045 registry: make it work with storage<void> also in C++17 f268fb60a entity: avoid breaking changes due to type members renaming 3520d6915 entity: add base_type 4da7a8451 entity: make checks work with 64b identifiers :) 382dfc3bb entity: strict check on entity/version masks b6dcdc816 entity: * also expose entity_mask and version mask to the final user * avoid default args with entt_traits::construct for backward compatibility c9d544089 doc: review/cleanup entity.md a bit (done) 3eb5faeed doc: review/cleanup entity.md a bit (work in progress) 7a328c7ed doc: updated links 6567aa195 doc: a note about listeners disconnection (close #958) 92319f011 entt_traits: split basic impl, simplify def 782d86b6e entt_traits: value_type -> type (cuz it's not a value type after all) c2cae37c1 entity_traits: make page_size type explicit 1026d26ec entt_traits: drop reserved value 7156803db test: local non-static constexpr variables f54ed5424 helper: local non-static constexpr variables f30b50195 algorithm: local non-static constexpr variables c90ab9aff sparse_set: * break dependency on traits_type::reserved * use a tombstone if all I need is a tombstone c2f6ca43f doc: graph (close #957) 3e5e41d88 test: cover some corner cases of the flow class 9eafc0431 flow: minor changes 0a82b777b component_traits: support specializations based on entity type 32bcc01a4 component: * make component_traits treat void properly * drop ignore_as_empty_v 9c3fe3546 nativs: entity module 83f8aed58 helper: use traits_type from storage class directly 2fd660274 snapshot: use public registry traits_type member type a554d406e registry: * public traits_type member type * break dependency on component_traits * use public storage traits_type member type 5f12f872e test: minor changes be4eb68a3 helper: * break dependency on component_traits * use public storage traits_type member type df5284d9e view: * break dependency on component_traits * use public storage traits_type member type 0e27d33e7 storage: public traits_type member type fe6e6ae73 sparse_set: public traits_type member type 9d29713ea entity: naming convention 270d0277d group: cleanup 0bd06c8d5 hashed_string: naming convention 733f215cc storage: break dependency between component_traits and storage_iterator ad01a69fe *: renaming/coding style dd9c1dade sparse_set: no need to differentiate template args for sparse_set_iterator b8f70519f doc: fixed typo 9b9d212dd *: coding style 3fe15969d doc: cleanup ec4bf222c meta: avoid the +1u trick for 0-sized arrays 1173908ee meta: avoid rebinding when forwarding requests 2595b8a92 doc: sigh_helper f4e2a8c76 sigh_builder: add all missing .template that msvc kindly accepted anyway 66e1a0565 entity: sigh_helper utility with tests (close #928) 87283dc41 storage: simplified impl in order to introduce multi-type storage more easily a802ebffe storage: * move storage_type[_t] and storage_for[_t] to fwd.hpp * no need to include storage.hpp when forward defining views b84b09421 doc: add Arch ECS to references.md (#954) 940fd0939 todo: add a note for a (soon to be released) change 920338be5 doc: add ecsact to links.md (thanks @zaucy for pointing this out) bcd1155b7 gh: add more gcc and clang versions 1dc88109e gh: update workflows 262c1f53c cmake: only enable -Wdocumentation for clang-cl 4af0a3a0d doc: cleanup be1641828 doc: cleanup b54a52fbf doc: fixed typo ae8815995 doc: fixed typo 62c764f68 doc: fixed typo 2c48cc10a cmake: enable documentation diagnostic for clang 82f286678 sigh: drop redundant function d56e5a269 registry: propagate allocator to context 1517b2951 doc: document delegate raw access bea7b43a1 delegate: target member function 2f878f8b5 sigh: refine ::collect fc68c1b29 view/group: cleanup 9081c185d meta: minor changes 7c4493f23 group: make filter storage available da4e73ab8 view: make filter storage available f3e7f98b4 registry: extra check when moving a registry 3925fc612 emitter: extra allocator check when moving c639130c1 dispatcher: extra allocator check when moving 75c311600 registry: cleanup e9e14eb49 meta: [[nodiscard]] d1558304f any: [[nodiscard]] 0531b530b snapshot: minor changes f9d0178dd workflow: bump iwyu version b66b8d37e test: suppress warning 05ef4c29d storage: minor changes 9c3d75669 test: cleanup include directives 93651e46f registry: drop [[deprecated]] functions ea901cbfa test: code coverage d5dc4f43e doc: meta.md 498e02f15 doc: core.md d0ea8f4f9 cmake: suppress some warnings for clang-cl, it goes a little wrong otherwise dec3b7bb3 test: suppress warnings 10bc8b05a test: use /W1 with VS (but for toolset v141, too bugged for that) ad77b54dc cmake: bump version to get some cool feature/update b6724b028 group: pass filter storage to groups (in-between change for full storage access) 54270b103 group: make them easily copyable/movable 31dc732a7 doc: graph.md f0e02d6d3 doc: container.md 156d6e4ea doc: poly.md 4375c1c3d doc: lib.md 24a9cd67e scheduler: forgot to add the fwd file to the previous commit :) ba8d522c1 doc: add the worst engine (love the name) to the list of links 3ae46214a doc: review process.md 5119fe8d7 scheduler: basic type model with default for common cases ed0319cdd view: avoid shadow warnings bc50da6a7 storage: suppress warnings with non copyable nor default constructible types 52b3b4c24 group: suppress warnings for unused variables in case of empty types 74bab529d test: minor changes b1b143917 meta: [[maybe_unused]] variable to avoid warnings with corner cases 7beb4c85c test: suppress a few warnings (entity) f3beb5670 test: suppress a few warnings (container) 446c67b69 test: suppress a few warnings (resource) c4507bd17 test: suppress a few warnings (poly) 61e872bb4 test: suppress a few warnings (meta) 9f22a3e23 test: suppress a few warnings (memory) 653dd5cd4 test: suppress a few warnings (tuple) bc53ed3be test: suppress a few warnings (flow) f935bbcce dense_set: suppress warnings due to possible narrowing conversions c7d505353 dense_map: suppress warnings due to possible narrowing conversions ea78f1d97 now working on version 3.12 REVERT: fef921132 update single include file REVERT: e52a93f8a ready to cut v3.11.1 REVERT: cd541f335 storage: * move storage_type[_t] and storage_for[_t] to fwd.hpp * no need to include storage.hpp when forward defining views REVERT: 255b8be8c view: avoid shadow warnings REVERT: 8cd7f064a storage: suppress warnings with non copyable nor default constructible types REVERT: 58ae4117c group: suppress warnings for unused variables in case of empty types REVERT: cfa1e805b meta: [[maybe_unused]] variable to avoid warnings with corner cases REVERT: ccedacec8 dense_set: suppress warnings due to possible narrowing conversions REVERT: 17578dc8c dense_map: suppress warnings due to possible narrowing conversions git-subtree-dir: external/entt/entt git-subtree-split: 344e03ac64a1f78424ab1150e2d4778e8df8431d
This commit is contained in:
@ -30,50 +30,43 @@ struct entt::component_traits<traits_based> {
|
||||
};
|
||||
|
||||
TEST(Component, VoidType) {
|
||||
using traits = entt::component_traits<void>;
|
||||
using traits_type = entt::component_traits<void>;
|
||||
|
||||
static_assert(traits::in_place_delete);
|
||||
static_assert(entt::ignore_as_empty_v<typename traits::type>);
|
||||
// we don't really care about this thanks to ignore_as_empty_v
|
||||
static_assert(traits::page_size != 0u);
|
||||
static_assert(!traits_type::in_place_delete);
|
||||
static_assert(traits_type::page_size == 0u);
|
||||
}
|
||||
|
||||
TEST(Component, Empty) {
|
||||
using traits = entt::component_traits<empty>;
|
||||
using traits_type = entt::component_traits<empty>;
|
||||
|
||||
static_assert(!traits::in_place_delete);
|
||||
static_assert(entt::ignore_as_empty_v<typename traits::type>);
|
||||
static_assert(traits::page_size == 0u);
|
||||
static_assert(!traits_type::in_place_delete);
|
||||
static_assert(traits_type::page_size == 0u);
|
||||
}
|
||||
|
||||
TEST(Component, NonEmpty) {
|
||||
using traits = entt::component_traits<non_empty>;
|
||||
using traits_type = entt::component_traits<non_empty>;
|
||||
|
||||
static_assert(!traits::in_place_delete);
|
||||
static_assert(!entt::ignore_as_empty_v<typename traits::type>);
|
||||
static_assert(traits::page_size == ENTT_PACKED_PAGE);
|
||||
static_assert(!traits_type::in_place_delete);
|
||||
static_assert(traits_type::page_size == ENTT_PACKED_PAGE);
|
||||
}
|
||||
|
||||
TEST(Component, NonMovable) {
|
||||
using traits = entt::component_traits<non_movable>;
|
||||
using traits_type = entt::component_traits<non_movable>;
|
||||
|
||||
static_assert(traits::in_place_delete);
|
||||
static_assert(!entt::ignore_as_empty_v<typename traits::type>);
|
||||
static_assert(traits::page_size == ENTT_PACKED_PAGE);
|
||||
static_assert(traits_type::in_place_delete);
|
||||
static_assert(traits_type::page_size == ENTT_PACKED_PAGE);
|
||||
}
|
||||
|
||||
TEST(Component, SelfContained) {
|
||||
using traits = entt::component_traits<self_contained>;
|
||||
using traits_type = entt::component_traits<self_contained>;
|
||||
|
||||
static_assert(traits::in_place_delete);
|
||||
static_assert(!entt::ignore_as_empty_v<typename traits::type>);
|
||||
static_assert(traits::page_size == 4u);
|
||||
static_assert(traits_type::in_place_delete);
|
||||
static_assert(traits_type::page_size == 4u);
|
||||
}
|
||||
|
||||
TEST(Component, TraitsBased) {
|
||||
using traits = entt::component_traits<traits_based>;
|
||||
using traits_type = entt::component_traits<traits_based>;
|
||||
|
||||
static_assert(!traits::in_place_delete);
|
||||
static_assert(!entt::ignore_as_empty_v<typename traits::type>);
|
||||
static_assert(traits::page_size == 8u);
|
||||
static_assert(!traits_type::in_place_delete);
|
||||
static_assert(traits_type::page_size == 8u);
|
||||
}
|
||||
|
@ -29,6 +29,12 @@ TEST(Entity, Traits) {
|
||||
|
||||
ASSERT_EQ(traits_type::combine(entt::tombstone, entt::null), tombstone);
|
||||
ASSERT_EQ(traits_type::combine(entt::null, entt::tombstone), null);
|
||||
|
||||
ASSERT_EQ(traits_type::next(entity), traits_type::construct(entt::to_integral(entity), entt::to_version(entity) + 1u));
|
||||
ASSERT_EQ(traits_type::next(other), traits_type::construct(entt::to_integral(other), entt::to_version(other) + 1u));
|
||||
|
||||
ASSERT_EQ(traits_type::next(entt::tombstone), traits_type::construct(entt::null, {}));
|
||||
ASSERT_EQ(traits_type::next(entt::null), traits_type::construct(entt::null, {}));
|
||||
}
|
||||
|
||||
TEST(Entity, Null) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/entity/group.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "../common/config.h"
|
||||
|
||||
struct empty_type {};
|
||||
|
||||
@ -56,7 +57,7 @@ TEST(NonOwningGroup, Functionalities) {
|
||||
for(auto entity: group) {
|
||||
ASSERT_EQ(std::get<0>(cgroup.get<const int, const char>(entity)), 42);
|
||||
ASSERT_EQ(std::get<1>(group.get<int, char>(entity)), '2');
|
||||
ASSERT_EQ(cgroup.get<const char>(entity), '2');
|
||||
ASSERT_EQ(cgroup.get<1>(entity), '2');
|
||||
}
|
||||
|
||||
ASSERT_EQ(group.handle().data()[0u], e1);
|
||||
@ -93,6 +94,7 @@ TEST(NonOwningGroup, Handle) {
|
||||
ASSERT_TRUE(handle.empty());
|
||||
ASSERT_FALSE(handle.contains(entity));
|
||||
ASSERT_EQ(&handle, &group.handle());
|
||||
ASSERT_NE(&handle, group.storage<int>());
|
||||
|
||||
registry.emplace<int>(entity);
|
||||
registry.emplace<char>(entity);
|
||||
@ -187,10 +189,10 @@ TEST(NonOwningGroup, Each) {
|
||||
auto cgroup = std::as_const(registry).group_if_exists(entt::get<const int, const char>);
|
||||
|
||||
registry.emplace<int>(entity[0u], 0);
|
||||
registry.emplace<char>(entity[0u], 0);
|
||||
registry.emplace<char>(entity[0u], static_cast<char>(0));
|
||||
|
||||
registry.emplace<int>(entity[1u], 1);
|
||||
registry.emplace<char>(entity[1u], 1);
|
||||
registry.emplace<char>(entity[1u], static_cast<char>(1));
|
||||
|
||||
auto iterable = group.each();
|
||||
auto citerable = cgroup.each();
|
||||
@ -201,16 +203,18 @@ TEST(NonOwningGroup, Each) {
|
||||
|
||||
auto it = iterable.begin();
|
||||
|
||||
ASSERT_EQ(it.base(), group.begin());
|
||||
ASSERT_EQ((it++, ++it), iterable.end());
|
||||
ASSERT_EQ(it.base(), group.end());
|
||||
|
||||
group.each([expected = 1u](auto entt, int &ivalue, char &cvalue) mutable {
|
||||
ASSERT_EQ(entt::to_integral(entt), expected);
|
||||
group.each([expected = 1](auto entt, int &ivalue, char &cvalue) mutable {
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), expected);
|
||||
ASSERT_EQ(ivalue, expected);
|
||||
ASSERT_EQ(cvalue, expected);
|
||||
--expected;
|
||||
});
|
||||
|
||||
cgroup.each([expected = 1u](const int &ivalue, const char &cvalue) mutable {
|
||||
cgroup.each([expected = 1](const int &ivalue, const char &cvalue) mutable {
|
||||
ASSERT_EQ(ivalue, expected);
|
||||
ASSERT_EQ(cvalue, expected);
|
||||
--expected;
|
||||
@ -224,8 +228,8 @@ TEST(NonOwningGroup, Each) {
|
||||
|
||||
// do not use iterable, make sure an iterable group works when created from a temporary
|
||||
for(auto [entt, ivalue, cvalue]: registry.group(entt::get<int, char>).each()) {
|
||||
ASSERT_EQ(entt::to_integral(entt), ivalue);
|
||||
ASSERT_EQ(entt::to_integral(entt), cvalue);
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), ivalue);
|
||||
ASSERT_EQ(static_cast<char>(entt::to_integral(entt)), cvalue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,9 +277,9 @@ TEST(NonOwningGroup, Sort) {
|
||||
ASSERT_EQ(group.handle().data()[1u], e1);
|
||||
ASSERT_EQ(group.handle().data()[2u], e2);
|
||||
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e0)), (std::make_tuple(0, 0u)));
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e1)), (std::make_tuple(1, 1u)));
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e2)), (std::make_tuple(2, 2u)));
|
||||
ASSERT_EQ((group.get<0, 1>(e0)), (std::make_tuple(0, 0u)));
|
||||
ASSERT_EQ((group.get<0, 1>(e1)), (std::make_tuple(1, 1u)));
|
||||
ASSERT_EQ((group.get<0, 1>(e2)), (std::make_tuple(2, 2u)));
|
||||
|
||||
ASSERT_FALSE(group.contains(e3));
|
||||
|
||||
@ -323,10 +327,10 @@ TEST(NonOwningGroup, SortAsAPool) {
|
||||
}
|
||||
|
||||
registry.sort<unsigned int>(std::less<unsigned int>{});
|
||||
group.sort<unsigned int>();
|
||||
group.sort_as(*group.storage<unsigned int>());
|
||||
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e0)), (std::make_tuple(0, 0u)));
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e1)), (std::make_tuple(1, 1u)));
|
||||
ASSERT_EQ((group.get<0, 1>(e1)), (std::make_tuple(1, 1u)));
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e2)), (std::make_tuple(2, 2u)));
|
||||
|
||||
ASSERT_FALSE(group.contains(e3));
|
||||
@ -384,9 +388,18 @@ TEST(NonOwningGroup, ConstNonConstAndAllInBetween) {
|
||||
|
||||
ASSERT_EQ(group.size(), 1u);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<0>({})), int &>);
|
||||
static_assert(std::is_same_v<decltype(group.get<int>({})), int &>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<1>({})), void>);
|
||||
static_assert(std::is_same_v<decltype(group.get<empty_type>({})), void>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<2>({})), const char &>);
|
||||
static_assert(std::is_same_v<decltype(group.get<const char>({})), const char &>);
|
||||
static_assert(std::is_same_v<decltype(group.get<int, const char>({})), std::tuple<int &, const char &>>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<int, empty_type, const char>({})), std::tuple<int &, const char &>>);
|
||||
static_assert(std::is_same_v<decltype(group.get<0, 1, 2>({})), std::tuple<int &, const char &>>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get({})), std::tuple<int &, const char &>>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(std::as_const(registry).group_if_exists(entt::get<int, char>)), decltype(std::as_const(registry).group_if_exists(entt::get<const int, const char>))>);
|
||||
@ -475,7 +488,7 @@ TEST(NonOwningGroup, ExcludedComponents) {
|
||||
if(entity == e0) {
|
||||
ASSERT_EQ(group.get<int>(e0), 0);
|
||||
} else if(entity == e2) {
|
||||
ASSERT_EQ(group.get<int>(e2), 2);
|
||||
ASSERT_EQ(group.get<0>(e2), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,7 +506,7 @@ TEST(NonOwningGroup, ExcludedComponents) {
|
||||
if(entity == e1) {
|
||||
ASSERT_EQ(group.get<int>(e1), 1);
|
||||
} else if(entity == e3) {
|
||||
ASSERT_EQ(group.get<int>(e3), 3);
|
||||
ASSERT_EQ(group.get<0>(e3), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -663,28 +676,100 @@ TEST(NonOwningGroup, IterableGroupAlgorithmCompatibility) {
|
||||
TEST(NonOwningGroup, Storage) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
const auto group = registry.group(entt::get<int, const char>);
|
||||
auto group = registry.group(entt::get<int, const char>, entt::exclude<double, const float>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.storage<0u>()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<int>()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<1u>()), const entt::storage_type_t<char> &>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const char>()), const entt::storage_type_t<char> &>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<0u>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<int>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const int>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<1u>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<char>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const char>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<2u>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<double>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const double>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<3u>()), const entt::storage_type_t<float> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<float>()), const entt::storage_type_t<float> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const float>()), const entt::storage_type_t<float> *>);
|
||||
|
||||
ASSERT_TRUE(group);
|
||||
|
||||
ASSERT_NE(group.storage<int>(), nullptr);
|
||||
ASSERT_NE(group.storage<1u>(), nullptr);
|
||||
ASSERT_NE(group.storage<double>(), nullptr);
|
||||
ASSERT_NE(group.storage<3u>(), nullptr);
|
||||
|
||||
ASSERT_EQ(group.size(), 0u);
|
||||
|
||||
group.storage<int>().emplace(entity);
|
||||
group.storage<int>()->emplace(entity);
|
||||
group.storage<double>()->emplace(entity);
|
||||
registry.emplace<char>(entity);
|
||||
registry.emplace<float>(entity);
|
||||
|
||||
ASSERT_EQ(group.size(), 0u);
|
||||
ASSERT_EQ(group.begin(), group.end());
|
||||
ASSERT_TRUE(group.storage<int>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<const char>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<double>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<const float>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<int, char, double, float>(entity)));
|
||||
|
||||
group.storage<double>()->erase(entity);
|
||||
registry.erase<float>(entity);
|
||||
|
||||
ASSERT_EQ(group.size(), 1u);
|
||||
ASSERT_TRUE(group.storage<int>().contains(entity));
|
||||
ASSERT_TRUE(group.storage<const char>().contains(entity));
|
||||
ASSERT_NE(group.begin(), group.end());
|
||||
ASSERT_TRUE(group.storage<const int>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<char>()->contains(entity));
|
||||
ASSERT_FALSE(group.storage<const double>()->contains(entity));
|
||||
ASSERT_FALSE(group.storage<float>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<int, char>(entity)));
|
||||
ASSERT_FALSE((registry.any_of<double, float>(entity)));
|
||||
|
||||
group.storage<0u>().erase(entity);
|
||||
group.storage<0u>()->erase(entity);
|
||||
|
||||
ASSERT_EQ(group.size(), 0u);
|
||||
ASSERT_TRUE(group.storage<1u>().contains(entity));
|
||||
ASSERT_FALSE((registry.all_of<int, char>(entity)));
|
||||
ASSERT_EQ(group.begin(), group.end());
|
||||
ASSERT_FALSE(group.storage<0u>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<1u>()->contains(entity));
|
||||
ASSERT_FALSE(group.storage<2u>()->contains(entity));
|
||||
ASSERT_FALSE(group.storage<3u>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<char>(entity)));
|
||||
ASSERT_FALSE((registry.any_of<int, double, float>(entity)));
|
||||
|
||||
group = {};
|
||||
|
||||
ASSERT_FALSE(group);
|
||||
|
||||
ASSERT_EQ(group.storage<0u>(), nullptr);
|
||||
ASSERT_EQ(group.storage<const char>(), nullptr);
|
||||
ASSERT_EQ(group.storage<2u>(), nullptr);
|
||||
ASSERT_EQ(group.storage<const float>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(NonOwningGroup, Overlapping) {
|
||||
entt::registry registry;
|
||||
|
||||
auto group = registry.group(entt::get<char>, entt::exclude<double>);
|
||||
auto other = registry.group<int>(entt::get<char>, entt::exclude<double>);
|
||||
|
||||
ASSERT_TRUE(group.empty());
|
||||
ASSERT_TRUE(other.empty());
|
||||
|
||||
const auto entity = registry.create();
|
||||
registry.emplace<char>(entity, '1');
|
||||
|
||||
ASSERT_FALSE(group.empty());
|
||||
ASSERT_TRUE(other.empty());
|
||||
|
||||
registry.emplace<int>(entity, 42);
|
||||
|
||||
ASSERT_FALSE(group.empty());
|
||||
ASSERT_FALSE(other.empty());
|
||||
|
||||
registry.emplace<double>(entity, 3.);
|
||||
|
||||
ASSERT_TRUE(group.empty());
|
||||
ASSERT_TRUE(other.empty());
|
||||
}
|
||||
|
||||
TEST(OwningGroup, Functionalities) {
|
||||
@ -721,16 +806,17 @@ TEST(OwningGroup, Functionalities) {
|
||||
|
||||
ASSERT_EQ(group.size(), 1u);
|
||||
|
||||
ASSERT_EQ(cgroup.storage<const int>().raw()[0u][0u], 42);
|
||||
ASSERT_EQ(group.storage<int>().raw()[0u][0u], 42);
|
||||
ASSERT_EQ(cgroup.storage<const int>()->raw()[0u][0u], 42);
|
||||
ASSERT_EQ(group.storage<int>()->raw()[0u][0u], 42);
|
||||
|
||||
for(auto entity: group) {
|
||||
ASSERT_EQ(std::get<0>(cgroup.get<const int, const char>(entity)), 42);
|
||||
ASSERT_EQ(std::get<1>(group.get<int, char>(entity)), '2');
|
||||
ASSERT_EQ(cgroup.get<const char>(entity), '2');
|
||||
ASSERT_EQ(cgroup.get<1>(entity), '2');
|
||||
}
|
||||
|
||||
ASSERT_EQ(group.storage<int>().raw()[0u][0u], 42);
|
||||
ASSERT_EQ(group.handle().data()[0u], e1);
|
||||
ASSERT_EQ(group.storage<int>()->raw()[0u][0u], 42);
|
||||
|
||||
registry.erase<char>(e0);
|
||||
registry.erase<char>(e1);
|
||||
@ -748,6 +834,26 @@ TEST(OwningGroup, Functionalities) {
|
||||
ASSERT_FALSE(invalid);
|
||||
}
|
||||
|
||||
TEST(OwningGroup, Handle) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
|
||||
auto group = registry.group<int>(entt::get<char>);
|
||||
auto &&handle = group.handle();
|
||||
|
||||
ASSERT_TRUE(handle.empty());
|
||||
ASSERT_FALSE(handle.contains(entity));
|
||||
ASSERT_EQ(&handle, &group.handle());
|
||||
ASSERT_EQ(&handle, group.storage<int>());
|
||||
|
||||
registry.emplace<int>(entity);
|
||||
registry.emplace<char>(entity);
|
||||
|
||||
ASSERT_FALSE(handle.empty());
|
||||
ASSERT_TRUE(handle.contains(entity));
|
||||
ASSERT_EQ(&handle, &group.handle());
|
||||
}
|
||||
|
||||
TEST(OwningGroup, Invalid) {
|
||||
entt::registry registry{};
|
||||
auto group = std::as_const(registry).group_if_exists<const int>(entt::get<const empty_type>);
|
||||
@ -831,10 +937,10 @@ TEST(OwningGroup, Each) {
|
||||
auto cgroup = std::as_const(registry).group_if_exists<const int>(entt::get<const char>);
|
||||
|
||||
registry.emplace<int>(entity[0u], 0);
|
||||
registry.emplace<char>(entity[0u], 0);
|
||||
registry.emplace<char>(entity[0u], static_cast<char>(0));
|
||||
|
||||
registry.emplace<int>(entity[1u], 1);
|
||||
registry.emplace<char>(entity[1u], 1);
|
||||
registry.emplace<char>(entity[1u], static_cast<char>(1));
|
||||
|
||||
auto iterable = group.each();
|
||||
auto citerable = cgroup.each();
|
||||
@ -845,16 +951,18 @@ TEST(OwningGroup, Each) {
|
||||
|
||||
auto it = iterable.begin();
|
||||
|
||||
ASSERT_EQ(it.base(), group.begin());
|
||||
ASSERT_EQ((it++, ++it), iterable.end());
|
||||
ASSERT_EQ(it.base(), group.end());
|
||||
|
||||
group.each([expected = 1u](auto entt, int &ivalue, char &cvalue) mutable {
|
||||
ASSERT_EQ(entt::to_integral(entt), expected);
|
||||
group.each([expected = 1](auto entt, int &ivalue, char &cvalue) mutable {
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), expected);
|
||||
ASSERT_EQ(ivalue, expected);
|
||||
ASSERT_EQ(cvalue, expected);
|
||||
--expected;
|
||||
});
|
||||
|
||||
cgroup.each([expected = 1u](const int &ivalue, const char &cvalue) mutable {
|
||||
cgroup.each([expected = 1](const int &ivalue, const char &cvalue) mutable {
|
||||
ASSERT_EQ(ivalue, expected);
|
||||
ASSERT_EQ(cvalue, expected);
|
||||
--expected;
|
||||
@ -868,8 +976,8 @@ TEST(OwningGroup, Each) {
|
||||
|
||||
// do not use iterable, make sure an iterable group works when created from a temporary
|
||||
for(auto [entt, ivalue, cvalue]: registry.group<int>(entt::get<char>).each()) {
|
||||
ASSERT_EQ(entt::to_integral(entt), ivalue);
|
||||
ASSERT_EQ(entt::to_integral(entt), cvalue);
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), ivalue);
|
||||
ASSERT_EQ(static_cast<char>(entt::to_integral(entt)), cvalue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -893,27 +1001,27 @@ TEST(OwningGroup, SortOrdered) {
|
||||
registry.emplace<boxed_int>(entities[4], 2);
|
||||
|
||||
group.sort([&group](const entt::entity lhs, const entt::entity rhs) {
|
||||
return group.get<boxed_int>(lhs).value < group.get<boxed_int>(rhs).value;
|
||||
return group.get<boxed_int>(lhs).value < group.get<0>(rhs).value;
|
||||
});
|
||||
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[0u], entities[0]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[1u], entities[1]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[2u], entities[2]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[3u], entities[3]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[4u], entities[4]);
|
||||
ASSERT_EQ(group.handle().data()[0u], entities[0]);
|
||||
ASSERT_EQ(group.handle().data()[1u], entities[1]);
|
||||
ASSERT_EQ(group.handle().data()[2u], entities[2]);
|
||||
ASSERT_EQ(group.handle().data()[3u], entities[3]);
|
||||
ASSERT_EQ(group.handle().data()[4u], entities[4]);
|
||||
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][3u].value, 1);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][4u].value, 2);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][3u].value, 1);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][4u].value, 2);
|
||||
|
||||
ASSERT_EQ(group.storage<char>().raw()[0u][0u], 'a');
|
||||
ASSERT_EQ(group.storage<char>().raw()[0u][1u], 'b');
|
||||
ASSERT_EQ(group.storage<char>().raw()[0u][2u], 'c');
|
||||
ASSERT_EQ(group.storage<char>()->raw()[0u][0u], 'a');
|
||||
ASSERT_EQ(group.storage<char>()->raw()[0u][1u], 'b');
|
||||
ASSERT_EQ(group.storage<char>()->raw()[0u][2u], 'c');
|
||||
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{12}, 'a')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
|
||||
ASSERT_EQ((group.get<0, 1>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[2])), (std::make_tuple(boxed_int{6}, 'c')));
|
||||
|
||||
ASSERT_FALSE(group.contains(entities[3]));
|
||||
@ -943,24 +1051,24 @@ TEST(OwningGroup, SortReverse) {
|
||||
return lhs.value < rhs.value;
|
||||
});
|
||||
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[0u], entities[2]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[1u], entities[1]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[2u], entities[0]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[3u], entities[3]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[4u], entities[4]);
|
||||
ASSERT_EQ(group.handle().data()[0u], entities[2]);
|
||||
ASSERT_EQ(group.handle().data()[1u], entities[1]);
|
||||
ASSERT_EQ(group.handle().data()[2u], entities[0]);
|
||||
ASSERT_EQ(group.handle().data()[3u], entities[3]);
|
||||
ASSERT_EQ(group.handle().data()[4u], entities[4]);
|
||||
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][3u].value, 1);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][4u].value, 2);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][3u].value, 1);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][4u].value, 2);
|
||||
|
||||
ASSERT_EQ(group.storage<char>().raw()[0u][0u], 'c');
|
||||
ASSERT_EQ(group.storage<char>().raw()[0u][1u], 'b');
|
||||
ASSERT_EQ(group.storage<char>().raw()[0u][2u], 'a');
|
||||
ASSERT_EQ(group.storage<char>()->raw()[0u][0u], 'c');
|
||||
ASSERT_EQ(group.storage<char>()->raw()[0u][1u], 'b');
|
||||
ASSERT_EQ(group.storage<char>()->raw()[0u][2u], 'a');
|
||||
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{6}, 'a')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
|
||||
ASSERT_EQ((group.get<0, 1>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[2])), (std::make_tuple(boxed_int{12}, 'c')));
|
||||
|
||||
ASSERT_FALSE(group.contains(entities[3]));
|
||||
@ -998,27 +1106,27 @@ TEST(OwningGroup, SortUnordered) {
|
||||
return std::get<1>(lhs) < std::get<1>(rhs);
|
||||
});
|
||||
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[0u], entities[4]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[1u], entities[3]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[2u], entities[0]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[3u], entities[1]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[4u], entities[2]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[5u], entities[5]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[6u], entities[6]);
|
||||
ASSERT_EQ(group.handle().data()[0u], entities[4]);
|
||||
ASSERT_EQ(group.handle().data()[1u], entities[3]);
|
||||
ASSERT_EQ(group.handle().data()[2u], entities[0]);
|
||||
ASSERT_EQ(group.handle().data()[3u], entities[1]);
|
||||
ASSERT_EQ(group.handle().data()[4u], entities[2]);
|
||||
ASSERT_EQ(group.handle().data()[5u], entities[5]);
|
||||
ASSERT_EQ(group.handle().data()[6u], entities[6]);
|
||||
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][3u].value, 3);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][4u].value, 1);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][5u].value, 4);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][6u].value, 5);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][3u].value, 3);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][4u].value, 1);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][5u].value, 4);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][6u].value, 5);
|
||||
|
||||
ASSERT_EQ(group.get<char>(group.storage<boxed_int>().data()[0u]), 'e');
|
||||
ASSERT_EQ(group.get<char>(group.storage<boxed_int>().data()[1u]), 'd');
|
||||
ASSERT_EQ(group.get<char>(group.storage<boxed_int>().data()[2u]), 'c');
|
||||
ASSERT_EQ(group.get<char>(group.storage<boxed_int>().data()[3u]), 'b');
|
||||
ASSERT_EQ(group.get<char>(group.storage<boxed_int>().data()[4u]), 'a');
|
||||
ASSERT_EQ(group.get<char>(group.handle().data()[0u]), 'e');
|
||||
ASSERT_EQ(group.get<1>(group.handle().data()[1u]), 'd');
|
||||
ASSERT_EQ(group.get<char>(group.handle().data()[2u]), 'c');
|
||||
ASSERT_EQ(group.get<1>(group.handle().data()[3u]), 'b');
|
||||
ASSERT_EQ(group.get<char>(group.handle().data()[4u]), 'a');
|
||||
|
||||
ASSERT_FALSE(group.contains(entities[5]));
|
||||
ASSERT_FALSE(group.contains(entities[6]));
|
||||
@ -1026,7 +1134,7 @@ TEST(OwningGroup, SortUnordered) {
|
||||
|
||||
TEST(OwningGroup, SortWithExclusionList) {
|
||||
entt::registry registry;
|
||||
auto group = registry.group<boxed_int>({}, entt::exclude<char>);
|
||||
auto group = registry.group<boxed_int>(entt::get<>, entt::exclude<char>);
|
||||
|
||||
entt::entity entities[5]{};
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
@ -1043,20 +1151,20 @@ TEST(OwningGroup, SortWithExclusionList) {
|
||||
return lhs < rhs;
|
||||
});
|
||||
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[0u], entities[4]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[1u], entities[3]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[2u], entities[1]);
|
||||
ASSERT_EQ(group.storage<boxed_int>().data()[3u], entities[0]);
|
||||
ASSERT_EQ(group.handle().data()[0u], entities[4]);
|
||||
ASSERT_EQ(group.handle().data()[1u], entities[3]);
|
||||
ASSERT_EQ(group.handle().data()[2u], entities[1]);
|
||||
ASSERT_EQ(group.handle().data()[3u], entities[0]);
|
||||
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][0u].value, 4);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][1u].value, 3);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][2u].value, 1);
|
||||
ASSERT_EQ(group.storage<boxed_int>().raw()[0u][3u].value, 0);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][0u].value, 4);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][1u].value, 3);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][2u].value, 1);
|
||||
ASSERT_EQ(group.storage<boxed_int>()->raw()[0u][3u].value, 0);
|
||||
|
||||
ASSERT_EQ(group.get<boxed_int>(entities[0]).value, 0);
|
||||
ASSERT_EQ(group.get<boxed_int>(entities[1]).value, 1);
|
||||
ASSERT_EQ(group.get<0>(entities[1]).value, 1);
|
||||
ASSERT_EQ(group.get<boxed_int>(entities[3]).value, 3);
|
||||
ASSERT_EQ(group.get<boxed_int>(entities[4]).value, 4);
|
||||
ASSERT_EQ(group.get<0>(entities[4]).value, 4);
|
||||
|
||||
ASSERT_FALSE(group.contains(entities[2]));
|
||||
}
|
||||
@ -1110,11 +1218,24 @@ TEST(OwningGroup, ConstNonConstAndAllInBetween) {
|
||||
|
||||
ASSERT_EQ(group.size(), 1u);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<0>({})), int &>);
|
||||
static_assert(std::is_same_v<decltype(group.get<int>({})), int &>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<1>({})), const char &>);
|
||||
static_assert(std::is_same_v<decltype(group.get<const char>({})), const char &>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<2>({})), void>);
|
||||
static_assert(std::is_same_v<decltype(group.get<empty_type>({})), void>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<3>({})), double &>);
|
||||
static_assert(std::is_same_v<decltype(group.get<double>({})), double &>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<4>({})), const float &>);
|
||||
static_assert(std::is_same_v<decltype(group.get<const float>({})), const float &>);
|
||||
static_assert(std::is_same_v<decltype(group.get<int, const char, double, const float>({})), std::tuple<int &, const char &, double &, const float &>>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get<int, const char, empty_type, double, const float>({})), std::tuple<int &, const char &, double &, const float &>>);
|
||||
static_assert(std::is_same_v<decltype(group.get<0, 1, 2, 3, 4>({})), std::tuple<int &, const char &, double &, const float &>>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.get({})), std::tuple<int &, const char &, double &, const float &>>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(std::as_const(registry).group_if_exists<int>(entt::get<char>)), decltype(std::as_const(registry).group_if_exists<const int>(entt::get<const char>))>);
|
||||
@ -1192,7 +1313,7 @@ TEST(OwningGroup, ExcludedComponents) {
|
||||
registry.emplace<int>(e1, 1);
|
||||
registry.emplace<char>(e1);
|
||||
|
||||
const auto group = registry.group<int>({}, entt::exclude<char, double>);
|
||||
const auto group = registry.group<int>(entt::get<>, entt::exclude<char, double>);
|
||||
|
||||
const auto e2 = registry.create();
|
||||
registry.emplace<int>(e2, 2);
|
||||
@ -1207,7 +1328,7 @@ TEST(OwningGroup, ExcludedComponents) {
|
||||
if(entity == e0) {
|
||||
ASSERT_EQ(group.get<int>(e0), 0);
|
||||
} else if(entity == e2) {
|
||||
ASSERT_EQ(group.get<int>(e2), 2);
|
||||
ASSERT_EQ(group.get<0>(e2), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1225,7 +1346,7 @@ TEST(OwningGroup, ExcludedComponents) {
|
||||
if(entity == e1) {
|
||||
ASSERT_EQ(group.get<int>(e1), 1);
|
||||
} else if(entity == e3) {
|
||||
ASSERT_EQ(group.get<int>(e3), 3);
|
||||
ASSERT_EQ(group.get<0>(e3), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1263,8 +1384,8 @@ TEST(OwningGroup, EmptyAndNonEmptyTypes) {
|
||||
|
||||
TEST(OwningGroup, TrackEntitiesOnComponentDestruction) {
|
||||
entt::registry registry;
|
||||
const auto group = registry.group<int>({}, entt::exclude<char>);
|
||||
const auto cgroup = std::as_const(registry).group_if_exists<const int>({}, entt::exclude<char>);
|
||||
const auto group = registry.group<int>(entt::get<>, entt::exclude<char>);
|
||||
const auto cgroup = std::as_const(registry).group_if_exists<const int>(entt::get<>, entt::exclude<char>);
|
||||
|
||||
const auto entity = registry.create();
|
||||
registry.emplace<int>(entity);
|
||||
@ -1403,7 +1524,7 @@ TEST(OwningGroup, SwappingValuesIsAllowed) {
|
||||
|
||||
// thanks to @andranik3949 for pointing out this missing test
|
||||
registry.view<const boxed_int>().each([](const auto entity, const auto &value) {
|
||||
ASSERT_EQ(entt::to_integral(entity), value.value);
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entity)), value.value);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1443,26 +1564,81 @@ TEST(OwningGroup, IterableGroupAlgorithmCompatibility) {
|
||||
TEST(OwningGroup, Storage) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
const auto group = registry.group<int>(entt::get<const char>);
|
||||
auto group = registry.group<int>(entt::get<const char>, entt::exclude<double, const float>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(group.storage<0u>()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<int>()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<1u>()), const entt::storage_type_t<char> &>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const char>()), const entt::storage_type_t<char> &>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<0u>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<int>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const int>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<1u>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<char>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const char>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<2u>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<double>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const double>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<3u>()), const entt::storage_type_t<float> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<float>()), const entt::storage_type_t<float> *>);
|
||||
static_assert(std::is_same_v<decltype(group.storage<const float>()), const entt::storage_type_t<float> *>);
|
||||
|
||||
ASSERT_TRUE(group);
|
||||
|
||||
ASSERT_NE(group.storage<int>(), nullptr);
|
||||
ASSERT_NE(group.storage<1u>(), nullptr);
|
||||
ASSERT_NE(group.storage<double>(), nullptr);
|
||||
ASSERT_NE(group.storage<3u>(), nullptr);
|
||||
|
||||
ASSERT_EQ(group.size(), 0u);
|
||||
|
||||
group.storage<int>().emplace(entity);
|
||||
group.storage<int>()->emplace(entity);
|
||||
group.storage<double>()->emplace(entity);
|
||||
registry.emplace<char>(entity);
|
||||
registry.emplace<float>(entity);
|
||||
|
||||
ASSERT_EQ(group.size(), 0u);
|
||||
ASSERT_EQ(group.begin(), group.end());
|
||||
ASSERT_TRUE(group.storage<int>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<const char>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<double>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<const float>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<int, char, double, float>(entity)));
|
||||
|
||||
group.storage<double>()->erase(entity);
|
||||
registry.erase<float>(entity);
|
||||
|
||||
ASSERT_EQ(group.size(), 1u);
|
||||
ASSERT_TRUE(group.storage<int>().contains(entity));
|
||||
ASSERT_TRUE(group.storage<const char>().contains(entity));
|
||||
ASSERT_NE(group.begin(), group.end());
|
||||
ASSERT_TRUE(group.storage<const int>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<char>()->contains(entity));
|
||||
ASSERT_FALSE(group.storage<const double>()->contains(entity));
|
||||
ASSERT_FALSE(group.storage<float>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<int, char>(entity)));
|
||||
ASSERT_FALSE((registry.any_of<double, float>(entity)));
|
||||
|
||||
group.storage<0u>().erase(entity);
|
||||
group.storage<0u>()->erase(entity);
|
||||
|
||||
ASSERT_EQ(group.size(), 0u);
|
||||
ASSERT_TRUE(group.storage<1u>().contains(entity));
|
||||
ASSERT_FALSE((registry.all_of<int, char>(entity)));
|
||||
ASSERT_EQ(group.begin(), group.end());
|
||||
ASSERT_FALSE(group.storage<0u>()->contains(entity));
|
||||
ASSERT_TRUE(group.storage<1u>()->contains(entity));
|
||||
ASSERT_FALSE(group.storage<2u>()->contains(entity));
|
||||
ASSERT_FALSE(group.storage<3u>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<char>(entity)));
|
||||
ASSERT_FALSE((registry.any_of<int, double, float>(entity)));
|
||||
|
||||
group = {};
|
||||
|
||||
ASSERT_FALSE(group);
|
||||
|
||||
ASSERT_EQ(group.storage<0u>(), nullptr);
|
||||
ASSERT_EQ(group.storage<const char>(), nullptr);
|
||||
ASSERT_EQ(group.storage<2u>(), nullptr);
|
||||
ASSERT_EQ(group.storage<const float>(), nullptr);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(OwningGroupDeathTest, Overlapping) {
|
||||
entt::registry registry;
|
||||
registry.group<char>(entt::get<int>, entt::exclude<double>);
|
||||
|
||||
ASSERT_DEATH((registry.group<char, float>(entt::get<float>, entt::exclude<double>)), "");
|
||||
ASSERT_DEATH(registry.group<char>(entt::get<int, float>, entt::exclude<double>), "");
|
||||
ASSERT_DEATH(registry.group<char>(entt::get<int>, entt::exclude<double, float>), "");
|
||||
}
|
||||
|
@ -83,8 +83,8 @@ TEST(BasicHandle, Destruction) {
|
||||
ASSERT_FALSE(handle);
|
||||
ASSERT_FALSE(handle.valid());
|
||||
ASSERT_NE(handle.registry(), nullptr);
|
||||
ASSERT_EQ(handle.entity(), entity);
|
||||
ASSERT_EQ(registry.current(entity), typename entt::registry::version_type{});
|
||||
ASSERT_EQ(handle.entity(), entt::entity{entt::null});
|
||||
|
||||
handle = entt::handle{registry, registry.create()};
|
||||
|
||||
@ -98,8 +98,8 @@ TEST(BasicHandle, Destruction) {
|
||||
ASSERT_FALSE(handle);
|
||||
ASSERT_FALSE(handle.valid());
|
||||
ASSERT_NE(handle.registry(), nullptr);
|
||||
ASSERT_EQ(handle.entity(), entity);
|
||||
ASSERT_NE(registry.current(entity), typename entt::registry::version_type{});
|
||||
ASSERT_EQ(handle.entity(), entt::entity{entt::null});
|
||||
}
|
||||
|
||||
TEST(BasicHandle, Comparison) {
|
||||
@ -275,6 +275,8 @@ TEST(BasicHandle, HandleStorageIterator) {
|
||||
|
||||
registry.emplace<int>(entity);
|
||||
registry.emplace<double>(entity);
|
||||
// required to test the find-first initialization step
|
||||
registry.storage<entt::entity>().erase(entity);
|
||||
|
||||
auto test = [](auto iterable) {
|
||||
auto end{iterable.begin()};
|
||||
@ -290,6 +292,13 @@ TEST(BasicHandle, HandleStorageIterator) {
|
||||
ASSERT_EQ(++begin, iterable.end());
|
||||
};
|
||||
|
||||
test(entt::handle{registry, entity}.storage());
|
||||
test(entt::const_handle{std::as_const(registry), entity}.storage());
|
||||
const auto handle = entt::handle{registry, entity};
|
||||
const auto chandle = entt::const_handle{std::as_const(registry), entity};
|
||||
|
||||
ASSERT_FALSE(registry.valid(entity));
|
||||
ASSERT_FALSE(handle);
|
||||
ASSERT_FALSE(chandle);
|
||||
|
||||
test(handle.storage());
|
||||
test(chandle.storage());
|
||||
}
|
||||
|
@ -16,6 +16,10 @@ struct stable_type {
|
||||
int value;
|
||||
};
|
||||
|
||||
void sigh_callback(int &value) {
|
||||
++value;
|
||||
}
|
||||
|
||||
TEST(Helper, AsView) {
|
||||
entt::registry registry;
|
||||
const entt::registry cregistry;
|
||||
@ -48,7 +52,7 @@ TEST(Helper, Invoke) {
|
||||
TEST(Helper, ToEntity) {
|
||||
entt::registry registry;
|
||||
const entt::entity null = entt::null;
|
||||
constexpr auto page_size = entt::component_traits<int>::page_size;
|
||||
constexpr auto page_size = entt::storage_type_t<int>::traits_type::page_size;
|
||||
const int value = 42;
|
||||
|
||||
ASSERT_EQ(entt::to_entity(registry, 42), null);
|
||||
@ -88,7 +92,7 @@ TEST(Helper, ToEntity) {
|
||||
TEST(Helper, ToEntityStableType) {
|
||||
entt::registry registry;
|
||||
const entt::entity null = entt::null;
|
||||
constexpr auto page_size = entt::component_traits<stable_type>::page_size;
|
||||
constexpr auto page_size = entt::storage_type_t<stable_type>::traits_type::page_size;
|
||||
const stable_type value{42};
|
||||
|
||||
ASSERT_EQ(entt::to_entity(registry, stable_type{42}), null);
|
||||
@ -124,3 +128,44 @@ TEST(Helper, ToEntityStableType) {
|
||||
ASSERT_EQ(entt::to_entity(registry, stable_type{42}), null);
|
||||
ASSERT_EQ(entt::to_entity(registry, value), null);
|
||||
}
|
||||
|
||||
TEST(Helper, SighHelper) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::registry registry{};
|
||||
const auto entt = registry.create();
|
||||
entt::sigh_helper helper{registry};
|
||||
int counter{};
|
||||
|
||||
ASSERT_EQ(&helper.registry(), ®istry);
|
||||
|
||||
helper.with<int>()
|
||||
.on_construct<&sigh_callback>(counter)
|
||||
.on_update<&sigh_callback>(counter)
|
||||
.on_destroy<&sigh_callback>(counter);
|
||||
|
||||
ASSERT_EQ(counter, 0);
|
||||
|
||||
registry.emplace<int>(entt);
|
||||
registry.replace<int>(entt);
|
||||
registry.erase<int>(entt);
|
||||
|
||||
ASSERT_EQ(counter, 3);
|
||||
|
||||
helper.with<double>("other"_hs)
|
||||
.on_construct<&sigh_callback>(counter)
|
||||
.on_update<&sigh_callback>(counter)
|
||||
.on_destroy<&sigh_callback>(counter);
|
||||
|
||||
registry.emplace<double>(entt);
|
||||
registry.replace<double>(entt);
|
||||
registry.erase<double>(entt);
|
||||
|
||||
ASSERT_EQ(counter, 3);
|
||||
|
||||
registry.storage<double>("other"_hs).emplace(entt);
|
||||
registry.storage<double>("other"_hs).patch(entt);
|
||||
registry.storage<double>("other"_hs).erase(entt);
|
||||
|
||||
ASSERT_EQ(counter, 6);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/type_info.hpp>
|
||||
#include <entt/entity/organizer.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
|
||||
@ -20,7 +22,7 @@ struct clazz {
|
||||
static void ro_int_char_with_payload(clazz &, entt::view<entt::get_t<const int, const char>>) {}
|
||||
};
|
||||
|
||||
void to_args_integrity(entt::view<entt::get_t<int>> view, std::size_t &value, entt::registry ®istry) {
|
||||
void to_args_integrity(entt::view<entt::get_t<int>> view, std::size_t &value, entt::registry &) {
|
||||
value = view.size();
|
||||
}
|
||||
|
||||
@ -363,6 +365,10 @@ TEST(Organizer, Prepare) {
|
||||
ASSERT_FALSE(registry.ctx().contains<char>());
|
||||
ASSERT_FALSE(registry.ctx().contains<double>());
|
||||
|
||||
ASSERT_EQ(std::as_const(registry).storage<int>(), nullptr);
|
||||
ASSERT_EQ(std::as_const(registry).storage<char>(), nullptr);
|
||||
ASSERT_EQ(std::as_const(registry).storage<double>(), nullptr);
|
||||
|
||||
for(auto &&vertex: graph) {
|
||||
vertex.prepare(registry);
|
||||
}
|
||||
@ -370,6 +376,10 @@ TEST(Organizer, Prepare) {
|
||||
ASSERT_FALSE(registry.ctx().contains<int>());
|
||||
ASSERT_FALSE(registry.ctx().contains<char>());
|
||||
ASSERT_TRUE(registry.ctx().contains<double>());
|
||||
|
||||
ASSERT_NE(std::as_const(registry).storage<int>(), nullptr);
|
||||
ASSERT_NE(std::as_const(registry).storage<char>(), nullptr);
|
||||
ASSERT_EQ(std::as_const(registry).storage<double>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(Organizer, Dependencies) {
|
||||
@ -428,5 +438,5 @@ TEST(Organizer, ToArgsIntegrity) {
|
||||
auto graph = organizer.graph();
|
||||
graph[0u].callback()(graph[0u].data(), registry);
|
||||
|
||||
ASSERT_EQ(registry.ctx().at<std::size_t>(), 0u);
|
||||
ASSERT_EQ(registry.ctx().get<std::size_t>(), 0u);
|
||||
}
|
||||
|
@ -40,18 +40,16 @@ struct aggregate {
|
||||
};
|
||||
|
||||
struct listener {
|
||||
template<typename Component>
|
||||
template<typename Type>
|
||||
static void sort(entt::registry ®istry) {
|
||||
registry.sort<Component>([](auto lhs, auto rhs) { return lhs < rhs; });
|
||||
registry.sort<Type>([](auto lhs, auto rhs) { return lhs < rhs; });
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
void incr(const entt::registry &, entt::entity entity) {
|
||||
last = entity;
|
||||
++counter;
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
void decr(const entt::registry &, entt::entity entity) {
|
||||
last = entity;
|
||||
--counter;
|
||||
@ -75,11 +73,11 @@ struct destruction_order {
|
||||
destruction_order(const entt::registry &ref, bool &ctx)
|
||||
: registry{&ref},
|
||||
ctx_check{&ctx} {
|
||||
*ctx_check = (registry->ctx().find<int>() != nullptr);
|
||||
*ctx_check = (registry->ctx().find<ctx_check_type>() != nullptr);
|
||||
}
|
||||
|
||||
~destruction_order() {
|
||||
*ctx_check = *ctx_check && (registry->ctx().find<int>() != nullptr);
|
||||
*ctx_check = *ctx_check && (registry->ctx().find<ctx_check_type>() != nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -87,6 +85,22 @@ private:
|
||||
bool *ctx_check{};
|
||||
};
|
||||
|
||||
enum class small_entity : std::uint32_t {};
|
||||
|
||||
struct small_entity_traits {
|
||||
using value_type = small_entity;
|
||||
using entity_type = uint32_t;
|
||||
using version_type = uint16_t;
|
||||
static constexpr entity_type entity_mask = 0xFF;
|
||||
static constexpr entity_type version_mask = 0x00;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct entt::entt_traits<small_entity>: entt::basic_entt_traits<small_entity_traits> {
|
||||
using base_type = entt::basic_entt_traits<small_entity_traits>;
|
||||
static constexpr auto page_size = ENTT_SPARSE_PAGE;
|
||||
};
|
||||
|
||||
TEST(Registry, Context) {
|
||||
entt::registry registry;
|
||||
auto &ctx = registry.ctx();
|
||||
@ -126,8 +140,8 @@ TEST(Registry, Context) {
|
||||
|
||||
ASSERT_EQ(ctx.emplace<const int>(0), 42);
|
||||
ASSERT_EQ(ctx.find<const int>(), cctx.find<int>());
|
||||
ASSERT_EQ(ctx.at<int>(), cctx.at<const int>());
|
||||
ASSERT_EQ(ctx.at<int>(), 42);
|
||||
ASSERT_EQ(ctx.get<int>(), cctx.get<const int>());
|
||||
ASSERT_EQ(ctx.get<int>(), 42);
|
||||
|
||||
ASSERT_EQ(ctx.find<double>(), nullptr);
|
||||
ASSERT_EQ(cctx.find<double>(), nullptr);
|
||||
@ -139,8 +153,8 @@ TEST(Registry, Context) {
|
||||
|
||||
ASSERT_EQ(ctx.insert_or_assign<const int>(0), 0);
|
||||
ASSERT_EQ(ctx.find<const int>(), cctx.find<int>());
|
||||
ASSERT_EQ(ctx.at<int>(), cctx.at<const int>());
|
||||
ASSERT_EQ(ctx.at<int>(), 0);
|
||||
ASSERT_EQ(ctx.get<int>(), cctx.get<const int>());
|
||||
ASSERT_EQ(ctx.get<int>(), 0);
|
||||
}
|
||||
|
||||
TEST(Registry, ContextHint) {
|
||||
@ -376,13 +390,12 @@ TEST(Registry, Functionalities) {
|
||||
TEST(Registry, Constructors) {
|
||||
entt::registry registry;
|
||||
entt::registry other{42};
|
||||
const entt::entity entity = entt::tombstone;
|
||||
|
||||
ASSERT_TRUE(registry.empty());
|
||||
ASSERT_TRUE(other.empty());
|
||||
|
||||
ASSERT_EQ(registry.released(), entity);
|
||||
ASSERT_EQ(other.released(), entity);
|
||||
ASSERT_EQ(registry.released(), 0u);
|
||||
ASSERT_EQ(other.released(), 0u);
|
||||
}
|
||||
|
||||
TEST(Registry, Move) {
|
||||
@ -486,6 +499,8 @@ TEST(Registry, Identifiers) {
|
||||
}
|
||||
|
||||
TEST(Registry, Data) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::registry registry;
|
||||
|
||||
ASSERT_EQ(std::as_const(registry).data(), nullptr);
|
||||
@ -497,8 +512,8 @@ TEST(Registry, Data) {
|
||||
const auto other = registry.create();
|
||||
registry.release(entity);
|
||||
|
||||
ASSERT_NE(*std::as_const(registry).data(), entity);
|
||||
ASSERT_EQ(*(std::as_const(registry).data() + 1u), other);
|
||||
ASSERT_EQ(*std::as_const(registry).data(), other);
|
||||
ASSERT_EQ(*(std::as_const(registry).data() + 1u), traits_type::next(entity));
|
||||
}
|
||||
|
||||
TEST(Registry, CreateManyEntitiesAtOnce) {
|
||||
@ -533,7 +548,7 @@ TEST(Registry, CreateManyEntitiesAtOnceWithListener) {
|
||||
entt::entity entities[3];
|
||||
listener listener;
|
||||
|
||||
registry.on_construct<int>().connect<&listener::incr<int>>(listener);
|
||||
registry.on_construct<int>().connect<&listener::incr>(listener);
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
registry.insert(std::begin(entities), std::end(entities), 42);
|
||||
registry.insert(std::begin(entities), std::end(entities), 'c');
|
||||
@ -542,8 +557,8 @@ TEST(Registry, CreateManyEntitiesAtOnceWithListener) {
|
||||
ASSERT_EQ(registry.get<char>(entities[1]), 'c');
|
||||
ASSERT_EQ(listener.counter, 3);
|
||||
|
||||
registry.on_construct<int>().disconnect<&listener::incr<int>>(listener);
|
||||
registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
|
||||
registry.on_construct<int>().disconnect<&listener::incr>(listener);
|
||||
registry.on_construct<empty_type>().connect<&listener::incr>(listener);
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
registry.insert(std::begin(entities), std::end(entities), 'a');
|
||||
registry.insert<empty_type>(std::begin(entities), std::end(entities));
|
||||
@ -560,8 +575,9 @@ TEST(Registry, CreateWithHint) {
|
||||
auto e3 = registry.create(entt::entity{3});
|
||||
auto e2 = registry.create(entt::entity{3});
|
||||
|
||||
ASSERT_EQ(e2, entt::entity{2});
|
||||
ASSERT_FALSE(registry.valid(entt::entity{1}));
|
||||
ASSERT_EQ(e2, entt::entity{1});
|
||||
ASSERT_FALSE(registry.valid(entt::entity{0}));
|
||||
ASSERT_FALSE(registry.valid(entt::entity{2}));
|
||||
ASSERT_EQ(e3, entt::entity{3});
|
||||
|
||||
registry.release(e2);
|
||||
@ -572,10 +588,10 @@ TEST(Registry, CreateWithHint) {
|
||||
e2 = registry.create();
|
||||
auto e1 = registry.create(entt::entity{2});
|
||||
|
||||
ASSERT_EQ(traits_type::to_entity(e2), 2u);
|
||||
ASSERT_EQ(traits_type::to_entity(e2), 1u);
|
||||
ASSERT_EQ(traits_type::to_version(e2), 1u);
|
||||
|
||||
ASSERT_EQ(traits_type::to_entity(e1), 1u);
|
||||
ASSERT_EQ(traits_type::to_entity(e1), 2u);
|
||||
ASSERT_EQ(traits_type::to_version(e1), 0u);
|
||||
|
||||
registry.release(e1);
|
||||
@ -640,6 +656,14 @@ TEST(Registry, CreateDestroyReleaseCornerCase) {
|
||||
ASSERT_EQ(registry.current(e1), 1u);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(RegistryDeathTest, CreateTooManyEntities) {
|
||||
entt::basic_registry<small_entity> registry;
|
||||
std::vector<small_entity> entities(entt::entt_traits<small_entity>::to_entity(entt::null));
|
||||
registry.create(entities.begin(), entities.end());
|
||||
|
||||
ASSERT_DEATH([[maybe_unused]] const auto entity = registry.create(), "");
|
||||
}
|
||||
|
||||
TEST(Registry, DestroyVersion) {
|
||||
entt::registry registry;
|
||||
|
||||
@ -666,7 +690,7 @@ ENTT_DEBUG_TEST(RegistryDeathTest, DestroyVersion) {
|
||||
ASSERT_DEATH(registry.destroy(entity, 3), "");
|
||||
}
|
||||
|
||||
TEST(Registry, RangeDestroy) {
|
||||
TEST(Registry, DestroyRange) {
|
||||
entt::registry registry;
|
||||
const auto iview = registry.view<int>();
|
||||
const auto icview = registry.view<int, char>();
|
||||
@ -722,6 +746,24 @@ TEST(Registry, RangeDestroy) {
|
||||
ASSERT_FALSE(registry.valid(entities[1u]));
|
||||
ASSERT_FALSE(registry.valid(entities[2u]));
|
||||
ASSERT_EQ(registry.storage<int>().size(), 0u);
|
||||
|
||||
entt::sparse_set managed{};
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
managed.push(std::begin(entities), std::end(entities));
|
||||
registry.insert<int>(managed.begin(), managed.end());
|
||||
|
||||
ASSERT_TRUE(registry.valid(managed[0u]));
|
||||
ASSERT_TRUE(registry.valid(managed[1u]));
|
||||
ASSERT_TRUE(registry.valid(managed[2u]));
|
||||
ASSERT_EQ(registry.storage<int>().size(), 3u);
|
||||
|
||||
registry.destroy(managed.begin(), managed.end());
|
||||
|
||||
ASSERT_FALSE(registry.valid(managed[0u]));
|
||||
ASSERT_FALSE(registry.valid(managed[1u]));
|
||||
ASSERT_FALSE(registry.valid(managed[2u]));
|
||||
ASSERT_EQ(registry.storage<int>().size(), 0u);
|
||||
}
|
||||
|
||||
TEST(Registry, StableDestroy) {
|
||||
@ -792,7 +834,7 @@ ENTT_DEBUG_TEST(RegistryDeathTest, ReleaseVersion) {
|
||||
ASSERT_DEATH(registry.release(entity, 3), "");
|
||||
}
|
||||
|
||||
TEST(Registry, RangeRelease) {
|
||||
TEST(Registry, ReleaseRange) {
|
||||
entt::registry registry;
|
||||
entt::entity entities[3u];
|
||||
|
||||
@ -930,10 +972,12 @@ TEST(Registry, Orphans) {
|
||||
|
||||
TEST(Registry, View) {
|
||||
entt::registry registry;
|
||||
auto mview = registry.view<int, char>();
|
||||
entt::entity entities[3u];
|
||||
|
||||
auto iview = registry.view<int>();
|
||||
auto cview = registry.view<char>();
|
||||
entt::entity entities[3u];
|
||||
auto mview = registry.view<int, char>();
|
||||
auto fview = registry.view<int>(entt::exclude<char>);
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
|
||||
@ -948,10 +992,55 @@ TEST(Registry, View) {
|
||||
ASSERT_EQ(iview.size(), 3u);
|
||||
ASSERT_EQ(cview.size(), 2u);
|
||||
|
||||
std::size_t cnt{};
|
||||
mview.each([&cnt](auto...) { ++cnt; });
|
||||
ASSERT_EQ(mview.size_hint(), 3u);
|
||||
ASSERT_EQ(fview.size_hint(), 3u);
|
||||
|
||||
ASSERT_EQ(cnt, 2u);
|
||||
mview.refresh();
|
||||
fview.refresh();
|
||||
|
||||
ASSERT_EQ(mview.size_hint(), 2u);
|
||||
ASSERT_EQ(fview.size_hint(), 3u);
|
||||
|
||||
ASSERT_NE(mview.begin(), mview.end());
|
||||
ASSERT_NE(fview.begin(), fview.end());
|
||||
|
||||
ASSERT_EQ(std::distance(mview.begin(), mview.end()), 2);
|
||||
ASSERT_EQ(std::distance(fview.begin(), fview.end()), 1);
|
||||
|
||||
mview.each([&entities, first = true](auto entity, auto &&...) mutable {
|
||||
ASSERT_EQ(entity, entities[2u * first]);
|
||||
first = false;
|
||||
});
|
||||
|
||||
fview.each([&entities](auto entity, auto &&...) {
|
||||
ASSERT_EQ(entity, entities[1u]);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Registry, ExcludeOnlyView) {
|
||||
entt::registry registry;
|
||||
entt::entity entities[4u];
|
||||
|
||||
auto view = registry.view<entt::entity>(entt::exclude<int>);
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
|
||||
registry.emplace<int>(entities[0u], 0);
|
||||
registry.emplace<int>(entities[2u], 0);
|
||||
registry.emplace<int>(entities[3u], 0);
|
||||
|
||||
registry.destroy(entities[3u]);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 4u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
// returns all matching identifiers, both in-use and available ones
|
||||
ASSERT_EQ(std::distance(view.begin(), view.end()), 2);
|
||||
|
||||
// skips available identifiers automatically, only returns in-use elements
|
||||
view.each([&entities](auto entity, auto &&...) {
|
||||
ASSERT_EQ(entity, entities[1u]);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Registry, NonOwningGroupInitOnFirstUse) {
|
||||
@ -964,7 +1053,7 @@ TEST(Registry, NonOwningGroupInitOnFirstUse) {
|
||||
registry.emplace<char>(entities[2u], 'c');
|
||||
|
||||
std::size_t cnt{};
|
||||
auto group = registry.group<>(entt::get<int, char>);
|
||||
auto group = registry.group(entt::get<int, char>);
|
||||
group.each([&cnt](auto...) { ++cnt; });
|
||||
|
||||
ASSERT_FALSE((registry.owned<int, char>()));
|
||||
@ -974,7 +1063,7 @@ TEST(Registry, NonOwningGroupInitOnFirstUse) {
|
||||
TEST(Registry, NonOwningGroupInitOnEmplace) {
|
||||
entt::registry registry;
|
||||
entt::entity entities[3u];
|
||||
auto group = registry.group<>(entt::get<int, char>);
|
||||
auto group = registry.group(entt::get<int, char>);
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
registry.insert<int>(std::begin(entities), std::end(entities), 0);
|
||||
@ -1097,7 +1186,7 @@ TEST(Registry, CleanViewAfterRemoveAndClear) {
|
||||
|
||||
TEST(Registry, CleanNonOwningGroupViewAfterRemoveAndClear) {
|
||||
entt::registry registry;
|
||||
auto group = registry.group<>(entt::get<int, char>);
|
||||
auto group = registry.group(entt::get<int, char>);
|
||||
|
||||
const auto entity = registry.create();
|
||||
registry.emplace<int>(entity, 0);
|
||||
@ -1188,107 +1277,21 @@ TEST(Registry, CleanPartialOwningGroupViewAfterRemoveAndClear) {
|
||||
ASSERT_EQ(group.size(), 0u);
|
||||
}
|
||||
|
||||
TEST(Registry, NestedGroups) {
|
||||
ENTT_DEBUG_TEST(RegistryDeathTest, NestedGroups) {
|
||||
entt::registry registry;
|
||||
entt::entity entities[10];
|
||||
registry.group<int, double>(entt::get<char>);
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
registry.insert<int>(std::begin(entities), std::end(entities));
|
||||
registry.insert<char>(std::begin(entities), std::end(entities));
|
||||
const auto g1 = registry.group<int>(entt::get<char>, entt::exclude<double>);
|
||||
ASSERT_DEATH(registry.group<int>(entt::get<char>), "");
|
||||
ASSERT_DEATH(registry.group<int>(entt::get<char, double>), "");
|
||||
ASSERT_DEATH(registry.group<int>(entt::get<char>, entt::exclude<double>), "");
|
||||
ASSERT_DEATH((registry.group<int, double>()), "");
|
||||
}
|
||||
|
||||
ASSERT_TRUE(registry.sortable(g1));
|
||||
ASSERT_EQ(g1.size(), 10u);
|
||||
ENTT_DEBUG_TEST(RegistryDeathTest, ConflictingGroups) {
|
||||
entt::registry registry;
|
||||
|
||||
const auto g2 = registry.group<int>(entt::get<char>);
|
||||
|
||||
ASSERT_TRUE(registry.sortable(g1));
|
||||
ASSERT_FALSE(registry.sortable(g2));
|
||||
ASSERT_EQ(g1.size(), 10u);
|
||||
ASSERT_EQ(g2.size(), 10u);
|
||||
|
||||
for(auto i = 0u; i < 5u; ++i) {
|
||||
ASSERT_TRUE(g1.contains(entities[i * 2 + 1]));
|
||||
ASSERT_TRUE(g1.contains(entities[i * 2]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2 + 1]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2]));
|
||||
registry.emplace<double>(entities[i * 2]);
|
||||
}
|
||||
|
||||
ASSERT_EQ(g1.size(), 5u);
|
||||
ASSERT_EQ(g2.size(), 10u);
|
||||
|
||||
for(auto i = 0u; i < 5u; ++i) {
|
||||
ASSERT_TRUE(g1.contains(entities[i * 2 + 1]));
|
||||
ASSERT_FALSE(g1.contains(entities[i * 2]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2 + 1]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2]));
|
||||
registry.erase<int>(entities[i * 2 + 1]);
|
||||
}
|
||||
|
||||
ASSERT_EQ(g1.size(), 0u);
|
||||
ASSERT_EQ(g2.size(), 5u);
|
||||
|
||||
const auto g3 = registry.group<int, float>(entt::get<char>, entt::exclude<double>);
|
||||
|
||||
ASSERT_FALSE(registry.sortable(g1));
|
||||
ASSERT_FALSE(registry.sortable(g2));
|
||||
ASSERT_TRUE(registry.sortable(g3));
|
||||
|
||||
ASSERT_EQ(g1.size(), 0u);
|
||||
ASSERT_EQ(g2.size(), 5u);
|
||||
ASSERT_EQ(g3.size(), 0u);
|
||||
|
||||
for(auto i = 0u; i < 5u; ++i) {
|
||||
ASSERT_FALSE(g1.contains(entities[i * 2 + 1]));
|
||||
ASSERT_FALSE(g1.contains(entities[i * 2]));
|
||||
ASSERT_FALSE(g2.contains(entities[i * 2 + 1]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2]));
|
||||
ASSERT_FALSE(g3.contains(entities[i * 2 + 1]));
|
||||
ASSERT_FALSE(g3.contains(entities[i * 2]));
|
||||
registry.emplace<int>(entities[i * 2 + 1]);
|
||||
}
|
||||
|
||||
ASSERT_EQ(g1.size(), 5u);
|
||||
ASSERT_EQ(g2.size(), 10u);
|
||||
ASSERT_EQ(g3.size(), 0u);
|
||||
|
||||
for(auto i = 0u; i < 5u; ++i) {
|
||||
ASSERT_TRUE(g1.contains(entities[i * 2 + 1]));
|
||||
ASSERT_FALSE(g1.contains(entities[i * 2]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2 + 1]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2]));
|
||||
ASSERT_FALSE(g3.contains(entities[i * 2 + 1]));
|
||||
ASSERT_FALSE(g3.contains(entities[i * 2]));
|
||||
registry.emplace<float>(entities[i * 2]);
|
||||
}
|
||||
|
||||
ASSERT_EQ(g1.size(), 5u);
|
||||
ASSERT_EQ(g2.size(), 10u);
|
||||
ASSERT_EQ(g3.size(), 0u);
|
||||
|
||||
for(auto i = 0u; i < 5u; ++i) {
|
||||
registry.erase<double>(entities[i * 2]);
|
||||
}
|
||||
|
||||
ASSERT_EQ(g1.size(), 10u);
|
||||
ASSERT_EQ(g2.size(), 10u);
|
||||
ASSERT_EQ(g3.size(), 5u);
|
||||
|
||||
for(auto i = 0u; i < 5u; ++i) {
|
||||
ASSERT_TRUE(g1.contains(entities[i * 2 + 1]));
|
||||
ASSERT_TRUE(g1.contains(entities[i * 2]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2 + 1]));
|
||||
ASSERT_TRUE(g2.contains(entities[i * 2]));
|
||||
ASSERT_FALSE(g3.contains(entities[i * 2 + 1]));
|
||||
ASSERT_TRUE(g3.contains(entities[i * 2]));
|
||||
registry.erase<int>(entities[i * 2 + 1]);
|
||||
registry.erase<int>(entities[i * 2]);
|
||||
}
|
||||
|
||||
ASSERT_EQ(g1.size(), 0u);
|
||||
ASSERT_EQ(g2.size(), 0u);
|
||||
ASSERT_EQ(g3.size(), 0u);
|
||||
registry.group<char>(entt::get<int>, entt::exclude<double>);
|
||||
ASSERT_DEATH(registry.group<char>(entt::get<float>, entt::exclude<double>), "");
|
||||
}
|
||||
|
||||
TEST(Registry, SortSingle) {
|
||||
@ -1379,10 +1382,10 @@ TEST(Registry, Signals) {
|
||||
entt::entity entities[2u];
|
||||
listener listener;
|
||||
|
||||
registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
|
||||
registry.on_destroy<empty_type>().connect<&listener::decr<empty_type>>(listener);
|
||||
registry.on_construct<int>().connect<&listener::incr<int>>(listener);
|
||||
registry.on_destroy<int>().connect<&listener::decr<int>>(listener);
|
||||
registry.on_construct<empty_type>().connect<&listener::incr>(listener);
|
||||
registry.on_destroy<empty_type>().connect<&listener::decr>(listener);
|
||||
registry.on_construct<int>().connect<&listener::incr>(listener);
|
||||
registry.on_destroy<int>().connect<&listener::decr>(listener);
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
registry.insert<empty_type>(std::begin(entities), std::end(entities));
|
||||
@ -1400,16 +1403,16 @@ TEST(Registry, Signals) {
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_EQ(listener.last, entities[0u]);
|
||||
|
||||
registry.on_destroy<empty_type>().disconnect<&listener::decr<empty_type>>(listener);
|
||||
registry.on_destroy<int>().disconnect<&listener::decr<int>>(listener);
|
||||
registry.on_destroy<empty_type>().disconnect<&listener::decr>(listener);
|
||||
registry.on_destroy<int>().disconnect<&listener::decr>(listener);
|
||||
|
||||
registry.erase<empty_type, int>(entities[1u]);
|
||||
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_EQ(listener.last, entities[0u]);
|
||||
|
||||
registry.on_construct<empty_type>().disconnect<&listener::incr<empty_type>>(listener);
|
||||
registry.on_construct<int>().disconnect<&listener::incr<int>>(listener);
|
||||
registry.on_construct<empty_type>().disconnect<&listener::incr>(listener);
|
||||
registry.on_construct<int>().disconnect<&listener::incr>(listener);
|
||||
|
||||
registry.emplace<empty_type>(entities[1u]);
|
||||
registry.emplace<int>(entities[1u]);
|
||||
@ -1417,8 +1420,8 @@ TEST(Registry, Signals) {
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_EQ(listener.last, entities[0u]);
|
||||
|
||||
registry.on_construct<int>().connect<&listener::incr<int>>(listener);
|
||||
registry.on_destroy<int>().connect<&listener::decr<int>>(listener);
|
||||
registry.on_construct<int>().connect<&listener::incr>(listener);
|
||||
registry.on_destroy<int>().connect<&listener::decr>(listener);
|
||||
|
||||
registry.emplace<int>(entities[0u]);
|
||||
registry.erase<int>(entities[1u]);
|
||||
@ -1426,8 +1429,8 @@ TEST(Registry, Signals) {
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_EQ(listener.last, entities[1u]);
|
||||
|
||||
registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
|
||||
registry.on_destroy<empty_type>().connect<&listener::decr<empty_type>>(listener);
|
||||
registry.on_construct<empty_type>().connect<&listener::incr>(listener);
|
||||
registry.on_destroy<empty_type>().connect<&listener::decr>(listener);
|
||||
|
||||
registry.erase<empty_type>(entities[1u]);
|
||||
registry.emplace<empty_type>(entities[0u]);
|
||||
@ -1454,8 +1457,8 @@ TEST(Registry, Signals) {
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_EQ(listener.last, entities[0u]);
|
||||
|
||||
registry.on_destroy<empty_type>().disconnect<&listener::decr<empty_type>>(listener);
|
||||
registry.on_destroy<int>().disconnect<&listener::decr<int>>(listener);
|
||||
registry.on_destroy<empty_type>().disconnect<&listener::decr>(listener);
|
||||
registry.on_destroy<int>().disconnect<&listener::decr>(listener);
|
||||
|
||||
registry.emplace_or_replace<empty_type>(entities[0u]);
|
||||
registry.emplace_or_replace<int>(entities[0u]);
|
||||
@ -1463,8 +1466,8 @@ TEST(Registry, Signals) {
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_EQ(listener.last, entities[0u]);
|
||||
|
||||
registry.on_update<empty_type>().connect<&listener::incr<empty_type>>(listener);
|
||||
registry.on_update<int>().connect<&listener::incr<int>>(listener);
|
||||
registry.on_update<empty_type>().connect<&listener::incr>(listener);
|
||||
registry.on_update<int>().connect<&listener::incr>(listener);
|
||||
|
||||
registry.emplace_or_replace<empty_type>(entities[0u]);
|
||||
registry.emplace_or_replace<int>(entities[0u]);
|
||||
@ -1479,6 +1482,84 @@ TEST(Registry, Signals) {
|
||||
ASSERT_EQ(listener.last, entities[0u]);
|
||||
}
|
||||
|
||||
TEST(Registry, SignalsOnRuntimePool) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
listener listener;
|
||||
|
||||
registry.on_construct<int>("custom"_hs).connect<&listener::incr>(listener);
|
||||
registry.on_update<int>("custom"_hs).connect<&listener::incr>(listener);
|
||||
registry.on_destroy<int>("custom"_hs).connect<&listener::incr>(listener);
|
||||
|
||||
ASSERT_EQ(listener.counter, 0);
|
||||
|
||||
registry.emplace<int>(entity);
|
||||
registry.patch<int>(entity);
|
||||
registry.erase<int>(entity);
|
||||
|
||||
ASSERT_EQ(listener.counter, 0);
|
||||
|
||||
registry.storage<int>("custom"_hs).emplace(entity);
|
||||
registry.storage<int>("custom"_hs).patch(entity);
|
||||
registry.storage<int>("custom"_hs).erase(entity);
|
||||
|
||||
ASSERT_EQ(listener.counter, 3);
|
||||
}
|
||||
|
||||
TEST(Registry, SignalsOnEntity) {
|
||||
entt::registry registry;
|
||||
listener listener;
|
||||
|
||||
registry.on_construct<entt::entity>().connect<&listener::incr>(listener);
|
||||
|
||||
entt::entity entity = registry.create();
|
||||
entt::entity other = registry.create();
|
||||
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_EQ(listener.last, other);
|
||||
|
||||
registry.destroy(other);
|
||||
registry.destroy(entity);
|
||||
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_EQ(listener.last, other);
|
||||
|
||||
registry.on_construct<entt::entity>().disconnect(&listener);
|
||||
|
||||
other = registry.create();
|
||||
entity = registry.create();
|
||||
|
||||
ASSERT_EQ(listener.counter, 2);
|
||||
ASSERT_NE(listener.last, entity);
|
||||
ASSERT_NE(listener.last, other);
|
||||
|
||||
registry.on_update<entt::entity>().connect<&listener::decr>(listener);
|
||||
registry.patch<entt::entity>(entity);
|
||||
|
||||
ASSERT_EQ(listener.counter, 1);
|
||||
ASSERT_EQ(listener.last, entity);
|
||||
|
||||
registry.on_update<entt::entity>().disconnect(&listener);
|
||||
registry.patch<entt::entity>(other);
|
||||
|
||||
ASSERT_EQ(listener.counter, 1);
|
||||
ASSERT_NE(listener.last, other);
|
||||
|
||||
registry.on_destroy<entt::entity>().connect<&listener::decr>(listener);
|
||||
registry.destroy(entity);
|
||||
|
||||
ASSERT_EQ(listener.counter, 0);
|
||||
ASSERT_EQ(listener.last, entity);
|
||||
|
||||
registry.on_destroy<entt::entity>().disconnect(&listener);
|
||||
registry.destroy(other);
|
||||
|
||||
ASSERT_EQ(listener.counter, 0);
|
||||
ASSERT_NE(listener.last, other);
|
||||
}
|
||||
|
||||
TEST(Registry, SignalWhenDestroying) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
@ -1576,6 +1657,17 @@ TEST(Registry, Erase) {
|
||||
ASSERT_EQ(registry.storage<char>().size(), 0u);
|
||||
ASSERT_EQ(registry.storage<double>().size(), 1u);
|
||||
|
||||
registry.insert<int>(std::begin(entities) + 1, std::end(entities) - 1u);
|
||||
registry.insert<char>(std::begin(entities) + 1, std::end(entities) - 1u);
|
||||
|
||||
ASSERT_EQ(registry.storage<int>().size(), 1u);
|
||||
ASSERT_EQ(registry.storage<char>().size(), 1u);
|
||||
|
||||
registry.erase<int, char>(iview.begin(), iview.end());
|
||||
|
||||
ASSERT_EQ(registry.storage<int>().size(), 0u);
|
||||
ASSERT_EQ(registry.storage<char>().size(), 0u);
|
||||
|
||||
registry.insert<int>(std::begin(entities), std::end(entities));
|
||||
registry.insert<char>(std::begin(entities), std::end(entities));
|
||||
|
||||
@ -1643,6 +1735,39 @@ TEST(Registry, StableErase) {
|
||||
ASSERT_EQ(registry.storage<double>().size(), 1u);
|
||||
}
|
||||
|
||||
TEST(Registry, EraseIf) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
|
||||
registry.emplace<int>(entity);
|
||||
registry.storage<int>("other"_hs).emplace(entity);
|
||||
registry.emplace<char>(entity);
|
||||
|
||||
ASSERT_TRUE(registry.storage<int>().contains(entity));
|
||||
ASSERT_TRUE(registry.storage<int>("other"_hs).contains(entity));
|
||||
ASSERT_TRUE(registry.storage<char>().contains(entity));
|
||||
|
||||
registry.erase_if(entity, [](auto &&...) { return false; });
|
||||
|
||||
ASSERT_TRUE(registry.storage<int>().contains(entity));
|
||||
ASSERT_TRUE(registry.storage<int>("other"_hs).contains(entity));
|
||||
ASSERT_TRUE(registry.storage<char>().contains(entity));
|
||||
|
||||
registry.erase_if(entity, [](entt::id_type id, auto &&...) { return id == "other"_hs; });
|
||||
|
||||
ASSERT_TRUE(registry.storage<int>().contains(entity));
|
||||
ASSERT_FALSE(registry.storage<int>("other"_hs).contains(entity));
|
||||
ASSERT_TRUE(registry.storage<char>().contains(entity));
|
||||
|
||||
registry.erase_if(entity, [](auto, const auto &storage) { return storage.type() == entt::type_id<char>(); });
|
||||
|
||||
ASSERT_TRUE(registry.storage<int>().contains(entity));
|
||||
ASSERT_FALSE(registry.storage<int>("other"_hs).contains(entity));
|
||||
ASSERT_FALSE(registry.storage<char>().contains(entity));
|
||||
}
|
||||
|
||||
TEST(Registry, Remove) {
|
||||
entt::registry registry;
|
||||
const auto iview = registry.view<int>();
|
||||
@ -1689,6 +1814,18 @@ TEST(Registry, Remove) {
|
||||
ASSERT_EQ(registry.storage<char>().size(), 0u);
|
||||
ASSERT_EQ(registry.storage<double>().size(), 1u);
|
||||
|
||||
registry.insert<int>(std::begin(entities) + 1, std::end(entities) - 1u);
|
||||
registry.insert<char>(std::begin(entities) + 1, std::end(entities) - 1u);
|
||||
|
||||
ASSERT_EQ(registry.storage<int>().size(), 1u);
|
||||
ASSERT_EQ(registry.storage<char>().size(), 1u);
|
||||
|
||||
registry.remove<int, char>(iview.begin(), iview.end());
|
||||
registry.remove<int, char>(iview.begin(), iview.end());
|
||||
|
||||
ASSERT_EQ(registry.storage<int>().size(), 0u);
|
||||
ASSERT_EQ(registry.storage<char>().size(), 0u);
|
||||
|
||||
registry.insert<int>(std::begin(entities), std::end(entities));
|
||||
registry.insert<char>(std::begin(entities), std::end(entities));
|
||||
|
||||
@ -1791,7 +1928,7 @@ TEST(Registry, NonOwningGroupInterleaved) {
|
||||
registry.emplace<int>(entity);
|
||||
registry.emplace<char>(entity);
|
||||
|
||||
const auto group = registry.group<>(entt::get<int, char>);
|
||||
const auto group = registry.group(entt::get<int, char>);
|
||||
|
||||
entity = registry.create();
|
||||
registry.emplace<int>(entity);
|
||||
@ -1845,7 +1982,7 @@ TEST(Registry, PartialOwningGroupInterleaved) {
|
||||
|
||||
TEST(Registry, NonOwningGroupSortInterleaved) {
|
||||
entt::registry registry;
|
||||
const auto group = registry.group<>(entt::get<int, char>);
|
||||
const auto group = registry.group(entt::get<int, char>);
|
||||
|
||||
const auto e0 = registry.create();
|
||||
registry.emplace<int>(e0, 0);
|
||||
@ -2009,7 +2146,7 @@ TEST(Registry, ScramblingPoolsIsAllowed) {
|
||||
|
||||
// thanks to @andranik3949 for pointing out this missing test
|
||||
registry.view<const int>().each([](const auto entity, const auto &value) {
|
||||
ASSERT_EQ(entt::to_integral(entity), value);
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entity)), value);
|
||||
});
|
||||
}
|
||||
|
||||
@ -2021,7 +2158,7 @@ TEST(Registry, RuntimePools) {
|
||||
const auto entity = registry.create();
|
||||
|
||||
static_assert(std::is_same_v<decltype(registry.storage<empty_type>()), entt::storage_type_t<empty_type> &>);
|
||||
static_assert(std::is_same_v<decltype(std::as_const(registry).storage<empty_type>()), const entt::storage_type_t<empty_type> &>);
|
||||
static_assert(std::is_same_v<decltype(std::as_const(registry).storage<empty_type>()), const entt::storage_type_t<empty_type> *>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(registry.storage("other"_hs)), entt::storage_type_t<empty_type>::base_type *>);
|
||||
static_assert(std::is_same_v<decltype(std::as_const(registry).storage("other"_hs)), const entt::storage_type_t<empty_type>::base_type *>);
|
||||
@ -2030,7 +2167,7 @@ TEST(Registry, RuntimePools) {
|
||||
ASSERT_EQ(std::as_const(registry).storage("rehto"_hs), nullptr);
|
||||
|
||||
ASSERT_EQ(®istry.storage<empty_type>("other"_hs), &storage);
|
||||
ASSERT_NE(&std::as_const(registry).storage<empty_type>(), &storage);
|
||||
ASSERT_NE(std::as_const(registry).storage<empty_type>(), &storage);
|
||||
|
||||
ASSERT_FALSE(registry.any_of<empty_type>(entity));
|
||||
ASSERT_FALSE(storage.contains(entity));
|
||||
@ -2070,6 +2207,7 @@ TEST(Registry, Storage) {
|
||||
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
|
||||
auto &storage = registry.storage<int>("int"_hs);
|
||||
storage.emplace(entity);
|
||||
|
||||
@ -2149,8 +2287,7 @@ TEST(Registry, RegistryStorageIterator) {
|
||||
|
||||
TEST(Registry, RegistryStorageIteratorConversion) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
registry.emplace<int>(entity);
|
||||
registry.storage<int>();
|
||||
|
||||
auto proxy = registry.storage();
|
||||
auto cproxy = std::as_const(registry).storage();
|
||||
@ -2176,6 +2313,22 @@ TEST(Registry, RegistryStorageIteratorConversion) {
|
||||
ASSERT_NE(++cit, it);
|
||||
}
|
||||
|
||||
TEST(Registry, VoidType) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
auto &storage = registry.storage<void>("custom"_hs);
|
||||
storage.emplace(entity);
|
||||
|
||||
ASSERT_TRUE(registry.storage<void>().empty());
|
||||
ASSERT_FALSE(registry.storage<void>("custom"_hs).empty());
|
||||
ASSERT_TRUE(registry.storage<void>("custom"_hs).contains(entity));
|
||||
|
||||
ASSERT_EQ(registry.storage<void>().type(), entt::type_id<void>());
|
||||
ASSERT_EQ(registry.storage<void>("custom"_hs).type(), entt::type_id<void>());
|
||||
}
|
||||
|
||||
TEST(Registry, NoEtoType) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <iterator>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/entity/mixin.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include <entt/entity/storage.hpp>
|
||||
#include "../common/throwing_allocator.hpp"
|
||||
@ -30,9 +31,20 @@ void listener(counter &counter, Registry &, typename Registry::entity_type) {
|
||||
++counter.value;
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, GenericType) {
|
||||
struct empty_each_tag final {};
|
||||
|
||||
template<>
|
||||
struct entt::basic_storage<empty_each_tag, entt::entity, std::allocator<empty_each_tag>>: entt::basic_storage<void, entt::entity, std::allocator<void>> {
|
||||
basic_storage(const std::allocator<empty_each_tag> &) {}
|
||||
|
||||
[[nodiscard]] iterable each() noexcept {
|
||||
return {internal::extended_storage_iterator{base_type::end()}, internal::extended_storage_iterator{base_type::end()}};
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SighMixin, GenericType) {
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
entt::sigh_storage_mixin<entt::storage<int>> pool;
|
||||
entt::sigh_mixin<entt::storage<int>> pool;
|
||||
entt::sparse_set &base = pool;
|
||||
entt::registry registry;
|
||||
|
||||
@ -40,10 +52,21 @@ TEST(SighStorageMixin, GenericType) {
|
||||
counter on_destroy{};
|
||||
|
||||
pool.bind(entt::forward_as_any(registry));
|
||||
|
||||
ASSERT_TRUE(pool.empty());
|
||||
|
||||
pool.insert(entities, entities + 1u);
|
||||
pool.erase(entities[0u]);
|
||||
|
||||
ASSERT_TRUE(pool.empty());
|
||||
|
||||
ASSERT_EQ(on_construct.value, 0);
|
||||
ASSERT_EQ(on_destroy.value, 0);
|
||||
|
||||
pool.on_construct().connect<&listener<entt::registry>>(on_construct);
|
||||
pool.on_destroy().connect<&listener<entt::registry>>(on_destroy);
|
||||
|
||||
ASSERT_NE(base.emplace(entities[0u]), base.end());
|
||||
ASSERT_NE(base.push(entities[0u]), base.end());
|
||||
|
||||
pool.emplace(entities[1u]);
|
||||
|
||||
@ -61,7 +84,7 @@ TEST(SighStorageMixin, GenericType) {
|
||||
ASSERT_EQ(on_destroy.value, 2);
|
||||
ASSERT_TRUE(pool.empty());
|
||||
|
||||
ASSERT_NE(base.insert(std::begin(entities), std::end(entities)), base.end());
|
||||
ASSERT_NE(base.push(std::begin(entities), std::end(entities)), base.end());
|
||||
|
||||
ASSERT_EQ(pool.get(entities[0u]), 0);
|
||||
ASSERT_EQ(pool.get(entities[1u]), 0);
|
||||
@ -95,9 +118,9 @@ TEST(SighStorageMixin, GenericType) {
|
||||
ASSERT_TRUE(pool.empty());
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, StableType) {
|
||||
TEST(SighMixin, StableType) {
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
entt::sigh_storage_mixin<entt::storage<stable_type>> pool;
|
||||
entt::sigh_mixin<entt::storage<stable_type>> pool;
|
||||
entt::sparse_set &base = pool;
|
||||
entt::registry registry;
|
||||
|
||||
@ -108,7 +131,7 @@ TEST(SighStorageMixin, StableType) {
|
||||
pool.on_construct().connect<&listener<entt::registry>>(on_construct);
|
||||
pool.on_destroy().connect<&listener<entt::registry>>(on_destroy);
|
||||
|
||||
ASSERT_NE(base.emplace(entities[0u]), base.end());
|
||||
ASSERT_NE(base.push(entities[0u]), base.end());
|
||||
|
||||
pool.emplace(entities[1u]);
|
||||
|
||||
@ -126,7 +149,7 @@ TEST(SighStorageMixin, StableType) {
|
||||
ASSERT_EQ(on_destroy.value, 2);
|
||||
ASSERT_FALSE(pool.empty());
|
||||
|
||||
ASSERT_NE(base.insert(std::begin(entities), std::end(entities)), base.end());
|
||||
ASSERT_NE(base.push(std::begin(entities), std::end(entities)), base.end());
|
||||
|
||||
ASSERT_EQ(pool.get(entities[0u]).value, 0);
|
||||
ASSERT_EQ(pool.get(entities[1u]).value, 0);
|
||||
@ -160,9 +183,9 @@ TEST(SighStorageMixin, StableType) {
|
||||
ASSERT_FALSE(pool.empty());
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, EmptyType) {
|
||||
TEST(SighMixin, EmptyType) {
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
entt::sigh_storage_mixin<entt::storage<empty_type>> pool;
|
||||
entt::sigh_mixin<entt::storage<empty_type>> pool;
|
||||
entt::sparse_set &base = pool;
|
||||
entt::registry registry;
|
||||
|
||||
@ -173,7 +196,7 @@ TEST(SighStorageMixin, EmptyType) {
|
||||
pool.on_construct().connect<&listener<entt::registry>>(on_construct);
|
||||
pool.on_destroy().connect<&listener<entt::registry>>(on_destroy);
|
||||
|
||||
ASSERT_NE(base.emplace(entities[0u]), base.end());
|
||||
ASSERT_NE(base.push(entities[0u]), base.end());
|
||||
|
||||
pool.emplace(entities[1u]);
|
||||
|
||||
@ -191,7 +214,7 @@ TEST(SighStorageMixin, EmptyType) {
|
||||
ASSERT_EQ(on_destroy.value, 2);
|
||||
ASSERT_TRUE(pool.empty());
|
||||
|
||||
ASSERT_NE(base.insert(std::begin(entities), std::end(entities)), base.end());
|
||||
ASSERT_NE(base.push(std::begin(entities), std::end(entities)), base.end());
|
||||
|
||||
ASSERT_TRUE(pool.contains(entities[0u]));
|
||||
ASSERT_TRUE(pool.contains(entities[1u]));
|
||||
@ -225,9 +248,9 @@ TEST(SighStorageMixin, EmptyType) {
|
||||
ASSERT_TRUE(pool.empty());
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, NonDefaultConstructibleType) {
|
||||
TEST(SighMixin, NonDefaultConstructibleType) {
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
entt::sigh_storage_mixin<entt::storage<non_default_constructible>> pool;
|
||||
entt::sigh_mixin<entt::storage<non_default_constructible>> pool;
|
||||
entt::sparse_set &base = pool;
|
||||
entt::registry registry;
|
||||
|
||||
@ -238,12 +261,12 @@ TEST(SighStorageMixin, NonDefaultConstructibleType) {
|
||||
pool.on_construct().connect<&listener<entt::registry>>(on_construct);
|
||||
pool.on_destroy().connect<&listener<entt::registry>>(on_destroy);
|
||||
|
||||
ASSERT_EQ(base.emplace(entities[0u]), base.end());
|
||||
ASSERT_EQ(base.push(entities[0u]), base.end());
|
||||
|
||||
pool.emplace(entities[1u], 3);
|
||||
|
||||
ASSERT_EQ(pool.size(), 1u);
|
||||
ASSERT_EQ(on_construct.value, 2);
|
||||
ASSERT_EQ(on_construct.value, 1);
|
||||
ASSERT_EQ(on_destroy.value, 0);
|
||||
ASSERT_FALSE(pool.empty());
|
||||
|
||||
@ -253,11 +276,11 @@ TEST(SighStorageMixin, NonDefaultConstructibleType) {
|
||||
base.erase(entities[1u]);
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(on_construct.value, 2);
|
||||
ASSERT_EQ(on_construct.value, 1);
|
||||
ASSERT_EQ(on_destroy.value, 1);
|
||||
ASSERT_TRUE(pool.empty());
|
||||
|
||||
ASSERT_EQ(base.insert(std::begin(entities), std::end(entities)), base.end());
|
||||
ASSERT_EQ(base.push(std::begin(entities), std::end(entities)), base.end());
|
||||
|
||||
ASSERT_FALSE(pool.contains(entities[0u]));
|
||||
ASSERT_FALSE(pool.contains(entities[1u]));
|
||||
@ -266,7 +289,7 @@ TEST(SighStorageMixin, NonDefaultConstructibleType) {
|
||||
pool.insert(std::begin(entities), std::end(entities), 3);
|
||||
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(on_construct.value, 6);
|
||||
ASSERT_EQ(on_construct.value, 3);
|
||||
ASSERT_EQ(on_destroy.value, 1);
|
||||
ASSERT_FALSE(pool.empty());
|
||||
|
||||
@ -276,13 +299,13 @@ TEST(SighStorageMixin, NonDefaultConstructibleType) {
|
||||
pool.erase(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(on_construct.value, 6);
|
||||
ASSERT_EQ(on_construct.value, 3);
|
||||
ASSERT_EQ(on_destroy.value, 3);
|
||||
ASSERT_TRUE(pool.empty());
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, VoidType) {
|
||||
entt::sigh_storage_mixin<entt::storage<void>> pool;
|
||||
TEST(SighMixin, VoidType) {
|
||||
entt::sigh_mixin<entt::storage<void>> pool;
|
||||
entt::registry registry;
|
||||
|
||||
counter on_construct{};
|
||||
@ -297,7 +320,7 @@ TEST(SighStorageMixin, VoidType) {
|
||||
ASSERT_EQ(pool.type(), entt::type_id<void>());
|
||||
ASSERT_TRUE(pool.contains(entt::entity{99}));
|
||||
|
||||
entt::sigh_storage_mixin<entt::storage<void>> other{std::move(pool)};
|
||||
entt::sigh_mixin<entt::storage<void>> other{std::move(pool)};
|
||||
|
||||
ASSERT_FALSE(pool.contains(entt::entity{99}));
|
||||
ASSERT_TRUE(other.contains(entt::entity{99}));
|
||||
@ -313,8 +336,8 @@ TEST(SighStorageMixin, VoidType) {
|
||||
ASSERT_EQ(on_destroy.value, 1);
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, Move) {
|
||||
entt::sigh_storage_mixin<entt::storage<int>> pool;
|
||||
TEST(SighMixin, Move) {
|
||||
entt::sigh_mixin<entt::storage<int>> pool;
|
||||
entt::registry registry;
|
||||
|
||||
counter on_construct{};
|
||||
@ -330,7 +353,7 @@ TEST(SighStorageMixin, Move) {
|
||||
ASSERT_TRUE(std::is_move_assignable_v<decltype(pool)>);
|
||||
ASSERT_EQ(pool.type(), entt::type_id<int>());
|
||||
|
||||
entt::sigh_storage_mixin<entt::storage<int>> other{std::move(pool)};
|
||||
entt::sigh_mixin<entt::storage<int>> other{std::move(pool)};
|
||||
|
||||
ASSERT_TRUE(pool.empty());
|
||||
ASSERT_FALSE(other.empty());
|
||||
@ -347,7 +370,7 @@ TEST(SighStorageMixin, Move) {
|
||||
ASSERT_EQ(pool.get(entt::entity{3}), 3);
|
||||
ASSERT_EQ(other.at(0u), static_cast<entt::entity>(entt::null));
|
||||
|
||||
other = entt::sigh_storage_mixin<entt::storage<int>>{};
|
||||
other = entt::sigh_mixin<entt::storage<int>>{};
|
||||
other.bind(entt::forward_as_any(registry));
|
||||
|
||||
other.emplace(entt::entity{42}, 42);
|
||||
@ -365,9 +388,9 @@ TEST(SighStorageMixin, Move) {
|
||||
ASSERT_EQ(on_destroy.value, 1);
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, Swap) {
|
||||
entt::sigh_storage_mixin<entt::storage<int>> pool;
|
||||
entt::sigh_storage_mixin<entt::storage<int>> other;
|
||||
TEST(SighMixin, Swap) {
|
||||
entt::sigh_mixin<entt::storage<int>> pool;
|
||||
entt::sigh_mixin<entt::storage<int>> other;
|
||||
entt::registry registry;
|
||||
|
||||
counter on_construct{};
|
||||
@ -411,7 +434,100 @@ TEST(SighStorageMixin, Swap) {
|
||||
ASSERT_EQ(on_destroy.value, 3);
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, CustomAllocator) {
|
||||
TEST(SighMixin, EmptyEachStorage) {
|
||||
entt::sigh_mixin<entt::storage<empty_each_tag>> pool;
|
||||
entt::registry registry;
|
||||
|
||||
counter on_destroy{};
|
||||
|
||||
pool.bind(entt::forward_as_any(registry));
|
||||
pool.on_destroy().connect<&listener<entt::registry>>(on_destroy);
|
||||
|
||||
ASSERT_TRUE(pool.empty());
|
||||
ASSERT_EQ(on_destroy.value, 0);
|
||||
|
||||
pool.push(entt::entity{42});
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_EQ(on_destroy.value, 0);
|
||||
|
||||
ASSERT_NE(pool.begin(), pool.end());
|
||||
ASSERT_EQ(pool.each().begin(), pool.each().end());
|
||||
ASSERT_EQ(on_destroy.value, 0);
|
||||
|
||||
pool.clear();
|
||||
|
||||
ASSERT_EQ(pool.begin(), pool.end());
|
||||
ASSERT_EQ(pool.each().begin(), pool.each().end());
|
||||
// no signal at all because of the (fake) empty iterable
|
||||
ASSERT_EQ(on_destroy.value, 0);
|
||||
}
|
||||
|
||||
TEST(SighMixin, StorageEntity) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::sigh_mixin<entt::storage<entt::entity>> pool;
|
||||
entt::registry registry;
|
||||
|
||||
counter on_construct{};
|
||||
counter on_destroy{};
|
||||
|
||||
pool.bind(entt::forward_as_any(registry));
|
||||
pool.on_construct().connect<&listener<entt::registry>>(on_construct);
|
||||
pool.on_destroy().connect<&listener<entt::registry>>(on_destroy);
|
||||
|
||||
pool.push(entt::entity{1});
|
||||
|
||||
ASSERT_EQ(on_construct.value, 1);
|
||||
ASSERT_EQ(on_destroy.value, 0);
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 1u);
|
||||
|
||||
pool.erase(entt::entity{1});
|
||||
|
||||
ASSERT_EQ(on_construct.value, 1);
|
||||
ASSERT_EQ(on_destroy.value, 1);
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
|
||||
pool.push(traits_type::construct(0, 2));
|
||||
pool.push(traits_type::construct(2, 1));
|
||||
|
||||
ASSERT_TRUE(pool.contains(traits_type::construct(0, 2)));
|
||||
ASSERT_TRUE(pool.contains(traits_type::construct(1, 1)));
|
||||
ASSERT_TRUE(pool.contains(traits_type::construct(2, 1)));
|
||||
|
||||
ASSERT_EQ(on_construct.value, 3);
|
||||
ASSERT_EQ(on_destroy.value, 1);
|
||||
ASSERT_EQ(pool.size(), 3u);
|
||||
ASSERT_EQ(pool.in_use(), 2u);
|
||||
|
||||
pool.clear();
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
|
||||
ASSERT_EQ(on_construct.value, 3);
|
||||
ASSERT_EQ(on_destroy.value, 3);
|
||||
|
||||
pool.emplace();
|
||||
pool.emplace(entt::entity{0});
|
||||
|
||||
entt::entity entities[1u]{};
|
||||
pool.insert(entities, entities + 1u);
|
||||
|
||||
ASSERT_EQ(on_construct.value, 6);
|
||||
ASSERT_EQ(on_destroy.value, 3);
|
||||
ASSERT_EQ(pool.size(), 3u);
|
||||
ASSERT_EQ(pool.in_use(), 3u);
|
||||
|
||||
pool.clear();
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
}
|
||||
|
||||
TEST(SighMixin, CustomAllocator) {
|
||||
auto test = [](auto pool, auto alloc) {
|
||||
using registry_type = typename decltype(pool)::registry_type;
|
||||
registry_type registry;
|
||||
@ -466,12 +582,12 @@ TEST(SighStorageMixin, CustomAllocator) {
|
||||
|
||||
test::throwing_allocator<entt::entity> allocator{};
|
||||
|
||||
test(entt::sigh_storage_mixin<entt::basic_storage<int, entt::entity, test::throwing_allocator<int>>>{allocator}, allocator);
|
||||
test(entt::sigh_storage_mixin<entt::basic_storage<std::true_type, entt::entity, test::throwing_allocator<std::true_type>>>{allocator}, allocator);
|
||||
test(entt::sigh_storage_mixin<entt::basic_storage<stable_type, entt::entity, test::throwing_allocator<stable_type>>>{allocator}, allocator);
|
||||
test(entt::sigh_mixin<entt::basic_storage<int, entt::entity, test::throwing_allocator<int>>>{allocator}, allocator);
|
||||
test(entt::sigh_mixin<entt::basic_storage<std::true_type, entt::entity, test::throwing_allocator<std::true_type>>>{allocator}, allocator);
|
||||
test(entt::sigh_mixin<entt::basic_storage<stable_type, entt::entity, test::throwing_allocator<stable_type>>>{allocator}, allocator);
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, ThrowingAllocator) {
|
||||
TEST(SighMixin, ThrowingAllocator) {
|
||||
auto test = [](auto pool) {
|
||||
using pool_allocator_type = typename decltype(pool)::allocator_type;
|
||||
using value_type = typename decltype(pool)::value_type;
|
||||
@ -511,7 +627,7 @@ TEST(SighStorageMixin, ThrowingAllocator) {
|
||||
|
||||
test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
|
||||
|
||||
ASSERT_THROW(base.emplace(entt::entity{0}), test::throwing_allocator<entt::entity>::exception_type);
|
||||
ASSERT_THROW(base.push(entt::entity{0}), test::throwing_allocator<entt::entity>::exception_type);
|
||||
ASSERT_FALSE(base.contains(entt::entity{0}));
|
||||
ASSERT_TRUE(base.empty());
|
||||
|
||||
@ -543,12 +659,12 @@ TEST(SighStorageMixin, ThrowingAllocator) {
|
||||
ASSERT_EQ(on_destroy.value, 1);
|
||||
};
|
||||
|
||||
test(entt::sigh_storage_mixin<entt::basic_storage<int, entt::entity, test::throwing_allocator<int>>>{});
|
||||
test(entt::sigh_storage_mixin<entt::basic_storage<stable_type, entt::entity, test::throwing_allocator<stable_type>>>{});
|
||||
test(entt::sigh_mixin<entt::basic_storage<int, entt::entity, test::throwing_allocator<int>>>{});
|
||||
test(entt::sigh_mixin<entt::basic_storage<stable_type, entt::entity, test::throwing_allocator<stable_type>>>{});
|
||||
}
|
||||
|
||||
TEST(SighStorageMixin, ThrowingComponent) {
|
||||
entt::sigh_storage_mixin<entt::storage<test::throwing_type>> pool;
|
||||
TEST(SighMixin, ThrowingComponent) {
|
||||
entt::sigh_mixin<entt::storage<test::throwing_type>> pool;
|
||||
using registry_type = typename decltype(pool)::registry_type;
|
||||
registry_type registry;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,6 +26,7 @@ TEST(SparseSet, Functionalities) {
|
||||
ASSERT_EQ(set.capacity(), 42u);
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
ASSERT_TRUE(set.contiguous());
|
||||
ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
|
||||
ASSERT_EQ(set.begin(), set.end());
|
||||
ASSERT_FALSE(set.contains(entt::entity{0}));
|
||||
@ -36,10 +37,11 @@ TEST(SparseSet, Functionalities) {
|
||||
ASSERT_EQ(set.capacity(), 42u);
|
||||
ASSERT_TRUE(set.empty());
|
||||
|
||||
set.emplace(entt::entity{42});
|
||||
set.push(entt::entity{42});
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(set.size(), 1u);
|
||||
ASSERT_TRUE(set.contiguous());
|
||||
ASSERT_NE(std::as_const(set).begin(), std::as_const(set).end());
|
||||
ASSERT_NE(set.begin(), set.end());
|
||||
ASSERT_FALSE(set.contains(entt::entity{0}));
|
||||
@ -48,12 +50,13 @@ TEST(SparseSet, Functionalities) {
|
||||
ASSERT_EQ(set.at(0u), entt::entity{42});
|
||||
ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
|
||||
ASSERT_EQ(set[0u], entt::entity{42});
|
||||
ASSERT_EQ(set.get(entt::entity{42}), nullptr);
|
||||
ASSERT_EQ(set.value(entt::entity{42}), nullptr);
|
||||
|
||||
set.erase(entt::entity{42});
|
||||
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
ASSERT_TRUE(set.contiguous());
|
||||
ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
|
||||
ASSERT_EQ(set.begin(), set.end());
|
||||
ASSERT_FALSE(set.contains(entt::entity{0}));
|
||||
@ -61,7 +64,7 @@ TEST(SparseSet, Functionalities) {
|
||||
ASSERT_EQ(set.at(0u), static_cast<entt::entity>(entt::null));
|
||||
ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
|
||||
|
||||
set.emplace(entt::entity{42});
|
||||
set.push(entt::entity{42});
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(set.index(entt::entity{42}), 0u);
|
||||
@ -73,6 +76,7 @@ TEST(SparseSet, Functionalities) {
|
||||
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
ASSERT_TRUE(set.contiguous());
|
||||
ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
|
||||
ASSERT_EQ(set.begin(), set.end());
|
||||
ASSERT_FALSE(set.contains(entt::entity{0}));
|
||||
@ -86,11 +90,11 @@ TEST(SparseSet, Contains) {
|
||||
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
|
||||
set.emplace(entt::entity{0});
|
||||
set.emplace(entt::entity{3});
|
||||
set.emplace(entt::entity{42});
|
||||
set.emplace(entt::entity{99});
|
||||
set.emplace(traits_type::construct(1, 5));
|
||||
set.push(entt::entity{0});
|
||||
set.push(entt::entity{3});
|
||||
set.push(entt::entity{42});
|
||||
set.push(entt::entity{99});
|
||||
set.push(traits_type::construct(1, 5));
|
||||
|
||||
ASSERT_FALSE(set.contains(entt::null));
|
||||
ASSERT_FALSE(set.contains(entt::tombstone));
|
||||
@ -133,8 +137,8 @@ TEST(SparseSet, Current) {
|
||||
ASSERT_EQ(set.current(traits_type::construct(0, 0)), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_EQ(set.current(traits_type::construct(3, 3)), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.emplace(traits_type::construct(0, 0));
|
||||
set.emplace(traits_type::construct(3, 3));
|
||||
set.push(traits_type::construct(0, 0));
|
||||
set.push(traits_type::construct(3, 3));
|
||||
|
||||
ASSERT_NE(set.current(traits_type::construct(0, 0)), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_NE(set.current(traits_type::construct(3, 3)), traits_type::to_version(entt::tombstone));
|
||||
@ -153,8 +157,8 @@ TEST(SparseSet, Index) {
|
||||
|
||||
entt::sparse_set set{};
|
||||
|
||||
set.emplace(traits_type::construct(0, 0));
|
||||
set.emplace(traits_type::construct(3, 3));
|
||||
set.push(traits_type::construct(0, 0));
|
||||
set.push(traits_type::construct(3, 3));
|
||||
|
||||
ASSERT_EQ(set.index(traits_type::construct(0, 0)), 0u);
|
||||
ASSERT_EQ(set.index(traits_type::construct(3, 3)), 1u);
|
||||
@ -175,7 +179,7 @@ ENTT_DEBUG_TEST(SparseSetDeathTest, Index) {
|
||||
|
||||
TEST(SparseSet, Move) {
|
||||
entt::sparse_set set;
|
||||
set.emplace(entt::entity{42});
|
||||
set.push(entt::entity{42});
|
||||
|
||||
ASSERT_TRUE(std::is_move_constructible_v<decltype(set)>);
|
||||
ASSERT_TRUE(std::is_move_assignable_v<decltype(set)>);
|
||||
@ -195,7 +199,7 @@ TEST(SparseSet, Move) {
|
||||
ASSERT_EQ(other.at(0u), static_cast<entt::entity>(entt::null));
|
||||
|
||||
other = entt::sparse_set{};
|
||||
other.emplace(entt::entity{3});
|
||||
other.push(entt::entity{3});
|
||||
other = std::move(set);
|
||||
|
||||
ASSERT_TRUE(set.empty());
|
||||
@ -208,10 +212,10 @@ TEST(SparseSet, Swap) {
|
||||
entt::sparse_set set;
|
||||
entt::sparse_set other{entt::deletion_policy::in_place};
|
||||
|
||||
set.emplace(entt::entity{42});
|
||||
set.push(entt::entity{42});
|
||||
|
||||
other.emplace(entt::entity{9});
|
||||
other.emplace(entt::entity{3});
|
||||
other.push(entt::entity{9});
|
||||
other.push(entt::entity{3});
|
||||
other.erase(entt::entity{9});
|
||||
|
||||
ASSERT_EQ(set.size(), 1u);
|
||||
@ -233,12 +237,12 @@ TEST(SparseSet, Pagination) {
|
||||
|
||||
ASSERT_EQ(set.extent(), 0u);
|
||||
|
||||
set.emplace(entt::entity{traits_type::page_size - 1u});
|
||||
set.push(entt::entity{traits_type::page_size - 1u});
|
||||
|
||||
ASSERT_EQ(set.extent(), traits_type::page_size);
|
||||
ASSERT_TRUE(set.contains(entt::entity{traits_type::page_size - 1u}));
|
||||
|
||||
set.emplace(entt::entity{traits_type::page_size});
|
||||
set.push(entt::entity{traits_type::page_size});
|
||||
|
||||
ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
|
||||
ASSERT_TRUE(set.contains(entt::entity{traits_type::page_size - 1u}));
|
||||
@ -263,17 +267,17 @@ TEST(SparseSet, Pagination) {
|
||||
ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
|
||||
}
|
||||
|
||||
TEST(SparseSet, Emplace) {
|
||||
TEST(SparseSet, Push) {
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_NE(set.emplace(entities[0u]), set.end());
|
||||
ASSERT_NE(set.push(entities[0u]), set.end());
|
||||
|
||||
set.erase(entities[0u]);
|
||||
|
||||
ASSERT_NE(set.emplace(entities[1u]), set.end());
|
||||
ASSERT_NE(set.emplace(entities[0u]), set.end());
|
||||
ASSERT_NE(set.push(entities[1u]), set.end());
|
||||
ASSERT_NE(set.push(entities[0u]), set.end());
|
||||
|
||||
ASSERT_EQ(set.at(0u), entities[1u]);
|
||||
ASSERT_EQ(set.at(1u), entities[0u]);
|
||||
@ -282,8 +286,8 @@ TEST(SparseSet, Emplace) {
|
||||
|
||||
set.erase(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_NE(set.emplace(entities[1u]), set.end());
|
||||
ASSERT_NE(set.emplace(entities[0u]), set.end());
|
||||
ASSERT_NE(set.push(entities[1u]), set.end());
|
||||
ASSERT_NE(set.push(entities[0u]), set.end());
|
||||
|
||||
ASSERT_EQ(set.at(0u), entities[1u]);
|
||||
ASSERT_EQ(set.at(1u), entities[0u]);
|
||||
@ -291,72 +295,16 @@ TEST(SparseSet, Emplace) {
|
||||
ASSERT_EQ(set.index(entities[1u]), 0u);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(SparseSetDeathTest, Emplace) {
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
set.emplace(entt::entity{42});
|
||||
|
||||
ASSERT_DEATH(set.emplace(entt::entity{42}), "");
|
||||
}
|
||||
|
||||
TEST(SparseSet, EmplaceOutOfBounds) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
entt::entity entities[2u]{entt::entity{0}, entt::entity{traits_type::page_size}};
|
||||
|
||||
ASSERT_NE(set.emplace(entities[0u]), set.end());
|
||||
ASSERT_EQ(set.extent(), traits_type::page_size);
|
||||
ASSERT_EQ(set.index(entities[0u]), 0u);
|
||||
|
||||
set.erase(entities[0u]);
|
||||
|
||||
ASSERT_NE(set.emplace(entities[1u]), set.end());
|
||||
ASSERT_EQ(set.extent(), 2u * traits_type::page_size);
|
||||
ASSERT_EQ(set.index(entities[1u]), 0u);
|
||||
}
|
||||
|
||||
TEST(SparseSet, Bump) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::sparse_set set;
|
||||
entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, traits_type::construct(9, 3)};
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_EQ(set.current(entities[0u]), 0u);
|
||||
ASSERT_EQ(set.current(entities[1u]), 0u);
|
||||
ASSERT_EQ(set.current(entities[2u]), 3u);
|
||||
|
||||
set.bump(entities[0u]);
|
||||
set.bump(traits_type::construct(traits_type::to_entity(entities[1u]), 1));
|
||||
set.bump(traits_type::construct(traits_type::to_entity(entities[2u]), 0));
|
||||
|
||||
ASSERT_EQ(set.current(entities[0u]), 0u);
|
||||
ASSERT_EQ(set.current(entities[1u]), 1u);
|
||||
ASSERT_EQ(set.current(entities[2u]), 0u);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(SparseSetDeathTest, Bump) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
set.emplace(entt::entity{3});
|
||||
|
||||
ASSERT_DEATH(set.bump(entt::null), "");
|
||||
ASSERT_DEATH(set.bump(entt::tombstone), "");
|
||||
ASSERT_DEATH(set.bump(entt::entity{42}), "");
|
||||
ASSERT_DEATH(set.bump(traits_type::construct(traits_type::to_entity(entt::entity{3}), traits_type::to_version(entt::tombstone))), "");
|
||||
}
|
||||
|
||||
TEST(SparseSet, Insert) {
|
||||
TEST(SparseSet, PushRange) {
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
set.emplace(entt::entity{12});
|
||||
set.push(entt::entity{12});
|
||||
|
||||
ASSERT_EQ(set.insert(std::end(entities), std::end(entities)), set.end());
|
||||
ASSERT_NE(set.insert(std::begin(entities), std::end(entities)), set.end());
|
||||
ASSERT_EQ(set.push(std::end(entities), std::end(entities)), set.end());
|
||||
ASSERT_NE(set.push(std::begin(entities), std::end(entities)), set.end());
|
||||
|
||||
set.emplace(entt::entity{24});
|
||||
set.push(entt::entity{24});
|
||||
|
||||
ASSERT_TRUE(set.contains(entities[0u]));
|
||||
ASSERT_TRUE(set.contains(entities[1u]));
|
||||
@ -378,7 +326,7 @@ TEST(SparseSet, Insert) {
|
||||
|
||||
set.erase(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_NE(set.insert(std::rbegin(entities), std::rend(entities)), set.end());
|
||||
ASSERT_NE(set.push(std::rbegin(entities), std::rend(entities)), set.end());
|
||||
|
||||
ASSERT_EQ(set.size(), 6u);
|
||||
ASSERT_EQ(set.at(4u), entities[1u]);
|
||||
@ -387,6 +335,64 @@ TEST(SparseSet, Insert) {
|
||||
ASSERT_EQ(set.index(entities[1u]), 4u);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(SparseSetDeathTest, Push) {
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
set.push(entt::entity{42});
|
||||
|
||||
ASSERT_DEATH(set.push(entt::entity{42}), "");
|
||||
ASSERT_DEATH(set.push(std::begin(entities), std::end(entities)), "");
|
||||
}
|
||||
|
||||
TEST(SparseSet, PushOutOfBounds) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
entt::entity entities[2u]{entt::entity{0}, entt::entity{traits_type::page_size}};
|
||||
|
||||
ASSERT_NE(set.push(entities[0u]), set.end());
|
||||
ASSERT_EQ(set.extent(), traits_type::page_size);
|
||||
ASSERT_EQ(set.index(entities[0u]), 0u);
|
||||
|
||||
set.erase(entities[0u]);
|
||||
|
||||
ASSERT_NE(set.push(entities[1u]), set.end());
|
||||
ASSERT_EQ(set.extent(), 2u * traits_type::page_size);
|
||||
ASSERT_EQ(set.index(entities[1u]), 0u);
|
||||
}
|
||||
|
||||
TEST(SparseSet, Bump) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::sparse_set set;
|
||||
entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, traits_type::construct(9, 3)};
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_EQ(set.current(entities[0u]), 0u);
|
||||
ASSERT_EQ(set.current(entities[1u]), 0u);
|
||||
ASSERT_EQ(set.current(entities[2u]), 3u);
|
||||
|
||||
ASSERT_EQ(set.bump(entities[0u]), 0u);
|
||||
ASSERT_EQ(set.bump(traits_type::construct(traits_type::to_entity(entities[1u]), 1)), 1u);
|
||||
ASSERT_EQ(set.bump(traits_type::construct(traits_type::to_entity(entities[2u]), 0)), 0u);
|
||||
|
||||
ASSERT_EQ(set.current(entities[0u]), 0u);
|
||||
ASSERT_EQ(set.current(entities[1u]), 1u);
|
||||
ASSERT_EQ(set.current(entities[2u]), 0u);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(SparseSetDeathTest, Bump) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
set.push(entt::entity{3});
|
||||
|
||||
ASSERT_DEATH(set.bump(entt::null), "");
|
||||
ASSERT_DEATH(set.bump(entt::tombstone), "");
|
||||
ASSERT_DEATH(set.bump(entt::entity{42}), "");
|
||||
ASSERT_DEATH(set.bump(traits_type::construct(traits_type::to_entity(entt::entity{3}), traits_type::to_version(entt::tombstone))), "");
|
||||
}
|
||||
|
||||
TEST(SparseSet, Erase) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
@ -396,7 +402,7 @@ TEST(SparseSet, Erase) {
|
||||
ASSERT_EQ(set.policy(), entt::deletion_policy::swap_and_pop);
|
||||
ASSERT_TRUE(set.empty());
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
set.erase(set.begin(), set.end());
|
||||
|
||||
ASSERT_TRUE(set.empty());
|
||||
@ -404,7 +410,7 @@ TEST(SparseSet, Erase) {
|
||||
ASSERT_EQ(set.current(entities[1u]), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
set.erase(entities, entities + 2u);
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
@ -418,7 +424,7 @@ TEST(SparseSet, Erase) {
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
std::swap(entities[1u], entities[2u]);
|
||||
set.erase(entities, entities + 2u);
|
||||
|
||||
@ -442,8 +448,8 @@ TEST(SparseSet, CrossErase) {
|
||||
entt::sparse_set other;
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
other.emplace(entities[1u]);
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
other.push(entities[1u]);
|
||||
set.erase(other.begin(), other.end());
|
||||
|
||||
ASSERT_TRUE(set.contains(entities[0u]));
|
||||
@ -461,9 +467,9 @@ TEST(SparseSet, StableErase) {
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.push(entities[0u]);
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
|
||||
set.erase(set.begin(), set.end());
|
||||
|
||||
@ -476,9 +482,9 @@ TEST(SparseSet, StableErase) {
|
||||
ASSERT_TRUE(set.at(1u) == entt::tombstone);
|
||||
ASSERT_TRUE(set.at(2u) == entt::tombstone);
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.push(entities[0u]);
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
|
||||
set.erase(entities, entities + 2u);
|
||||
|
||||
@ -497,9 +503,9 @@ TEST(SparseSet, StableErase) {
|
||||
ASSERT_EQ(set.size(), 3u);
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.push(entities[0u]);
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
|
||||
std::swap(entities[1u], entities[2u]);
|
||||
set.erase(entities, entities + 2u);
|
||||
@ -527,9 +533,9 @@ TEST(SparseSet, StableErase) {
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.push(entities[0u]);
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
|
||||
set.erase(entities[2u]);
|
||||
|
||||
@ -546,13 +552,13 @@ TEST(SparseSet, StableErase) {
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_TRUE(*set.begin() == entt::tombstone);
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.push(entities[0u]);
|
||||
|
||||
ASSERT_EQ(*++set.begin(), entities[0u]);
|
||||
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.emplace(entt::entity{0});
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
set.push(entt::entity{0});
|
||||
|
||||
ASSERT_EQ(set.size(), 4u);
|
||||
ASSERT_EQ(*set.begin(), entt::entity{0});
|
||||
@ -580,8 +586,8 @@ TEST(SparseSet, CrossStableErase) {
|
||||
entt::sparse_set other{entt::deletion_policy::in_place};
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
other.emplace(entities[1u]);
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
other.push(entities[1u]);
|
||||
set.erase(other.begin(), other.end());
|
||||
|
||||
ASSERT_TRUE(set.contains(entities[0u]));
|
||||
@ -599,11 +605,11 @@ TEST(SparseSet, Remove) {
|
||||
ASSERT_TRUE(set.empty());
|
||||
|
||||
ASSERT_EQ(set.remove(std::begin(entities), std::end(entities)), 0u);
|
||||
ASSERT_EQ(set.remove(entities[1u]), 0u);
|
||||
ASSERT_FALSE(set.remove(entities[1u]));
|
||||
|
||||
ASSERT_TRUE(set.empty());
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
|
||||
ASSERT_TRUE(set.empty());
|
||||
@ -611,7 +617,7 @@ TEST(SparseSet, Remove) {
|
||||
ASSERT_EQ(set.current(entities[1u]), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_EQ(set.remove(entities, entities + 2u), 2u);
|
||||
ASSERT_FALSE(set.empty());
|
||||
@ -620,12 +626,12 @@ TEST(SparseSet, Remove) {
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entities[2u]));
|
||||
ASSERT_EQ(*set.begin(), entities[2u]);
|
||||
|
||||
ASSERT_EQ(set.remove(entities[2u]), 1u);
|
||||
ASSERT_EQ(set.remove(entities[2u]), 0u);
|
||||
ASSERT_TRUE(set.remove(entities[2u]));
|
||||
ASSERT_FALSE(set.remove(entities[2u]));
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.insert(entities, entities + 2u);
|
||||
set.push(entities, entities + 2u);
|
||||
|
||||
ASSERT_EQ(set.remove(std::begin(entities), std::end(entities)), 2u);
|
||||
ASSERT_EQ(set.current(entities[0u]), traits_type::to_version(entt::tombstone));
|
||||
@ -633,7 +639,7 @@ TEST(SparseSet, Remove) {
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_TRUE(set.empty());
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
std::swap(entities[1u], entities[2u]);
|
||||
|
||||
ASSERT_EQ(set.remove(entities, entities + 2u), 2u);
|
||||
@ -641,9 +647,9 @@ TEST(SparseSet, Remove) {
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(*set.begin(), entities[2u]);
|
||||
|
||||
ASSERT_EQ(set.remove(traits_type::construct(9, 0)), 0u);
|
||||
ASSERT_EQ(set.remove(entt::tombstone), 0u);
|
||||
ASSERT_EQ(set.remove(entt::null), 0u);
|
||||
ASSERT_FALSE(set.remove(traits_type::construct(9, 0)));
|
||||
ASSERT_FALSE(set.remove(entt::tombstone));
|
||||
ASSERT_FALSE(set.remove(entt::null));
|
||||
}
|
||||
|
||||
TEST(SparseSet, CrossRemove) {
|
||||
@ -651,8 +657,8 @@ TEST(SparseSet, CrossRemove) {
|
||||
entt::sparse_set other;
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
other.emplace(entities[1u]);
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
other.push(entities[1u]);
|
||||
set.remove(other.begin(), other.end());
|
||||
|
||||
ASSERT_TRUE(set.contains(entities[0u]));
|
||||
@ -671,14 +677,14 @@ TEST(SparseSet, StableRemove) {
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
|
||||
ASSERT_EQ(set.remove(std::begin(entities), std::end(entities)), 0u);
|
||||
ASSERT_EQ(set.remove(entities[1u]), 0u);
|
||||
ASSERT_FALSE(set.remove(entities[1u]));
|
||||
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.push(entities[0u]);
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
|
||||
ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
|
||||
ASSERT_EQ(set.remove(set.begin(), set.end()), 0u);
|
||||
@ -692,9 +698,9 @@ TEST(SparseSet, StableRemove) {
|
||||
ASSERT_TRUE(set.at(1u) == entt::tombstone);
|
||||
ASSERT_TRUE(set.at(2u) == entt::tombstone);
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.push(entities[0u]);
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
|
||||
ASSERT_EQ(set.remove(entities, entities + 2u), 2u);
|
||||
ASSERT_EQ(set.remove(entities, entities + 2u), 0u);
|
||||
@ -708,16 +714,16 @@ TEST(SparseSet, StableRemove) {
|
||||
ASSERT_TRUE(set.at(0u) == entt::tombstone);
|
||||
ASSERT_TRUE(set.at(1u) == entt::tombstone);
|
||||
|
||||
ASSERT_EQ(set.remove(entities[2u]), 1u);
|
||||
ASSERT_EQ(set.remove(entities[2u]), 0u);
|
||||
ASSERT_TRUE(set.remove(entities[2u]));
|
||||
ASSERT_FALSE(set.remove(entities[2u]));
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(set.size(), 3u);
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.push(entities[0u]);
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
|
||||
std::swap(entities[1u], entities[2u]);
|
||||
|
||||
@ -747,19 +753,19 @@ TEST(SparseSet, StableRemove) {
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.push(entities[0u]);
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
|
||||
ASSERT_EQ(set.remove(entities[2u]), 1u);
|
||||
ASSERT_EQ(set.remove(entities[2u]), 0u);
|
||||
ASSERT_TRUE(set.remove(entities[2u]));
|
||||
ASSERT_FALSE(set.remove(entities[2u]));
|
||||
|
||||
ASSERT_NE(set.current(entities[0u]), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_NE(set.current(entities[1u]), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
ASSERT_EQ(set.remove(entities[0u]), 1u);
|
||||
ASSERT_EQ(set.remove(entities[1u]), 1u);
|
||||
ASSERT_TRUE(set.remove(entities[0u]));
|
||||
ASSERT_TRUE(set.remove(entities[1u]));
|
||||
ASSERT_EQ(set.remove(entities, entities + 2u), 0u);
|
||||
|
||||
ASSERT_EQ(set.size(), 3u);
|
||||
@ -768,13 +774,13 @@ TEST(SparseSet, StableRemove) {
|
||||
ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_TRUE(*set.begin() == entt::tombstone);
|
||||
|
||||
set.emplace(entities[0u]);
|
||||
set.push(entities[0u]);
|
||||
|
||||
ASSERT_EQ(*++set.begin(), entities[0u]);
|
||||
|
||||
set.emplace(entities[1u]);
|
||||
set.emplace(entities[2u]);
|
||||
set.emplace(entt::entity{0});
|
||||
set.push(entities[1u]);
|
||||
set.push(entities[2u]);
|
||||
set.push(entt::entity{0});
|
||||
|
||||
ASSERT_EQ(set.size(), 4u);
|
||||
ASSERT_EQ(*set.begin(), entt::entity{0});
|
||||
@ -786,8 +792,8 @@ TEST(SparseSet, StableRemove) {
|
||||
ASSERT_NE(set.current(entities[1u]), traits_type::to_version(entt::tombstone));
|
||||
ASSERT_NE(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
|
||||
|
||||
ASSERT_EQ(set.remove(traits_type::construct(9, 0)), 0u);
|
||||
ASSERT_EQ(set.remove(entt::null), 0u);
|
||||
ASSERT_FALSE(set.remove(traits_type::construct(9, 0)));
|
||||
ASSERT_FALSE(set.remove(entt::null));
|
||||
}
|
||||
|
||||
TEST(SparseSet, CrossStableRemove) {
|
||||
@ -795,8 +801,8 @@ TEST(SparseSet, CrossStableRemove) {
|
||||
entt::sparse_set other{entt::deletion_policy::in_place};
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
other.emplace(entities[1u]);
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
other.push(entities[1u]);
|
||||
set.remove(other.begin(), other.end());
|
||||
|
||||
ASSERT_TRUE(set.contains(entities[0u]));
|
||||
@ -815,13 +821,13 @@ TEST(SparseSet, Compact) {
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
|
||||
set.emplace(entt::entity{0});
|
||||
set.push(entt::entity{0});
|
||||
set.compact();
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(set.size(), 1u);
|
||||
|
||||
set.emplace(entt::entity{42});
|
||||
set.push(entt::entity{42});
|
||||
set.erase(entt::entity{0});
|
||||
|
||||
ASSERT_EQ(set.size(), 2u);
|
||||
@ -832,7 +838,7 @@ TEST(SparseSet, Compact) {
|
||||
ASSERT_EQ(set.size(), 1u);
|
||||
ASSERT_EQ(set.index(entt::entity{42}), 0u);
|
||||
|
||||
set.emplace(entt::entity{0});
|
||||
set.push(entt::entity{0});
|
||||
set.compact();
|
||||
|
||||
ASSERT_EQ(set.size(), 2u);
|
||||
@ -851,8 +857,8 @@ TEST(SparseSet, SwapEntity) {
|
||||
|
||||
entt::sparse_set set;
|
||||
|
||||
set.emplace(traits_type::construct(3, 5));
|
||||
set.emplace(traits_type::construct(42, 99));
|
||||
set.push(traits_type::construct(3, 5));
|
||||
set.push(traits_type::construct(42, 99));
|
||||
|
||||
ASSERT_EQ(set.index(traits_type::construct(3, 5)), 0u);
|
||||
ASSERT_EQ(set.index(traits_type::construct(42, 99)), 1u);
|
||||
@ -878,9 +884,9 @@ ENTT_DEBUG_TEST(SparseSetDeathTest, SwapEntity) {
|
||||
TEST(SparseSet, Clear) {
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
|
||||
set.emplace(entt::entity{3});
|
||||
set.emplace(entt::entity{42});
|
||||
set.emplace(entt::entity{9});
|
||||
set.push(entt::entity{3});
|
||||
set.push(entt::entity{42});
|
||||
set.push(entt::entity{9});
|
||||
set.erase(entt::entity{42});
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
@ -895,9 +901,9 @@ TEST(SparseSet, Clear) {
|
||||
ASSERT_EQ(set.find(entt::entity{3}), set.end());
|
||||
ASSERT_EQ(set.find(entt::entity{9}), set.end());
|
||||
|
||||
set.emplace(entt::entity{3});
|
||||
set.emplace(entt::entity{42});
|
||||
set.emplace(entt::entity{9});
|
||||
set.push(entt::entity{3});
|
||||
set.push(entt::entity{42});
|
||||
set.push(entt::entity{9});
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(set.size(), 3u);
|
||||
@ -913,6 +919,64 @@ TEST(SparseSet, Clear) {
|
||||
ASSERT_EQ(set.find(entt::entity{9}), set.end());
|
||||
}
|
||||
|
||||
TEST(SparseSet, Contiguous) {
|
||||
entt::sparse_set swap_and_pop{entt::deletion_policy::swap_and_pop};
|
||||
entt::sparse_set in_place{entt::deletion_policy::in_place};
|
||||
|
||||
const entt::entity entity{42};
|
||||
const entt::entity other{3};
|
||||
|
||||
ASSERT_TRUE(swap_and_pop.contiguous());
|
||||
ASSERT_TRUE(in_place.contiguous());
|
||||
|
||||
swap_and_pop.push(entity);
|
||||
in_place.push(entity);
|
||||
|
||||
swap_and_pop.push(other);
|
||||
in_place.push(other);
|
||||
|
||||
ASSERT_TRUE(swap_and_pop.contiguous());
|
||||
ASSERT_TRUE(in_place.contiguous());
|
||||
|
||||
swap_and_pop.erase(entity);
|
||||
in_place.erase(entity);
|
||||
|
||||
ASSERT_TRUE(swap_and_pop.contiguous());
|
||||
ASSERT_FALSE(in_place.contiguous());
|
||||
|
||||
swap_and_pop.push(entity);
|
||||
in_place.push(entity);
|
||||
|
||||
ASSERT_TRUE(swap_and_pop.contiguous());
|
||||
ASSERT_TRUE(in_place.contiguous());
|
||||
|
||||
swap_and_pop.erase(other);
|
||||
in_place.erase(other);
|
||||
|
||||
ASSERT_TRUE(swap_and_pop.contiguous());
|
||||
ASSERT_FALSE(in_place.contiguous());
|
||||
|
||||
in_place.compact();
|
||||
|
||||
ASSERT_TRUE(swap_and_pop.contiguous());
|
||||
ASSERT_TRUE(in_place.contiguous());
|
||||
|
||||
swap_and_pop.push(other);
|
||||
in_place.push(other);
|
||||
|
||||
swap_and_pop.erase(entity);
|
||||
in_place.erase(entity);
|
||||
|
||||
ASSERT_TRUE(swap_and_pop.contiguous());
|
||||
ASSERT_FALSE(in_place.contiguous());
|
||||
|
||||
swap_and_pop.clear();
|
||||
in_place.clear();
|
||||
|
||||
ASSERT_TRUE(swap_and_pop.contiguous());
|
||||
ASSERT_TRUE(in_place.contiguous());
|
||||
}
|
||||
|
||||
TEST(SparseSet, Iterator) {
|
||||
using iterator = typename entt::sparse_set::iterator;
|
||||
|
||||
@ -921,13 +985,20 @@ TEST(SparseSet, Iterator) {
|
||||
static_assert(std::is_same_v<iterator::reference, const entt::entity &>);
|
||||
|
||||
entt::sparse_set set;
|
||||
set.emplace(entt::entity{3});
|
||||
set.push(entt::entity{3});
|
||||
|
||||
iterator end{set.begin()};
|
||||
iterator begin{};
|
||||
|
||||
ASSERT_EQ(end.data(), set.data());
|
||||
ASSERT_EQ(begin.data(), nullptr);
|
||||
|
||||
begin = set.end();
|
||||
std::swap(begin, end);
|
||||
|
||||
ASSERT_EQ(end.data(), set.data());
|
||||
ASSERT_EQ(begin.data(), set.data());
|
||||
|
||||
ASSERT_EQ(begin, set.cbegin());
|
||||
ASSERT_EQ(end, set.cend());
|
||||
ASSERT_NE(begin, end);
|
||||
@ -967,7 +1038,7 @@ TEST(SparseSet, Iterator) {
|
||||
ASSERT_EQ(begin.index(), 0);
|
||||
ASSERT_EQ(end.index(), -1);
|
||||
|
||||
set.emplace(entt::entity{42});
|
||||
set.push(entt::entity{42});
|
||||
begin = set.begin();
|
||||
|
||||
ASSERT_EQ(begin.index(), 1);
|
||||
@ -985,7 +1056,7 @@ TEST(SparseSet, ReverseIterator) {
|
||||
static_assert(std::is_same_v<reverse_iterator::reference, const entt::entity &>);
|
||||
|
||||
entt::sparse_set set;
|
||||
set.emplace(entt::entity{3});
|
||||
set.push(entt::entity{3});
|
||||
|
||||
reverse_iterator end{set.rbegin()};
|
||||
reverse_iterator begin{};
|
||||
@ -1031,7 +1102,7 @@ TEST(SparseSet, ReverseIterator) {
|
||||
ASSERT_EQ(begin.base().index(), -1);
|
||||
ASSERT_EQ(end.base().index(), 0);
|
||||
|
||||
set.emplace(entt::entity{42});
|
||||
set.push(entt::entity{42});
|
||||
end = set.rend();
|
||||
|
||||
ASSERT_EQ(begin.base().index(), -1);
|
||||
@ -1045,9 +1116,9 @@ TEST(SparseSet, Find) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::sparse_set set;
|
||||
set.emplace(entt::entity{3});
|
||||
set.emplace(entt::entity{42});
|
||||
set.emplace(traits_type::construct(99, 1));
|
||||
set.push(entt::entity{3});
|
||||
set.push(entt::entity{42});
|
||||
set.push(traits_type::construct(99, 1));
|
||||
|
||||
ASSERT_NE(set.find(entt::entity{3}), set.end());
|
||||
ASSERT_NE(set.find(entt::entity{42}), set.end());
|
||||
@ -1069,9 +1140,9 @@ TEST(SparseSet, Find) {
|
||||
TEST(SparseSet, Data) {
|
||||
entt::sparse_set set;
|
||||
|
||||
set.emplace(entt::entity{3});
|
||||
set.emplace(entt::entity{12});
|
||||
set.emplace(entt::entity{42});
|
||||
set.push(entt::entity{3});
|
||||
set.push(entt::entity{12});
|
||||
set.push(entt::entity{42});
|
||||
|
||||
ASSERT_EQ(set.index(entt::entity{3}), 0u);
|
||||
ASSERT_EQ(set.index(entt::entity{12}), 1u);
|
||||
@ -1086,7 +1157,7 @@ TEST(SparseSet, SortOrdered) {
|
||||
entt::sparse_set set;
|
||||
entt::entity entities[5u]{entt::entity{42}, entt::entity{12}, entt::entity{9}, entt::entity{7}, entt::entity{3}};
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
set.sort(std::less{});
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(entities), std::rend(entities), set.begin(), set.end()));
|
||||
@ -1096,7 +1167,7 @@ TEST(SparseSet, SortReverse) {
|
||||
entt::sparse_set set;
|
||||
entt::entity entities[5u]{entt::entity{3}, entt::entity{7}, entt::entity{9}, entt::entity{12}, entt::entity{42}};
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
set.sort(std::less{});
|
||||
|
||||
ASSERT_TRUE(std::equal(std::begin(entities), std::end(entities), set.begin(), set.end()));
|
||||
@ -1106,7 +1177,7 @@ TEST(SparseSet, SortUnordered) {
|
||||
entt::sparse_set set;
|
||||
entt::entity entities[5u]{entt::entity{9}, entt::entity{7}, entt::entity{3}, entt::entity{12}, entt::entity{42}};
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
set.sort(std::less{});
|
||||
|
||||
auto begin = set.begin();
|
||||
@ -1124,7 +1195,7 @@ TEST(SparseSet, SortRange) {
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
entt::entity entities[5u]{entt::entity{7}, entt::entity{9}, entt::entity{3}, entt::entity{12}, entt::entity{42}};
|
||||
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
set.erase(entities[0u]);
|
||||
|
||||
ASSERT_EQ(set.size(), 5u);
|
||||
@ -1139,7 +1210,7 @@ TEST(SparseSet, SortRange) {
|
||||
|
||||
set.clear();
|
||||
set.compact();
|
||||
set.insert(std::begin(entities), std::end(entities));
|
||||
set.push(std::begin(entities), std::end(entities));
|
||||
set.sort_n(0u, std::less{});
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(entities), std::rend(entities), set.begin(), set.end()));
|
||||
@ -1167,7 +1238,7 @@ ENTT_DEBUG_TEST(SparseSetDeathTest, SortRange) {
|
||||
entt::sparse_set set{entt::deletion_policy::in_place};
|
||||
entt::entity entity{42};
|
||||
|
||||
set.emplace(entity);
|
||||
set.push(entity);
|
||||
set.erase(entity);
|
||||
|
||||
ASSERT_DEATH(set.sort_n(0u, std::less{});, "");
|
||||
@ -1179,11 +1250,11 @@ TEST(SparseSet, RespectDisjoint) {
|
||||
entt::sparse_set rhs;
|
||||
|
||||
entt::entity lhs_entities[3u]{entt::entity{3}, entt::entity{12}, entt::entity{42}};
|
||||
lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
lhs.push(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
|
||||
|
||||
lhs.respect(rhs);
|
||||
lhs.sort_as(rhs);
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
|
||||
}
|
||||
@ -1193,15 +1264,15 @@ TEST(SparseSet, RespectOverlap) {
|
||||
entt::sparse_set rhs;
|
||||
|
||||
entt::entity lhs_entities[3u]{entt::entity{3}, entt::entity{12}, entt::entity{42}};
|
||||
lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
lhs.push(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
|
||||
entt::entity rhs_entities[1u]{entt::entity{12}};
|
||||
rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
rhs.push(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
|
||||
ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
|
||||
|
||||
lhs.respect(rhs);
|
||||
lhs.sort_as(rhs);
|
||||
|
||||
auto begin = lhs.begin();
|
||||
auto end = lhs.end();
|
||||
@ -1217,15 +1288,15 @@ TEST(SparseSet, RespectOrdered) {
|
||||
entt::sparse_set rhs;
|
||||
|
||||
entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
|
||||
lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
lhs.push(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
|
||||
entt::entity rhs_entities[6u]{entt::entity{6}, entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
|
||||
rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
rhs.push(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
|
||||
ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
|
||||
|
||||
rhs.respect(lhs);
|
||||
rhs.sort_as(lhs);
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
|
||||
}
|
||||
@ -1235,15 +1306,15 @@ TEST(SparseSet, RespectReverse) {
|
||||
entt::sparse_set rhs;
|
||||
|
||||
entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
|
||||
lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
lhs.push(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
|
||||
entt::entity rhs_entities[6u]{entt::entity{5}, entt::entity{4}, entt::entity{3}, entt::entity{2}, entt::entity{1}, entt::entity{6}};
|
||||
rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
rhs.push(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
|
||||
ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
|
||||
|
||||
rhs.respect(lhs);
|
||||
rhs.sort_as(lhs);
|
||||
|
||||
auto begin = rhs.begin();
|
||||
auto end = rhs.end();
|
||||
@ -1262,15 +1333,15 @@ TEST(SparseSet, RespectUnordered) {
|
||||
entt::sparse_set rhs;
|
||||
|
||||
entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
|
||||
lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
lhs.push(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
|
||||
entt::entity rhs_entities[6u]{entt::entity{3}, entt::entity{2}, entt::entity{6}, entt::entity{1}, entt::entity{4}, entt::entity{5}};
|
||||
rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
rhs.push(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
|
||||
ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
|
||||
|
||||
rhs.respect(lhs);
|
||||
rhs.sort_as(lhs);
|
||||
|
||||
auto begin = rhs.begin();
|
||||
auto end = rhs.end();
|
||||
@ -1291,15 +1362,15 @@ TEST(SparseSet, RespectInvalid) {
|
||||
entt::sparse_set rhs;
|
||||
|
||||
entt::entity lhs_entities[3u]{entt::entity{1}, entt::entity{2}, traits_type::construct(3, 1)};
|
||||
lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
lhs.push(std::begin(lhs_entities), std::end(lhs_entities));
|
||||
|
||||
entt::entity rhs_entities[3u]{entt::entity{2}, entt::entity{1}, traits_type::construct(3, 2)};
|
||||
rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
rhs.push(std::begin(rhs_entities), std::end(rhs_entities));
|
||||
|
||||
ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
|
||||
ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
|
||||
|
||||
rhs.respect(lhs);
|
||||
rhs.sort_as(lhs);
|
||||
|
||||
auto begin = rhs.begin();
|
||||
auto end = rhs.end();
|
||||
@ -1315,7 +1386,7 @@ TEST(SparseSet, RespectInvalid) {
|
||||
|
||||
TEST(SparseSet, CanModifyDuringIteration) {
|
||||
entt::sparse_set set;
|
||||
set.emplace(entt::entity{0});
|
||||
set.push(entt::entity{0});
|
||||
|
||||
ASSERT_EQ(set.capacity(), 1u);
|
||||
|
||||
@ -1338,8 +1409,8 @@ TEST(SparseSet, CustomAllocator) {
|
||||
|
||||
ASSERT_EQ(set.capacity(), 1u);
|
||||
|
||||
set.emplace(entt::entity{0});
|
||||
set.emplace(entt::entity{1});
|
||||
set.push(entt::entity{0});
|
||||
set.push(entt::entity{1});
|
||||
|
||||
entt::basic_sparse_set<entt::entity, test::throwing_allocator<entt::entity>> other{std::move(set), allocator};
|
||||
|
||||
@ -1389,11 +1460,11 @@ TEST(SparseSet, ThrowingAllocator) {
|
||||
|
||||
test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
|
||||
|
||||
ASSERT_THROW(set.emplace(entt::entity{0}), test::throwing_allocator<entt::entity>::exception_type);
|
||||
ASSERT_THROW(set.push(entt::entity{0}), test::throwing_allocator<entt::entity>::exception_type);
|
||||
ASSERT_EQ(set.extent(), traits_type::page_size);
|
||||
ASSERT_EQ(set.capacity(), 0u);
|
||||
|
||||
set.emplace(entt::entity{0});
|
||||
set.push(entt::entity{0});
|
||||
test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
|
||||
|
||||
ASSERT_THROW(set.reserve(2u), test::throwing_allocator<entt::entity>::exception_type);
|
||||
@ -1403,7 +1474,7 @@ TEST(SparseSet, ThrowingAllocator) {
|
||||
|
||||
test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
|
||||
|
||||
ASSERT_THROW(set.emplace(entt::entity{1}), test::throwing_allocator<entt::entity>::exception_type);
|
||||
ASSERT_THROW(set.push(entt::entity{1}), test::throwing_allocator<entt::entity>::exception_type);
|
||||
ASSERT_EQ(set.extent(), traits_type::page_size);
|
||||
ASSERT_TRUE(set.contains(entt::entity{0}));
|
||||
ASSERT_FALSE(set.contains(entt::entity{1}));
|
||||
@ -1412,7 +1483,7 @@ TEST(SparseSet, ThrowingAllocator) {
|
||||
entt::entity entities[2u]{entt::entity{1}, entt::entity{traits_type::page_size}};
|
||||
test::throwing_allocator<entt::entity>::trigger_after_allocate = true;
|
||||
|
||||
ASSERT_THROW(set.insert(std::begin(entities), std::end(entities)), test::throwing_allocator<entt::entity>::exception_type);
|
||||
ASSERT_THROW(set.push(std::begin(entities), std::end(entities)), test::throwing_allocator<entt::entity>::exception_type);
|
||||
ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
|
||||
ASSERT_TRUE(set.contains(entt::entity{0}));
|
||||
ASSERT_TRUE(set.contains(entt::entity{1}));
|
||||
@ -1420,7 +1491,7 @@ TEST(SparseSet, ThrowingAllocator) {
|
||||
ASSERT_EQ(set.capacity(), 2u);
|
||||
ASSERT_EQ(set.size(), 2u);
|
||||
|
||||
set.emplace(entities[1u]);
|
||||
set.push(entities[1u]);
|
||||
|
||||
ASSERT_TRUE(set.contains(entt::entity{traits_type::page_size}));
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
628
test/entt/entity/storage_entity.cpp
Normal file
628
test/entt/entity/storage_entity.cpp
Normal file
@ -0,0 +1,628 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/entity/storage.hpp>
|
||||
#include "../common/config.h"
|
||||
#include "../common/throwing_allocator.hpp"
|
||||
|
||||
TEST(StorageEntity, TypeAndPolicy) {
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
ASSERT_EQ(pool.type(), entt::type_id<entt::entity>());
|
||||
ASSERT_EQ(pool.policy(), entt::deletion_policy::swap_and_pop);
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Functionalities) {
|
||||
entt::entity entities[2u]{entt::entity{0}, entt::entity{1}};
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
ASSERT_TRUE(pool.empty());
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
|
||||
ASSERT_EQ(*pool.push(entt::null), entities[0u]);
|
||||
ASSERT_EQ(*pool.push(entt::tombstone), entities[1u]);
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 2u);
|
||||
|
||||
pool.in_use(1u);
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 1u);
|
||||
|
||||
ASSERT_NO_THROW(pool.get(entities[0u]));
|
||||
ASSERT_EQ(pool.get_as_tuple(entities[0u]), std::tuple<>{});
|
||||
|
||||
pool.erase(entities[0u]);
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(StorageEntityDeathTest, Get) {
|
||||
entt::storage<entt::entity> pool;
|
||||
pool.emplace(entt::entity{99});
|
||||
|
||||
ASSERT_DEATH(pool.get(entt::entity{3}), "");
|
||||
ASSERT_DEATH([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{3}), "");
|
||||
|
||||
ASSERT_NO_THROW(pool.get(entt::entity{99}));
|
||||
ASSERT_NO_THROW([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{99}));
|
||||
|
||||
pool.erase(entt::entity{99});
|
||||
|
||||
ASSERT_DEATH(pool.get(entt::entity{99}), "");
|
||||
ASSERT_DEATH([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{99}), "");
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Move) {
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.push(entt::entity{1});
|
||||
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 1u);
|
||||
|
||||
ASSERT_TRUE(std::is_move_constructible_v<decltype(pool)>);
|
||||
ASSERT_TRUE(std::is_move_assignable_v<decltype(pool)>);
|
||||
|
||||
entt::storage<entt::entity> other{std::move(pool)};
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(other.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
ASSERT_EQ(other.in_use(), 1u);
|
||||
ASSERT_EQ(pool.at(0u), static_cast<entt::entity>(entt::null));
|
||||
ASSERT_EQ(other.at(0u), entt::entity{1});
|
||||
|
||||
pool = std::move(other);
|
||||
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 1u);
|
||||
ASSERT_EQ(other.in_use(), 0u);
|
||||
ASSERT_EQ(pool.at(0u), entt::entity{1});
|
||||
ASSERT_EQ(other.at(0u), static_cast<entt::entity>(entt::null));
|
||||
|
||||
other = entt::storage<entt::entity>{};
|
||||
|
||||
other.push(entt::entity{3});
|
||||
other = std::move(pool);
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(other.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
ASSERT_EQ(other.in_use(), 1u);
|
||||
ASSERT_EQ(pool.at(0u), static_cast<entt::entity>(entt::null));
|
||||
ASSERT_EQ(other.at(0u), entt::entity{1});
|
||||
|
||||
other.clear();
|
||||
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
ASSERT_EQ(other.in_use(), 0u);
|
||||
|
||||
ASSERT_EQ(*other.push(entt::null), entt::entity{0});
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Swap) {
|
||||
entt::storage<entt::entity> pool;
|
||||
entt::storage<entt::entity> other;
|
||||
|
||||
pool.push(entt::entity{1});
|
||||
|
||||
other.push(entt::entity{2});
|
||||
other.push(entt::entity{0});
|
||||
other.erase(entt::entity{2});
|
||||
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(other.size(), 3u);
|
||||
ASSERT_EQ(pool.in_use(), 1u);
|
||||
ASSERT_EQ(other.in_use(), 1u);
|
||||
|
||||
pool.swap(other);
|
||||
|
||||
ASSERT_EQ(pool.size(), 3u);
|
||||
ASSERT_EQ(other.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 1u);
|
||||
ASSERT_EQ(other.in_use(), 1u);
|
||||
|
||||
ASSERT_EQ(pool.at(0u), entt::entity{0});
|
||||
ASSERT_EQ(other.at(0u), entt::entity{1});
|
||||
|
||||
pool.clear();
|
||||
other.clear();
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
ASSERT_EQ(other.in_use(), 0u);
|
||||
|
||||
ASSERT_EQ(*other.push(entt::null), entt::entity{0});
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Push) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
ASSERT_EQ(*pool.push(entt::null), entt::entity{0});
|
||||
ASSERT_EQ(*pool.push(entt::tombstone), entt::entity{1});
|
||||
ASSERT_EQ(*pool.push(entt::entity{0}), entt::entity{2});
|
||||
ASSERT_EQ(*pool.push(traits_type::construct(1, 1)), entt::entity{3});
|
||||
ASSERT_EQ(*pool.push(traits_type::construct(5, 3)), traits_type::construct(5, 3));
|
||||
|
||||
ASSERT_LT(pool.index(entt::entity{0}), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{1}), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{2}), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{3}), pool.in_use());
|
||||
ASSERT_GE(pool.index(entt::entity{4}), pool.in_use());
|
||||
ASSERT_LT(pool.index(traits_type::construct(5, 3)), pool.in_use());
|
||||
|
||||
ASSERT_EQ(*pool.push(traits_type::construct(4, 42)), traits_type::construct(4, 42));
|
||||
ASSERT_EQ(*pool.push(traits_type::construct(4, 43)), entt::entity{6});
|
||||
|
||||
entt::entity entities[2u]{entt::entity{1}, traits_type::construct(5, 3)};
|
||||
|
||||
pool.erase(entities, entities + 2u);
|
||||
pool.erase(entt::entity{2});
|
||||
|
||||
ASSERT_EQ(pool.current(entities[0u]), 1);
|
||||
ASSERT_EQ(pool.current(entities[1u]), 4);
|
||||
ASSERT_EQ(pool.current(entt::entity{2}), 1);
|
||||
|
||||
ASSERT_LT(pool.index(entt::entity{0}), pool.in_use());
|
||||
ASSERT_GE(pool.index(traits_type::construct(1, 1)), pool.in_use());
|
||||
ASSERT_GE(pool.index(traits_type::construct(2, 1)), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{3}), pool.in_use());
|
||||
ASSERT_LT(pool.index(traits_type::construct(4, 42)), pool.in_use());
|
||||
ASSERT_GE(pool.index(traits_type::construct(5, 4)), pool.in_use());
|
||||
|
||||
ASSERT_EQ(*pool.push(entt::null), traits_type::construct(2, 1));
|
||||
ASSERT_EQ(*pool.push(traits_type::construct(1, 3)), traits_type::construct(1, 3));
|
||||
ASSERT_EQ(*pool.push(entt::null), traits_type::construct(5, 4));
|
||||
ASSERT_EQ(*pool.push(entt::null), entt::entity{7});
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Emplace) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
entt::entity entities[2u]{};
|
||||
|
||||
ASSERT_EQ(pool.emplace(), entt::entity{0});
|
||||
ASSERT_EQ(pool.emplace(entt::null), entt::entity{1});
|
||||
ASSERT_EQ(pool.emplace(entt::tombstone), entt::entity{2});
|
||||
ASSERT_EQ(pool.emplace(entt::entity{0}), entt::entity{3});
|
||||
ASSERT_EQ(pool.emplace(traits_type::construct(1, 1)), entt::entity{4});
|
||||
ASSERT_EQ(pool.emplace(traits_type::construct(6, 3)), traits_type::construct(6, 3));
|
||||
|
||||
ASSERT_LT(pool.index(entt::entity{0}), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{1}), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{2}), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{3}), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{4}), pool.in_use());
|
||||
ASSERT_GE(pool.index(entt::entity{5}), pool.in_use());
|
||||
ASSERT_LT(pool.index(traits_type::construct(6, 3)), pool.in_use());
|
||||
|
||||
ASSERT_EQ(pool.emplace(traits_type::construct(5, 42)), traits_type::construct(5, 42));
|
||||
ASSERT_EQ(pool.emplace(traits_type::construct(5, 43)), entt::entity{7});
|
||||
|
||||
pool.erase(entt::entity{2});
|
||||
|
||||
ASSERT_EQ(pool.emplace(), traits_type::construct(2, 1));
|
||||
|
||||
pool.erase(traits_type::construct(2, 1));
|
||||
pool.insert(entities, entities + 2u);
|
||||
|
||||
ASSERT_EQ(entities[0u], traits_type::construct(2, 2));
|
||||
ASSERT_EQ(entities[1u], entt::entity{8});
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Patch) {
|
||||
entt::storage<entt::entity> pool;
|
||||
const auto entity = pool.emplace();
|
||||
|
||||
int counter = 0;
|
||||
auto callback = [&counter]() { ++counter; };
|
||||
|
||||
ASSERT_EQ(counter, 0);
|
||||
|
||||
pool.patch(entity);
|
||||
pool.patch(entity, callback);
|
||||
pool.patch(entity, callback, callback);
|
||||
|
||||
ASSERT_EQ(counter, 3);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(StorageEntityDeathTest, Patch) {
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
ASSERT_DEATH(pool.patch(entt::null), "");
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Insert) {
|
||||
entt::storage<entt::entity> pool;
|
||||
entt::entity entities[2u]{};
|
||||
|
||||
pool.insert(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_TRUE(pool.contains(entities[0u]));
|
||||
ASSERT_TRUE(pool.contains(entities[1u]));
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 2u);
|
||||
|
||||
pool.erase(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
|
||||
pool.insert(entities, entities + 1u);
|
||||
|
||||
ASSERT_TRUE(pool.contains(entities[0u]));
|
||||
ASSERT_FALSE(pool.contains(entities[1u]));
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 1u);
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Pack) {
|
||||
entt::storage<entt::entity> pool;
|
||||
entt::entity entities[3u]{entt::entity{1}, entt::entity{3}, entt::entity{42}};
|
||||
|
||||
pool.push(entities, entities + 3u);
|
||||
std::swap(entities[0u], entities[1u]);
|
||||
|
||||
const auto len = pool.pack(entities + 1u, entities + 3u);
|
||||
auto it = pool.each().cbegin().base();
|
||||
|
||||
ASSERT_NE(it, pool.cbegin());
|
||||
ASSERT_NE(it, pool.cend());
|
||||
|
||||
ASSERT_EQ(len, 2u);
|
||||
ASSERT_NE(it + len, pool.cend());
|
||||
ASSERT_EQ(it + len + 1u, pool.cend());
|
||||
|
||||
ASSERT_EQ(*it++, entities[1u]);
|
||||
ASSERT_EQ(*it++, entities[2u]);
|
||||
|
||||
ASSERT_NE(it, pool.cend());
|
||||
ASSERT_EQ(*it++, entities[0u]);
|
||||
ASSERT_EQ(it, pool.cend());
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Iterable) {
|
||||
using iterator = typename entt::storage<entt::entity>::iterable::iterator;
|
||||
|
||||
static_assert(std::is_same_v<iterator::value_type, std::tuple<entt::entity>>);
|
||||
static_assert(std::is_same_v<typename iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>);
|
||||
static_assert(std::is_same_v<typename iterator::reference, typename iterator::value_type>);
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.emplace(entt::entity{1});
|
||||
pool.emplace(entt::entity{3});
|
||||
pool.emplace(entt::entity{42});
|
||||
|
||||
pool.erase(entt::entity{3});
|
||||
|
||||
auto iterable = pool.each();
|
||||
|
||||
iterator end{iterable.begin()};
|
||||
iterator begin{};
|
||||
begin = iterable.end();
|
||||
std::swap(begin, end);
|
||||
|
||||
ASSERT_EQ(begin, iterable.begin());
|
||||
ASSERT_EQ(end, iterable.end());
|
||||
ASSERT_NE(begin, end);
|
||||
|
||||
ASSERT_NE(begin.base(), pool.begin());
|
||||
ASSERT_EQ(begin.base(), pool.end() - pool.in_use());
|
||||
ASSERT_EQ(end.base(), pool.end());
|
||||
|
||||
ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{42});
|
||||
ASSERT_EQ(std::get<0>(*begin), entt::entity{42});
|
||||
|
||||
ASSERT_EQ(begin++, iterable.begin());
|
||||
ASSERT_EQ(begin.base(), pool.end() - 1);
|
||||
ASSERT_EQ(++begin, iterable.end());
|
||||
ASSERT_EQ(begin.base(), pool.end());
|
||||
|
||||
for(auto [entity]: iterable) {
|
||||
static_assert(std::is_same_v<decltype(entity), entt::entity>);
|
||||
ASSERT_TRUE(entity != entt::entity{3});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(StorageEntity, ConstIterable) {
|
||||
using iterator = typename entt::storage<entt::entity>::const_iterable::iterator;
|
||||
|
||||
static_assert(std::is_same_v<iterator::value_type, std::tuple<entt::entity>>);
|
||||
static_assert(std::is_same_v<typename iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>);
|
||||
static_assert(std::is_same_v<typename iterator::reference, typename iterator::value_type>);
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.emplace(entt::entity{1});
|
||||
pool.emplace(entt::entity{3});
|
||||
pool.emplace(entt::entity{42});
|
||||
|
||||
pool.erase(entt::entity{3});
|
||||
|
||||
auto iterable = std::as_const(pool).each();
|
||||
|
||||
iterator end{iterable.cbegin()};
|
||||
iterator begin{};
|
||||
begin = iterable.cend();
|
||||
std::swap(begin, end);
|
||||
|
||||
ASSERT_EQ(begin, iterable.cbegin());
|
||||
ASSERT_EQ(end, iterable.cend());
|
||||
ASSERT_NE(begin, end);
|
||||
|
||||
ASSERT_NE(begin.base(), pool.begin());
|
||||
ASSERT_EQ(begin.base(), pool.end() - pool.in_use());
|
||||
ASSERT_EQ(end.base(), pool.end());
|
||||
|
||||
ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{42});
|
||||
ASSERT_EQ(std::get<0>(*begin), entt::entity{42});
|
||||
|
||||
ASSERT_EQ(begin++, iterable.begin());
|
||||
ASSERT_EQ(begin.base(), pool.end() - 1);
|
||||
ASSERT_EQ(++begin, iterable.end());
|
||||
ASSERT_EQ(begin.base(), pool.end());
|
||||
|
||||
for(auto [entity]: iterable) {
|
||||
static_assert(std::is_same_v<decltype(entity), entt::entity>);
|
||||
ASSERT_TRUE(entity != entt::entity{3});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(StorageEntity, IterableIteratorConversion) {
|
||||
entt::storage<entt::entity> pool;
|
||||
pool.emplace(entt::entity{3});
|
||||
|
||||
typename entt::storage<entt::entity>::iterable::iterator it = pool.each().begin();
|
||||
typename entt::storage<entt::entity>::const_iterable::iterator cit = it;
|
||||
|
||||
static_assert(std::is_same_v<decltype(*it), std::tuple<entt::entity>>);
|
||||
static_assert(std::is_same_v<decltype(*cit), std::tuple<entt::entity>>);
|
||||
|
||||
ASSERT_EQ(it, cit);
|
||||
ASSERT_NE(++cit, it);
|
||||
}
|
||||
|
||||
TEST(StorageEntity, IterableAlgorithmCompatibility) {
|
||||
entt::storage<entt::entity> pool;
|
||||
pool.emplace(entt::entity{3});
|
||||
|
||||
const auto iterable = pool.each();
|
||||
const auto it = std::find_if(iterable.begin(), iterable.end(), [](auto args) { return std::get<0>(args) == entt::entity{3}; });
|
||||
|
||||
ASSERT_EQ(std::get<0>(*it), entt::entity{3});
|
||||
}
|
||||
|
||||
TEST(StorageEntity, ReverseIterable) {
|
||||
using iterator = typename entt::storage<entt::entity>::reverse_iterable::iterator;
|
||||
|
||||
static_assert(std::is_same_v<iterator::value_type, std::tuple<entt::entity>>);
|
||||
static_assert(std::is_same_v<typename iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>);
|
||||
static_assert(std::is_same_v<typename iterator::reference, typename iterator::value_type>);
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.emplace(entt::entity{1});
|
||||
pool.emplace(entt::entity{3});
|
||||
pool.emplace(entt::entity{42});
|
||||
|
||||
pool.erase(entt::entity{3});
|
||||
|
||||
auto iterable = pool.reach();
|
||||
|
||||
iterator end{iterable.begin()};
|
||||
iterator begin{};
|
||||
begin = iterable.end();
|
||||
std::swap(begin, end);
|
||||
|
||||
ASSERT_EQ(begin, iterable.begin());
|
||||
ASSERT_EQ(end, iterable.end());
|
||||
ASSERT_NE(begin, end);
|
||||
|
||||
ASSERT_EQ(begin.base(), pool.rbegin());
|
||||
ASSERT_EQ(end.base(), pool.rbegin() + pool.in_use());
|
||||
ASSERT_NE(end.base(), pool.rend());
|
||||
|
||||
ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{1});
|
||||
ASSERT_EQ(std::get<0>(*begin), entt::entity{1});
|
||||
|
||||
ASSERT_EQ(begin++, iterable.begin());
|
||||
ASSERT_EQ(begin.base(), pool.rbegin() + 1);
|
||||
ASSERT_EQ(++begin, iterable.end());
|
||||
ASSERT_EQ(begin.base(), pool.rbegin() + 2);
|
||||
|
||||
for(auto [entity]: iterable) {
|
||||
static_assert(std::is_same_v<decltype(entity), entt::entity>);
|
||||
ASSERT_TRUE(entity != entt::entity{3});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(StorageEntity, ReverseConstIterable) {
|
||||
using iterator = typename entt::storage<entt::entity>::const_reverse_iterable::iterator;
|
||||
|
||||
static_assert(std::is_same_v<iterator::value_type, std::tuple<entt::entity>>);
|
||||
static_assert(std::is_same_v<typename iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>);
|
||||
static_assert(std::is_same_v<typename iterator::reference, typename iterator::value_type>);
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.emplace(entt::entity{1});
|
||||
pool.emplace(entt::entity{3});
|
||||
pool.emplace(entt::entity{42});
|
||||
|
||||
pool.erase(entt::entity{3});
|
||||
|
||||
auto iterable = std::as_const(pool).reach();
|
||||
|
||||
iterator end{iterable.cbegin()};
|
||||
iterator begin{};
|
||||
begin = iterable.cend();
|
||||
std::swap(begin, end);
|
||||
|
||||
ASSERT_EQ(begin, iterable.cbegin());
|
||||
ASSERT_EQ(end, iterable.cend());
|
||||
ASSERT_NE(begin, end);
|
||||
|
||||
ASSERT_EQ(begin.base(), pool.rbegin());
|
||||
ASSERT_EQ(end.base(), pool.rbegin() + pool.in_use());
|
||||
ASSERT_NE(end.base(), pool.rend());
|
||||
|
||||
ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{1});
|
||||
ASSERT_EQ(std::get<0>(*begin), entt::entity{1});
|
||||
|
||||
ASSERT_EQ(begin++, iterable.begin());
|
||||
ASSERT_EQ(begin.base(), pool.rbegin() + 1);
|
||||
ASSERT_EQ(++begin, iterable.end());
|
||||
ASSERT_EQ(begin.base(), pool.rbegin() + 2);
|
||||
|
||||
for(auto [entity]: iterable) {
|
||||
static_assert(std::is_same_v<decltype(entity), entt::entity>);
|
||||
ASSERT_TRUE(entity != entt::entity{3});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(StorageEntity, ReverseIterableIteratorConversion) {
|
||||
entt::storage<entt::entity> pool;
|
||||
pool.emplace(entt::entity{3});
|
||||
|
||||
typename entt::storage<entt::entity>::reverse_iterable::iterator it = pool.reach().begin();
|
||||
typename entt::storage<entt::entity>::const_reverse_iterable::iterator cit = it;
|
||||
|
||||
static_assert(std::is_same_v<decltype(*it), std::tuple<entt::entity>>);
|
||||
static_assert(std::is_same_v<decltype(*cit), std::tuple<entt::entity>>);
|
||||
|
||||
ASSERT_EQ(it, cit);
|
||||
ASSERT_NE(++cit, it);
|
||||
}
|
||||
|
||||
TEST(StorageEntity, ReverseIterableAlgorithmCompatibility) {
|
||||
entt::storage<entt::entity> pool;
|
||||
pool.emplace(entt::entity{3});
|
||||
|
||||
const auto iterable = pool.reach();
|
||||
const auto it = std::find_if(iterable.begin(), iterable.end(), [](auto args) { return std::get<0>(args) == entt::entity{3}; });
|
||||
|
||||
ASSERT_EQ(std::get<0>(*it), entt::entity{3});
|
||||
}
|
||||
|
||||
TEST(StorageEntity, SwapElements) {
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.push(entt::entity{0});
|
||||
pool.push(entt::entity{1});
|
||||
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 2u);
|
||||
ASSERT_TRUE(pool.contains(entt::entity{0}));
|
||||
ASSERT_TRUE(pool.contains(entt::entity{1}));
|
||||
|
||||
ASSERT_EQ(*pool.begin(), entt::entity{1});
|
||||
ASSERT_EQ(*++pool.begin(), entt::entity{0});
|
||||
|
||||
pool.swap_elements(entt::entity{0}, entt::entity{1});
|
||||
|
||||
ASSERT_EQ(*pool.begin(), entt::entity{0});
|
||||
ASSERT_EQ(*++pool.begin(), entt::entity{1});
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(StorageEntityDeathTest, SwapElements) {
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.push(entt::entity{1});
|
||||
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 1u);
|
||||
ASSERT_TRUE(pool.contains(entt::entity{0}));
|
||||
ASSERT_TRUE(pool.contains(entt::entity{1}));
|
||||
|
||||
ASSERT_DEATH(pool.swap_elements(entt::entity{0}, entt::entity{1}), "");
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(StorageEntityDeathTest, InUse) {
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.push(entt::entity{0});
|
||||
pool.push(entt::entity{1});
|
||||
|
||||
ASSERT_DEATH(pool.in_use(3u), "");
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(StorageEntityDeathTest, SortAndRespect) {
|
||||
entt::storage<entt::entity> pool;
|
||||
entt::storage<entt::entity> other;
|
||||
|
||||
pool.push(entt::entity{1});
|
||||
pool.push(entt::entity{2});
|
||||
pool.erase(entt::entity{2});
|
||||
|
||||
other.push(entt::entity{2});
|
||||
|
||||
ASSERT_DEATH(pool.sort([](auto...) { return true; }), "");
|
||||
ASSERT_DEATH(pool.sort_as(other), "");
|
||||
}
|
||||
|
||||
TEST(StorageEntity, CustomAllocator) {
|
||||
test::throwing_allocator<entt::entity> allocator{};
|
||||
entt::basic_storage<entt::entity, entt::entity, test::throwing_allocator<entt::entity>> pool{allocator};
|
||||
|
||||
pool.reserve(1u);
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
|
||||
pool.push(entt::entity{0});
|
||||
pool.push(entt::entity{1});
|
||||
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 2u);
|
||||
|
||||
decltype(pool) other{std::move(pool), allocator};
|
||||
|
||||
ASSERT_TRUE(pool.empty());
|
||||
ASSERT_FALSE(other.empty());
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(other.size(), 2u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
ASSERT_EQ(other.in_use(), 2u);
|
||||
|
||||
pool = std::move(other);
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_TRUE(other.empty());
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 2u);
|
||||
ASSERT_EQ(other.in_use(), 0u);
|
||||
|
||||
pool.swap(other);
|
||||
pool = std::move(other);
|
||||
|
||||
ASSERT_FALSE(pool.empty());
|
||||
ASSERT_TRUE(other.empty());
|
||||
ASSERT_EQ(pool.size(), 2u);
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 2u);
|
||||
ASSERT_EQ(other.in_use(), 0u);
|
||||
|
||||
pool.clear();
|
||||
|
||||
ASSERT_EQ(pool.size(), 0u);
|
||||
ASSERT_EQ(pool.in_use(), 0u);
|
||||
}
|
@ -24,7 +24,6 @@ TEST(SingleComponentView, Functionalities) {
|
||||
|
||||
ASSERT_TRUE(view.empty());
|
||||
|
||||
registry.emplace<int>(e1);
|
||||
registry.emplace<char>(e1);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(view.begin()++);
|
||||
@ -70,6 +69,42 @@ TEST(SingleComponentView, Functionalities) {
|
||||
ASSERT_FALSE(invalid);
|
||||
}
|
||||
|
||||
TEST(SingleComponentView, InvalidView) {
|
||||
entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<>> view{};
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_TRUE(view.empty());
|
||||
ASSERT_FALSE(view.contains(entt::null));
|
||||
ASSERT_EQ(view.find(entt::null), view.end());
|
||||
|
||||
ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
|
||||
ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
|
||||
|
||||
ASSERT_EQ(view.begin(), typename decltype(view)::iterator{});
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
|
||||
ASSERT_EQ(view.rbegin(), typename decltype(view)::reverse_iterator{});
|
||||
ASSERT_EQ(view.rbegin(), view.rend());
|
||||
|
||||
auto iterable = view.each();
|
||||
|
||||
ASSERT_EQ(iterable.begin(), iterable.end());
|
||||
ASSERT_EQ(iterable.cbegin(), iterable.cend());
|
||||
|
||||
view.each([](const int &) { FAIL(); });
|
||||
view.each([](const entt::entity, const int &) { FAIL(); });
|
||||
|
||||
entt::storage<int> storage;
|
||||
view.storage(storage);
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
|
||||
view.each([](const int &) { FAIL(); });
|
||||
view.each([](const entt::entity, const int &) { FAIL(); });
|
||||
}
|
||||
|
||||
TEST(SingleComponentView, Constructors) {
|
||||
entt::storage<int> storage{};
|
||||
|
||||
@ -81,7 +116,8 @@ TEST(SingleComponentView, Constructors) {
|
||||
ASSERT_TRUE(from_storage);
|
||||
ASSERT_TRUE(from_tuple);
|
||||
|
||||
ASSERT_EQ(&from_storage.handle(), &from_tuple.handle());
|
||||
ASSERT_NE(from_storage.handle(), nullptr);
|
||||
ASSERT_EQ(from_storage.handle(), from_tuple.handle());
|
||||
}
|
||||
|
||||
TEST(SingleComponentView, Handle) {
|
||||
@ -89,17 +125,19 @@ TEST(SingleComponentView, Handle) {
|
||||
const auto entity = registry.create();
|
||||
|
||||
auto view = registry.view<int>();
|
||||
auto &&handle = view.handle();
|
||||
auto *handle = view.handle();
|
||||
|
||||
ASSERT_TRUE(handle.empty());
|
||||
ASSERT_FALSE(handle.contains(entity));
|
||||
ASSERT_EQ(&handle, &view.handle());
|
||||
ASSERT_NE(handle, nullptr);
|
||||
|
||||
ASSERT_TRUE(handle->empty());
|
||||
ASSERT_FALSE(handle->contains(entity));
|
||||
ASSERT_EQ(handle, view.handle());
|
||||
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
ASSERT_FALSE(handle.empty());
|
||||
ASSERT_TRUE(handle.contains(entity));
|
||||
ASSERT_EQ(&handle, &view.handle());
|
||||
ASSERT_FALSE(handle->empty());
|
||||
ASSERT_TRUE(handle->contains(entity));
|
||||
ASSERT_EQ(handle, view.handle());
|
||||
}
|
||||
|
||||
TEST(SingleComponentView, LazyTypeFromConstRegistry) {
|
||||
@ -111,8 +149,8 @@ TEST(SingleComponentView, LazyTypeFromConstRegistry) {
|
||||
registry.emplace<empty_type>(entity);
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
ASSERT_TRUE(cview);
|
||||
ASSERT_TRUE(eview);
|
||||
ASSERT_FALSE(cview);
|
||||
ASSERT_FALSE(eview);
|
||||
|
||||
ASSERT_TRUE(cview.empty());
|
||||
ASSERT_EQ(eview.size(), 0u);
|
||||
@ -164,14 +202,6 @@ TEST(SingleComponentView, Contains) {
|
||||
|
||||
TEST(SingleComponentView, Empty) {
|
||||
entt::registry registry;
|
||||
|
||||
const auto e0 = registry.create();
|
||||
registry.emplace<char>(e0);
|
||||
registry.emplace<double>(e0);
|
||||
|
||||
const auto e1 = registry.create();
|
||||
registry.emplace<char>(e1);
|
||||
|
||||
auto view = registry.view<int>();
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
@ -198,15 +228,17 @@ TEST(SingleComponentView, Each) {
|
||||
|
||||
auto it = iterable.begin();
|
||||
|
||||
ASSERT_EQ(it.base(), view.begin());
|
||||
ASSERT_EQ((it++, ++it), iterable.end());
|
||||
ASSERT_EQ(it.base(), view.end());
|
||||
|
||||
view.each([expected = 1u](auto entt, int &value) mutable {
|
||||
ASSERT_EQ(entt::to_integral(entt), expected);
|
||||
view.each([expected = 1](auto entt, int &value) mutable {
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), expected);
|
||||
ASSERT_EQ(value, expected);
|
||||
--expected;
|
||||
});
|
||||
|
||||
cview.each([expected = 1u](const int &value) mutable {
|
||||
cview.each([expected = 1](const int &value) mutable {
|
||||
ASSERT_EQ(value, expected);
|
||||
--expected;
|
||||
});
|
||||
@ -219,7 +251,7 @@ TEST(SingleComponentView, Each) {
|
||||
|
||||
// do not use iterable, make sure an iterable view works when created from a temporary
|
||||
for(auto [entt, value]: view.each()) {
|
||||
ASSERT_EQ(entt::to_integral(entt), value);
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,15 +366,13 @@ TEST(SingleComponentView, Find) {
|
||||
|
||||
TEST(SingleComponentView, EmptyTypes) {
|
||||
entt::registry registry;
|
||||
entt::entity entities[2u];
|
||||
entt::entity entity = registry.create();
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
registry.emplace<int>(entities[0u], 0);
|
||||
registry.emplace<empty_type>(entities[0u]);
|
||||
registry.emplace<char>(entities[1u], 'c');
|
||||
registry.emplace<int>(entity, 0);
|
||||
registry.emplace<empty_type>(entity);
|
||||
|
||||
registry.view<empty_type>().each([&](const auto entt) {
|
||||
ASSERT_EQ(entities[0u], entt);
|
||||
ASSERT_EQ(entity, entt);
|
||||
});
|
||||
|
||||
registry.view<empty_type>().each([check = true]() mutable {
|
||||
@ -352,11 +382,11 @@ TEST(SingleComponentView, EmptyTypes) {
|
||||
|
||||
for(auto [entt]: registry.view<empty_type>().each()) {
|
||||
static_assert(std::is_same_v<decltype(entt), entt::entity>);
|
||||
ASSERT_EQ(entities[0u], entt);
|
||||
ASSERT_EQ(entity, entt);
|
||||
}
|
||||
|
||||
registry.view<int>().each([&](const auto entt, int) {
|
||||
ASSERT_EQ(entities[0u], entt);
|
||||
ASSERT_EQ(entity, entt);
|
||||
});
|
||||
|
||||
registry.view<int>().each([check = true](int) mutable {
|
||||
@ -367,7 +397,7 @@ TEST(SingleComponentView, EmptyTypes) {
|
||||
for(auto [entt, iv]: registry.view<int>().each()) {
|
||||
static_assert(std::is_same_v<decltype(entt), entt::entity>);
|
||||
static_assert(std::is_same_v<decltype(iv), int &>);
|
||||
ASSERT_EQ(entities[0u], entt);
|
||||
ASSERT_EQ(entity, entt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,35 +489,87 @@ TEST(SingleComponentView, StableType) {
|
||||
TEST(SingleComponentView, Storage) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
const auto view = registry.view<int>();
|
||||
const auto cview = registry.view<const char>();
|
||||
auto view = registry.view<int>();
|
||||
auto cview = registry.view<const char>();
|
||||
|
||||
static_assert(std::is_same_v<decltype(view.storage()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<0u>()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<int>()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(cview.storage()), const entt::storage_type_t<char> &>);
|
||||
static_assert(std::is_same_v<decltype(cview.storage<0u>()), const entt::storage_type_t<char> &>);
|
||||
static_assert(std::is_same_v<decltype(cview.storage<const char>()), const entt::storage_type_t<char> &>);
|
||||
static_assert(std::is_same_v<decltype(view.storage()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<0u>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<int>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<const int>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(cview.storage()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(cview.storage<0u>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(cview.storage<char>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(cview.storage<const char>()), const entt::storage_type_t<char> *>);
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_TRUE(cview);
|
||||
|
||||
ASSERT_NE(view.storage<int>(), nullptr);
|
||||
ASSERT_NE(cview.storage<0u>(), nullptr);
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(cview.size(), 0u);
|
||||
|
||||
view.storage().emplace(entity);
|
||||
view.storage()->emplace(entity);
|
||||
registry.emplace<char>(entity);
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(cview.size(), 1u);
|
||||
ASSERT_TRUE(view.storage<int>().contains(entity));
|
||||
ASSERT_TRUE(cview.storage<0u>().contains(entity));
|
||||
ASSERT_TRUE(view.storage<int>()->contains(entity));
|
||||
ASSERT_TRUE(cview.storage<0u>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<int, char>(entity)));
|
||||
|
||||
view.storage().erase(entity);
|
||||
view.storage()->erase(entity);
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(cview.size(), 1u);
|
||||
ASSERT_FALSE(view.storage<0u>().contains(entity));
|
||||
ASSERT_TRUE(cview.storage<const char>().contains(entity));
|
||||
ASSERT_FALSE(view.storage<0u>()->contains(entity));
|
||||
ASSERT_TRUE(cview.storage<const char>()->contains(entity));
|
||||
ASSERT_FALSE((registry.all_of<int, char>(entity)));
|
||||
|
||||
view = {};
|
||||
cview = {};
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
ASSERT_FALSE(cview);
|
||||
|
||||
ASSERT_EQ(view.storage<0u>(), nullptr);
|
||||
ASSERT_EQ(cview.storage<const char>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(SingleComponentView, SwapStorage) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::registry registry;
|
||||
entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<>> view;
|
||||
entt::basic_view<entt::get_t<const entt::storage<int>>, entt::exclude_t<>> cview;
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
ASSERT_FALSE(cview);
|
||||
ASSERT_EQ(view.storage<0u>(), nullptr);
|
||||
ASSERT_EQ(cview.storage<const int>(), nullptr);
|
||||
|
||||
const entt::entity entity{42u};
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
view.storage(registry.storage<int>());
|
||||
cview.storage(registry.storage<int>());
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_TRUE(cview);
|
||||
ASSERT_NE(view.storage<0u>(), nullptr);
|
||||
ASSERT_NE(cview.storage<const int>(), nullptr);
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(cview.size(), 1u);
|
||||
ASSERT_TRUE(view.contains(entity));
|
||||
ASSERT_TRUE(cview.contains(entity));
|
||||
|
||||
view.storage(registry.storage<int>("other"_hs));
|
||||
cview.storage(registry.storage<int>("other"_hs));
|
||||
|
||||
ASSERT_TRUE(view.empty());
|
||||
ASSERT_TRUE(cview.empty());
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, Functionalities) {
|
||||
@ -532,6 +614,46 @@ TEST(MultiComponentView, Functionalities) {
|
||||
ASSERT_FALSE(invalid);
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, InvalidView) {
|
||||
entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<entt::storage<char>>> view{};
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 0u);
|
||||
ASSERT_FALSE(view.contains(entt::null));
|
||||
ASSERT_EQ(view.find(entt::null), view.end());
|
||||
|
||||
ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
|
||||
ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
|
||||
|
||||
ASSERT_EQ(view.begin(), typename decltype(view)::iterator{});
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
|
||||
auto iterable = view.each();
|
||||
|
||||
ASSERT_EQ(iterable.begin(), iterable.end());
|
||||
ASSERT_EQ(iterable.cbegin(), iterable.cend());
|
||||
|
||||
view.each([](const int &) { FAIL(); });
|
||||
view.each([](const entt::entity, const int &) { FAIL(); });
|
||||
|
||||
entt::storage<int> storage;
|
||||
view.storage(storage);
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
|
||||
view.each([](const int &) { FAIL(); });
|
||||
view.each([](const entt::entity, const int &) { FAIL(); });
|
||||
|
||||
entt::storage<char> other;
|
||||
view.storage(other);
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
|
||||
view.each([](const int &) { FAIL(); });
|
||||
view.each([](const entt::entity, const int &) { FAIL(); });
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, Constructors) {
|
||||
entt::storage<int> storage{};
|
||||
|
||||
@ -543,7 +665,8 @@ TEST(MultiComponentView, Constructors) {
|
||||
ASSERT_TRUE(from_storage);
|
||||
ASSERT_TRUE(from_tuple);
|
||||
|
||||
ASSERT_EQ(&from_storage.handle(), &from_tuple.handle());
|
||||
ASSERT_NE(from_storage.handle(), nullptr);
|
||||
ASSERT_EQ(from_storage.handle(), from_tuple.handle());
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, Handle) {
|
||||
@ -551,30 +674,34 @@ TEST(MultiComponentView, Handle) {
|
||||
const auto entity = registry.create();
|
||||
|
||||
auto view = registry.view<int, char>();
|
||||
auto &&handle = view.handle();
|
||||
auto *handle = view.handle();
|
||||
|
||||
ASSERT_TRUE(handle.empty());
|
||||
ASSERT_FALSE(handle.contains(entity));
|
||||
ASSERT_EQ(&handle, &view.handle());
|
||||
ASSERT_NE(handle, nullptr);
|
||||
|
||||
ASSERT_TRUE(handle->empty());
|
||||
ASSERT_FALSE(handle->contains(entity));
|
||||
ASSERT_EQ(handle, view.handle());
|
||||
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
ASSERT_FALSE(handle.empty());
|
||||
ASSERT_TRUE(handle.contains(entity));
|
||||
ASSERT_EQ(&handle, &view.handle());
|
||||
ASSERT_FALSE(handle->empty());
|
||||
ASSERT_TRUE(handle->contains(entity));
|
||||
ASSERT_EQ(handle, view.handle());
|
||||
|
||||
view = view.refresh();
|
||||
auto &&other = view.handle();
|
||||
view.refresh();
|
||||
auto *other = view.handle();
|
||||
|
||||
ASSERT_TRUE(other.empty());
|
||||
ASSERT_FALSE(other.contains(entity));
|
||||
ASSERT_EQ(&other, &view.handle());
|
||||
ASSERT_NE(&handle, &other);
|
||||
ASSERT_NE(other, nullptr);
|
||||
|
||||
view = view.use<int>();
|
||||
ASSERT_TRUE(other->empty());
|
||||
ASSERT_FALSE(other->contains(entity));
|
||||
ASSERT_EQ(other, view.handle());
|
||||
ASSERT_NE(handle, other);
|
||||
|
||||
ASSERT_NE(&other, &view.handle());
|
||||
ASSERT_EQ(&handle, &view.handle());
|
||||
view.use<int>();
|
||||
|
||||
ASSERT_NE(other, view.handle());
|
||||
ASSERT_EQ(handle, view.handle());
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, LazyTypesFromConstRegistry) {
|
||||
@ -585,7 +712,7 @@ TEST(MultiComponentView, LazyTypesFromConstRegistry) {
|
||||
registry.emplace<empty_type>(entity);
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_FALSE(view);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 0u);
|
||||
ASSERT_FALSE(view.contains(entity));
|
||||
@ -604,7 +731,7 @@ TEST(MultiComponentView, LazyExcludedTypeFromConstRegistry) {
|
||||
|
||||
auto view = std::as_const(registry).view<const int>(entt::exclude<char>);
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_FALSE(view);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
ASSERT_TRUE(view.contains(entity));
|
||||
@ -683,7 +810,6 @@ TEST(MultiComponentView, SizeHint) {
|
||||
entt::registry registry;
|
||||
|
||||
const auto e0 = registry.create();
|
||||
registry.emplace<double>(e0);
|
||||
registry.emplace<int>(e0);
|
||||
registry.emplace<float>(e0);
|
||||
|
||||
@ -705,10 +831,10 @@ TEST(MultiComponentView, Each) {
|
||||
auto cview = std::as_const(registry).view<const int, const char>();
|
||||
|
||||
registry.emplace<int>(entity[0u], 0);
|
||||
registry.emplace<char>(entity[0u], 0);
|
||||
registry.emplace<char>(entity[0u], static_cast<char>(0));
|
||||
|
||||
registry.emplace<int>(entity[1u], 1);
|
||||
registry.emplace<char>(entity[1u], 1);
|
||||
registry.emplace<char>(entity[1u], static_cast<char>(1));
|
||||
|
||||
auto iterable = view.each();
|
||||
auto citerable = cview.each();
|
||||
@ -719,16 +845,18 @@ TEST(MultiComponentView, Each) {
|
||||
|
||||
auto it = iterable.begin();
|
||||
|
||||
ASSERT_EQ(it.base(), view.begin());
|
||||
ASSERT_EQ((it++, ++it), iterable.end());
|
||||
ASSERT_EQ(it.base(), view.end());
|
||||
|
||||
view.each([expected = 1u](auto entt, int &ivalue, char &cvalue) mutable {
|
||||
ASSERT_EQ(entt::to_integral(entt), expected);
|
||||
view.each([expected = 1](auto entt, int &ivalue, char &cvalue) mutable {
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), expected);
|
||||
ASSERT_EQ(ivalue, expected);
|
||||
ASSERT_EQ(cvalue, expected);
|
||||
--expected;
|
||||
});
|
||||
|
||||
cview.each([expected = 1u](const int &ivalue, const char &cvalue) mutable {
|
||||
cview.each([expected = 1](const int &ivalue, const char &cvalue) mutable {
|
||||
ASSERT_EQ(ivalue, expected);
|
||||
ASSERT_EQ(cvalue, expected);
|
||||
--expected;
|
||||
@ -742,13 +870,14 @@ TEST(MultiComponentView, Each) {
|
||||
|
||||
// do not use iterable, make sure an iterable view works when created from a temporary
|
||||
for(auto [entt, ivalue, cvalue]: registry.view<int, char>().each()) {
|
||||
ASSERT_EQ(entt::to_integral(entt), ivalue);
|
||||
ASSERT_EQ(entt::to_integral(entt), cvalue);
|
||||
ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), ivalue);
|
||||
ASSERT_EQ(static_cast<char>(entt::to_integral(entt)), cvalue);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, EachWithSuggestedType) {
|
||||
entt::registry registry;
|
||||
auto view = registry.view<int, char>();
|
||||
|
||||
for(auto i = 0; i < 3; ++i) {
|
||||
const auto entity = registry.create();
|
||||
@ -760,7 +889,8 @@ TEST(MultiComponentView, EachWithSuggestedType) {
|
||||
const auto entity = registry.create();
|
||||
registry.emplace<int>(entity, 99);
|
||||
|
||||
registry.view<int, char>().use<int>().each([value = 2](const auto curr, const auto) mutable {
|
||||
view.use<int>();
|
||||
view.each([value = 2](const auto curr, const auto) mutable {
|
||||
ASSERT_EQ(curr, value--);
|
||||
});
|
||||
|
||||
@ -768,7 +898,8 @@ TEST(MultiComponentView, EachWithSuggestedType) {
|
||||
return lhs < rhs;
|
||||
});
|
||||
|
||||
registry.view<int, char>().use<0u>().each([value = 0](const auto curr, const auto) mutable {
|
||||
view.use<0u>();
|
||||
view.each([value = 0](const auto curr, const auto) mutable {
|
||||
ASSERT_EQ(curr, value++);
|
||||
});
|
||||
|
||||
@ -787,8 +918,9 @@ TEST(MultiComponentView, EachWithSuggestedType) {
|
||||
});
|
||||
|
||||
value = {};
|
||||
view.use<int>();
|
||||
|
||||
for(auto &&curr: registry.view<int, char>().use<int>().each()) {
|
||||
for(auto &&curr: view.each()) {
|
||||
ASSERT_EQ(std::get<1>(curr), static_cast<int>(value++));
|
||||
}
|
||||
}
|
||||
@ -955,6 +1087,10 @@ TEST(MultiComponentView, ExcludedComponents) {
|
||||
TEST(MultiComponentView, EmptyTypes) {
|
||||
entt::registry registry;
|
||||
|
||||
auto v1 = registry.view<int, char, empty_type>(entt::exclude<double>);
|
||||
auto v2 = registry.view<int, empty_type, char>(entt::exclude<double>);
|
||||
auto v3 = registry.view<empty_type, int, char>(entt::exclude<double>);
|
||||
|
||||
const auto entity = registry.create();
|
||||
registry.emplace<int>(entity);
|
||||
registry.emplace<char>(entity);
|
||||
@ -970,57 +1106,61 @@ TEST(MultiComponentView, EmptyTypes) {
|
||||
registry.emplace<int>(ignored);
|
||||
registry.emplace<char>(ignored);
|
||||
|
||||
registry.view<int, char, empty_type>(entt::exclude<double>).each([entity](const auto entt, int, char) {
|
||||
v1.each([entity](const auto entt, int, char) {
|
||||
ASSERT_EQ(entity, entt);
|
||||
});
|
||||
|
||||
for(auto [entt, iv, cv]: registry.view<int, char, empty_type>(entt::exclude<double>).each()) {
|
||||
for(auto [entt, iv, cv]: v1.each()) {
|
||||
static_assert(std::is_same_v<decltype(entt), entt::entity>);
|
||||
static_assert(std::is_same_v<decltype(iv), int &>);
|
||||
static_assert(std::is_same_v<decltype(cv), char &>);
|
||||
ASSERT_EQ(entity, entt);
|
||||
}
|
||||
|
||||
registry.view<int, empty_type, char>(entt::exclude<double>).each([check = true](int, char) mutable {
|
||||
v2.each([check = true](int, char) mutable {
|
||||
ASSERT_TRUE(check);
|
||||
check = false;
|
||||
});
|
||||
|
||||
for(auto [entt, iv, cv]: registry.view<int, empty_type, char>(entt::exclude<double>).each()) {
|
||||
for(auto [entt, iv, cv]: v2.each()) {
|
||||
static_assert(std::is_same_v<decltype(entt), entt::entity>);
|
||||
static_assert(std::is_same_v<decltype(iv), int &>);
|
||||
static_assert(std::is_same_v<decltype(cv), char &>);
|
||||
ASSERT_EQ(entity, entt);
|
||||
}
|
||||
|
||||
registry.view<empty_type, int, char>(entt::exclude<double>).each([entity](const auto entt, int, char) {
|
||||
v3.each([entity](const auto entt, int, char) {
|
||||
ASSERT_EQ(entity, entt);
|
||||
});
|
||||
|
||||
for(auto [entt, iv, cv]: registry.view<empty_type, int, char>(entt::exclude<double>).each()) {
|
||||
for(auto [entt, iv, cv]: v3.each()) {
|
||||
static_assert(std::is_same_v<decltype(entt), entt::entity>);
|
||||
static_assert(std::is_same_v<decltype(iv), int &>);
|
||||
static_assert(std::is_same_v<decltype(cv), char &>);
|
||||
ASSERT_EQ(entity, entt);
|
||||
}
|
||||
|
||||
registry.view<empty_type, int, char>(entt::exclude<double>).use<empty_type>().each([entity](const auto entt, int, char) {
|
||||
v3.use<empty_type>();
|
||||
v3.each([entity](const auto entt, int, char) {
|
||||
ASSERT_EQ(entity, entt);
|
||||
});
|
||||
|
||||
for(auto [entt, iv, cv]: registry.view<empty_type, int, char>(entt::exclude<double>).use<0u>().each()) {
|
||||
v3.use<0u>();
|
||||
for(auto [entt, iv, cv]: v3.each()) {
|
||||
static_assert(std::is_same_v<decltype(entt), entt::entity>);
|
||||
static_assert(std::is_same_v<decltype(iv), int &>);
|
||||
static_assert(std::is_same_v<decltype(cv), char &>);
|
||||
ASSERT_EQ(entity, entt);
|
||||
}
|
||||
|
||||
registry.view<int, empty_type, char>(entt::exclude<double>).use<1u>().each([check = true](int, char) mutable {
|
||||
v2.use<1u>();
|
||||
v2.each([check = true](int, char) mutable {
|
||||
ASSERT_TRUE(check);
|
||||
check = false;
|
||||
});
|
||||
|
||||
for(auto [entt, iv, cv]: registry.view<int, empty_type, char>(entt::exclude<double>).use<empty_type>().each()) {
|
||||
v2.use<empty_type>();
|
||||
for(auto [entt, iv, cv]: v2.each()) {
|
||||
static_assert(std::is_same_v<decltype(entt), entt::entity>);
|
||||
static_assert(std::is_same_v<decltype(iv), int &>);
|
||||
static_assert(std::is_same_v<decltype(cv), char &>);
|
||||
@ -1111,7 +1251,7 @@ TEST(MultiComponentView, StableType) {
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
|
||||
view = view.use<stable_type>();
|
||||
view.use<stable_type>();
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 2u);
|
||||
ASSERT_FALSE(view.contains(entity));
|
||||
@ -1146,7 +1286,9 @@ TEST(MultiComponentView, StableType) {
|
||||
|
||||
TEST(MultiComponentView, StableTypeWithExcludedComponent) {
|
||||
entt::registry registry;
|
||||
auto view = registry.view<stable_type>(entt::exclude<int>).use<stable_type>();
|
||||
auto view = registry.view<stable_type>(entt::exclude<int>);
|
||||
|
||||
view.use<stable_type>();
|
||||
|
||||
const auto entity = registry.create();
|
||||
const auto other = registry.create();
|
||||
@ -1223,8 +1365,118 @@ TEST(MultiComponentView, SameComponentTypes) {
|
||||
ASSERT_EQ(second, 9);
|
||||
}
|
||||
|
||||
ASSERT_EQ(&view.handle(), &storage);
|
||||
ASSERT_EQ(&view.use<1u>().handle(), &other);
|
||||
ASSERT_EQ(view.handle(), &storage);
|
||||
|
||||
view.use<1u>();
|
||||
|
||||
ASSERT_EQ(view.handle(), &other);
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, Storage) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
auto view = registry.view<int, const char>(entt::exclude<double, const float>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(view.storage<0u>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<int>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<const int>()), entt::storage_type_t<int> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<1u>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<char>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<const char>()), const entt::storage_type_t<char> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<2u>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<double>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<const double>()), entt::storage_type_t<double> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<3u>()), const entt::storage_type_t<float> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<float>()), const entt::storage_type_t<float> *>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<const float>()), const entt::storage_type_t<float> *>);
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
|
||||
ASSERT_NE(view.storage<int>(), nullptr);
|
||||
ASSERT_NE(view.storage<1u>(), nullptr);
|
||||
ASSERT_NE(view.storage<double>(), nullptr);
|
||||
ASSERT_NE(view.storage<3u>(), nullptr);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 0u);
|
||||
|
||||
view.storage<int>()->emplace(entity);
|
||||
view.storage<double>()->emplace(entity);
|
||||
registry.emplace<char>(entity);
|
||||
registry.emplace<float>(entity);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
ASSERT_TRUE(view.storage<int>()->contains(entity));
|
||||
ASSERT_TRUE(view.storage<const char>()->contains(entity));
|
||||
ASSERT_TRUE(view.storage<double>()->contains(entity));
|
||||
ASSERT_TRUE(view.storage<const float>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<int, char, double, float>(entity)));
|
||||
|
||||
view.storage<double>()->erase(entity);
|
||||
registry.erase<float>(entity);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
ASSERT_TRUE(view.storage<const int>()->contains(entity));
|
||||
ASSERT_TRUE(view.storage<char>()->contains(entity));
|
||||
ASSERT_FALSE(view.storage<const double>()->contains(entity));
|
||||
ASSERT_FALSE(view.storage<float>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<int, char>(entity)));
|
||||
ASSERT_FALSE((registry.any_of<double, float>(entity)));
|
||||
|
||||
view.storage<0u>()->erase(entity);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
ASSERT_FALSE(view.storage<0u>()->contains(entity));
|
||||
ASSERT_TRUE(view.storage<1u>()->contains(entity));
|
||||
ASSERT_FALSE(view.storage<2u>()->contains(entity));
|
||||
ASSERT_FALSE(view.storage<3u>()->contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<char>(entity)));
|
||||
ASSERT_FALSE((registry.any_of<int, double, float>(entity)));
|
||||
|
||||
view = {};
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
|
||||
ASSERT_EQ(view.storage<0u>(), nullptr);
|
||||
ASSERT_EQ(view.storage<const char>(), nullptr);
|
||||
ASSERT_EQ(view.storage<2u>(), nullptr);
|
||||
ASSERT_EQ(view.storage<const float>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, SwapStorage) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::registry registry;
|
||||
entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<const entt::storage<char>>> view;
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
ASSERT_EQ(view.storage<0u>(), nullptr);
|
||||
ASSERT_EQ(view.storage<const char>(), nullptr);
|
||||
|
||||
const entt::entity entity{42u};
|
||||
registry.emplace<int>(entity);
|
||||
registry.emplace<char>(entity);
|
||||
|
||||
view.storage(registry.storage<int>());
|
||||
view.storage<1u>(registry.storage<char>());
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_NE(view.storage<int>(), nullptr);
|
||||
ASSERT_NE(view.storage<1u>(), nullptr);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
ASSERT_FALSE(view.contains(entity));
|
||||
|
||||
view.storage(registry.storage<char>("other"_hs));
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
ASSERT_TRUE(view.contains(entity));
|
||||
|
||||
view.storage(registry.storage<int>("empty"_hs));
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 0u);
|
||||
}
|
||||
|
||||
TEST(View, Pipe) {
|
||||
@ -1241,10 +1493,10 @@ TEST(View, Pipe) {
|
||||
registry.emplace<char>(other);
|
||||
registry.emplace<stable_type>(other);
|
||||
|
||||
const auto view1 = registry.view<int>(entt::exclude<const double>);
|
||||
const auto view2 = registry.view<const char>(entt::exclude<float>);
|
||||
const auto view3 = registry.view<empty_type>();
|
||||
const auto view4 = registry.view<stable_type>();
|
||||
auto view1 = registry.view<int>(entt::exclude<const double>);
|
||||
auto view2 = registry.view<const char>(entt::exclude<float>);
|
||||
auto view3 = registry.view<empty_type>();
|
||||
auto view4 = registry.view<stable_type>();
|
||||
|
||||
static_assert(std::is_same_v<entt::basic_view<entt::get_t<entt::storage_type_t<int>, const entt::storage_type_t<char>>, entt::exclude_t<const entt::storage_type_t<double>, entt::storage_type_t<float>>>, decltype(view1 | view2)>);
|
||||
static_assert(std::is_same_v<entt::basic_view<entt::get_t<const entt::storage_type_t<char>, entt::storage_type_t<int>>, entt::exclude_t<entt::storage_type_t<float>, const entt::storage_type_t<double>>>, decltype(view2 | view1)>);
|
||||
@ -1261,30 +1513,26 @@ TEST(View, Pipe) {
|
||||
|
||||
ASSERT_FALSE((view1 | view4 | view2).contains(entity));
|
||||
ASSERT_TRUE((view1 | view4 | view2).contains(other));
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, Storage) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
const auto view = registry.view<int, const char>();
|
||||
|
||||
static_assert(std::is_same_v<decltype(view.storage<0u>()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<int>()), entt::storage_type_t<int> &>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<1u>()), const entt::storage_type_t<char> &>);
|
||||
static_assert(std::is_same_v<decltype(view.storage<const char>()), const entt::storage_type_t<char> &>);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 0u);
|
||||
|
||||
view.storage<int>().emplace(entity);
|
||||
registry.emplace<char>(entity);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
ASSERT_TRUE(view.storage<const char>().contains(entity));
|
||||
ASSERT_TRUE((registry.all_of<int, char>(entity)));
|
||||
|
||||
view.storage<0u>().erase(entity);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 0u);
|
||||
ASSERT_TRUE(view.storage<1u>().contains(entity));
|
||||
ASSERT_FALSE((registry.all_of<int, char>(entity)));
|
||||
|
||||
view1 = {};
|
||||
view3 = {};
|
||||
|
||||
ASSERT_FALSE(view1);
|
||||
ASSERT_TRUE(view2);
|
||||
ASSERT_FALSE(view3);
|
||||
ASSERT_TRUE(view4);
|
||||
|
||||
auto pack14 = view1 | view4;
|
||||
auto pack32 = view3 | view2;
|
||||
|
||||
ASSERT_FALSE(pack14);
|
||||
ASSERT_FALSE(pack32);
|
||||
|
||||
ASSERT_EQ(pack14.storage<int>(), nullptr);
|
||||
ASSERT_EQ(pack14.storage<const double>(), nullptr);
|
||||
ASSERT_NE(pack14.storage<stable_type>(), nullptr);
|
||||
|
||||
ASSERT_EQ(pack32.storage<empty_type>(), nullptr);
|
||||
ASSERT_NE(pack32.storage<const char>(), nullptr);
|
||||
ASSERT_NE(pack32.storage<float>(), nullptr);
|
||||
}
|
||||
|
Reference in New Issue
Block a user