Browse Source

added actor class

Michele Caini 8 years ago
parent
commit
68ce4dc689
5 changed files with 213 additions and 1 deletions
  1. 2 1
      README.md
  2. 152 0
      src/entt/entity/actor.hpp
  3. 1 0
      src/entt/entt.hpp
  4. 1 0
      test/CMakeLists.txt
  5. 57 0
      test/entt/entity/actor.cpp

+ 2 - 1
README.md

@@ -51,6 +51,7 @@ compile-time or at runtime).
 * An incredibly fast entity-component system based on sparse sets, with its own
 * An incredibly fast entity-component system based on sparse sets, with its own
 views and a _pay for what you use_ policy to adjust performance and memory
 views and a _pay for what you use_ policy to adjust performance and memory
 pressure according to the users' requirements.
 pressure according to the users' requirements.
+* Actor class for those who aren't confident with entity-component systems.
 * The smallest and most basic implementation of a service locator ever seen.
 * The smallest and most basic implementation of a service locator ever seen.
 * A cooperative scheduler for processes of any type.
 * A cooperative scheduler for processes of any type.
 * All what is needed for resource management (cache, loaders, handles).
 * All what is needed for resource management (cache, loaders, handles).
@@ -152,7 +153,7 @@ compared to my first choice (that was already amazingly fast indeed).<br/>
 Here is a comparision between the two (both of them compiled with GCC 7.2.0 on a
 Here is a comparision between the two (both of them compiled with GCC 7.2.0 on a
 Dell XPS 13 out of the mid 2014):
 Dell XPS 13 out of the mid 2014):
 
 
-| Benchmark | EntityX (experimental/compile_time) | EnTT |
+| Benchmark | EntityX (compile-time) | EnTT |
 |-----------|-------------|-------------|
 |-----------|-------------|-------------|
 | Creating 10M entities | 0.1289s | **0.0409s** |
 | Creating 10M entities | 0.1289s | **0.0409s** |
 | Destroying 10M entities | **0.0531s** | 0.0546s |
 | Destroying 10M entities | **0.0531s** | 0.0546s |

+ 152 - 0
src/entt/entity/actor.hpp

@@ -0,0 +1,152 @@
+#ifndef ENTT_ENTITY_ACTOR_HPP
+#define ENTT_ENTITY_ACTOR_HPP
+
+
+#include <utility>
+#include "registry.hpp"
+
+
+namespace entt {
+
+
+/**
+ * @brief Dedicated to those who aren't confident with entity-component systems.
+ *
+ * Tiny wrapper around a registry, for all those users that aren't confident
+ * with entity-component systems and prefer to iterate objects directly.
+ *
+ * @tparam Entity A valid entity type (see entt_traits for more details).
+ * @tparam Delta Type to use to provide elapsed time.
+ */
+template<typename Entity, typename Delta>
+struct Actor {
+    /*! @brief Type of registry used internally. */
+    using registry_type = Registry<Entity>;
+    /*! @brief Type used to provide elapsed time. */
+    using delta_type = Delta;
+
+    /**
+     * @brief Constructs an actor by using the given registry.
+     * @param reg An entity-component system properly initialized.
+     */
+    Actor(Registry<Entity> &reg)
+        : reg{reg}, entity{reg.create()}
+    {}
+
+    /*! @brief Default destructor. */
+    virtual ~Actor() {
+        reg.destroy(entity);
+    }
+
+    /*! @brief Default copy constructor. */
+    Actor(const Actor &) = default;
+    /*! @brief Default move constructor. */
+    Actor(Actor &&) = default;
+
+    /*! @brief Default copy assignment operator. @return This actor. */
+    Actor & operator=(const Actor &) = default;
+    /*! @brief Default move assignment operator. @return This actor. */
+    Actor & operator=(Actor &&) = default;
+
+    /**
+     * @brief Assigns the given component to an actor.
+     *
+     * A new instance of the given component is created and initialized with the
+     * arguments provided (the component must have a proper constructor or be of
+     * aggregate type). Then the component is assigned to the actor.<br/>
+     * In case the actor already has a component of the given type, it's
+     * replaced with the new one.
+     *
+     * @tparam Component Type of the component to create.
+     * @tparam Args Types of arguments to use to construct the component.
+     * @param args Parameters to use to initialize the component.
+     * @return A reference to the newly created component.
+     */
+    template<typename Component, typename... Args>
+    Component & set(Args&&... args) {
+        return reg.template accomodate<Component>(entity, std::forward<Args>(args)...);
+    }
+
+    /**
+     * @brief Removes the given component from an actor.
+     * @tparam Component Type of the component to remove.
+     */
+    template<typename Component>
+    void unset() {
+        reg.template remove<Component>(entity);
+    }
+
+    /**
+     * @brief Checks if an actor has the given component.
+     * @tparam Component Type of the component for which to perform the check.
+     * @return True if the actor has the component, false otherwise.
+     */
+    template<typename Component>
+    bool has() const noexcept {
+        return reg.template has<Component>(entity);
+    }
+
+    /**
+     * @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 entity.
+     */
+    template<typename Component>
+    const Component & get() const noexcept {
+        return reg.template get<Component>(entity);
+    }
+
+    /**
+     * @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 entity.
+     */
+    template<typename Component>
+    Component & get() noexcept {
+        return const_cast<Component &>(const_cast<const Actor *>(this)->get<Component>());
+    }
+
+    /**
+     * @brief Returns a reference to the underlying registry.
+     * @return A reference to the underlying registry
+     */
+    const registry_type & registry() const noexcept {
+        return reg;
+    }
+
+    /**
+     * @brief Returns a reference to the underlying registry.
+     * @return A reference to the underlying registry
+     */
+    registry_type & registry() noexcept {
+        return const_cast<registry_type &>(const_cast<const Actor *>(this)->registry());
+    }
+
+    /**
+     * @brief Updates an actor, whatever it means to update it.
+     * @param delta Elapsed time.
+     */
+    virtual void update(delta_type delta) = 0;
+
+private:
+    registry_type &reg;
+    Entity entity;
+};
+
+
+/**
+ * @brief Default actor class.
+ *
+ * The default actor is the best choice for almost all the applications.<br/>
+ * Users should have a really good reason to choose something different.
+ *
+ * @tparam Delta Type to use to provide elapsed time.
+ */
+template<typename Delta>
+using DefaultActor = Actor<std::uint32_t, Delta>;
+
+
+}
+
+
+#endif // ENTT_ENTITY_ACTOR_HPP

