From 6fd7cec7d4bbf5aeb361b3f1337671bb0f9af61b Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Thu, 28 Nov 2024 10:13:11 +0100 Subject: manager mediator refactor --- src/crepe/manager/CMakeLists.txt | 20 ++++ src/crepe/manager/ComponentManager.cpp | 63 ++++++++++++ src/crepe/manager/ComponentManager.h | 161 ++++++++++++++++++++++++++++++ src/crepe/manager/ComponentManager.hpp | 161 ++++++++++++++++++++++++++++++ src/crepe/manager/EventManager.cpp | 46 +++++++++ src/crepe/manager/EventManager.h | 161 ++++++++++++++++++++++++++++++ src/crepe/manager/EventManager.hpp | 36 +++++++ src/crepe/manager/Manager.cpp | 6 ++ src/crepe/manager/Manager.h | 17 ++++ src/crepe/manager/Mediator.h | 29 ++++++ src/crepe/manager/SaveManager.cpp | 173 +++++++++++++++++++++++++++++++++ src/crepe/manager/SaveManager.h | 114 ++++++++++++++++++++++ src/crepe/manager/SceneManager.cpp | 35 +++++++ src/crepe/manager/SceneManager.h | 52 ++++++++++ src/crepe/manager/SceneManager.hpp | 25 +++++ 15 files changed, 1099 insertions(+) create mode 100644 src/crepe/manager/CMakeLists.txt create mode 100644 src/crepe/manager/ComponentManager.cpp create mode 100644 src/crepe/manager/ComponentManager.h create mode 100644 src/crepe/manager/ComponentManager.hpp create mode 100644 src/crepe/manager/EventManager.cpp create mode 100644 src/crepe/manager/EventManager.h create mode 100644 src/crepe/manager/EventManager.hpp create mode 100644 src/crepe/manager/Manager.cpp create mode 100644 src/crepe/manager/Manager.h create mode 100644 src/crepe/manager/Mediator.h create mode 100644 src/crepe/manager/SaveManager.cpp create mode 100644 src/crepe/manager/SaveManager.h create mode 100644 src/crepe/manager/SceneManager.cpp create mode 100644 src/crepe/manager/SceneManager.h create mode 100644 src/crepe/manager/SceneManager.hpp (limited to 'src/crepe/manager') diff --git a/src/crepe/manager/CMakeLists.txt b/src/crepe/manager/CMakeLists.txt new file mode 100644 index 0000000..517b8a2 --- /dev/null +++ b/src/crepe/manager/CMakeLists.txt @@ -0,0 +1,20 @@ +target_sources(crepe PUBLIC + ComponentManager.cpp + EventManager.cpp + Manager.cpp + SaveManager.cpp + SceneManager.cpp +) + +target_sources(crepe PUBLIC FILE_SET HEADERS FILES + ComponentManager.h + ComponentManager.hpp + EventManager.h + EventManager.hpp + Manager.h + Mediator.h + SaveManager.h + SceneManager.h + SceneManager.hpp +) + diff --git a/src/crepe/manager/ComponentManager.cpp b/src/crepe/manager/ComponentManager.cpp new file mode 100644 index 0000000..5a96158 --- /dev/null +++ b/src/crepe/manager/ComponentManager.cpp @@ -0,0 +1,63 @@ +#include "../api/GameObject.h" +#include "../util/Log.h" +#include "../types.h" + +#include "ComponentManager.h" + +using namespace crepe; +using namespace std; + +ComponentManager::ComponentManager(Mediator & mediator) : Manager(mediator) { + mediator.component_manager = *this; + dbg_trace(); +} +ComponentManager::~ComponentManager() { dbg_trace(); } + +void ComponentManager::delete_all_components_of_id(game_object_id_t id) { + // Do not delete persistent objects + if (this->persistent[id]) { + return; + } + + // Loop through all the types (in the unordered_map<>) + for (auto & [type, component_array] : this->components) { + // Make sure that the id (that we are looking for) is within the boundaries of the vector<> + if (id < component_array.size()) { + // Clear the components at this specific id + component_array[id].clear(); + } + } +} + +void ComponentManager::delete_all_components() { + // Loop through all the types (in the unordered_map<>) + for (auto & [type, component_array] : this->components) { + // Loop through all the ids (in the vector<>) + for (game_object_id_t id = 0; id < component_array.size(); id++) { + // Do not delete persistent objects + if (!this->persistent[id]) { + // Clear the components at this specific id + component_array[id].clear(); + } + } + } + + this->next_id = 0; +} + +GameObject ComponentManager::new_object(const string & name, const string & tag, + const vec2 & position, double rotation, double scale) { + // Find the first available id (taking persistent objects into account) + while (this->persistent[this->next_id]) { + this->next_id++; + } + + GameObject object{*this, this->next_id, name, tag, position, rotation, scale}; + this->next_id++; + + return object; +} + +void ComponentManager::set_persistent(game_object_id_t id, bool persistent) { + this->persistent[id] = persistent; +} diff --git a/src/crepe/manager/ComponentManager.h b/src/crepe/manager/ComponentManager.h new file mode 100644 index 0000000..ad37586 --- /dev/null +++ b/src/crepe/manager/ComponentManager.h @@ -0,0 +1,161 @@ +#pragma once + +#include +#include +#include +#include + +#include "../Component.h" +#include "../types.h" + +#include "Manager.h" + +namespace crepe { + +class GameObject; + +/** + * \brief Manages all components + * + * This class manages all components. It provides methods to add, delete and get components. + */ +class ComponentManager : public Manager { + // TODO: This relation should be removed! I (loek) believe that the scene manager should + // create/destroy components because the GameObject's are stored in concrete Scene classes, + // which will in turn call GameObject's destructor, which will in turn call + // ComponentManager::delete_components_by_id or something. This is a pretty major change, so + // here is a comment and temporary fix instead :tada: + friend class SceneManager; + +public: + ComponentManager(Mediator & mediator); + ~ComponentManager(); // dbg_trace + + /** + * \brief Create a new game object using the component manager + * + * \param name Metadata::name (required) + * \param tag Metadata::tag (optional, empty by default) + * \param position Transform::position (optional, origin by default) + * \param rotation Transform::rotation (optional, 0 by default) + * \param scale Transform::scale (optional, 1 by default) + * + * \returns GameObject interface + * + * \note This method automatically assigns a new entity ID + */ + GameObject new_object(const std::string & name, const std::string & tag = "", + const vec2 & position = {0, 0}, double rotation = 0, + double scale = 1); + +protected: + /** + * GameObject is used as an interface to add/remove components, and the game programmer is + * supposed to use it instead of interfacing with the component manager directly. + */ + friend class GameObject; + /** + * \brief Add a component to the ComponentManager + * + * This method adds a component to the ComponentManager. The component is created with the + * given arguments and added to the ComponentManager. + * + * \tparam T The type of the component + * \tparam Args The types of the arguments + * \param id The id of the GameObject this component belongs to + * \param args The arguments to create the component + * \return The created component + */ + template + T & add_component(game_object_id_t id, Args &&... args); + /** + * \brief Delete all components of a specific type and id + * + * This method deletes all components of a specific type and id. + * + * \tparam T The type of the component + * \param id The id of the GameObject this component belongs to + */ + template + void delete_components_by_id(game_object_id_t id); + /** + * \brief Delete all components of a specific type + * + * This method deletes all components of a specific type. + * + * \tparam T The type of the component + */ + template + void delete_components(); + /** + * \brief Delete all components of a specific id + * + * This method deletes all components of a specific id. + * + * \param id The id of the GameObject this component belongs to + */ + void delete_all_components_of_id(game_object_id_t id); + /** + * \brief Delete all components + * + * This method deletes all components. + */ + void delete_all_components(); + /** + * \brief Set a GameObject as persistent + * + * This method sets a GameObject as persistent. If a GameObject is persistent, its + * components will not be deleted. + * + * \param id The id of the GameObject to set as persistent + * \param persistent The persistent flag + */ + void set_persistent(game_object_id_t id, bool persistent); + +public: + /** + * \brief Get all components of a specific type and id + * + * This method gets all components of a specific type and id. + * + * \tparam T The type of the component + * \param id The id of the GameObject this component belongs to + * \return A vector of all components of the specific type and id + */ + template + RefVector get_components_by_id(game_object_id_t id) const; + /** + * \brief Get all components of a specific type + * + * This method gets all components of a specific type. + * + * \tparam T The type of the component + * \return A vector of all components of the specific type + */ + template + RefVector get_components_by_type() const; + +private: + /** + * \brief The components + * + * This unordered_map stores all components. The key is the type of the component and the + * value is a vector of vectors of unique pointers to the components. + * + * Every component type has its own vector of vectors of unique pointers to the components. + * 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>>> + components; + + //! Persistent flag for each GameObject + std::unordered_map persistent; + + //! ID of next GameObject allocated by \c ComponentManager::new_object + game_object_id_t next_id = 0; +}; + +} // namespace crepe + +#include "ComponentManager.hpp" diff --git a/src/crepe/manager/ComponentManager.hpp b/src/crepe/manager/ComponentManager.hpp new file mode 100644 index 0000000..ffb38ec --- /dev/null +++ b/src/crepe/manager/ComponentManager.hpp @@ -0,0 +1,161 @@ +#pragma once + +#include + +#include "ComponentManager.h" +#include "types.h" + +namespace crepe { + +template +T & ComponentManager::add_component(game_object_id_t id, Args &&... args) { + using namespace std; + + static_assert(is_base_of::value, + "add_component must recieve a derivative class of Component"); + + // Determine the type of T (this is used as the key of the unordered_map<>) + type_index type = typeid(T); + + // Check if this component type is already in the unordered_map<> + if (this->components.find(type) == this->components.end()) { + //If not, create a new (empty) vector<> of vector> + this->components[type] = vector>>(); + } + + // Resize the vector<> if the id is greater than the current size + if (id >= this->components[type].size()) { + // Initialize new slots to nullptr (resize does automatically init to nullptr) + this->components[type].resize(id + 1); + } + + // Create a new component of type T (arguments directly forwarded). The + // constructor must be called by ComponentManager. + T * instance_ptr = new T(id, forward(args)...); + if (instance_ptr == nullptr) throw std::bad_alloc(); + + T & instance_ref = *instance_ptr; + unique_ptr instance = unique_ptr(instance_ptr); + + // Check if the vector size is not greater than get_instances_max + int max_instances = instance->get_instances_max(); + if (max_instances != -1 && components[type][id].size() >= max_instances) { + throw std::runtime_error( + "Exceeded maximum number of instances for this component type"); + } + + // store its unique_ptr in the vector<> + this->components[type][id].push_back(std::move(instance)); + + return instance_ref; +} + +template +void ComponentManager::delete_components_by_id(game_object_id_t id) { + using namespace std; + + // Do not delete persistent objects + if (this->persistent[id]) { + return; + } + + // Determine the type of T (this is used as the key of the unordered_map<>) + type_index type = typeid(T); + + // Find the type (in the unordered_map<>) + if (this->components.find(type) != this->components.end()) { + // Get the correct vector<> + vector>> & component_array = this->components[type]; + + // Make sure that the id (that we are looking for) is within the boundaries of the vector<> + if (id < component_array.size()) { + // Clear the whole vector<> of this specific type and id + component_array[id].clear(); + } + } +} + +template +void ComponentManager::delete_components() { + // Determine the type of T (this is used as the key of the unordered_map<>) + std::type_index type = typeid(T); + + if (this->components.find(type) == this->components.end()) return; + + // Loop through the whole vector<> of this specific type + for (game_object_id_t i = 0; i < this->components[type].size(); ++i) { + // Do not delete persistent objects + if (!this->persistent[i]) { + this->components[type][i].clear(); + } + } +} + +template +RefVector 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 component_vector; + + if (this->components.find(type) == this->components.end()) return component_vector; + + // Get the correct vector<> + const vector>> & 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_ptr : component_array[id]) { + // Cast the unique_ptr to a raw pointer + T * casted_component = static_cast(component_ptr.get()); + + if (casted_component == nullptr) continue; + + // Add the dereferenced raw pointer to the vector<> + component_vector.push_back(*casted_component); + } + + return component_vector; +} + +template +RefVector ComponentManager::get_components_by_type() 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 component_vector; + + // Find the type (in the unordered_map<>) + if (this->components.find(type) == this->components.end()) return component_vector; + + // Get the correct vector<> + const vector>> & component_array = this->components.at(type); + + // Loop through the whole vector<> + for (const vector> & component : component_array) { + // Loop trough the whole vector<> + for (const unique_ptr & component_ptr : component) { + // Cast the unique_ptr to a raw pointer + T * casted_component = static_cast(component_ptr.get()); + + // Ensure that the cast was successful + if (casted_component == nullptr) continue; + + // Add the dereferenced raw pointer to the vector<> + component_vector.emplace_back(ref(*casted_component)); + } + } + + // Return the vector<> + return component_vector; +} + +} // namespace crepe diff --git a/src/crepe/manager/EventManager.cpp b/src/crepe/manager/EventManager.cpp new file mode 100644 index 0000000..20f0dd3 --- /dev/null +++ b/src/crepe/manager/EventManager.cpp @@ -0,0 +1,46 @@ +#include "EventManager.h" + +using namespace crepe; +using namespace std; + +EventManager & EventManager::get_instance() { + static EventManager instance; + return instance; +} + +void EventManager::dispatch_events() { + for (auto & event : this->events_queue) { + this->handle_event(event.type, event.channel, *event.event.get()); + } + this->events_queue.clear(); +} + +void EventManager::handle_event(type_index type, event_channel_t channel, const Event & data) { + auto handlers_it = this->subscribers.find(type); + if (handlers_it == this->subscribers.end()) return; + + vector & handlers = handlers_it->second; + for (auto & handler : handlers) { + bool check_channel = handler.channel != CHANNEL_ALL || channel != CHANNEL_ALL; + if (check_channel && handler.channel != channel) continue; + + bool handled = handler.callback->exec(data); + if (handled) return; + } +} + +void EventManager::clear() { + this->subscribers.clear(); + this->events_queue.clear(); +} + +void EventManager::unsubscribe(subscription_t id) { + for (auto & [event_type, handlers] : this->subscribers) { + for (auto it = handlers.begin(); it != handlers.end(); it++) { + // find listener with subscription id + if ((*it).id != id) continue; + it = handlers.erase(it); + return; + } + } +} diff --git a/src/crepe/manager/EventManager.h b/src/crepe/manager/EventManager.h new file mode 100644 index 0000000..d634f54 --- /dev/null +++ b/src/crepe/manager/EventManager.h @@ -0,0 +1,161 @@ +#pragma once + +#include +#include +#include +#include + +#include "../api/Event.h" +#include "../api/EventHandler.h" + +namespace crepe { + +//! Event listener unique ID +typedef size_t subscription_t; + +/** + * \brief Event channel + * + * Events can be sent to a specific channel, which prevents listeners on other channels from + * being called. The default channel is EventManager::CHANNEL_ALL, which calls all listeners. + */ +typedef size_t event_channel_t; + +/** + * \class EventManager + * \brief Manages event subscriptions, triggers, and queues, enabling decoupled event handling. + * + * The `EventManager` acts as a centralized event system. It allows for registering callbacks + * for specific event types, triggering events synchronously, queueing events for later + * processing, and managing subscriptions via unique identifiers. + */ +class EventManager { +public: + static constexpr const event_channel_t CHANNEL_ALL = -1; + + /** + * \brief Get the singleton instance of the EventManager. + * + * This method returns the unique instance of the EventManager, creating it if it + * doesn't already exist. Ensures only one instance is active in the program. + * + * \return Reference to the singleton instance of the EventManager. + */ + static EventManager & get_instance(); + + /** + * \brief Subscribe to a specific event type. + * + * Registers a callback for a given event type and optional channel. Each callback + * is assigned a unique subscription ID that can be used for later unsubscription. + * + * \tparam EventType The type of the event to subscribe to. + * \param callback The callback function to be invoked when the event is triggered. + * \param channel The channel number to subscribe to (default is CHANNEL_ALL, which listens to all channels). + * \return A unique subscription ID associated with the registered callback. + */ + template + subscription_t subscribe(const EventHandler & callback, + event_channel_t channel = CHANNEL_ALL); + + /** + * \brief Unsubscribe a previously registered callback. + * + * Removes a callback from the subscription list based on its unique subscription ID. + * + * \param event_id The unique subscription ID of the callback to remove. + */ + void unsubscribe(subscription_t event_id); + + /** + * \brief Trigger an event immediately. + * + * Synchronously invokes all registered callbacks for the given event type on the specified channel. + * + * \tparam EventType The type of the event to trigger. + * \param event The event instance to pass to the callbacks. + * \param channel The channel to trigger the event on (default is CHANNEL_ALL, which triggers on all channels). + */ + template + void trigger_event(const EventType & event = {}, event_channel_t channel = CHANNEL_ALL); + + /** + * \brief Queue an event for later processing. + * + * Adds an event to the event queue to be processed during the next call to `dispatch_events`. + * + * \tparam EventType The type of the event to queue. + * \param event The event instance to queue. + * \param channel The channel to associate with the event (default is CHANNEL_ALL). + */ + template + void queue_event(const EventType & event = {}, event_channel_t channel = CHANNEL_ALL); + + /** + * \brief Process all queued events. + * + * Iterates through the event queue and triggers callbacks for each queued event. + * Events are removed from the queue once processed. + */ + void dispatch_events(); + + /** + * \brief Clear all subscriptions. + * + * Removes all registered event handlers and clears the subscription list. + */ + void clear(); + +private: + /** + * \brief Default constructor for the EventManager. + * + * Constructor is private to enforce the singleton pattern. + */ + EventManager() = default; + + /** + * \struct QueueEntry + * \brief Represents an entry in the event queue. + */ + struct QueueEntry { + std::unique_ptr event; ///< The event instance. + event_channel_t channel = CHANNEL_ALL; ///< The channel associated with the event. + std::type_index type; ///< The type of the event. + }; + + /** + * \brief Internal event handler + * + * This function processes a single event, and is used to process events both during + * EventManager::dispatch_events and inside EventManager::trigger_event + * + * \param type \c typeid of concrete Event class + * \param channel Event channel + * \param data Event data + */ + void handle_event(std::type_index type, event_channel_t channel, const Event & data); + + /** + * \struct CallbackEntry + * \brief Represents a registered event handler callback. + */ + struct CallbackEntry { + std::unique_ptr callback; ///< The callback function wrapper. + event_channel_t channel = CHANNEL_ALL; ///< The channel this callback listens to. + subscription_t id = -1; ///< Unique subscription ID. + }; + + //! The queue of events to be processed during dispatch. + std::vector events_queue; + + //! A map of event type to registered callbacks. + std::unordered_map> subscribers; + + //! Counter to generate unique subscription IDs. + subscription_t subscription_counter = 0; +}; + +} // namespace crepe + +#include "EventManager.hpp" diff --git a/src/crepe/manager/EventManager.hpp b/src/crepe/manager/EventManager.hpp new file mode 100644 index 0000000..a5f4556 --- /dev/null +++ b/src/crepe/manager/EventManager.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "EventManager.h" + +namespace crepe { + +template +subscription_t EventManager::subscribe(const EventHandler & callback, + event_channel_t channel) { + subscription_counter++; + std::type_index event_type = typeid(EventType); + std::unique_ptr> handler + = std::make_unique>(callback); + std::vector & handlers = this->subscribers[event_type]; + handlers.emplace_back(CallbackEntry{ + .callback = std::move(handler), .channel = channel, .id = subscription_counter}); + return subscription_counter; +} + +template +void EventManager::queue_event(const EventType & event, event_channel_t channel) { + static_assert(std::is_base_of::value, + "EventType must derive from Event"); + this->events_queue.push_back(QueueEntry{ + .event = std::make_unique(event), + .channel = channel, + .type = typeid(EventType), + }); +} + +template +void EventManager::trigger_event(const EventType & event, event_channel_t channel) { + this->handle_event(typeid(EventType), channel, event); +} + +} // namespace crepe diff --git a/src/crepe/manager/Manager.cpp b/src/crepe/manager/Manager.cpp new file mode 100644 index 0000000..fe7c936 --- /dev/null +++ b/src/crepe/manager/Manager.cpp @@ -0,0 +1,6 @@ +#include "Manager.h" + +using namespace crepe; + +Manager::Manager(Mediator & mediator) : mediator(mediator) { } + diff --git a/src/crepe/manager/Manager.h b/src/crepe/manager/Manager.h new file mode 100644 index 0000000..9adfd0b --- /dev/null +++ b/src/crepe/manager/Manager.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Mediator.h" + +namespace crepe { + +class Manager { +public: + Manager(Mediator & mediator); + virtual ~Manager() = default; + +protected: + Mediator & mediator; +}; + +} + diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h new file mode 100644 index 0000000..ce35d5c --- /dev/null +++ b/src/crepe/manager/Mediator.h @@ -0,0 +1,29 @@ +#pragma once + +#include "../util/OptionalRef.h" + +// TODO: remove these singletons: +#include "SaveManager.h" +#include "EventManager.h" + +namespace crepe { + +class ComponentManager; +class SceneManager; + +/** + * Struct to pass references to classes that would otherwise need to be singletons down to + * other classes within the engine hierarchy. Made to prevent constant changes to subclasses to + * pass specific references through dependency injection. All references on this struct + * *should* be explicitly checked for availability as this struct does not guarantee anything. + * + * \todo Find better solution + */ +struct Mediator { + OptionalRef component_manager; + OptionalRef scene_manager; + OptionalRef save_manager = SaveManager::get_instance(); + OptionalRef event_manager = EventManager::get_instance(); +}; + +} diff --git a/src/crepe/manager/SaveManager.cpp b/src/crepe/manager/SaveManager.cpp new file mode 100644 index 0000000..121d017 --- /dev/null +++ b/src/crepe/manager/SaveManager.cpp @@ -0,0 +1,173 @@ +#include "../facade/DB.h" +#include "../util/Log.h" +#include "../api/Config.h" +#include "../ValueBroker.h" + +#include "SaveManager.h" + +using namespace std; +using namespace crepe; + +template <> +string SaveManager::serialize(const string & value) const noexcept { + return value; +} +template +string SaveManager::serialize(const T & value) const noexcept { + return to_string(value); +} +template string SaveManager::serialize(const uint8_t &) const noexcept; +template string SaveManager::serialize(const int8_t &) const noexcept; +template string SaveManager::serialize(const uint16_t &) const noexcept; +template string SaveManager::serialize(const int16_t &) const noexcept; +template string SaveManager::serialize(const uint32_t &) const noexcept; +template string SaveManager::serialize(const int32_t &) const noexcept; +template string SaveManager::serialize(const uint64_t &) const noexcept; +template string SaveManager::serialize(const int64_t &) const noexcept; +template string SaveManager::serialize(const float &) const noexcept; +template string SaveManager::serialize(const double &) const noexcept; + +template <> +uint64_t SaveManager::deserialize(const string & value) const noexcept { + try { + return stoul(value); + } catch (std::invalid_argument &) { + return 0; + } +} +template <> +int64_t SaveManager::deserialize(const string & value) const noexcept { + try { + return stol(value); + } catch (std::invalid_argument &) { + return 0; + } +} +template <> +float SaveManager::deserialize(const string & value) const noexcept { + try { + return stof(value); + } catch (std::invalid_argument &) { + return 0; + } + return stof(value); +} +template <> +double SaveManager::deserialize(const string & value) const noexcept { + try { + return stod(value); + } catch (std::invalid_argument &) { + return 0; + } +} +template <> +string SaveManager::deserialize(const string & value) const noexcept { + return value; +} + +template <> +uint8_t SaveManager::deserialize(const string & value) const noexcept { + return deserialize(value); +} +template <> +int8_t SaveManager::deserialize(const string & value) const noexcept { + return deserialize(value); +} +template <> +uint16_t SaveManager::deserialize(const string & value) const noexcept { + return deserialize(value); +} +template <> +int16_t SaveManager::deserialize(const string & value) const noexcept { + return deserialize(value); +} +template <> +uint32_t SaveManager::deserialize(const string & value) const noexcept { + return deserialize(value); +} +template <> +int32_t SaveManager::deserialize(const string & value) const noexcept { + return deserialize(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); +} + +template <> +void SaveManager::set(const string & key, const string & value) { + DB & db = this->get_db(); + db.set(key, value); +} +template +void SaveManager::set(const string & key, const T & value) { + DB & db = this->get_db(); + db.set(key, std::to_string(value)); +} +template void SaveManager::set(const string &, const uint8_t &); +template void SaveManager::set(const string &, const int8_t &); +template void SaveManager::set(const string &, const uint16_t &); +template void SaveManager::set(const string &, const int16_t &); +template void SaveManager::set(const string &, const uint32_t &); +template void SaveManager::set(const string &, const int32_t &); +template void SaveManager::set(const string &, const uint64_t &); +template void SaveManager::set(const string &, const int64_t &); +template void SaveManager::set(const string &, const float &); +template void SaveManager::set(const string &, const double &); + +template +ValueBroker SaveManager::get(const string & key, const T & default_value) { + if (!this->has(key)) this->set(key, default_value); + return this->get(key); +} +template ValueBroker SaveManager::get(const string &, const uint8_t &); +template ValueBroker SaveManager::get(const string &, const int8_t &); +template ValueBroker SaveManager::get(const string &, const uint16_t &); +template ValueBroker SaveManager::get(const string &, const int16_t &); +template ValueBroker SaveManager::get(const string &, const uint32_t &); +template ValueBroker SaveManager::get(const string &, const int32_t &); +template ValueBroker SaveManager::get(const string &, const uint64_t &); +template ValueBroker SaveManager::get(const string &, const int64_t &); +template ValueBroker SaveManager::get(const string &, const float &); +template ValueBroker SaveManager::get(const string &, const double &); +template ValueBroker SaveManager::get(const string &, const string &); + +template +ValueBroker SaveManager::get(const string & key) { + T value; + return { + [this, key](const T & target) { this->set(key, target); }, + [this, key, value]() mutable -> const T & { + value = this->deserialize(this->get_db().get(key)); + return value; + }, + }; +} +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); +template ValueBroker SaveManager::get(const string &); diff --git a/src/crepe/manager/SaveManager.h b/src/crepe/manager/SaveManager.h new file mode 100644 index 0000000..3d8c852 --- /dev/null +++ b/src/crepe/manager/SaveManager.h @@ -0,0 +1,114 @@ +#pragma once + +#include + +#include "../ValueBroker.h" + +namespace crepe { + +class DB; + +/** + * \brief Save data manager + * + * This class provides access to a simple key-value store that stores + * - integers (8-64 bit, signed or unsigned) + * - real numbers (float or double) + * - string (std::string) + * + * The underlying database is a key-value store. + */ +class SaveManager { +public: + /** + * \brief Get a read/write reference to a value and initialize it if it does not yet exist + * + * \param key The value key + * \param default_value Value to initialize \c key with if it does not already exist in the + * database + * + * \return Read/write reference to the value + */ + template + ValueBroker get(const std::string & key, const T & default_value); + + /** + * \brief Get a read/write reference to a value + * + * \param key The value key + * + * \return Read/write reference to the value + * + * \note Attempting to read this value before it is initialized (i.e. set) will result in an + * exception + */ + template + ValueBroker get(const std::string & key); + + /** + * \brief Set a value directly + * + * \param key The value key + * \param value The value to store + */ + template + void set(const std::string & key, const T & value); + + /** + * \brief Check if the save file has a value for this \c key + * + * \param key The value key + * + * \returns True if the key exists, or false if it does not + */ + bool has(const std::string & key); + +private: + SaveManager(); + virtual ~SaveManager() = default; + +private: + /** + * \brief Serialize an arbitrary value to STL string + * + * \tparam T Type of arbitrary value + * + * \returns String representation of value + */ + template + std::string serialize(const T &) const noexcept; + + /** + * \brief Deserialize an STL string back to type \c T + * + * \tparam T Type of value + * \param value Serialized value + * + * \returns Deserialized value + */ + template + 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; + +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(); +}; + +} // namespace crepe diff --git a/src/crepe/manager/SceneManager.cpp b/src/crepe/manager/SceneManager.cpp new file mode 100644 index 0000000..50a9fbb --- /dev/null +++ b/src/crepe/manager/SceneManager.cpp @@ -0,0 +1,35 @@ +#include +#include + +#include "ComponentManager.h" +#include "SceneManager.h" + +using namespace crepe; +using namespace std; + +SceneManager::SceneManager(Mediator & mediator) : Manager(mediator) { + mediator.scene_manager = *this; +} + +void SceneManager::set_next_scene(const string & name) { next_scene = name; } + +void SceneManager::load_next_scene() { + // next scene not set + if (this->next_scene.empty()) return; + + auto it = find_if(this->scenes.begin(), this->scenes.end(), + [&next_scene = this->next_scene](unique_ptr & scene) { + return scene.get()->get_name() == next_scene; + }); + + // next scene not found + if (it == this->scenes.end()) return; + unique_ptr & scene = *it; + + // Delete all components of the current scene + ComponentManager & mgr = this->mediator.component_manager; + mgr.delete_all_components(); + + // Load the new scene + scene->load_scene(); +} diff --git a/src/crepe/manager/SceneManager.h b/src/crepe/manager/SceneManager.h new file mode 100644 index 0000000..e0955c2 --- /dev/null +++ b/src/crepe/manager/SceneManager.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +#include "../api/Scene.h" + +#include "Manager.h" + +namespace crepe { + +class ComponentManager; + +/** + * \brief Manages scenes + * + * This class manages scenes. It can add new scenes and load them. It also manages the current scene + * and the next scene. + */ +class SceneManager : public Manager { +public: + SceneManager(Mediator & mediator); + +public: + /** + * \brief Add a new concrete scene to the scene manager + * + * \tparam T Type of concrete scene + */ + template + void add_scene(Args &&... args); + /** + * \brief Set the next scene + * + * This scene will be loaded at the end of the frame + * + * \param name Name of the next scene + */ + void set_next_scene(const std::string & name); + //! Load a new scene (if there is one) + void load_next_scene(); + +private: + //! Vector of concrete scenes (added by add_scene()) + std::vector> scenes; + //! Next scene to load + std::string next_scene; +}; + +} // namespace crepe + +#include "SceneManager.hpp" diff --git a/src/crepe/manager/SceneManager.hpp b/src/crepe/manager/SceneManager.hpp new file mode 100644 index 0000000..dff4e51 --- /dev/null +++ b/src/crepe/manager/SceneManager.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "SceneManager.h" + +namespace crepe { + +template +void SceneManager::add_scene(Args &&... args) { + using namespace std; + static_assert(is_base_of::value, "T must be derived from Scene"); + + Scene * scene = new T(std::forward(args)...); + unique_ptr unique_scene(scene); + + unique_scene->mediator = this->mediator; + + this->scenes.emplace_back(std::move(unique_scene)); + + // The first scene added, is the one that will be loaded at the beginning + if (next_scene.empty()) { + next_scene = scene->get_name(); + } +} + +} // namespace crepe -- cgit v1.2.3 From 7a07c56d572a6f30d0aa611bd566197bc04c3b33 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Thu, 28 Nov 2024 13:13:54 +0100 Subject: add more documentation to Mediator + fix system mediator use --- src/crepe/manager/Mediator.h | 6 +++++- src/crepe/system/AnimatorSystem.cpp | 2 +- src/crepe/system/ParticleSystem.cpp | 2 +- src/crepe/system/PhysicsSystem.cpp | 2 +- src/crepe/system/RenderSystem.cpp | 6 +++--- src/crepe/system/ScriptSystem.cpp | 2 +- src/crepe/system/System.cpp | 2 +- src/crepe/system/System.h | 2 +- 8 files changed, 14 insertions(+), 10 deletions(-) (limited to 'src/crepe/manager') diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h index ce35d5c..a91509e 100644 --- a/src/crepe/manager/Mediator.h +++ b/src/crepe/manager/Mediator.h @@ -17,7 +17,11 @@ class SceneManager; * pass specific references through dependency injection. All references on this struct * *should* be explicitly checked for availability as this struct does not guarantee anything. * - * \todo Find better solution + * \note Dereferencing members of this struct should be deferred. If you are a user of this + * class, keep a reference to this mediator instead of just picking references from it when you + * receive an instance. + * + * \warning This class should never be directly accessible from the API */ struct Mediator { OptionalRef component_manager; diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index 57ee6e2..8bb6465 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -9,7 +9,7 @@ using namespace crepe; void AnimatorSystem::update() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector animations = mgr.get_components_by_type(); diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp index ebae56b..b14c52f 100644 --- a/src/crepe/system/ParticleSystem.cpp +++ b/src/crepe/system/ParticleSystem.cpp @@ -12,7 +12,7 @@ using namespace crepe; void ParticleSystem::update() { // Get all emitters - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector emitters = mgr.get_components_by_type(); for (ParticleEmitter & emitter : emitters) { diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index 071ca21..eba9dfa 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -11,7 +11,7 @@ using namespace crepe; void PhysicsSystem::update() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector rigidbodies = mgr.get_components_by_type(); RefVector transforms = mgr.get_components_by_type(); diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index ea60a95..4e97b3e 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -22,7 +22,7 @@ void RenderSystem::clear_screen() { this->context.clear_screen(); } void RenderSystem::present_screen() { this->context.present_screen(); } const Camera & RenderSystem::update_camera() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector cameras = mgr.get_components_by_type(); @@ -62,7 +62,7 @@ void RenderSystem::update() { bool RenderSystem::render_particle(const Sprite & sprite, const Camera & cam, const double & scale) { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; vector> emitters = mgr.get_components_by_id(sprite.game_object_id); @@ -102,7 +102,7 @@ void RenderSystem::render_normal(const Sprite & sprite, const Camera & cam, } void RenderSystem::render() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; const Camera & cam = this->update_camera(); RefVector sprites = mgr.get_components_by_type(); diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index 7ecbe78..2e16eb0 100644 --- a/src/crepe/system/ScriptSystem.cpp +++ b/src/crepe/system/ScriptSystem.cpp @@ -10,7 +10,7 @@ using namespace crepe; void ScriptSystem::update() { dbg_trace(); - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector behavior_scripts = mgr.get_components_by_type(); for (BehaviorScript & behavior_script : behavior_scripts) { diff --git a/src/crepe/system/System.cpp b/src/crepe/system/System.cpp index 392d920..f68549b 100644 --- a/src/crepe/system/System.cpp +++ b/src/crepe/system/System.cpp @@ -4,4 +4,4 @@ using namespace crepe; -System::System(const Mediator & mediator) : component_manager(mediator.component_manager) { dbg_trace(); } +System::System(const Mediator & mediator) : mediator(mediator) { dbg_trace(); } diff --git a/src/crepe/system/System.h b/src/crepe/system/System.h index 92bfd50..4e7fc6d 100644 --- a/src/crepe/system/System.h +++ b/src/crepe/system/System.h @@ -25,7 +25,7 @@ public: virtual ~System() = default; protected: - ComponentManager & component_manager; + const Mediator & mediator; }; } // namespace crepe -- cgit v1.2.3 From 2d5721820063031b65d64b1b2b1b4797b71935af Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 30 Nov 2024 16:41:22 +0100 Subject: `make format` --- src/crepe/api/LoopManager.cpp | 5 +---- src/crepe/api/LoopManager.h | 2 +- src/crepe/api/Scene.h | 3 ++- src/crepe/api/Script.cpp | 1 - src/crepe/api/Script.h | 4 ++-- src/crepe/manager/ComponentManager.cpp | 2 +- src/crepe/manager/Manager.cpp | 3 +-- src/crepe/manager/Manager.h | 3 +-- src/crepe/manager/Mediator.h | 4 ++-- src/crepe/manager/SaveManager.cpp | 4 ++-- src/crepe/system/PhysicsSystem.cpp | 2 +- src/crepe/system/RenderSystem.cpp | 2 +- src/crepe/system/ScriptSystem.cpp | 2 +- src/test/ECSTest.cpp | 3 ++- src/test/EventTest.cpp | 6 ++---- src/test/ParticleTest.cpp | 3 ++- src/test/PhysicsTest.cpp | 3 ++- src/test/RenderSystemTest.cpp | 3 ++- src/test/SceneManagerTest.cpp | 7 ++++--- src/test/ScriptEventTest.cpp | 7 +++---- src/test/ScriptSceneTest.cpp | 3 +-- src/test/ScriptTest.cpp | 3 +-- src/test/ScriptTest.h | 8 +++++--- 23 files changed, 40 insertions(+), 43 deletions(-) (limited to 'src/crepe/manager') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index b277185..731cfb7 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -22,9 +22,7 @@ LoopManager::LoopManager() { this->load_system(); } -void LoopManager::process_input() { - this->sdl_context.handle_events(this->game_running); -} +void LoopManager::process_input() { this->sdl_context.handle_events(this->game_running); } void LoopManager::start() { this->setup(); @@ -69,4 +67,3 @@ void LoopManager::render() { } void LoopManager::update() {} - diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 6ea5ccc..d8910a0 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -2,10 +2,10 @@ #include +#include "../facade/SDLContext.h" #include "../manager/ComponentManager.h" #include "../manager/SceneManager.h" #include "../system/System.h" -#include "../facade/SDLContext.h" #include "LoopTimer.h" diff --git a/src/crepe/api/Scene.h b/src/crepe/api/Scene.h index 66dad17..9f1e8ce 100644 --- a/src/crepe/api/Scene.h +++ b/src/crepe/api/Scene.h @@ -2,8 +2,8 @@ #include -#include "../util/OptionalRef.h" #include "../manager/Mediator.h" +#include "../util/OptionalRef.h" namespace crepe { @@ -37,6 +37,7 @@ public: // TODO: Late references should ALWAYS be private! This is currently kept as-is so unit tests // keep passing, but this reference should not be directly accessible by the user!!! + protected: /** * \name Late references diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp index a27838e..4091fd4 100644 --- a/src/crepe/api/Script.cpp +++ b/src/crepe/api/Script.cpp @@ -25,4 +25,3 @@ void Script::set_next_scene(const string & name) { SceneManager & mgr = mediator.scene_manager; mgr.set_next_scene(name); } - diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index e1f86b2..1b339b0 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -2,10 +2,10 @@ #include +#include "../manager/EventManager.h" +#include "../manager/Mediator.h" #include "../types.h" #include "../util/OptionalRef.h" -#include "../manager/Mediator.h" -#include "../manager/EventManager.h" namespace crepe { diff --git a/src/crepe/manager/ComponentManager.cpp b/src/crepe/manager/ComponentManager.cpp index 5a96158..80cf8b4 100644 --- a/src/crepe/manager/ComponentManager.cpp +++ b/src/crepe/manager/ComponentManager.cpp @@ -1,6 +1,6 @@ #include "../api/GameObject.h" -#include "../util/Log.h" #include "../types.h" +#include "../util/Log.h" #include "ComponentManager.h" diff --git a/src/crepe/manager/Manager.cpp b/src/crepe/manager/Manager.cpp index fe7c936..1182785 100644 --- a/src/crepe/manager/Manager.cpp +++ b/src/crepe/manager/Manager.cpp @@ -2,5 +2,4 @@ using namespace crepe; -Manager::Manager(Mediator & mediator) : mediator(mediator) { } - +Manager::Manager(Mediator & mediator) : mediator(mediator) {} diff --git a/src/crepe/manager/Manager.h b/src/crepe/manager/Manager.h index 9adfd0b..4f21ef4 100644 --- a/src/crepe/manager/Manager.h +++ b/src/crepe/manager/Manager.h @@ -13,5 +13,4 @@ protected: Mediator & mediator; }; -} - +} // namespace crepe diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h index a91509e..71bd1c9 100644 --- a/src/crepe/manager/Mediator.h +++ b/src/crepe/manager/Mediator.h @@ -3,8 +3,8 @@ #include "../util/OptionalRef.h" // TODO: remove these singletons: -#include "SaveManager.h" #include "EventManager.h" +#include "SaveManager.h" namespace crepe { @@ -30,4 +30,4 @@ struct Mediator { OptionalRef event_manager = EventManager::get_instance(); }; -} +} // namespace crepe diff --git a/src/crepe/manager/SaveManager.cpp b/src/crepe/manager/SaveManager.cpp index 121d017..d4ed1c1 100644 --- a/src/crepe/manager/SaveManager.cpp +++ b/src/crepe/manager/SaveManager.cpp @@ -1,7 +1,7 @@ +#include "../ValueBroker.h" +#include "../api/Config.h" #include "../facade/DB.h" #include "../util/Log.h" -#include "../api/Config.h" -#include "../ValueBroker.h" #include "SaveManager.h" diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index eba9dfa..bebcf3d 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -1,10 +1,10 @@ #include -#include "../manager/ComponentManager.h" #include "../api/Config.h" #include "../api/Rigidbody.h" #include "../api/Transform.h" #include "../api/Vector2.h" +#include "../manager/ComponentManager.h" #include "PhysicsSystem.h" diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 4e97b3e..0ad685c 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -5,12 +5,12 @@ #include #include -#include "../manager/ComponentManager.h" #include "../api/Camera.h" #include "../api/ParticleEmitter.h" #include "../api/Sprite.h" #include "../api/Transform.h" #include "../facade/SDLContext.h" +#include "../manager/ComponentManager.h" #include "RenderSystem.h" diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index 2e16eb0..d6b2ca1 100644 --- a/src/crepe/system/ScriptSystem.cpp +++ b/src/crepe/system/ScriptSystem.cpp @@ -1,6 +1,6 @@ -#include "../manager/ComponentManager.h" #include "../api/BehaviorScript.h" #include "../api/Script.h" +#include "../manager/ComponentManager.h" #include "ScriptSystem.h" diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp index 22c4fe7..3e6c61c 100644 --- a/src/test/ECSTest.cpp +++ b/src/test/ECSTest.cpp @@ -2,17 +2,18 @@ #define protected public -#include #include #include #include #include +#include using namespace std; using namespace crepe; class ECSTest : public ::testing::Test { Mediator m; + public: ComponentManager mgr{m}; }; diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp index 350dd07..dccd554 100644 --- a/src/test/EventTest.cpp +++ b/src/test/EventTest.cpp @@ -2,9 +2,9 @@ #include #include -#include #include #include +#include using namespace std; using namespace std::chrono_literals; @@ -37,9 +37,7 @@ public: }; TEST_F(EventManagerTest, EventSubscription) { - EventHandler key_handler = [](const KeyPressEvent & e) { - return true; - }; + EventHandler key_handler = [](const KeyPressEvent & e) { return true; }; // Subscribe to KeyPressEvent EventManager::get_instance().subscribe(key_handler, 1); diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp index 4e9fa4e..a659fe5 100644 --- a/src/test/ParticleTest.cpp +++ b/src/test/ParticleTest.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +17,7 @@ using namespace crepe; class ParticlesTest : public ::testing::Test { Mediator m; + public: ComponentManager component_manager{m}; ParticleSystem particle_system{m}; diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp index 01b7c51..43af8e4 100644 --- a/src/test/PhysicsTest.cpp +++ b/src/test/PhysicsTest.cpp @@ -1,8 +1,8 @@ -#include #include #include #include #include +#include #include #include @@ -12,6 +12,7 @@ using namespace crepe; class PhysicsTest : public ::testing::Test { Mediator m; + public: ComponentManager component_manager{m}; PhysicsSystem system{m}; diff --git a/src/test/RenderSystemTest.cpp b/src/test/RenderSystemTest.cpp index 3528e46..c105dcb 100644 --- a/src/test/RenderSystemTest.cpp +++ b/src/test/RenderSystemTest.cpp @@ -7,11 +7,11 @@ #define protected public #include -#include #include #include #include #include +#include #include @@ -21,6 +21,7 @@ using namespace testing; class RenderSystemTest : public Test { Mediator m; + public: ComponentManager mgr{m}; RenderSystem sys{m}; diff --git a/src/test/SceneManagerTest.cpp b/src/test/SceneManagerTest.cpp index d027d89..9bb260c 100644 --- a/src/test/SceneManagerTest.cpp +++ b/src/test/SceneManagerTest.cpp @@ -1,13 +1,13 @@ #include -#include -#include -#include #include #include #include #include #include +#include +#include +#include using namespace std; using namespace crepe; @@ -57,6 +57,7 @@ private: class SceneManagerTest : public ::testing::Test { Mediator m; + public: ComponentManager component_mgr{m}; SceneManager scene_mgr{m}; diff --git a/src/test/ScriptEventTest.cpp b/src/test/ScriptEventTest.cpp index 7a9abbb..5da31e7 100644 --- a/src/test/ScriptEventTest.cpp +++ b/src/test/ScriptEventTest.cpp @@ -4,13 +4,13 @@ #define private public #define protected public -#include -#include #include #include #include #include #include +#include +#include #include #include "ScriptTest.h" @@ -32,7 +32,7 @@ TEST_F(ScriptEventTest, Inactive) { EventManager & evmgr = this->event_manager; unsigned event_count = 0; - script.subscribe([&](const MyEvent &){ + script.subscribe([&](const MyEvent &) { event_count++; return true; }); @@ -48,4 +48,3 @@ TEST_F(ScriptEventTest, Inactive) { evmgr.trigger_event(); EXPECT_EQ(1, event_count); } - diff --git a/src/test/ScriptSceneTest.cpp b/src/test/ScriptSceneTest.cpp index f96ae8b..9ee1e52 100644 --- a/src/test/ScriptSceneTest.cpp +++ b/src/test/ScriptSceneTest.cpp @@ -4,8 +4,8 @@ #define private public #define protected public -#include #include "ScriptTest.h" +#include using namespace std; using namespace crepe; @@ -28,4 +28,3 @@ TEST_F(ScriptSceneTest, Inactive) { script.set_next_scene(non_default_value); EXPECT_EQ(non_default_value, scene_manager.next_scene); } - diff --git a/src/test/ScriptTest.cpp b/src/test/ScriptTest.cpp index 6d0d5fb..1d2d6dd 100644 --- a/src/test/ScriptTest.cpp +++ b/src/test/ScriptTest.cpp @@ -1,5 +1,5 @@ -#include #include +#include // stupid hack to allow access to private/protected members under test #define private public @@ -75,4 +75,3 @@ TEST_F(ScriptTest, UpdateInactive) { system.update(); } } - diff --git a/src/test/ScriptTest.h b/src/test/ScriptTest.h index 9a71ba7..1bbfdd3 100644 --- a/src/test/ScriptTest.h +++ b/src/test/ScriptTest.h @@ -1,22 +1,24 @@ #pragma once -#include #include +#include -#include -#include #include #include +#include +#include class ScriptTest : public testing::Test { protected: crepe::Mediator mediator; + public: crepe::ComponentManager component_manager{mediator}; crepe::ScriptSystem system{mediator}; class MyScript : public crepe::Script { // NOTE: explicitly stating `public:` is not required on actual scripts + public: MOCK_METHOD(void, init, (), (override)); MOCK_METHOD(void, update, (), (override)); -- cgit v1.2.3 From cfb67ffddb9f4bb0357c2b9df4239bfee7364c5a Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 4 Dec 2024 14:21:26 +0100 Subject: process PR feedback --- src/crepe/api/BehaviorScript.hpp | 10 ++++------ src/crepe/manager/Manager.h | 8 ++++++++ src/crepe/system/System.h | 5 ++--- 3 files changed, 14 insertions(+), 9 deletions(-) (limited to 'src/crepe/manager') diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp index 6de0157..b9bb1e2 100644 --- a/src/crepe/api/BehaviorScript.hpp +++ b/src/crepe/api/BehaviorScript.hpp @@ -13,14 +13,12 @@ template BehaviorScript & BehaviorScript::set_script(Args &&... args) { dbg_trace(); static_assert(std::is_base_of::value); - Script * s = new T(std::forward(args)...); - Mediator & mediator = this->mediator; + this->script = std::unique_ptr