null entity

This commit is contained in:
Michele Caini
2018-06-11 08:23:07 +02:00
parent ef57d7e7b6
commit 612017aaa2
5 changed files with 144 additions and 13 deletions

View File

@@ -425,19 +425,6 @@ auto version = registry.version(entity);
auto curr = registry.current(entity);
```
Finally, there is also a sort of _null identifier_ made available to users. It's
treated as if it were a _null pointer_ that doesn't identify any entity. A
registry will reject this identifier in all cases because it isn't considered
valid.<br/>
The rules that define a _null identifier_ are a bit tricky to explain. However,
being `Entity` the type of the entities (for example, `std::uint32_t`), users
can easily construct a _null identifier_ by flipping all the bits of the _zero_:
```cpp
using Entity = std::uint32_t;
const auto null = ~Entity{};
```
Components can be assigned to or removed from entities at any time with a few
calls to member functions of the registry. As for the entities, the registry
offers also a set of functionalities users can use to work with the components.
@@ -1136,6 +1123,34 @@ A dependency can easily be broken by means of the same function template:
entt::dependency<AType, AnotherType>(entt::break_t{}, registry.construction<MyType>());
```
### Null entity
In `EnTT`, there exists a sort of _null entity_ made available to users that is
accessible via the `entt::null` variable.<br/>
The framework guarantees that the following expression always returns false:
```cpp
registry.valid(entt::null);
```
In other terms, a registry will reject the null entity in all cases because it
isn't considered valid. It means that the null entity cannot own components or
tags for obvious reasons.<br/>
The type of the null entity is internal and should not be used for any purpose
other than defining the null entity itself. However, there exist implicit
conversions from the null entity to identifiers of any allowed type:
```cpp
typename entt::DefaultRegistry::entity_type null = entt::null;
```
Similarly, the null entity can be compared to any other identifier:
```cpp
const auto entity = registry.create();
const bool null = (entity == entt::null);
```
## View: to persist or not to persist?
First of all, it is worth answering an obvious question: why views?<br/>

View File

@@ -0,0 +1,87 @@
#ifndef ENTT_ENTITY_ENTITY_HPP
#define ENTT_ENTITY_ENTITY_HPP
#include "../config/config.h"
#include "entt_traits.hpp"
namespace entt {
namespace internal {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
template<typename Entity>
static constexpr auto null = ~typename entt_traits<Entity>::entity_type{};
struct Null {
explicit constexpr Null() = default;
template<typename Entity>
constexpr operator Entity() const ENTT_NOEXCEPT {
return null<Entity>;
}
constexpr bool operator==(Null) const ENTT_NOEXCEPT {
return true;
}
constexpr bool operator!=(Null) const ENTT_NOEXCEPT {
return false;
}
template<typename Entity>
constexpr bool operator==(const Entity entity) const ENTT_NOEXCEPT {
return entity == null<Entity>;
}
template<typename Entity>
constexpr bool operator!=(const Entity entity) const ENTT_NOEXCEPT {
return entity != null<Entity>;
}
};
template<typename Entity>
constexpr bool operator==(const Entity entity, Null null) ENTT_NOEXCEPT {
return null == entity;
}
template<typename Entity>
constexpr bool operator!=(const Entity entity, Null null) ENTT_NOEXCEPT {
return null != entity;
}
/**
* Internal details not to be documented.
* @endcond TURN_OFF_DOXYGEN
*/
}
/**
* @brief Null entity.
*
* There exist implicit conversions from this variable to entity identifiers of
* any allowed type. Similarly, there exist comparision operators between the
* null entity and any other entity identifier.
*/
constexpr auto null = internal::Null{};
}
#endif // ENTT_ENTITY_ENTITY_HPP

View File

@@ -3,6 +3,7 @@
#include "core/hashed_string.hpp"
#include "core/ident.hpp"
#include "entity/actor.hpp"
#include "entity/entity.hpp"
#include "entity/entt_traits.hpp"
#include "entity/helper.hpp"
#include "entity/prototype.hpp"

View File

@@ -53,6 +53,7 @@ ADD_ENTT_TEST(ident entt/core/ident.cpp)
# Test entity
ADD_ENTT_TEST(actor entt/entity/actor.cpp)
ADD_ENTT_TEST(entity entt/entity/entity.cpp)
ADD_ENTT_TEST(helper entt/entity/helper.cpp)
ADD_ENTT_TEST(prototype entt/entity/prototype.cpp)
ADD_ENTT_TEST(registry entt/entity/registry.cpp)

View File

@@ -0,0 +1,27 @@
#include <functional>
#include <gtest/gtest.h>
#include <entt/entity/entity.hpp>
#include <entt/entity/registry.hpp>
template<bool>
struct S {};
TEST(Traits, Null) {
entt::DefaultRegistry registry{};
const auto entity = registry.create();
registry.assign<int>(entity, 42);
ASSERT_TRUE(~typename entt::DefaultRegistry::entity_type{} == entt::null);
ASSERT_TRUE(entt::null == entt::null);
ASSERT_FALSE(entt::null != entt::null);
ASSERT_FALSE(entity == entt::null);
ASSERT_FALSE(entt::null == entity);
ASSERT_TRUE(entity != entt::null);
ASSERT_TRUE(entt::null != entity);
ASSERT_FALSE(registry.valid(entt::null));
}