Initial commit - restart from existing code

This commit is contained in:
Tom Ray
2026-02-13 19:15:05 +01:00
parent 11df621bb2
commit 7c352bc280
1906 changed files with 491226 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
#include <cstdint>
#include <gtest/gtest.h>
#include <entt/entity/entity.hpp>
#include <entt/entity/registry.hpp>
struct entity_id final {
using entity_type = std::uint32_t;
static constexpr auto null = entt::null;
constexpr entity_id(entity_type value = null) noexcept
: entt{value} {}
~entity_id() = default;
constexpr entity_id(const entity_id &other) = default;
constexpr entity_id(entity_id &&other) noexcept = default;
constexpr entity_id &operator=(const entity_id &other) = default;
constexpr entity_id &operator=(entity_id &&other) noexcept = default;
constexpr operator entity_type() const noexcept {
return entt;
}
private:
entity_type entt;
};
TEST(Example, CustomIdentifier) {
entt::basic_registry<entity_id> registry{};
entity_id entity{};
ASSERT_FALSE(registry.valid(entity));
ASSERT_TRUE(entity == entt::null);
entity = registry.create();
ASSERT_TRUE(registry.valid(entity));
ASSERT_TRUE(entity != entt::null);
ASSERT_FALSE((registry.all_of<int, char>(entity)));
ASSERT_EQ(registry.try_get<int>(entity), nullptr);
registry.emplace<int>(entity, 2);
ASSERT_TRUE((registry.any_of<int, char>(entity)));
ASSERT_EQ(registry.get<int>(entity), 2);
registry.destroy(entity);
ASSERT_FALSE(registry.valid(entity));
ASSERT_TRUE(entity != entt::null);
entity = registry.create();
ASSERT_TRUE(registry.valid(entity));
ASSERT_TRUE(entity != entt::null);
}

View File

@@ -0,0 +1,124 @@
#include <gtest/gtest.h>
#include <entt/core/hashed_string.hpp>
#include <entt/core/utility.hpp>
#include <entt/entity/registry.hpp>
#include <entt/entity/storage.hpp>
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/policy.hpp>
#include <entt/meta/resolve.hpp>
enum class my_entity : entt::id_type {};
template<typename Type>
// NOLINTNEXTLINE(*-exception-escape)
struct meta_mixin: Type {
using allocator_type = typename Type::allocator_type;
using element_type = typename Type::element_type;
explicit meta_mixin(const allocator_type &allocator);
};
template<typename Type, typename Entity>
struct entt::storage_type<Type, Entity> {
using type = meta_mixin<basic_storage<Type, Entity>>;
};
template<typename Type>
meta_mixin<Type>::meta_mixin(const allocator_type &allocator)
: Type{allocator} {
using namespace entt::literals;
entt::meta_factory<element_type>{}
// cross registry, same type
.template func<entt::overload<entt::storage_for_t<element_type, entt::entity> &(const entt::id_type)>(&entt::basic_registry<entt::entity>::storage<element_type>), entt::as_ref_t>("storage"_hs)
// cross registry, different types
.template func<entt::overload<entt::storage_for_t<element_type, my_entity> &(const entt::id_type)>(&entt::basic_registry<my_entity>::storage<element_type>), entt::as_ref_t>("storage"_hs);
}
template<typename Type>
struct EntityCopy: testing::Test {
using type = Type;
};
using EntityCopyTypes = ::testing::Types<entt::basic_registry<entt::entity>, entt::basic_registry<my_entity>>;
TYPED_TEST_SUITE(EntityCopy, EntityCopyTypes, );
TEST(EntityCopy, SameRegistry) {
using namespace entt::literals;
entt::registry registry{};
auto &&custom = registry.storage<double>("custom"_hs);
const auto src = registry.create();
const auto dst = registry.create();
custom.emplace(src, 1.);
registry.emplace<int>(src, 2);
registry.emplace<char>(src, 'c');
ASSERT_EQ(registry.storage<entt::entity>().size(), 2u);
ASSERT_TRUE(custom.contains(src));
ASSERT_FALSE(custom.contains(dst));
ASSERT_TRUE((registry.all_of<int, char>(src)));
ASSERT_FALSE((registry.any_of<int, char>(dst)));
for(auto [id, storage]: registry.storage()) {
// discard the custom storage because why not, this is just an example after all
if(id != "custom"_hs && storage.contains(src)) {
storage.push(dst, storage.value(src));
}
}
ASSERT_EQ(registry.storage<entt::entity>().size(), 2u);
ASSERT_TRUE(custom.contains(src));
ASSERT_FALSE(custom.contains(dst));
ASSERT_TRUE((registry.all_of<int, char>(src)));
ASSERT_TRUE((registry.all_of<int, char>(dst)));
ASSERT_EQ(registry.get<int>(dst), 2);
ASSERT_EQ(registry.get<char>(dst), 'c');
}
TYPED_TEST(EntityCopy, CrossRegistry) {
using namespace entt::literals;
entt::basic_registry<entt::entity> src{};
// other registry type, see typed test suite
typename TestFixture::type dst{};
const auto entity = src.create();
const auto copy = dst.create();
src.emplace<int>(entity, 2);
src.emplace<char>(entity, 'c');
ASSERT_EQ(src.storage<entt::entity>().size(), 1u);
ASSERT_EQ(dst.template storage<typename TestFixture::type::entity_type>().size(), 1u);
ASSERT_TRUE((src.all_of<int, char>(entity)));
ASSERT_FALSE((dst.template all_of<int, char>(copy)));
for(auto [id, storage]: src.storage()) {
if(storage.contains(entity)) {
auto *other = dst.storage(id);
if(!other) {
using namespace entt::literals;
entt::resolve(storage.type()).invoke("storage"_hs, {}, entt::forward_as_meta(dst), id);
other = dst.storage(id);
}
other->push(copy, storage.value(entity));
}
}
ASSERT_EQ(src.storage<entt::entity>().size(), 1u);
ASSERT_EQ(dst.template storage<typename TestFixture::type::entity_type>().size(), 1u);
ASSERT_TRUE((src.all_of<int, char>(entity)));
ASSERT_TRUE((dst.template all_of<int, char>(copy)));
ASSERT_EQ(dst.template get<int>(copy), 2);
ASSERT_EQ(dst.template get<char>(copy), 'c');
}

