review stomp & spawn (close #306)

This commit is contained in:
Michele Caini
2019-09-06 17:21:07 +02:00
parent b3be6c75c3
commit 454f072f13
3 changed files with 54 additions and 40 deletions

8
TODO
View File

@@ -26,8 +26,8 @@ TODO
- we should always resolve by looking into the list of types when working across boundaries, no direct resolve
* nested groups: AB/ABC/ABCD/... (hints: sort, check functions)
* snapshot rework/deprecation
* create(hint: entity) -> force-create
* assign<T...>(first, last)
- create(hint: entity) -> force-create
- assign<T...>(first, last)
* use unordered_map for named pools and context variables:
* use direct access (pool-like) also for context variables
* improves multi-stomp
- use direct access (pool-like) also for context variables
- improves multi-stomp

View File

@@ -218,6 +218,24 @@ class basic_registry {
}
}
auto generate() {
Entity entt;
if(destroyed == null) {
entt = entities.emplace_back(entity_type(entities.size()));
// traits_type::entity_mask is reserved to allow for null identifiers
ENTT_ASSERT(to_integer(entt) < traits_type::entity_mask);
} else {
const auto curr = to_integer(destroyed);
const auto version = to_integer(entities[curr]) & (traits_type::version_mask << traits_type::entity_shift);
destroyed = entity_type{to_integer(entities[curr]) & traits_type::entity_mask};
entt = entity_type{curr | version};
entities[curr] = entt;
}
return entt;
}
void release(const Entity entity) {
// lengthens the implicit list of destroyed entities
const auto entt = to_integer(entity) & traits_type::entity_mask;
@@ -557,14 +575,11 @@ public:
*/
template<typename... Component>
auto create() {
entity_type entities[1]{};
if constexpr(sizeof...(Component) == 0) {
create<Component...>(std::begin(entities), std::end(entities));
return entities[0];
return generate();
} else {
auto it = create<Component...>(std::begin(entities), std::end(entities));
return std::tuple<entity_type, decltype(assign<Component>(entities[0]))...>{entities[0], *std::get<typename pool_type<Component>::iterator_type>(it)...};
const entity_type entt = generate();
return std::tuple<entity_type, decltype(assign<Component>({}))...>{entt, assign<Component>(entt)...};
}
}
@@ -586,25 +601,7 @@ public:
*/
template<typename... Component, typename It>
auto create(It first, It last) {
static_assert(std::is_convertible_v<entity_type, typename std::iterator_traits<It>::value_type>);
std::generate(first, last, [this]() {
entity_type curr;
if(destroyed == null) {
curr = entities.emplace_back(entity_type(entities.size()));
// traits_type::entity_mask is reserved to allow for null identifiers
ENTT_ASSERT(to_integer(curr) < traits_type::entity_mask);
} else {
const auto entt = to_integer(destroyed);
const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
destroyed = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
curr = entity_type{entt | version};
entities[entt] = curr;
}
return curr;
});
std::generate(first, last, [this]() { return generate(); });
if constexpr(sizeof...(Component) > 0) {
// the reverse iterators guarantee the ordering between entities and components (hint: the pools return begin())
@@ -632,10 +629,10 @@ public:
* @return A valid entity identifier.
*/
template<typename... Component, typename... Exclude>
auto create(entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
entity_type entities[1]{};
create<Component...>(std::begin(entities), std::end(entities), src, other, exclude<Exclude...>);
return entities[0];
entity_type create(entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
const auto entt = create();
stomp<Component...>(entt, src, other, exclude<Exclude...>);
return entt;
}
/**
@@ -666,8 +663,8 @@ public:
if constexpr(sizeof...(Component) == 0) {
stomp<Component...>(first, last, src, other, exclude<Exclude...>);
} else {
static_assert(sizeof...(Component) == 0 || sizeof...(Exclude) == 0);
(assure<Component>()->batch(*this, first, last, other.get<Component>(src)), ...);
static_assert(sizeof...(Exclude) == 0);
(assure<Component>()->batch(*this, std::make_reverse_iterator(last), std::make_reverse_iterator(first), other.get<Component>(src)), ...);
}
}
@@ -1499,7 +1496,6 @@ public:
*/
template<typename It>
entt::basic_runtime_view<Entity> runtime_view(It first, It last) const {
static_assert(std::is_same_v<typename std::iterator_traits<It>::value_type, component>);
std::vector<const sparse_set<Entity> *> set(std::distance(first, last));
std::transform(first, last, set.begin(), [this](const component ctype) {
@@ -1613,8 +1609,8 @@ public:
*/
template<typename... Component, typename... Exclude>
void stomp(const entity_type dst, const entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
const entity_type entities[1]{dst};
stomp<Component...>(std::begin(entities), std::end(entities), src, other, exclude<Exclude...>);
const entity_type entt[1]{dst};
stomp<Component...>(std::begin(entt), std::end(entt), src, other, exclude<Exclude...>);
}
/**
@@ -1632,7 +1628,6 @@ public:
template<typename... Component, typename It, typename... Exclude>
void stomp(It first, It last, const entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
static_assert(sizeof...(Component) == 0 || sizeof...(Exclude) == 0);
static_assert(std::conjunction_v<std::is_copy_constructible<Component>...>);
for(auto pos = other.pools.size(); pos; --pos) {
const auto &pdata = other.pools[pos-1];

View File

@@ -1548,7 +1548,7 @@ TEST(Registry, StompMulti) {
entt::entity entities[2];
registry.create(std::begin(entities), std::end(entities));
registry.stomp(std::begin(entities), std::end(entities), prototype, registry);
registry.stomp<int, char, double>(std::begin(entities), std::end(entities), prototype, registry);
ASSERT_TRUE((registry.has<int, char>(entities[0])));
ASSERT_TRUE((registry.has<int, char>(entities[1])));
@@ -1556,6 +1556,25 @@ TEST(Registry, StompMulti) {
ASSERT_EQ(registry.get<char>(entities[1]), 'c');
}
TEST(Registry, StompExcludeMulti) {
entt::registry registry;
const auto prototype = registry.create();
registry.assign<int>(prototype, 3);
registry.assign<char>(prototype, 'c');
entt::entity entities[2];
registry.create(std::begin(entities), std::end(entities));
registry.stomp(std::begin(entities), std::end(entities), prototype, registry, entt::exclude<char>);
ASSERT_TRUE((registry.has<int>(entities[0])));
ASSERT_TRUE((registry.has<int>(entities[1])));
ASSERT_FALSE((registry.has<char>(entities[0])));
ASSERT_FALSE((registry.has<char>(entities[1])));
ASSERT_EQ(registry.get<int>(entities[0]), 3);
ASSERT_EQ(registry.get<int>(entities[1]), 3);
}
TEST(Registry, StompMoveOnlyComponent) {
entt::registry registry;