aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/manager
diff options
context:
space:
mode:
Diffstat (limited to 'src/crepe/manager')
-rw-r--r--src/crepe/manager/ComponentManager.cpp11
-rw-r--r--src/crepe/manager/ComponentManager.h73
-rw-r--r--src/crepe/manager/ComponentManager.hpp81
-rw-r--r--src/crepe/manager/Mediator.h4
-rw-r--r--src/crepe/manager/SaveManager.cpp33
-rw-r--r--src/crepe/manager/SaveManager.h32
6 files changed, 169 insertions, 65 deletions
diff --git a/src/crepe/manager/ComponentManager.cpp b/src/crepe/manager/ComponentManager.cpp
index 80cf8b4..df30d27 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,13 @@ 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 44429d9..19a8e81 100644
--- a/src/crepe/manager/ComponentManager.h
+++ b/src/crepe/manager/ComponentManager.h
@@ -1,6 +1,7 @@
#pragma once
#include <memory>
+#include <set>
#include <typeindex>
#include <unordered_map>
#include <vector>
@@ -134,8 +135,77 @@ public:
*/
template <typename T>
RefVector<T> get_components_by_type() const;
+ /**
+ * \brief Get all components of a specific type on a GameObject with name \c name
+ *
+ * \tparam T The type of the component
+ * \param name Metadata::name for the same game_object_id as the returned components
+ * \return Components matching criteria
+ */
+ template <typename T>
+ RefVector<T> get_components_by_name(const std::string & name) const;
+ /**
+ * \brief Get all components of a specific type on a GameObject with tag \c tag
+ *
+ * \tparam T The type of the component
+ * \param name Metadata::tag for the same game_object_id as the returned components
+ * \return Components matching criteria
+ */
+ template <typename T>
+ RefVector<T> get_components_by_tag(const std::string & tag) const;
+
+private:
+ /**
+ * \brief Get object IDs by predicate function
+ *
+ * This function calls the predicate function \c pred for all components matching type \c T,
+ * and adds their parent game_object_id to a \c std::set if the predicate returns true.
+ *
+ * \tparam T The type of the component to check the predicate against
+ * \param pred Predicate function
+ *
+ * \note The predicate function may be called for multiple components with the same \c
+ * game_object_id. In this case, the ID is added if *any* call returns \c true.
+ *
+ * \returns game_object_id for all components where the predicate returned true
+ */
+ template <typename T>
+ std::set<game_object_id_t>
+ get_objects_by_predicate(const std::function<bool(const T &)> & pred) const;
+
+ /**
+ * \brief Get components of type \c T for multiple game object IDs
+ *
+ * \tparam T The type of the components to return
+ * \param ids The object IDs
+ *
+ * \return All components matching type \c T and one of the IDs in \c ids
+ */
+ template <typename T>
+ RefVector<T> get_components_by_ids(const std::set<game_object_id_t> & ids) const;
+
+ /**
+ * \brief Get object IDs for objects with name \c name
+ *
+ * \param name Object name to match
+ * \returns Object IDs where Metadata::name is equal to \c name
+ */
+ std::set<game_object_id_t> get_objects_by_name(const std::string & name) const;
+ /**
+ * \brief Get object IDs for objects with tag \c tag
+ *
+ * \param tag Object tag to match
+ * \returns Object IDs where Metadata::tag is equal to \c tag
+ */
+ std::set<game_object_id_t> get_objects_by_tag(const std::string & tag) const;
private:
+ //! By Component \c std::type_index (readability helper type)
+ template <typename T>
+ using by_type = std::unordered_map<std::type_index, T>;
+ //! By \c game_object_id index (readability helper type)
+ template <typename T>
+ using by_id_index = std::vector<T>;
/**
* \brief The components
*
@@ -146,8 +216,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;
diff --git a/src/crepe/manager/ComponentManager.hpp b/src/crepe/manager/ComponentManager.hpp
index ffb38ec..9e70865 100644
--- a/src/crepe/manager/ComponentManager.hpp
+++ b/src/crepe/manager/ComponentManager.hpp
@@ -95,32 +95,25 @@ 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;
-
- // 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());
-
- if (casted_component == nullptr) continue;
+ static_assert(is_base_of<Component, T>::value,
+ "get_components_by_id must recieve a derivative class of Component");
- // Add the dereferenced raw pointer to the vector<>
- component_vector.push_back(*casted_component);
+ type_index type = typeid(T);
+ if (!this->components.contains(type)) return {};
+
+ const by_id_index<vector<unique_ptr<Component>>> & components_by_id
+ = this->components.at(type);
+ if (id >= components_by_id.size()) return {};
+
+ 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 +151,46 @@ 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;
+}
+
+template <typename T>
+RefVector<T>
+ComponentManager::get_components_by_ids(const std::set<game_object_id_t> & ids) const {
+ using namespace std;
+
+ RefVector<T> out = {};
+ for (game_object_id_t id : ids) {
+ RefVector<T> components = get_components_by_id<T>(id);
+ out.insert(out.end(), components.begin(), components.end());
+ }
+
+ return out;
+}
+
+template <typename T>
+RefVector<T> ComponentManager::get_components_by_name(const std::string & name) const {
+ return this->get_components_by_ids<T>(this->get_objects_by_name(name));
+}
+
+template <typename T>
+RefVector<T> ComponentManager::get_components_by_tag(const std::string & tag) const {
+ return this->get_components_by_ids<T>(this->get_objects_by_tag(tag));
+}
+
} // namespace crepe
diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h
index bb51d6b..d5f7e00 100644
--- a/src/crepe/manager/Mediator.h
+++ b/src/crepe/manager/Mediator.h
@@ -5,11 +5,13 @@
// TODO: remove these singletons:
#include "EventManager.h"
#include "SaveManager.h"
+#include "api/LoopTimer.h"
namespace crepe {
class ComponentManager;
class SceneManager;
+class SaveManager;
class ResourceManager;
class SDLContext;
class LoopTimer;
@@ -30,7 +32,7 @@ struct Mediator {
OptionalRef<SDLContext> sdl_context;
OptionalRef<ComponentManager> component_manager;
OptionalRef<SceneManager> scene_manager;
- OptionalRef<SaveManager> save_manager = SaveManager::get_instance();
+ OptionalRef<SaveManager> save_manager;
OptionalRef<EventManager> event_manager = EventManager::get_instance();
OptionalRef<ResourceManager> resource_manager;
OptionalRef<LoopTimer> timer;
diff --git a/src/crepe/manager/SaveManager.cpp b/src/crepe/manager/SaveManager.cpp
index d4ed1c1..691ea2f 100644
--- a/src/crepe/manager/SaveManager.cpp
+++ b/src/crepe/manager/SaveManager.cpp
@@ -1,13 +1,25 @@
#include "../ValueBroker.h"
#include "../api/Config.h"
#include "../facade/DB.h"
-#include "../util/Log.h"
#include "SaveManager.h"
using namespace std;
using namespace crepe;
+SaveManager::SaveManager(Mediator & mediator) : Manager(mediator) {
+ mediator.save_manager = *this;
+}
+
+DB & SaveManager::get_db() {
+ if (this->db == nullptr) {
+ Config & cfg = Config::get_instance();
+ this->db
+ = {new DB(cfg.savemgr.location), [](void * db) { delete static_cast<DB *>(db); }};
+ }
+ return *static_cast<DB *>(this->db.get());
+}
+
template <>
string SaveManager::serialize(const string & value) const noexcept {
return value;
@@ -90,22 +102,6 @@ int32_t SaveManager::deserialize(const string & value) const noexcept {
return deserialize<int64_t>(value);
}
-SaveManager::SaveManager() { dbg_trace(); }
-
-SaveManager & SaveManager::get_instance() {
- dbg_trace();
- static SaveManager instance;
- return instance;
-}
-
-DB & SaveManager::get_db() {
- Config & cfg = Config::get_instance();
- // TODO: make this path relative to XDG_DATA_HOME on Linux and whatever the
- // default equivalent is on Windows using some third party library
- static DB db(cfg.savemgr.location);
- return db;
-}
-
bool SaveManager::has(const string & key) {
DB & db = this->get_db();
return db.has(key);
@@ -155,7 +151,8 @@ ValueBroker<T> SaveManager::get(const string & key) {
return {
[this, key](const T & target) { this->set<T>(key, target); },
[this, key, value]() mutable -> const T & {
- value = this->deserialize<T>(this->get_db().get(key));
+ DB & db = this->get_db();
+ value = this->deserialize<T>(db.get(key));
return value;
},
};
diff --git a/src/crepe/manager/SaveManager.h b/src/crepe/manager/SaveManager.h
index 3d8c852..61a978d 100644
--- a/src/crepe/manager/SaveManager.h
+++ b/src/crepe/manager/SaveManager.h
@@ -1,9 +1,12 @@
#pragma once
+#include <functional>
#include <memory>
#include "../ValueBroker.h"
+#include "Manager.h"
+
namespace crepe {
class DB;
@@ -18,7 +21,7 @@ class DB;
*
* The underlying database is a key-value store.
*/
-class SaveManager {
+class SaveManager : public Manager {
public:
/**
* \brief Get a read/write reference to a value and initialize it if it does not yet exist
@@ -63,8 +66,8 @@ public:
*/
bool has(const std::string & key);
-private:
- SaveManager();
+public:
+ SaveManager(Mediator & mediator);
virtual ~SaveManager() = default;
private:
@@ -89,26 +92,13 @@ private:
template <typename T>
T deserialize(const std::string & value) const noexcept;
-public:
- // singleton
- static SaveManager & get_instance();
- SaveManager(const SaveManager &) = delete;
- SaveManager(SaveManager &&) = delete;
- SaveManager & operator=(const SaveManager &) = delete;
- SaveManager & operator=(SaveManager &&) = delete;
+protected:
+ //! Create or return DB
+ virtual DB & get_db();
private:
- /**
- * \brief Create an instance of DB and return its reference
- *
- * \returns DB instance
- *
- * This function exists because DB is a facade class, which can't directly be used in the API
- * without workarounds
- *
- * TODO: better solution
- */
- static DB & get_db();
+ //! Database
+ std::unique_ptr<void, std::function<void(void *)>> db = nullptr;
};
} // namespace crepe