View File

@@ -0,0 +1,143 @@
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <gtest/gtest.h>
#include <entt/config/config.h>
#include <entt/core/enum.hpp>
#include <entt/core/fwd.hpp>
#include <entt/entity/entity.hpp>
#include <entt/entity/mixin.hpp>
#include <entt/entity/registry.hpp>
#include <entt/entity/view.hpp>
enum class my_entity : entt::id_type {
disabled = 0x10000000,
_entt_enum_as_bitmask
};
struct entity_traits {
using value_type = my_entity;
using entity_type = std::uint32_t;
using version_type = std::uint16_t;
static constexpr entity_type entity_mask = 0xFFFF; // 16b
static constexpr entity_type version_mask = 0x0FFF; // 12b
};
template<>
struct entt::entt_traits<my_entity>: entt::basic_entt_traits<entity_traits> {
static constexpr std::size_t page_size = ENTT_SPARSE_PAGE;
};
namespace {
[[nodiscard]] bool is_disabled(const my_entity entity) {
return ((entity & my_entity::disabled) == my_entity::disabled);
}
} // namespace
TEST(Example, DisabledEntity) {
entt::basic_registry<my_entity> registry{};
auto view = registry.view<my_entity, int>();
const my_entity entity = registry.create(entt::entt_traits<my_entity>::construct(4u, 1u));
const my_entity other = registry.create(entt::entt_traits<my_entity>::construct(3u, 0u));
registry.emplace<int>(entity);
registry.emplace<int>(other);
ASSERT_FALSE(is_disabled(*registry.storage<my_entity>().find(entity)));
ASSERT_FALSE(is_disabled(*registry.storage<my_entity>().find(other)));
ASSERT_FALSE(is_disabled(*registry.storage<int>().find(entity)));
ASSERT_FALSE(is_disabled(*registry.storage<int>().find(other)));
registry.storage<my_entity>().bump(entity | my_entity::disabled);
ASSERT_TRUE(is_disabled(*registry.storage<my_entity>().find(entity)));
ASSERT_FALSE(is_disabled(*registry.storage<my_entity>().find(other)));
ASSERT_FALSE(is_disabled(*registry.storage<int>().find(entity)));
ASSERT_FALSE(is_disabled(*registry.storage<int>().find(other)));
view.use<my_entity>();
ASSERT_EQ(std::distance(view.begin(), view.end()), 2);
for(auto entt: view) {
if(entt::to_entity(entt) == entt::to_entity(entity)) {
ASSERT_NE(entt, entity);
ASSERT_EQ(entt::to_version(entt), entt::to_version(entity));
ASSERT_TRUE(is_disabled(entt));
} else {
ASSERT_EQ(entt, other);
ASSERT_EQ(entt::to_version(entt), entt::to_version(other));
ASSERT_FALSE(is_disabled(entt));
}
}
view.use<int>();
ASSERT_EQ(std::distance(view.begin(), view.end()), 2);
for(auto entt: view) {
ASSERT_FALSE(is_disabled(entt));
}
registry.storage<my_entity>().bump(entity);
registry.storage<int>().bump(other | my_entity::disabled);
ASSERT_FALSE(is_disabled(*registry.storage<my_entity>().find(entity)));
ASSERT_FALSE(is_disabled(*registry.storage<my_entity>().find(other)));
ASSERT_FALSE(is_disabled(*registry.storage<int>().find(entity)));
ASSERT_TRUE(is_disabled(*registry.storage<int>().find(other)));
view.use<my_entity>();
ASSERT_EQ(std::distance(view.begin(), view.end()), 2);
for(auto entt: view) {
ASSERT_FALSE(is_disabled(entt));
}
view.use<int>();
ASSERT_EQ(std::distance(view.begin(), view.end()), 2);
for(auto entt: view) {
if(entt::to_entity(entt) == entt::to_entity(other)) {
ASSERT_NE(entt, other);
ASSERT_EQ(entt::to_version(entt), entt::to_version(other));
ASSERT_TRUE(is_disabled(entt));
} else {
ASSERT_EQ(entt, entity);
ASSERT_EQ(entt::to_version(entt), entt::to_version(entity));
ASSERT_FALSE(is_disabled(entt));
}
}
registry.storage<int>().bump(other);
ASSERT_FALSE(is_disabled(*registry.storage<my_entity>().find(entity)));
ASSERT_FALSE(is_disabled(*registry.storage<my_entity>().find(other)));
ASSERT_FALSE(is_disabled(*registry.storage<int>().find(entity)));
ASSERT_FALSE(is_disabled(*registry.storage<int>().find(other)));
view.use<my_entity>();
ASSERT_EQ(std::distance(view.begin(), view.end()), 2);
for(auto entt: view) {
ASSERT_FALSE(is_disabled(entt));
}
view.use<int>();
ASSERT_EQ(std::distance(view.begin(), view.end()), 2);
for(auto entt: view) {
ASSERT_FALSE(is_disabled(entt));
}
}

