added get_if where possible

This commit is contained in:
Michele Caini
2018-10-27 13:45:51 +02:00
parent 375124642d
commit 5859a18b3a
8 changed files with 179 additions and 40 deletions
-1
View File
@@ -15,7 +15,6 @@
* composable looper so as to pack erased systems, compose runners at different rates and run them at once in the loop
* meta: sort of meta view based on meta stuff to iterate entities, void * and meta info objects
* meta: move-to-head optimization when searching by name on parts (data, func, etc)
* registry::probe<component>(entt) (returns a component * if entt has the component, nullptr otherwise)
* hashed string: add implicit check on construction for uniqueness (optional)
* add a note about multithreading support to the README file
* signals on entity creation/destruction
+32 -12
View File
@@ -120,23 +120,43 @@ struct actor {
}
/**
* @brief Returns a reference to the given component for an actor.
* @tparam Component Type of the component to get.
* @return A reference to the instance of the component owned by the actor.
* @brief Returns references to the given components for an actor.
* @tparam Component Types of components to get.
* @return References to the components owned by the actor.
*/
template<typename Component>
const Component & get() const ENTT_NOEXCEPT {
return reg->template get<Component>(entt);
template<typename... Component>
decltype(auto) get() const ENTT_NOEXCEPT {
return reg->template get<Component...>(entt);
}
/**
* @brief Returns a reference to the given component for an actor.
* @tparam Component Type of the component to get.
* @return A reference to the instance of the component owned by the actor.
* @brief Returns references to the given components for an actor.
* @tparam Component Types of components to get.
* @return References to the components owned by the actor.
*/
template<typename Component>
inline Component & get() ENTT_NOEXCEPT {
return const_cast<Component &>(std::as_const(*this).template get<Component>());
template<typename... Component>
decltype(auto) get() ENTT_NOEXCEPT {
return reg->template get<Component...>(entt);
}
/**
* @brief Returns pointers to the given components for an actor.
* @tparam Component Types of components to get.
* @return Pointers to the components owned by the actor.
*/
template<typename... Component>
auto get_if() const ENTT_NOEXCEPT {
return reg->template get_if<Component...>(entt);
}
/**
* @brief Returns pointers to the given components for an actor.
* @tparam Component Types of components to get.
* @return Pointers to the components owned by the actor.
*/
template<typename... Component>
auto get_if() ENTT_NOEXCEPT {
return reg->template get_if<Component...>(entt);
}
/**
+31 -6
View File
@@ -49,11 +49,6 @@ class prototype final {
basic_fn_type *assign;
};
template<typename Component>
inline const Component & component() const ENTT_NOEXCEPT {
return reg->template get<component_wrapper<Component>>(entity).component;
}
void release() {
if(reg->valid(entity)) {
reg->destroy(entity);
@@ -189,7 +184,8 @@ public:
template<typename... Component>
decltype(auto) get() const ENTT_NOEXCEPT {
if constexpr(sizeof...(Component) == 1) {
return component<Component...>();
const auto &component = reg->template get<component_wrapper<Component...>>(entity).component;
return component;
} else {
return std::tuple<const Component &...>{get<Component>()...};
}
@@ -216,6 +212,35 @@ public:
}
}
/**
* @brief Returns pointers to the given components.
* @tparam Component Types of components to get.
* @return Pointers to the components owned by the prototype.
*/
template<typename... Component>
auto get_if() const ENTT_NOEXCEPT {
if constexpr(sizeof...(Component) == 1) {
const auto *wrapper = reg->template get_if<component_wrapper<Component...>>(entity);
return wrapper ? &wrapper->component : nullptr;
} else {
return std::tuple<const Component *...>{get_if<Component>()...};
}
}
/**
* @brief Returns pointers to the given components.
* @tparam Component Types of components to get.
* @return Pointers to the components owned by the prototype.
*/
template<typename... Component>
inline auto get_if() ENTT_NOEXCEPT {
if constexpr(sizeof...(Component) == 1) {
return (const_cast<Component *>(std::as_const(*this).template get_if<Component>()), ...);
} else {
return std::tuple<Component *...>{get_if<Component>()...};
}
}
/**
* @brief Creates a new entity using a given prototype.
*
+44
View File
@@ -624,6 +624,50 @@ public:
}
}
/**
* @brief Returns pointers to the given components for an entity.
*
* @warning
* Attempting to use an invalid entity results in undefined behavior.<br/>
* An assertion will abort the execution at runtime in debug mode in case of
* invalid entity.
*
* @tparam Component Types of components to get.
* @param entity A valid entity identifier.
* @return Pointers to the components owned by the entity.
*/
template<typename... Component>
auto get_if([[maybe_unused]] const entity_type entity) const ENTT_NOEXCEPT {
assert(valid(entity));
if constexpr(sizeof...(Component) == 1) {
return managed<Component...>() ? pool<Component...>().get_if(entity) : nullptr;
} else {
return std::tuple<const Component *...>{get_if<Component>(entity)...};
}
}
/**
* @brief Returns pointers to the given components for an entity.
*
* @warning
* Attempting to use an invalid entity results in undefined behavior.<br/>
* An assertion will abort the execution at runtime in debug mode in case of
* invalid entity.
*
* @tparam Component Types of components to get.
* @param entity A valid entity identifier.
* @return Pointers to the components owned by the entity.
*/
template<typename... Component>
inline auto get_if([[maybe_unused]] const entity_type entity) ENTT_NOEXCEPT {
if constexpr(sizeof...(Component) == 1) {
return (const_cast<Component *>(std::as_const(*this).template get_if<Component>(entity)), ...);
} else {
return std::tuple<Component *...>{get_if<Component>(entity)...};
}
}
/**
* @brief Replaces the given component for an entity.
*
+24 -6
View File
@@ -683,7 +683,7 @@ class sparse_set<Entity, Type>: public sparse_set<Entity> {
};
public:
/*! @brief Type of the objects associated to the entities. */
/*! @brief Type of the objects associated with the entities. */
using object_type = Type;
/*! @brief Underlying entity identifier. */
using entity_type = typename underlying_type::entity_type;
@@ -881,7 +881,7 @@ public:
}
/**
* @brief Returns the object associated to an entity.
* @brief Returns the object associated with an entity.
*
* @warning
* Attempting to use an entity that doesn't belong to the sparse set results
@@ -890,14 +890,14 @@ public:
* sparse set doesn't contain the given entity.
*
* @param entity A valid entity identifier.
* @return The object associated to the entity.
* @return The object associated with the entity.
*/
const object_type & get(const entity_type entity) const ENTT_NOEXCEPT {
return instances[underlying_type::get(entity)];
}
/**
* @brief Returns the object associated to an entity.
* @brief Returns the object associated with an entity.
*
* @warning
* Attempting to use an entity that doesn't belong to the sparse set results
@@ -906,12 +906,30 @@ public:
* sparse set doesn't contain the given entity.
*
* @param entity A valid entity identifier.
* @return The object associated to the entity.
* @return The object associated with the entity.
*/
inline object_type & get(const entity_type entity) ENTT_NOEXCEPT {
return const_cast<object_type &>(std::as_const(*this).get(entity));
}
/**
* @brief Returns a pointer to the object associated with an entity, if any.
* @param entity A valid entity identifier.
* @return The object associated with the entity, if any.
*/
const object_type * get_if(const entity_type entity) const ENTT_NOEXCEPT {
return underlying_type::has(entity) ? (instances.data() + underlying_type::get(entity)) : nullptr;
}
/**
* @brief Returns a pointer to the object associated with an entity, if any.
* @param entity A valid entity identifier.
* @return The object associated with the entity, if any.
*/
inline object_type * get_if(const entity_type entity) ENTT_NOEXCEPT {
return const_cast<object_type *>(std::as_const(*this).get_if(entity));
}
/**
* @brief Assigns an entity to a sparse set and constructs its object.
*
@@ -929,7 +947,7 @@ public:
* @tparam Args Types of arguments to use to construct the object.
* @param entity A valid entity identifier.
* @param args Parameters to use to construct an object for the entity.
* @return The object associated to the entity.
* @return The object associated with the entity.
*/
template<typename... Args>
object_type & construct(const entity_type entity, Args &&... args) {
+25 -15
View File
@@ -3,8 +3,6 @@
#include <entt/entity/actor.hpp>
#include <entt/entity/registry.hpp>
struct actor_component final {};
TEST(Actor, Component) {
entt::registry<> registry;
entt::actor actor{registry};
@@ -12,31 +10,43 @@ TEST(Actor, Component) {
ASSERT_EQ(&registry, &actor.backend());
ASSERT_EQ(&registry, &cactor.backend());
ASSERT_TRUE(registry.empty<actor_component>());
ASSERT_TRUE(registry.empty<int>());
ASSERT_FALSE(registry.empty());
ASSERT_FALSE(actor.has<actor_component>());
ASSERT_FALSE(actor.has<int>());
const auto &component = actor.assign<actor_component>();
const auto &cint = actor.assign<int>();
const auto &cchar = actor.assign<char>();
ASSERT_EQ(&component, &actor.get<actor_component>());
ASSERT_EQ(&component, &cactor.get<actor_component>());
ASSERT_FALSE(registry.empty<actor_component>());
ASSERT_EQ(&cint, &actor.get<int>());
ASSERT_EQ(&cchar, &cactor.get<char>());
ASSERT_EQ(&cint, &std::get<0>(actor.get<int, char>()));
ASSERT_EQ(&cchar, &std::get<1>(actor.get<int, char>()));
ASSERT_EQ(&cint, std::get<0>(actor.get_if<int, char, double>()));
ASSERT_EQ(&cchar, std::get<1>(actor.get_if<int, char, double>()));
ASSERT_EQ(nullptr, std::get<2>(actor.get_if<int, char, double>()));
ASSERT_EQ(nullptr, actor.get_if<double>());
ASSERT_EQ(&cchar, actor.get_if<char>());
ASSERT_EQ(&cint, actor.get_if<int>());
ASSERT_FALSE(registry.empty<int>());
ASSERT_FALSE(registry.empty());
ASSERT_TRUE(actor.has<actor_component>());
ASSERT_TRUE(actor.has<int>());
ASSERT_TRUE(actor.has<char>());
ASSERT_FALSE(actor.has<double>());
actor.remove<actor_component>();
actor.remove<int>();
ASSERT_TRUE(registry.empty<actor_component>());
ASSERT_TRUE(registry.empty<int>());
ASSERT_FALSE(registry.empty());
ASSERT_FALSE(actor.has<actor_component>());
ASSERT_FALSE(actor.has<int>());
}
TEST(Actor, EntityLifetime) {
entt::registry<> registry;
auto *actor = new entt::actor{registry};
actor->assign<actor_component>();
actor->assign<int>();
ASSERT_FALSE(registry.empty<actor_component>());
ASSERT_FALSE(registry.empty<int>());
ASSERT_FALSE(registry.empty());
registry.each([actor](const auto entity) {
@@ -45,6 +55,6 @@ TEST(Actor, EntityLifetime) {
delete actor;
ASSERT_TRUE(registry.empty<actor_component>());
ASSERT_TRUE(registry.empty<int>());
ASSERT_TRUE(registry.empty());
}
+8
View File
@@ -21,6 +21,14 @@ TEST(Prototype, SameRegistry) {
ASSERT_EQ(std::get<0>(prototype.get<int, char>()), 3);
ASSERT_EQ(std::get<1>(cprototype.get<int, char>()), 'c');
ASSERT_NE(prototype.get_if<int>(), nullptr);
ASSERT_NE(prototype.get_if<char>(), nullptr);
ASSERT_EQ(prototype.get_if<double>(), nullptr);
ASSERT_EQ(*prototype.get_if<int>(), 3);
ASSERT_EQ(*cprototype.get_if<char>(), 'c');
ASSERT_EQ(*std::get<0>(prototype.get_if<int, char, double>()), 3);
ASSERT_EQ(*std::get<1>(cprototype.get_if<int, char, double>()), 'c');
const auto e0 = prototype.create();
ASSERT_TRUE((prototype.has<int, char>()));
+15
View File
@@ -74,6 +74,13 @@ TEST(Registry, Functionalities) {
ASSERT_FALSE((registry.has<int, char>(e0)));
ASSERT_TRUE((registry.has<int, char>(e1)));
ASSERT_EQ(registry.get_if<int>(e0), nullptr);
ASSERT_NE(registry.get_if<int>(e1), nullptr);
ASSERT_EQ(registry.get_if<char>(e0), nullptr);
ASSERT_NE(registry.get_if<char>(e1), nullptr);
ASSERT_EQ(registry.get_if<double>(e0), nullptr);
ASSERT_EQ(registry.get_if<double>(e1), nullptr);
ASSERT_EQ(registry.assign<int>(e0, 42), 42);
ASSERT_EQ(registry.assign<char>(e0, 'c'), 'c');
ASSERT_NO_THROW(registry.remove<int>(e1));
@@ -96,8 +103,16 @@ TEST(Registry, Functionalities) {
ASSERT_EQ(registry.get<int>(e0), 42);
ASSERT_EQ(registry.get<char>(e0), 'c');
ASSERT_NE(registry.get_if<int>(e0), nullptr);
ASSERT_NE(registry.get_if<char>(e0), nullptr);
ASSERT_EQ(registry.get_if<double>(e0), nullptr);
ASSERT_EQ(*registry.get_if<int>(e0), 42);
ASSERT_EQ(*registry.get_if<char>(e0), 'c');
ASSERT_EQ(std::get<0>(registry.get<int, char>(e0)), 42);
ASSERT_EQ(*std::get<0>(registry.get_if<int, char, double>(e0)), 42);
ASSERT_EQ(std::get<1>(static_cast<const entt::registry<> &>(registry).get<int, char>(e0)), 'c');
ASSERT_EQ(*std::get<1>(static_cast<const entt::registry<> &>(registry).get_if<int, char, double>(e0)), 'c');
ASSERT_EQ(registry.get<int>(e0), registry.get<int>(e2));
ASSERT_EQ(registry.get<char>(e0), registry.get<char>(e2));