+ 1 - 0
src/entt/entt.hpp

@@ -1,6 +1,7 @@
 #include "core/family.hpp"
 #include "core/family.hpp"
 #include "core/hashed_string.hpp"
 #include "core/hashed_string.hpp"
 #include "core/ident.hpp"
 #include "core/ident.hpp"
+#include "entity/actor.hpp"
 #include "entity/registry.hpp"
 #include "entity/registry.hpp"
 #include "entity/sparse_set.hpp"
 #include "entity/sparse_set.hpp"
 #include "entity/traits.hpp"
 #include "entity/traits.hpp"

+ 1 - 0
test/CMakeLists.txt

@@ -35,6 +35,7 @@ add_test(NAME core COMMAND core)
 add_executable(
 add_executable(
     entity
     entity
     $<TARGET_OBJECTS:odr>
     $<TARGET_OBJECTS:odr>
+    entt/entity/actor.cpp
     entt/entity/registry.cpp
     entt/entity/registry.cpp
     entt/entity/sparse_set.cpp
     entt/entity/sparse_set.cpp
     entt/entity/view.cpp
     entt/entity/view.cpp

+ 57 - 0
test/entt/entity/actor.cpp

@@ -0,0 +1,57 @@
+#include <functional>
+#include <gtest/gtest.h>
+#include <entt/entity/actor.hpp>
+#include <entt/entity/registry.hpp>
+
+struct TestActor: entt::DefaultActor<unsigned int> {
+    using entt::DefaultActor<unsigned int>::DefaultActor;
+    void update(unsigned int) {}
+};
+
+struct Position final {};
+struct Velocity final {};
+
+TEST(Actor, Functionalities) {
+    entt::DefaultRegistry registry;
+    TestActor *actor = new TestActor{registry};
+    const auto &cactor = *actor;
+
+    ASSERT_EQ(&registry, &actor->registry());
+    ASSERT_EQ(&registry, &cactor.registry());
+    ASSERT_TRUE(registry.empty<Position>());
+    ASSERT_TRUE(registry.empty<Velocity>());
+    ASSERT_FALSE(registry.empty());
+    ASSERT_FALSE(actor->has<Position>());
+    ASSERT_FALSE(actor->has<Velocity>());
+
+    const auto &position = actor->set<Position>();
+
+    ASSERT_EQ(&position, &actor->get<Position>());
+    ASSERT_EQ(&position, &cactor.get<Position>());
+    ASSERT_FALSE(registry.empty<Position>());
+    ASSERT_TRUE(registry.empty<Velocity>());
+    ASSERT_FALSE(registry.empty());
+    ASSERT_TRUE(actor->has<Position>());
+    ASSERT_FALSE(actor->has<Velocity>());
+
+    actor->unset<Position>();
+
+    ASSERT_TRUE(registry.empty<Position>());
+    ASSERT_TRUE(registry.empty<Velocity>());
+    ASSERT_FALSE(registry.empty());
+    ASSERT_FALSE(actor->has<Position>());
+    ASSERT_FALSE(actor->has<Velocity>());
+
+    actor->set<Position>();
+    actor->set<Velocity>();
+
+    ASSERT_FALSE(registry.empty());
+    ASSERT_FALSE(registry.empty<Position>());
+    ASSERT_FALSE(registry.empty<Velocity>());
+
+    delete actor;
+
+    ASSERT_TRUE(registry.empty());
+    ASSERT_TRUE(registry.empty<Position>());
+    ASSERT_TRUE(registry.empty<Velocity>());
+}