diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | Doxyfile | 4 | ||||
-rw-r--r-- | entityx/deps/Dependencies.cc | 11 | ||||
-rw-r--r-- | entityx/deps/Dependencies.h | 54 | ||||
-rw-r--r-- | entityx/deps/Dependencies_test.cc | 77 |
5 files changed, 146 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 761a031..ba530fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,7 +102,7 @@ set(install_libs entityx) include(CheckCXX11SharedPtr.cmake) -set(sources entityx/tags/TagsComponent.cc entityx/System.cc entityx/Event.cc entityx/Entity.cc entityx/Manager.cc) +set(sources entityx/tags/TagsComponent.cc entityx/deps/Dependencies.cc entityx/System.cc entityx/Event.cc entityx/Entity.cc entityx/Manager.cc) add_library(entityx STATIC ${sources}) if (ENTITYX_BUILD_SHARED) @@ -157,6 +157,7 @@ if (ENTITYX_BUILD_TESTING) create_test(event_test entityx/Event_test.cc) create_test(system_test entityx/System_test.cc) create_test(tags_component_test entityx/tags/TagsComponent_test.cc) + create_test(dependencies_test entityx/deps/Dependencies_test.cc) if (Boost_PYTHON_LIBRARY) add_definitions(-DENTITYX_PYTHON_TEST_DATA=\"${CMAKE_CURRENT_SOURCE_DIR}/entityx/python\") create_test(python_test entityx/python/PythonSystem_test.cc entityx_python ${Boost_PYTHON_LIBRARY} ${PYTHON_LIBRARIES}) @@ -654,7 +654,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = entityx +INPUT = entityx README.md entityx/python/README.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -672,7 +672,7 @@ INPUT_ENCODING = UTF-8 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl -FILE_PATTERNS = *.h *.md +FILE_PATTERNS = *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. diff --git a/entityx/deps/Dependencies.cc b/entityx/deps/Dependencies.cc new file mode 100644 index 0000000..9271a2f --- /dev/null +++ b/entityx/deps/Dependencies.cc @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2013 Alec Thomas <alec@swapoff.org> + * All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. + * + * Author: Alec Thomas <alec@swapoff.org> + */ + +#include "entityx/deps/Dependencies.h" diff --git a/entityx/deps/Dependencies.h b/entityx/deps/Dependencies.h new file mode 100644 index 0000000..69e68bb --- /dev/null +++ b/entityx/deps/Dependencies.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2013 Alec Thomas <alec@swapoff.org> + * All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. + * + * Author: Alec Thomas <alec@swapoff.org> + */ +#pragma once + +#include "entityx/System.h" +#include "entityx/Event.h" +#include "entityx/Entity.h" + +namespace entityx { +namespace deps { + +/** + * An entityx::System for declaring component dependencies. + * + * eg. To declare that a `Physics` component must always be paired with `Position` + * and `Direction` components: + * + * system_manager->add<Dependency<Physics, Position, Direction>>(); + */ +template <typename C, typename ... Deps> +class Dependency : public System<Dependency<C, Deps...>>, public Receiver<Dependency<C, Deps...>> { +public: + void receive(const ComponentAddedEvent<C> &event) { + assign<Deps...>(event.entity); + } + + virtual void configure(ptr<EventManager> events) override { + events->subscribe<ComponentAddedEvent<C>>(*this); + } + + virtual void update(ptr<EntityManager> entities, ptr<EventManager> events, double dt) override {} + +private: + template <typename D> + void assign(Entity entity) { + if (!entity.component<D>()) entity.assign<D>(); + } + + template <typename D, typename D1, typename ... Ds> + void assign(Entity entity) { + assign<D>(entity); + assign<D1, Ds...>(entity); + } +}; + +} // namespace deps +} // namespace entityx diff --git a/entityx/deps/Dependencies_test.cc b/entityx/deps/Dependencies_test.cc new file mode 100644 index 0000000..8a2f17c --- /dev/null +++ b/entityx/deps/Dependencies_test.cc @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013 Alec Thomas <alec@swapoff.org> + * All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. + * + * Author: Alec Thomas <alec@swapoff.org> + */ + +#include <gtest/gtest.h> +#include "entityx/deps/Dependencies.h" + + +namespace ex = entityx; +namespace deps = entityx::deps; + + +struct A : public ex::Component<A> {}; +struct B : public ex::Component<B> { + explicit B(bool b = false) : b(b) {} + + bool b; +}; +struct C : public ex::Component<C> {}; + + +class DepsTest : public ::testing::Test { + protected: + DepsTest() : events(ex::EventManager::make()), + entities(ex::EntityManager::make(events)), + systems(ex::SystemManager::make(entities, events)) {} + + ex::ptr<ex::EventManager> events; + ex::ptr<ex::EntityManager> entities; + ex::ptr<ex::SystemManager> systems; + + virtual void SetUp() {} +}; + + +TEST_F(DepsTest, TestSingleDependency) { + systems->add<deps::Dependency<A, B>>(); + systems->configure(); + + ex::Entity e = entities->create(); + ASSERT_FALSE(static_cast<bool>(e.component<A>())); + ASSERT_FALSE(static_cast<bool>(e.component<B>())); + e.assign<A>(); + ASSERT_TRUE(static_cast<bool>(e.component<A>())); + ASSERT_TRUE(static_cast<bool>(e.component<B>())); +} + +TEST_F(DepsTest, TestMultipleDependencies) { + systems->add<deps::Dependency<A, B, C>>(); + systems->configure(); + + ex::Entity e = entities->create(); + ASSERT_FALSE(static_cast<bool>(e.component<A>())); + ASSERT_FALSE(static_cast<bool>(e.component<B>())); + ASSERT_FALSE(static_cast<bool>(e.component<C>())); + e.assign<A>(); + ASSERT_TRUE(static_cast<bool>(e.component<A>())); + ASSERT_TRUE(static_cast<bool>(e.component<B>())); + ASSERT_TRUE(static_cast<bool>(e.component<C>())); +} + +TEST_F(DepsTest, TestDependencyDoesNotRecreateComponent) { + systems->add<deps::Dependency<A, B>>(); + systems->configure(); + + ex::Entity e = entities->create(); + e.assign<B>(true); + ASSERT_TRUE(e.component<B>()->b); + e.assign<A>(); + ASSERT_TRUE(e.component<B>()->b); +} |