]> code.bitgloo.com Git - clyne/entityx.git/commitdiff
Add `Dependency<C, D1, D2...>` System for automatic component
authorAlec Thomas <alec@swapoff.org>
Fri, 4 Oct 2013 14:41:04 +0000 (10:41 -0400)
committerAlec Thomas <alec@swapoff.org>
Fri, 4 Oct 2013 14:41:04 +0000 (10:41 -0400)
dependencies.

CMakeLists.txt
Doxyfile
entityx/deps/Dependencies.cc [new file with mode: 0644]
entityx/deps/Dependencies.h [new file with mode: 0644]
entityx/deps/Dependencies_test.cc [new file with mode: 0644]

index 761a031284e1985c19cfbde7b8d8de16ba24833e..ba530fa45692a7005051d8cdb229bf90341bacef 100644 (file)
@@ -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})
index bcbc8977f3bb6757ca9937d98911028c88b3e8ff..d1154623f3bc3cf64cdbdf1eb88b70b1d7298c43 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -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 (file)
index 0000000..9271a2f
--- /dev/null
@@ -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 (file)
index 0000000..69e68bb
--- /dev/null
@@ -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 (file)
index 0000000..8a2f17c
--- /dev/null
@@ -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);
+}