registry: uses type_id_v rather than families
This commit is contained in:
5
TODO
5
TODO
@@ -19,6 +19,7 @@
|
||||
* any-of rule for views/groups (eg entity has A and any of B/C/D)
|
||||
* sparse set: there exists an alternative to paginated sparse arrays?
|
||||
* see warning (vs2017 only): d:\a\entt\entt\src\entt\entity\registry.hpp(108)
|
||||
* remove duktape example (and eventually provide a new one)?
|
||||
* registry
|
||||
- ::assure -> pool_type<T> &
|
||||
- ::group improve, reduce code
|
||||
@@ -26,6 +27,10 @@
|
||||
* Mission: get rid of named types
|
||||
- make it possible to use custom generators (eg for plugins)
|
||||
* registry
|
||||
* remove entt::component
|
||||
* clean-up superfluous to_integer
|
||||
* ENTT_ID_TYPE id() (eg dispatcher) can be a data member rather than a virtual function
|
||||
* define a kind of assure also for context variables
|
||||
* meta: use type_id, remove import, everything should work transparently
|
||||
* type_id_enabled and fallback on old-fashioned families otherwise
|
||||
* add discard pool functionality (+ test)
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include "../config/config.h"
|
||||
#include "../core/family.hpp"
|
||||
#include "../core/algorithm.hpp"
|
||||
#include "../core/attribute.h"
|
||||
#include "../core/type_info.hpp"
|
||||
#include "../core/type_traits.hpp"
|
||||
#include "../signal/sigh.hpp"
|
||||
#include "runtime_view.hpp"
|
||||
@@ -42,15 +41,6 @@ namespace entt {
|
||||
*/
|
||||
template<typename Entity>
|
||||
class basic_registry {
|
||||
struct ENTT_API registry_context_family;
|
||||
struct ENTT_API registry_component_family;
|
||||
|
||||
template<typename Type>
|
||||
using context_family = family<Type, registry_context_family>;
|
||||
|
||||
template<typename Type>
|
||||
using component_family = family<Type, registry_component_family>;
|
||||
|
||||
using traits_type = entt_traits<std::underlying_type_t<Entity>>;
|
||||
|
||||
template<typename Component>
|
||||
@@ -157,6 +147,7 @@ class basic_registry {
|
||||
};
|
||||
|
||||
struct pool_data {
|
||||
ENTT_ID_TYPE id;
|
||||
std::unique_ptr<sparse_set<Entity>> pool;
|
||||
void(* assure)(basic_registry &, const sparse_set<Entity> &);
|
||||
void(* remove)(sparse_set<Entity> &, basic_registry &, const Entity);
|
||||
@@ -166,23 +157,28 @@ class basic_registry {
|
||||
struct group_data {
|
||||
std::size_t extent[3];
|
||||
std::unique_ptr<void, void(*)(void *)> group;
|
||||
bool(* owned)(const component) ENTT_NOEXCEPT;
|
||||
bool(* get)(const component) ENTT_NOEXCEPT;
|
||||
bool(* exclude)(const component) ENTT_NOEXCEPT;
|
||||
bool(* owned)(const ENTT_ID_TYPE) ENTT_NOEXCEPT;
|
||||
bool(* get)(const ENTT_ID_TYPE) ENTT_NOEXCEPT;
|
||||
bool(* exclude)(const ENTT_ID_TYPE) ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
struct basic_variable {
|
||||
virtual ~basic_variable() = default;
|
||||
virtual ENTT_ID_TYPE id() const ENTT_NOEXCEPT = 0;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct variable_handler: basic_variable {
|
||||
Type value;
|
||||
|
||||
template<typename... Args>
|
||||
variable_handler(Args &&... args)
|
||||
: value{std::forward<Args>(args)...}
|
||||
{}
|
||||
|
||||
Type value;
|
||||
ENTT_ID_TYPE id() const ENTT_NOEXCEPT override {
|
||||
return type_id_v<Type>;
|
||||
}
|
||||
};
|
||||
|
||||
auto generate() {
|
||||
@@ -214,31 +210,37 @@ class basic_registry {
|
||||
|
||||
template<typename Component, typename... Args>
|
||||
const pool_type<Component> * assure(Args &&... args) const {
|
||||
const auto ctype = to_integer(type<Component>());
|
||||
static_assert(std::is_same_v<Component, std::decay_t<Component>>);
|
||||
static std::size_t index{pools.size()};
|
||||
|
||||
if(!(ctype < pools.size())) {
|
||||
pools.resize(ctype+1);
|
||||
}
|
||||
if(!(index < pools.size()) || pools[index].id != type_id_v<Component>) {
|
||||
index = std::find_if(pools.cbegin(), pools.cend(), [](auto &&cpool) {
|
||||
return cpool.id == type_id_v<Component>;
|
||||
}) - pools.cbegin();
|
||||
|
||||
if(!pools[ctype].pool) {
|
||||
pools[ctype].pool = std::make_unique<pool_type<Component>>(std::forward<Args>(args)...);
|
||||
if(index == pools.size()) {
|
||||
auto &&pdata = pools.emplace_back();
|
||||
|
||||
pools[ctype].remove = [](sparse_set<Entity> &cpool, basic_registry &owner, const Entity entt) {
|
||||
static_cast<pool_type<Component> &>(cpool).remove(owner, entt);
|
||||
};
|
||||
pdata.id = type_id_v<Component>;
|
||||
pdata.pool = std::make_unique<pool_type<Component>>(std::forward<Args>(args)...);
|
||||
|
||||
if constexpr(std::is_copy_constructible_v<std::decay_t<Component>>) {
|
||||
pools[ctype].assure = [](basic_registry &other, const sparse_set<Entity> &cpool) {
|
||||
other.assure<Component>(static_cast<const pool_type<Component> &>(cpool));
|
||||
pdata.remove = [](sparse_set<Entity> &cpool, basic_registry &owner, const Entity entt) {
|
||||
static_cast<pool_type<Component> &>(cpool).remove(owner, entt);
|
||||
};
|
||||
|
||||
pools[ctype].stomp = [](basic_registry &other, const Entity dst, const sparse_set<Entity> &cpool, const Entity src) {
|
||||
other.assign_or_replace<Component>(dst, static_cast<const pool_type<Component> &>(cpool).get(src));
|
||||
};
|
||||
if constexpr(std::is_copy_constructible_v<std::decay_t<Component>>) {
|
||||
pdata.assure = [](basic_registry &other, const sparse_set<Entity> &cpool) {
|
||||
other.assure<Component>(static_cast<const pool_type<Component> &>(cpool));
|
||||
};
|
||||
|
||||
pdata.stomp = [](basic_registry &other, const Entity dst, const sparse_set<Entity> &cpool, const Entity src) {
|
||||
other.assign_or_replace<Component>(dst, static_cast<const pool_type<Component> &>(cpool).get(src));
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<pool_type<Component> *>(pools[ctype].pool.get());
|
||||
return static_cast<pool_type<Component> *>(pools[index].pool.get());
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
@@ -263,20 +265,6 @@ public:
|
||||
/*! @brief Default move assignment operator. @return This registry. */
|
||||
basic_registry & operator=(basic_registry &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Returns the opaque identifier of a component.
|
||||
*
|
||||
* The given component doesn't need to be necessarily in use.<br/>
|
||||
* Identifiers aren't guaranteed to be stable between different runs.
|
||||
*
|
||||
* @tparam Component Type of component to query.
|
||||
* @return The opaque identifier of the given type of component.
|
||||
*/
|
||||
template<typename Component>
|
||||
static component type() ENTT_NOEXCEPT {
|
||||
return component{component_family<std::decay_t<Component>>::type()};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares a pool for the given type if required.
|
||||
* @tparam Component Type of component for which to prepare a pool.
|
||||
@@ -285,7 +273,7 @@ public:
|
||||
*/
|
||||
template<typename Component, typename... Args>
|
||||
void prepare(Args &&... args) {
|
||||
ENTT_ASSERT(!(to_integer(type<Component>()) < pools.size()) || !pools[to_integer(type<Component>())].pool);
|
||||
ENTT_ASSERT(std::none_of(pools.cbegin(), pools.cend(), [](auto &&pdata) { return pdata.id == type_id_v<Component>; }));
|
||||
assure<Component>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -569,7 +557,7 @@ public:
|
||||
ENTT_ASSERT(valid(entity));
|
||||
|
||||
for(auto pos = pools.size(); pos; --pos) {
|
||||
if(auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->has(entity)) {
|
||||
if(auto &pdata = pools[pos-1]; pdata.pool->has(entity)) {
|
||||
pdata.remove(*pdata.pool, *this, entity);
|
||||
}
|
||||
}
|
||||
@@ -956,8 +944,7 @@ public:
|
||||
bool orphan = true;
|
||||
|
||||
for(std::size_t pos{}, last = pools.size(); pos < last && orphan; ++pos) {
|
||||
const auto &pdata = pools[pos];
|
||||
orphan = !(pdata.pool && pdata.pool->has(entity));
|
||||
orphan = !pools[pos].pool->has(entity);
|
||||
}
|
||||
|
||||
return orphan;
|
||||
@@ -1216,7 +1203,7 @@ public:
|
||||
template<typename... Component, typename... Exclude>
|
||||
entt::basic_view<Entity, exclude_t<Exclude...>, Component...> view(exclude_t<Exclude...> = {}) {
|
||||
static_assert(sizeof...(Component) > 0);
|
||||
return { assure<Component>()..., assure<Exclude>()... };
|
||||
return { assure<std::decay_t<Component>>()..., assure<Exclude>()... };
|
||||
}
|
||||
|
||||
/*! @copydoc view */
|
||||
@@ -1272,15 +1259,15 @@ public:
|
||||
using handler_type = group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...>;
|
||||
|
||||
[[maybe_unused]] constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
|
||||
const auto cpools = std::make_tuple(assure<Owned>()..., assure<Get>()..., assure<Exclude>()...);
|
||||
const auto cpools = std::make_tuple(assure<std::decay_t<Owned>>()..., assure<std::decay_t<Get>>()..., assure<Exclude>()...);
|
||||
const std::size_t extent[3]{sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)};
|
||||
handler_type *handler = nullptr;
|
||||
|
||||
if(auto it = std::find_if(groups.cbegin(), groups.cend(), [&extent](const auto &gdata) {
|
||||
return std::equal(std::begin(extent), std::end(extent), std::begin(gdata.extent))
|
||||
&& (gdata.owned(type<Owned>()) && ...)
|
||||
&& (gdata.get(type<Get>()) && ...)
|
||||
&& (gdata.exclude(type<Exclude>()) && ...);
|
||||
&& (gdata.owned(type_id_v<std::decay_t<Owned>>) && ...)
|
||||
&& (gdata.get(type_id_v<std::decay_t<Get>>) && ...)
|
||||
&& (gdata.exclude(type_id_v<Exclude>) && ...);
|
||||
}); it != groups.cend())
|
||||
{
|
||||
handler = static_cast<handler_type *>(it->group.get());
|
||||
@@ -1293,26 +1280,31 @@ public:
|
||||
group_data gdata{
|
||||
{ sizeof...(Owned), sizeof...(Get), sizeof...(Exclude) },
|
||||
decltype(group_data::group){new handler_type{cpools}, [](void *gptr) { delete static_cast<handler_type *>(gptr); }},
|
||||
[](const component ctype) ENTT_NOEXCEPT { return ((ctype == type<Owned>()) || ...); },
|
||||
[](const component ctype) ENTT_NOEXCEPT { return ((ctype == type<Get>()) || ...); },
|
||||
[](const component ctype) ENTT_NOEXCEPT { return ((ctype == type<Exclude>()) || ...); }
|
||||
[](const auto ctype) ENTT_NOEXCEPT { return ((ctype == type_id_v<std::decay_t<Owned>>) || ...); },
|
||||
[](const auto ctype) ENTT_NOEXCEPT { return ((ctype == type_id_v<std::decay_t<Get>>) || ...); },
|
||||
[](const auto ctype) ENTT_NOEXCEPT { return ((ctype == type_id_v<Exclude>) || ...); }
|
||||
};
|
||||
|
||||
if constexpr(sizeof...(Owned) == 0) {
|
||||
handler = static_cast<handler_type *>(groups.emplace_back(std::move(gdata)).group.get());
|
||||
} else {
|
||||
ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [&extent](const auto &curr) {
|
||||
const std::size_t diff[3]{ (0u + ... + curr.owned(type<Owned>())), (0u + ... + curr.get(type<Get>())), (0u + ... + curr.exclude(type<Exclude>())) };
|
||||
const std::size_t diff[3]{
|
||||
(0u + ... + curr.owned(type_id_v<std::decay_t<Owned>>)),
|
||||
(0u + ... + curr.get(type_id_v<std::decay_t<Get>>)),
|
||||
(0u + ... + curr.exclude(type_id_v<Exclude>))
|
||||
};
|
||||
|
||||
return !diff[0] || ((std::equal(std::begin(diff), std::end(diff), extent) || std::equal(std::begin(diff), std::end(diff), curr.extent)));
|
||||
}));
|
||||
|
||||
const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [&size](const auto &curr) {
|
||||
const std::size_t diff = (0u + ... + curr.owned(type<Owned>()));
|
||||
const std::size_t diff = (0u + ... + curr.owned(type_id_v<std::decay_t<Owned>>));
|
||||
return !diff || (size > (curr.extent[0] + curr.extent[1] + curr.extent[2]));
|
||||
});
|
||||
|
||||
const auto prev = std::find_if(std::make_reverse_iterator(next), groups.crend(), [](const auto &curr) {
|
||||
return (0u + ... + curr.owned(type<Owned>()));
|
||||
return (0u + ... + curr.owned(type_id_v<std::decay_t<Owned>>));
|
||||
});
|
||||
|
||||
maybe_valid_if = (next == groups.cend() ? maybe_valid_if : next->group.get());
|
||||
@@ -1432,7 +1424,11 @@ public:
|
||||
std::vector<const sparse_set<Entity> *> selected(std::distance(first, last));
|
||||
|
||||
std::transform(first, last, selected.begin(), [this](const component ctype) {
|
||||
return to_integer(ctype) < pools.size() ? pools[to_integer(ctype)].pool.get() : nullptr;
|
||||
const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) {
|
||||
return pdata.id == to_integer(ctype);
|
||||
});
|
||||
|
||||
return it == pools.cend() ? nullptr : it->pool.get();
|
||||
});
|
||||
|
||||
return { std::move(selected) };
|
||||
@@ -1480,7 +1476,7 @@ public:
|
||||
|
||||
if constexpr(sizeof...(Component) == 0) {
|
||||
for(size_type pos{}; pos < pools.size(); ++pos) {
|
||||
if(const auto &pdata = pools[pos]; pdata.assure && ((pos != to_integer(type<Exclude>())) && ...)) {
|
||||
if(const auto &pdata = pools[pos]; pdata.assure && ((pdata.id != type_id_v<Exclude>) && ...)) {
|
||||
pdata.assure(other, *pdata.pool);
|
||||
}
|
||||
}
|
||||
@@ -1533,7 +1529,7 @@ public:
|
||||
void stomp(const entity_type dst, const basic_registry &other, const entity_type src, exclude_t<Exclude...> = {}) {
|
||||
if constexpr(sizeof...(Component) == 0) {
|
||||
for(size_type pos{}; pos < other.pools.size(); ++pos) {
|
||||
if(const auto &pdata = other.pools[pos]; pdata.stomp && ((pos != to_integer(type<Exclude>())) && ...) && pdata.pool->has(src)) {
|
||||
if(const auto &pdata = other.pools[pos]; pdata.stomp && ((pdata.id != type_id_v<Exclude>) && ...) && pdata.pool->has(src)) {
|
||||
pdata.stomp(*this, dst, *pdata.pool, src);
|
||||
}
|
||||
}
|
||||
@@ -1629,14 +1625,9 @@ public:
|
||||
*/
|
||||
template<typename Type, typename... Args>
|
||||
Type & set(Args &&... args) {
|
||||
const auto vtype = context_family<std::decay_t<Type>>::type();
|
||||
|
||||
if(!(vtype < vars.size())) {
|
||||
vars.resize(vtype+1);
|
||||
}
|
||||
|
||||
vars[vtype] = std::make_unique<variable_handler<Type>>(std::forward<Args>(args)...);
|
||||
return static_cast<variable_handler<Type> &>(*vars[vtype]).value;
|
||||
unset<Type>();
|
||||
vars.push_back(std::make_unique<variable_handler<Type>>(std::forward<Args>(args)...));
|
||||
return static_cast<variable_handler<Type> &>(*vars.back()).value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1645,9 +1636,9 @@ public:
|
||||
*/
|
||||
template<typename Type>
|
||||
void unset() {
|
||||
if(const auto vtype = context_family<std::decay_t<Type>>::type(); vtype < vars.size()) {
|
||||
vars[vtype].reset();
|
||||
}
|
||||
vars.erase(std::remove_if(vars.begin(), vars.end(), [](auto &&handler) {
|
||||
return handler->id() == type_id_v<Type>;
|
||||
}), vars.end());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1675,8 +1666,11 @@ public:
|
||||
*/
|
||||
template<typename Type>
|
||||
const Type * try_ctx() const {
|
||||
const auto vtype = context_family<std::decay_t<Type>>::type();
|
||||
return vtype < vars.size() && vars[vtype] ? &static_cast<variable_handler<Type> &>(*vars[vtype]).value : nullptr;
|
||||
auto it = std::find_if(vars.cbegin(), vars.cend(), [](auto &&handler) {
|
||||
return handler->id() == type_id_v<Type>;
|
||||
});
|
||||
|
||||
return it == vars.cend() ? nullptr : &static_cast<const variable_handler<Type> &>(*it->get()).value;
|
||||
}
|
||||
|
||||
/*! @copydoc try_ctx */
|
||||
|
||||
@@ -87,7 +87,7 @@ class dispatcher {
|
||||
if(!(index < pools.size()) || pools[index]->id() != type_id_v<Event>) {
|
||||
index = std::find_if(pools.cbegin(), pools.cend(), [](auto &&cpool) {
|
||||
return cpool->id() == type_id_v<Event>;
|
||||
}) - pools.begin();
|
||||
}) - pools.cbegin();
|
||||
|
||||
if(index == pools.size()) {
|
||||
pools.push_back(std::make_unique<pool_handler<Event>>());
|
||||
|
||||
@@ -126,7 +126,7 @@ class emitter {
|
||||
if(!(index < pools.size()) || pools[index]->id() != type_id_v<Event>) {
|
||||
index = std::find_if(pools.cbegin(), pools.cend(), [](auto &&cpool) {
|
||||
return cpool->id() == type_id_v<Event>;
|
||||
}) - pools.begin();
|
||||
}) - pools.cbegin();
|
||||
|
||||
if(index == pools.size()) {
|
||||
pools.push_back(std::make_unique<pool_handler<Event>>());
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <chrono>
|
||||
#include <iterator>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/type_info.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
|
||||
struct position {
|
||||
@@ -167,7 +168,7 @@ TEST(Benchmark, IterateSingleComponentRuntime1M) {
|
||||
}
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = { registry.type<position>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<position>} };
|
||||
|
||||
timer timer;
|
||||
registry.runtime_view(std::begin(types), std::end(types)).each(func);
|
||||
@@ -332,7 +333,7 @@ TEST(Benchmark, IterateTwoComponentsRuntime1M) {
|
||||
}
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = { registry.type<position>(), registry.type<velocity>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<position>}, entt::component{entt::type_id_v<velocity>} };
|
||||
|
||||
timer timer;
|
||||
registry.runtime_view(std::begin(types), std::end(types)).each(func);
|
||||
@@ -360,7 +361,7 @@ TEST(Benchmark, IterateTwoComponentsRuntime1MHalf) {
|
||||
}
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = { registry.type<position>(), registry.type<velocity>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<position>}, entt::component{entt::type_id_v<velocity>} };
|
||||
|
||||
timer timer;
|
||||
registry.runtime_view(std::begin(types), std::end(types)).each(func);
|
||||
@@ -388,7 +389,7 @@ TEST(Benchmark, IterateTwoComponentsRuntime1MOne) {
|
||||
}
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = { registry.type<position>(), registry.type<velocity>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<position>}, entt::component{entt::type_id_v<velocity>} };
|
||||
|
||||
timer timer;
|
||||
registry.runtime_view(std::begin(types), std::end(types)).each(func);
|
||||
@@ -561,7 +562,7 @@ TEST(Benchmark, IterateThreeComponentsRuntime1M) {
|
||||
}
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = { registry.type<position>(), registry.type<velocity>(), registry.type<comp<0>>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<position>}, entt::component{entt::type_id_v<velocity>}, entt::component{entt::type_id_v<comp<0>>} };
|
||||
|
||||
timer timer;
|
||||
registry.runtime_view(std::begin(types), std::end(types)).each(func);
|
||||
@@ -591,7 +592,7 @@ TEST(Benchmark, IterateThreeComponentsRuntime1MHalf) {
|
||||
}
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = { registry.type<position>(), registry.type<velocity>(), registry.type<comp<0>>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<position>}, entt::component{entt::type_id_v<velocity>}, entt::component{entt::type_id_v<comp<0>>} };
|
||||
|
||||
timer timer;
|
||||
registry.runtime_view(std::begin(types), std::end(types)).each(func);
|
||||
@@ -621,7 +622,7 @@ TEST(Benchmark, IterateThreeComponentsRuntime1MOne) {
|
||||
}
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = { registry.type<position>(), registry.type<velocity>(), registry.type<comp<0>>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<position>}, entt::component{entt::type_id_v<velocity>}, entt::component{entt::type_id_v<comp<0>>} };
|
||||
|
||||
timer timer;
|
||||
registry.runtime_view(std::begin(types), std::end(types)).each(func);
|
||||
@@ -836,11 +837,11 @@ TEST(Benchmark, IterateFiveComponentsRuntime1M) {
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = {
|
||||
registry.type<position>(),
|
||||
registry.type<velocity>(),
|
||||
registry.type<comp<0>>(),
|
||||
registry.type<comp<1>>(),
|
||||
registry.type<comp<2>>()
|
||||
entt::component{entt::type_id_v<position>},
|
||||
entt::component{entt::type_id_v<velocity>},
|
||||
entt::component{entt::type_id_v<comp<0>>},
|
||||
entt::component{entt::type_id_v<comp<1>>},
|
||||
entt::component{entt::type_id_v<comp<2>>}
|
||||
};
|
||||
|
||||
timer timer;
|
||||
@@ -876,11 +877,11 @@ TEST(Benchmark, IterateFiveComponentsRuntime1MHalf) {
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = {
|
||||
registry.type<position>(),
|
||||
registry.type<velocity>(),
|
||||
registry.type<comp<0>>(),
|
||||
registry.type<comp<1>>(),
|
||||
registry.type<comp<2>>()
|
||||
entt::component{entt::type_id_v<position>},
|
||||
entt::component{entt::type_id_v<velocity>},
|
||||
entt::component{entt::type_id_v<comp<0>>},
|
||||
entt::component{entt::type_id_v<comp<1>>},
|
||||
entt::component{entt::type_id_v<comp<2>>}
|
||||
};
|
||||
|
||||
timer timer;
|
||||
@@ -916,11 +917,11 @@ TEST(Benchmark, IterateFiveComponentsRuntime1MOne) {
|
||||
|
||||
auto test = [®istry](auto func) {
|
||||
entt::component types[] = {
|
||||
registry.type<position>(),
|
||||
registry.type<velocity>(),
|
||||
registry.type<comp<0>>(),
|
||||
registry.type<comp<1>>(),
|
||||
registry.type<comp<2>>()
|
||||
entt::component{entt::type_id_v<position>},
|
||||
entt::component{entt::type_id_v<velocity>},
|
||||
entt::component{entt::type_id_v<comp<0>>},
|
||||
entt::component{entt::type_id_v<comp<1>>},
|
||||
entt::component{entt::type_id_v<comp<2>>}
|
||||
};
|
||||
|
||||
timer timer;
|
||||
|
||||
@@ -10,9 +10,8 @@ TEST(Helper, AsView) {
|
||||
|
||||
([](entt::view<entt::exclude_t<>, int>) {})(entt::as_view{registry});
|
||||
([](entt::view<entt::exclude_t<int>, char, double>) {})(entt::as_view{registry});
|
||||
([](entt::view<entt::exclude_t<const int>, char, double>) {})(entt::as_view{registry});
|
||||
([](entt::view<entt::exclude_t<const int>, const char, double>) {})(entt::as_view{registry});
|
||||
([](entt::view<entt::exclude_t<const int>, const char, const double>) {})(entt::as_view{registry});
|
||||
([](entt::view<entt::exclude_t<int>, const char, double>) {})(entt::as_view{registry});
|
||||
([](entt::view<entt::exclude_t<int>, const char, const double>) {})(entt::as_view{registry});
|
||||
}
|
||||
|
||||
TEST(Helper, AsGroup) {
|
||||
@@ -20,9 +19,8 @@ TEST(Helper, AsGroup) {
|
||||
const entt::registry cregistry;
|
||||
|
||||
([](entt::group<entt::exclude_t<int>, entt::get_t<char>, double>) {})(entt::as_group{registry});
|
||||
([](entt::group<entt::exclude_t<const int>, entt::get_t<char>, double>) {})(entt::as_group{registry});
|
||||
([](entt::group<entt::exclude_t<const int>, entt::get_t<const char>, double>) {})(entt::as_group{registry});
|
||||
([](entt::group<entt::exclude_t<const int>, entt::get_t<const char>, const double>) {})(entt::as_group{registry});
|
||||
([](entt::group<entt::exclude_t<int>, entt::get_t<const char>, double>) {})(entt::as_group{registry});
|
||||
([](entt::group<entt::exclude_t<int>, entt::get_t<const char>, const double>) {})(entt::as_group{registry});
|
||||
}
|
||||
|
||||
TEST(Helper, Tag) {
|
||||
|
||||
@@ -78,12 +78,6 @@ TEST(Registry, Context) {
|
||||
ASSERT_EQ(registry.try_ctx<float>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(Registry, Types) {
|
||||
entt::registry registry;
|
||||
ASSERT_EQ(registry.type<int>(), registry.type<int>());
|
||||
ASSERT_NE(registry.type<double>(), registry.type<int>());
|
||||
}
|
||||
|
||||
TEST(Registry, Functionalities) {
|
||||
entt::registry registry;
|
||||
|
||||
@@ -1540,9 +1534,7 @@ TEST(Registry, Constness) {
|
||||
entt::registry registry;
|
||||
|
||||
ASSERT_TRUE((std::is_same_v<decltype(registry.assign<int>({})), int &>));
|
||||
ASSERT_TRUE((std::is_same_v<decltype(registry.assign<const int>({})), int &>));
|
||||
ASSERT_TRUE((std::is_same_v<decltype(registry.assign<empty_type>({})), empty_type>));
|
||||
ASSERT_TRUE((std::is_same_v<decltype(registry.assign<const empty_type>({})), empty_type>));
|
||||
|
||||
ASSERT_TRUE((std::is_same_v<decltype(registry.get<int>({})), int &>));
|
||||
ASSERT_TRUE((std::is_same_v<decltype(registry.get<int, char>({})), std::tuple<int &, char &>>));
|
||||
|
||||
@@ -11,7 +11,7 @@ TEST(RuntimeView, Functionalities) {
|
||||
registry.reserve<int>(0);
|
||||
registry.reserve<char>(0);
|
||||
|
||||
entt::component types[] = { registry.type<int>(), registry.type<char>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<int>}, entt::component{entt::type_id_v<char>} };
|
||||
auto view = registry.runtime_view(std::begin(types), std::end(types));
|
||||
|
||||
ASSERT_TRUE(view.empty());
|
||||
@@ -54,7 +54,7 @@ TEST(RuntimeView, Iterator) {
|
||||
registry.assign<int>(entity);
|
||||
registry.assign<char>(entity);
|
||||
|
||||
entt::component types[] = { registry.type<int>(), registry.type<char>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<int>}, entt::component{entt::type_id_v<char>} };
|
||||
auto view = registry.runtime_view(std::begin(types), std::end(types));
|
||||
using iterator_type = typename decltype(view)::iterator_type;
|
||||
|
||||
@@ -90,7 +90,7 @@ TEST(RuntimeView, Contains) {
|
||||
|
||||
registry.destroy(e0);
|
||||
|
||||
entt::component types[] = { registry.type<int>(), registry.type<char>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<int>}, entt::component{entt::type_id_v<char>} };
|
||||
auto view = registry.runtime_view(std::begin(types), std::end(types));
|
||||
|
||||
ASSERT_FALSE(view.contains(e0));
|
||||
@@ -109,7 +109,7 @@ TEST(RuntimeView, Empty) {
|
||||
registry.assign<char>(e1);
|
||||
registry.assign<float>(e1);
|
||||
|
||||
entt::component types[] = { registry.type<char>(), registry.type<int>(), registry.type<float>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<int>}, entt::component{entt::type_id_v<char>}, entt::component{entt::type_id_v<float>} };
|
||||
auto view = registry.runtime_view(std::begin(types), std::end(types));
|
||||
|
||||
view.each([](auto) { FAIL(); });
|
||||
@@ -129,7 +129,7 @@ TEST(RuntimeView, Each) {
|
||||
registry.assign<int>(e1);
|
||||
registry.assign<char>(e1);
|
||||
|
||||
entt::component types[] = { registry.type<int>(), registry.type<char>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<int>}, entt::component{entt::type_id_v<char>} };
|
||||
auto view = registry.runtime_view(std::begin(types), std::end(types));
|
||||
std::size_t cnt = 0;
|
||||
|
||||
@@ -151,7 +151,7 @@ TEST(RuntimeView, EachWithHoles) {
|
||||
registry.assign<int>(e0, 0);
|
||||
registry.assign<int>(e2, 2);
|
||||
|
||||
entt::component types[] = { registry.type<int>(), registry.type<char>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<int>}, entt::component{entt::type_id_v<char>} };
|
||||
auto view = registry.runtime_view(std::begin(types), std::end(types));
|
||||
|
||||
view.each([e0](auto entity) {
|
||||
@@ -165,7 +165,7 @@ TEST(RuntimeView, MissingPool) {
|
||||
const auto e0 = registry.create();
|
||||
registry.assign<int>(e0);
|
||||
|
||||
entt::component types[] = { registry.type<int>(), registry.type<char>() };
|
||||
entt::component types[] = { entt::component{entt::type_id_v<int>}, entt::component{entt::type_id_v<char>} };
|
||||
auto view = registry.runtime_view(std::begin(types), std::end(types));
|
||||
|
||||
ASSERT_TRUE(view.empty());
|
||||
|
||||
@@ -2,24 +2,6 @@
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "types.h"
|
||||
|
||||
ENTT_API entt::component int_type() {
|
||||
entt::registry registry;
|
||||
|
||||
(void)registry.type<double>();
|
||||
(void)registry.type<float>();
|
||||
|
||||
return registry.type<int>();
|
||||
}
|
||||
|
||||
ENTT_API entt::component char_type() {
|
||||
entt::registry registry;
|
||||
|
||||
(void)registry.type<double>();
|
||||
(void)registry.type<float>();
|
||||
|
||||
return registry.type<char>();
|
||||
}
|
||||
|
||||
ENTT_API void update_position(int delta, entt::registry ®istry) {
|
||||
registry.view<position, velocity>().each([delta](auto &pos, auto &vel) {
|
||||
pos.x += delta * vel.dx;
|
||||
|
||||
@@ -4,25 +4,9 @@
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "types.h"
|
||||
|
||||
ENTT_API entt::component int_type();
|
||||
ENTT_API entt::component char_type();
|
||||
|
||||
ENTT_API void update_position(int, entt::registry &);
|
||||
ENTT_API void assign_velocity(int, entt::registry &);
|
||||
|
||||
TEST(Lib, Types) {
|
||||
entt::registry registry;
|
||||
|
||||
ASSERT_EQ(registry.type<int>(), registry.type<const int>());
|
||||
ASSERT_EQ(registry.type<char>(), registry.type<const char>());
|
||||
|
||||
ASSERT_EQ(registry.type<int>(), int_type());
|
||||
ASSERT_EQ(registry.type<char>(), char_type());
|
||||
|
||||
ASSERT_EQ(registry.type<const char>(), char_type());
|
||||
ASSERT_EQ(registry.type<const int>(), int_type());
|
||||
}
|
||||
|
||||
TEST(Lib, Registry) {
|
||||
entt::registry registry;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <duktape.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/type_info.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
|
||||
template<typename Type>
|
||||
@@ -122,9 +123,6 @@ duk_ret_t get(duk_context *ctx, entt::registry ®istry) {
|
||||
}
|
||||
|
||||
class duktape_registry {
|
||||
// I'm pretty sure I won't have more than 99 components in the example
|
||||
static constexpr ENTT_ID_TYPE udef = 100;
|
||||
|
||||
struct func_map {
|
||||
using func_type = duk_ret_t(*)(duk_context *, entt::registry &);
|
||||
|
||||
@@ -136,7 +134,7 @@ class duktape_registry {
|
||||
|
||||
template<typename... Comp>
|
||||
void reg() {
|
||||
((func[to_integer(registry.type<Comp>())] = {
|
||||
((func[entt::type_id_v<Comp>] = {
|
||||
&::set<Comp>,
|
||||
&::unset<Comp>,
|
||||
&::has<Comp>,
|
||||
@@ -162,13 +160,11 @@ class duktape_registry {
|
||||
auto ®istry = dreg.registry;
|
||||
auto type = duk_require_uint(ctx, 1);
|
||||
|
||||
if(type >= udef) {
|
||||
type = to_integer(registry.type<duktape_runtime>());
|
||||
}
|
||||
const auto it = func.find(type);
|
||||
|
||||
assert(func.find(type) != func.cend());
|
||||
|
||||
return (func[type].*Op)(ctx, registry);
|
||||
return (it == func.cend())
|
||||
? (func[entt::type_id_v<duktape_runtime>].*Op)(ctx, registry)
|
||||
: (it->second.*Op)(ctx, registry);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -179,7 +175,7 @@ public:
|
||||
}
|
||||
|
||||
static duk_ret_t identifier(duk_context *ctx) {
|
||||
static auto next = udef;
|
||||
static ENTT_ID_TYPE next{};
|
||||
duk_push_uint(ctx, next++);
|
||||
return 1;
|
||||
}
|
||||
@@ -210,7 +206,6 @@ public:
|
||||
static duk_ret_t entities(duk_context *ctx) {
|
||||
const duk_idx_t nargs = duk_get_top(ctx);
|
||||
auto &dreg = instance(ctx);
|
||||
duk_uarridx_t pos = 0;
|
||||
|
||||
duk_push_array(ctx);
|
||||
|
||||
@@ -220,18 +215,19 @@ public:
|
||||
for(duk_idx_t arg = 0; arg < nargs; arg++) {
|
||||
auto type = duk_require_uint(ctx, arg);
|
||||
|
||||
if(type < udef) {
|
||||
components.push_back(entt::component{type});
|
||||
} else {
|
||||
if(dreg.func.find(type) == dreg.func.cend()) {
|
||||
if(runtime.empty()) {
|
||||
components.push_back(dreg.registry.type<duktape_runtime>());
|
||||
components.push_back(entt::component{entt::type_id_v<duktape_runtime>});
|
||||
}
|
||||
|
||||
runtime.push_back(entt::component{type});
|
||||
} else {
|
||||
components.push_back(entt::component{type});
|
||||
}
|
||||
}
|
||||
|
||||
auto view = dreg.registry.runtime_view(components.cbegin(), components.cend());
|
||||
duk_uarridx_t pos = 0;
|
||||
|
||||
for(const auto entity: view) {
|
||||
if(runtime.empty()) {
|
||||
@@ -269,15 +265,15 @@ const duk_function_list_entry js_duktape_registry_methods[] = {
|
||||
{ nullptr, nullptr, 0 }
|
||||
};
|
||||
|
||||
void export_types(duk_context *context, entt::registry ®istry) {
|
||||
auto export_type = [idx = duk_push_object(context)](auto *ctx, auto ®, auto type, const auto *name) {
|
||||
void export_types(duk_context *context) {
|
||||
auto export_type = [idx = duk_push_object(context)](auto *ctx, auto type, const auto *name) {
|
||||
duk_push_string(ctx, name);
|
||||
duk_push_uint(ctx, to_integer(reg.template type<typename decltype(type)::type>()));
|
||||
duk_push_uint(ctx, entt::type_id_v<typename decltype(type)::type>);
|
||||
duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_CLEAR_WRITABLE);
|
||||
};
|
||||
|
||||
export_type(context, registry, tag<position>{}, "position");
|
||||
export_type(context, registry, tag<renderable>{}, "renderable");
|
||||
export_type(context, tag<position>{}, "position");
|
||||
export_type(context, tag<renderable>{}, "renderable");
|
||||
|
||||
duk_put_global_string(context, "Types");
|
||||
}
|
||||
@@ -302,7 +298,7 @@ TEST(Mod, Duktape) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
export_types(ctx, registry);
|
||||
export_types(ctx);
|
||||
export_duktape_registry(ctx, dreg);
|
||||
|
||||
const char *s0 = ""
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#define CR_HOST
|
||||
|
||||
#include <cr.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "types.h"
|
||||
|
||||
TEST(Lib, Registry) {
|
||||
entt::registry registry;
|
||||
|
||||
for(auto i = 0; i < 3; ++i) {
|
||||
const auto entity = registry.create();
|
||||
registry.assign<position>(entity, i, i+1);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(registry.empty<position>());
|
||||
ASSERT_TRUE(registry.empty<velocity>());
|
||||
|
||||
cr_plugin ctx;
|
||||
ctx.userdata = ®istry;
|
||||
cr_plugin_load(ctx, PLUGIN);
|
||||
cr_plugin_update(ctx);
|
||||
|
||||
ASSERT_FALSE(registry.empty<position>());
|
||||
ASSERT_FALSE(registry.empty<velocity>());
|
||||
|
||||
registry.view<position>().each([](auto entity, auto &position) {
|
||||
ASSERT_EQ(position.x, entt::to_integer(entity) + 2);
|
||||
ASSERT_EQ(position.y, entt::to_integer(entity) + 3);
|
||||
});
|
||||
|
||||
cr_plugin_close(ctx);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <cr.h>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "types.h"
|
||||
|
||||
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
|
||||
switch (operation) {
|
||||
case CR_STEP:
|
||||
[ctx]() {
|
||||
auto *registry = static_cast<entt::registry *>(ctx->userdata);
|
||||
registry->reset<velocity>();
|
||||
|
||||
for(auto entity: registry->view<position>()) {
|
||||
registry->assign<velocity>(entity, 1, 1);
|
||||
}
|
||||
|
||||
registry->view<position, velocity>().each([](auto &pos, auto &vel) {
|
||||
pos.x += 2 * vel.dx;
|
||||
pos.y += 2 * vel.dy;
|
||||
});
|
||||
}();
|
||||
break;
|
||||
case CR_LOAD:
|
||||
case CR_UNLOAD:
|
||||
case CR_CLOSE:
|
||||
// nothing to do here, this is only a test.
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef ENTT_PLUGIN_REGISTRY_TYPES_H
|
||||
#define ENTT_PLUGIN_REGISTRY_TYPES_H
|
||||
|
||||
struct position {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct velocity {
|
||||
int dx;
|
||||
int dy;
|
||||
};
|
||||
|
||||
#endif // ENTT_PLUGIN_REGISTRY_TYPES_H
|
||||
|
||||
Reference in New Issue
Block a user