View File

@@ -0,0 +1,43 @@
#include <array>
#include <type_traits>
#include <gtest/gtest.h>
#include <entt/entity/registry.hpp>
#include <entt/entity/storage.hpp>
template<typename Type, typename Entity>
struct entt::storage_type<Type, Entity> {
// no signal regardless of element type ...
using type = basic_storage<Type, Entity>;
};
template<typename Entity>
struct entt::storage_type<char, Entity> {
// ... unless it's char, because yes.
using type = sigh_mixin<basic_storage<char, Entity>>;
};
template<typename, typename, typename = void>
struct has_on_construct: std::false_type {};
template<typename Entity, typename Type>
struct has_on_construct<Entity, Type, std::void_t<decltype(&entt::storage_type_t<Type>::on_construct)>>: std::true_type {};
template<typename Entity, typename Type>
inline constexpr auto has_on_construct_v = has_on_construct<Entity, Type>::value;
TEST(Example, SignalLess) {
// invoking registry::on_construct<int> is a compile-time error
ASSERT_FALSE((has_on_construct_v<entt::entity, int>));
ASSERT_TRUE((has_on_construct_v<entt::entity, char>));
entt::registry registry;
const std::array entity{registry.create()};
// literally a test for storage_adapter_mixin
registry.emplace<int>(entity[0], 0);
registry.erase<int>(entity[0]);
registry.insert<int>(entity.begin(), entity.end(), 3);
registry.patch<int>(entity[0], [](auto &value) { value = 2; });
ASSERT_EQ(registry.get<int>(entity[0]), 2);
}