aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-12-06 17:13:59 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-12-06 17:13:59 +0100
commitf4824f5e7e6cee12bec602f3240770945a73d043 (patch)
tree7d51652e5395ca70f995c0d059c36e1dd18bd8ae
parent0bed469e2ececfa240085a34252dd7ed23519de3 (diff)
add more fetching functions to ComponentManager
-rw-r--r--src/crepe/api/Script.h7
-rw-r--r--src/crepe/manager/ComponentManager.cpp14
-rw-r--r--src/crepe/manager/ComponentManager.h18
-rw-r--r--src/crepe/manager/ComponentManager.hpp51
-rw-r--r--src/test/ECSTest.cpp34
5 files changed, 101 insertions, 23 deletions
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index 1b339b0..5862bae 100644
--- a/src/crepe/api/Script.h
+++ b/src/crepe/api/Script.h
@@ -85,6 +85,13 @@ protected:
RefVector<T> get_components() const;
/**
+ * \copydoc ComponentManager::get_components_by_id
+ * \see ComponentManager::get_components_by_id
+ */
+ template <typename T>
+ RefVector<T> get_components_by_id(game_object_id_t id) const;
+
+ /**
* \brief Log a message using Log::logf
*
* \tparam Args Log::logf parameters
diff --git a/src/crepe/manager/ComponentManager.cpp b/src/crepe/manager/ComponentManager.cpp
index 80cf8b4..44774d9 100644
--- a/src/crepe/manager/ComponentManager.cpp
+++ b/src/crepe/manager/ComponentManager.cpp
@@ -1,4 +1,5 @@
#include "../api/GameObject.h"
+#include "../api/Metadata.h"
#include "../types.h"
#include "../util/Log.h"
@@ -61,3 +62,16 @@ GameObject ComponentManager::new_object(const string & name, const string & tag,
void ComponentManager::set_persistent(game_object_id_t id, bool persistent) {
this->persistent[id] = persistent;
}
+
+set<game_object_id_t> ComponentManager::get_objects_by_name(const string & name) const {
+ return this->get_objects_by_predicate<Metadata>([name](const Metadata & data) {
+ return data.name == name;
+ });
+}
+
+set<game_object_id_t> ComponentManager::get_objects_by_tag(const string & tag) const {
+ return this->get_objects_by_predicate<Metadata>([tag](const Metadata & data) {
+ return data.tag == tag;
+ });
+}
+
diff --git a/src/crepe/manager/ComponentManager.h b/src/crepe/manager/ComponentManager.h
index ad37586..5f2cf3c 100644
--- a/src/crepe/manager/ComponentManager.h
+++ b/src/crepe/manager/ComponentManager.h
@@ -4,6 +4,7 @@
#include <typeindex>
#include <unordered_map>
#include <vector>
+#include <set>
#include "../Component.h"
#include "../types.h"
@@ -136,6 +137,17 @@ public:
RefVector<T> get_components_by_type() const;
private:
+ template <typename T>
+ std::set<game_object_id_t> get_objects_by_predicate(const std::function<bool (const T &)> & pred) const;
+
+ std::set<game_object_id_t> get_objects_by_name(const std::string & name) const;
+ std::set<game_object_id_t> get_objects_by_tag(const std::string & tag) const;
+
+private:
+ template <typename T>
+ using by_type = std::unordered_map<std::type_index, T>;
+ template <typename T>
+ using by_id_index = std::vector<T>;
/**
* \brief The components
*
@@ -146,8 +158,7 @@ private:
* The first vector is for the ids of the GameObjects and the second vector is for the
* components (because a GameObject might have multiple components).
*/
- std::unordered_map<std::type_index, std::vector<std::vector<std::unique_ptr<Component>>>>
- components;
+ by_type<by_id_index<std::vector<std::unique_ptr<Component>>>> components;
//! Persistent flag for each GameObject
std::unordered_map<game_object_id_t, bool> persistent;
@@ -156,6 +167,9 @@ private:
game_object_id_t next_id = 0;
};
+// template <>
+// RefVector<Component> ComponentManager::get_components_by_id(game_object_id_t id) const;
+
} // namespace crepe
#include "ComponentManager.hpp"
diff --git a/src/crepe/manager/ComponentManager.hpp b/src/crepe/manager/ComponentManager.hpp
index ffb38ec..25c2747 100644
--- a/src/crepe/manager/ComponentManager.hpp
+++ b/src/crepe/manager/ComponentManager.hpp
@@ -95,32 +95,24 @@ template <typename T>
RefVector<T> ComponentManager::get_components_by_id(game_object_id_t id) const {
using namespace std;
- // Determine the type of T (this is used as the key of the unordered_map<>)
- type_index type = typeid(T);
-
- // Create an empty vector<>
- RefVector<T> component_vector;
-
- if (this->components.find(type) == this->components.end()) return component_vector;
-
- // Get the correct vector<>
- const vector<vector<unique_ptr<Component>>> & component_array = this->components.at(type);
-
- // Make sure that the id (that we are looking for) is within the boundaries of the vector<>
- if (id >= component_array.size()) return component_vector;
+ static_assert(is_base_of<Component, T>::value,
+ "get_components_by_id must recieve a derivative class of Component");
- // Loop trough the whole vector<>
- for (const unique_ptr<Component> & component_ptr : component_array[id]) {
- // Cast the unique_ptr to a raw pointer
- T * casted_component = static_cast<T *>(component_ptr.get());
+ type_index type = typeid(T);
+ if (!this->components.contains(type)) return {};
- if (casted_component == nullptr) continue;
+ const by_id_index<vector<unique_ptr<Component>>> & components_by_id = this->components.at(type);
+ if (id >= components_by_id.size()) return {};
- // Add the dereferenced raw pointer to the vector<>
- component_vector.push_back(*casted_component);
+ RefVector<T> out = {};
+ const vector<unique_ptr<Component>> & components = components_by_id.at(id);
+ for (auto & component_ptr : components) {
+ if (component_ptr == nullptr) continue;
+ Component & component = *component_ptr.get();
+ out.push_back(static_cast<T &>(component));
}
- return component_vector;
+ return out;
}
template <typename T>
@@ -158,4 +150,21 @@ RefVector<T> ComponentManager::get_components_by_type() const {
return component_vector;
}
+template <typename T>
+std::set<game_object_id_t> ComponentManager::get_objects_by_predicate(const std::function<bool (const T &)> & pred) const {
+ using namespace std;
+
+ set<game_object_id_t> objects = {};
+ RefVector<T> components = this->get_components_by_type<T>();
+
+ for (const T & component : components) {
+ game_object_id_t id = dynamic_cast<const Component &>(component).game_object_id;
+ if (objects.contains(id)) continue;
+ if (!pred(component)) continue;
+ objects.insert(id);
+ }
+
+ return objects;
+}
+
} // namespace crepe
diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp
index 3e6c61c..a169b3b 100644
--- a/src/test/ECSTest.cpp
+++ b/src/test/ECSTest.cpp
@@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#define protected public
+#define private public
#include <crepe/api/GameObject.h>
#include <crepe/api/Metadata.h>
@@ -387,3 +388,36 @@ TEST_F(ECSTest, resetPersistent) {
EXPECT_EQ(metadata.size(), 0);
EXPECT_EQ(transform.size(), 0);
}
+
+TEST_F(ECSTest, GetByName) {
+ GameObject foo = mgr.new_object("foo");
+ GameObject bar = mgr.new_object("bar");
+
+ {
+ auto objects = mgr.get_objects_by_name("");
+ EXPECT_EQ(objects.size(), 0);
+ }
+
+ {
+ auto objects = mgr.get_objects_by_name("foo");
+ EXPECT_EQ(objects.size(), 1);
+ EXPECT_TRUE(objects.contains(foo.id));
+ }
+}
+
+TEST_F(ECSTest, GetByTag) {
+ GameObject foo = mgr.new_object("foo", "common tag");
+ GameObject bar = mgr.new_object("bar", "common tag");
+
+ {
+ auto objects = mgr.get_objects_by_tag("");
+ EXPECT_EQ(objects.size(), 0);
+ }
+
+ {
+ auto objects = mgr.get_objects_by_tag("common tag");
+ EXPECT_EQ(objects.size(), 2);
+ EXPECT_TRUE(objects.contains(foo.id));
+ EXPECT_TRUE(objects.contains(bar.id));
+ }
+}