diff options
author | JAROWMR <jarorutjes07@gmail.com> | 2024-11-21 20:40:08 +0100 |
---|---|---|
committer | JAROWMR <jarorutjes07@gmail.com> | 2024-11-21 20:40:08 +0100 |
commit | d58a059fd6398527274e77a37b65aa105c8a778b (patch) | |
tree | 26d345400739ec685bbe6b26d8d789bbe33b02aa /src/crepe/api | |
parent | faa9adb84ad3f675587b52fba79cf44b7bdd2034 (diff) | |
parent | 115d6f50152dc018073345800ca90b85846ebaa9 (diff) |
merge with master
Diffstat (limited to 'src/crepe/api')
27 files changed, 658 insertions, 636 deletions
diff --git a/src/crepe/api/Asset.cpp b/src/crepe/api/Asset.cpp new file mode 100644 index 0000000..e148367 --- /dev/null +++ b/src/crepe/api/Asset.cpp @@ -0,0 +1,54 @@ +#include <filesystem> +#include <stdexcept> +#include <whereami.h> + +#include "api/Config.h" + +#include "Asset.h" + +using namespace crepe; +using namespace std; + +Asset::Asset(const string & src) : src(find_asset(src)) {} +Asset::Asset(const char * src) : src(find_asset(src)) {} + +const string & Asset::get_path() const noexcept { return this->src; } + +string Asset::find_asset(const string & src) const { + auto & cfg = Config::get_instance(); + string & root_pattern = cfg.asset.root_pattern; + + // if root_pattern is empty, find_asset must return all paths as-is + if (root_pattern.empty()) return src; + + // absolute paths do not need to be resolved, only canonicalized + filesystem::path path = src; + if (path.is_absolute()) return filesystem::canonical(path); + + // find directory matching root_pattern + filesystem::path root = this->whereami(); + while (1) { + if (filesystem::exists(root / root_pattern)) break; + if (!root.has_parent_path()) + throw runtime_error(format("Asset: Cannot find root pattern ({})", root_pattern)); + root = root.parent_path(); + } + + // join path to root (base directory) and canonicalize + return filesystem::canonical(root / path); +} + +string Asset::whereami() const noexcept { + string path; + size_t path_length = wai_getExecutablePath(NULL, 0, NULL); + path.resize(path_length + 1); // wai writes null byte + wai_getExecutablePath(path.data(), path_length, NULL); + path.resize(path_length); + return path; +} + +bool Asset::operator==(const Asset & other) const noexcept { return this->src == other.src; } + +size_t std::hash<const Asset>::operator()(const Asset & asset) const noexcept { + return std::hash<string>{}(asset.get_path()); +}; diff --git a/src/crepe/api/Asset.h b/src/crepe/api/Asset.h new file mode 100644 index 0000000..bfd0ac7 --- /dev/null +++ b/src/crepe/api/Asset.h @@ -0,0 +1,84 @@ +#pragma once + +#include <string> + +namespace crepe { + +/** + * \brief Asset location helper + * + * This class is used to locate game asset files, and should *always* be used + * instead of reading file paths directly. + */ +class Asset { +public: + /** + * \param src Unique identifier to asset + */ + Asset(const std::string & src); + /** + * \param src Unique identifier to asset + */ + Asset(const char * src); + +public: + /** + * \brief Get the path to this asset + * \return path to this asset + */ + const std::string & get_path() const noexcept; + + /** + * \brief Comparison operator + * \param other Possibly different instance of \c Asset to test equality against + * \return True if \c this and \c other are equal + */ + bool operator==(const Asset & other) const noexcept; + +private: + //! path to asset + const std::string src; + +private: + /** + * \brief Locate asset path, or throw exception if it cannot be found + * + * This function resolves asset locations relative to crepe::Config::root_pattern if it is + * set and \p src is a relative path. If \p src is an absolute path, it is canonicalized. + * This function only returns if the file can be found. + * + * \param src Arbitrary path to resource file + * + * \returns \p src if crepe::Config::root_pattern is empty + * \returns Canonical path to \p src + * + * \throws std::runtime_error if root_pattern cannot be found + * \throws std::filesystem::filesystem_error if the resolved path does not exist + * \throws std::filesystem::filesystem_error if the path cannot be canonicalized + */ + std::string find_asset(const std::string & src) const; + /** + * \returns The path to the current executable + */ + std::string whereami() const noexcept; +}; + +} // namespace crepe + +namespace std { + +//! Hash helper struct +template <> +struct hash<const crepe::Asset> { + /** + * \brief Hash operator for crepe::Asset + * + * This function hashes a crepe::Asset instance, allowing it to be used as a key in an \c + * std::unordered_map. + * + * \returns Hash value + */ + size_t operator()(const crepe::Asset & asset) const noexcept; +}; + +} // namespace std diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 07b3a82..830f5bd 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -20,11 +20,12 @@ target_sources(crepe PUBLIC BoxCollider.cpp CircleCollider.cpp EventManager.cpp - EventHandler.cpp IKeyListener.cpp IMouseListener.cpp LoopManager.cpp LoopTimer.cpp + Asset.cpp + EventHandler.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -54,9 +55,11 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES EventManager.h EventManager.hpp EventHandler.h + EventHandler.hpp Event.h IKeyListener.h IMouseListener.h LoopManager.h LoopTimer.h + Asset.h ) diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 3ab877a..13eabd1 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -62,6 +62,20 @@ public: */ double gravity = 1; } physics; + + //! Asset loading options + struct { + /** + * \brief Pattern to match for Asset base directory + * + * All non-absolute paths resolved using \c Asset will be made relative to + * the first parent directory relative to the calling executable where + * appending this pattern results in a path that exists. If this string is + * empty, path resolution is disabled, and Asset will return all paths + * as-is. + */ + std::string root_pattern = ".crepe-root"; + } asset; }; } // namespace crepe diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index bd6a541..8a6b931 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -1,59 +1,115 @@ +// TODO discussing the location of these events #pragma once -#include "KeyCodes.h" -#include <iostream> + #include <string> -#include <typeindex> + #include "system/CollisionSystem.h" -class Event { -public: -}; +#include "KeyCodes.h" +/** + * \brief Base class for all event types in the system. + */ +class Event {}; + +/** + * \brief Event triggered when a key is pressed. + */ class KeyPressEvent : public Event { public: - int repeat = 0; + //! false if first time press, true if key is repeated + bool repeat = false; + + //! The key that was pressed. Keycode key = Keycode::NONE; }; +/** + * \brief Event triggered when a key is released. + */ class KeyReleaseEvent : public Event { public: + //! The key that was released. Keycode key = Keycode::NONE; }; +/** + * \brief Event triggered when a mouse button is pressed. + */ class MousePressEvent : public Event { public: + //! X-coordinate of the mouse position at the time of the event. int mouse_x = 0; + + //! Y-coordinate of the mouse position at the time of the event. int mouse_y = 0; + + //! The mouse button that was pressed. MouseButton button = MouseButton::NONE; }; +/** + * \brief Event triggered when a mouse button is clicked (press and release). + */ class MouseClickEvent : public Event { public: + //! X-coordinate of the mouse position at the time of the event. int mouse_x = 0; + + //! Y-coordinate of the mouse position at the time of the event. int mouse_y = 0; + + //! The mouse button that was clicked. MouseButton button = MouseButton::NONE; }; + +/** + * \brief Event triggered when a mouse button is released. + */ class MouseReleaseEvent : public Event { public: + //! X-coordinate of the mouse position at the time of the event. int mouse_x = 0; + + //! Y-coordinate of the mouse position at the time of the event. int mouse_y = 0; + + //! The mouse button that was released. MouseButton button = MouseButton::NONE; }; + +/** + * \brief Event triggered when the mouse is moved. + */ class MouseMoveEvent : public Event { public: + //! X-coordinate of the mouse position at the time of the event. int mouse_x = 0; + + //! Y-coordinate of the mouse position at the time of the event. int mouse_y = 0; }; + +/** + * \brief Event triggered during a collision between objects. + */ class CollisionEvent : public Event { public: crepe::CollisionSystem::CollisionInfo info; CollisionEvent(const crepe::CollisionSystem::CollisionInfo& collisionInfo) : info(collisionInfo) {} }; + +/** + * \brief Event triggered when text is submitted, e.g., from a text input. + */ class TextSubmitEvent : public Event { public: + //! The submitted text. std::string text = ""; }; -class ShutDownEvent : public Event { -public: -}; + +/** + * \brief Event triggered to indicate the application is shutting down. + */ +class ShutDownEvent : public Event {}; diff --git a/src/crepe/api/EventHandler.cpp b/src/crepe/api/EventHandler.cpp index 93a116a..4dc232f 100644 --- a/src/crepe/api/EventHandler.cpp +++ b/src/crepe/api/EventHandler.cpp @@ -1,2 +1,5 @@ #include "EventHandler.h" -bool IEventHandlerWrapper::exec(const Event & e) { return call(e); } + +using namespace crepe; + +bool IEventHandlerWrapper::exec(const Event & e) { return this->call(e); } diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index 0ab90de..ef659fd 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -1,9 +1,11 @@ #pragma once -#include "Event.h" + #include <functional> -#include <iostream> -#include <typeindex> +#include <string> +#include "Event.h" + +namespace crepe { /** * \brief A type alias for an event handler function. * @@ -11,8 +13,9 @@ * indicating whether the event is handled. * * \tparam EventType The type of event this handler will handle. + * + * Returning \c false from an event handler results in the event being propogated to other listeners for the same event type, while returning \c true stops propogation altogether. */ -// TODO: typedef template <typename EventType> using EventHandler = std::function<bool(const EventType & e)>; @@ -21,7 +24,7 @@ using EventHandler = std::function<bool(const EventType & e)>; * \brief An abstract base class for event handler wrappers. * * This class provides the interface for handling events. Derived classes must implement the - * `call()` method to process events and the `get_type()` method to return the handler's type. + * `call()` method to process events */ class IEventHandlerWrapper { public: @@ -40,15 +43,6 @@ public: */ bool exec(const Event & e); - /** - * \brief Get the type of the event handler. - * - * This method returns the type of the event handler as a string. - * - * \return A string representing the handler's type. - */ - virtual std::string get_type() const = 0; - private: /** * \brief The method responsible for handling the event. @@ -81,8 +75,7 @@ public: * * \param handler The event handler function. */ - explicit EventHandlerWrapper(const EventHandler<EventType> & handler) - : m_handler(handler), m_handler_type(m_handler.target_type().name()) {} + explicit EventHandlerWrapper(const EventHandler<EventType> & handler); private: /** @@ -93,20 +86,11 @@ private: * \param e The event to be handled. * \return A boolean value indicating whether the event is handled. */ - bool call(const Event & e) override { - return m_handler(static_cast<const EventType &>(e)); - } - - /** - * \brief Returns the type of the handler. - * - * This method returns a string representing the type of the event handler. - * - * \return The handler type as a string. - */ - std::string get_type() const override { return m_handler_type; } + bool call(const Event & e) override; //! The event handler function. - EventHandler<EventType> m_handler; - //! The type name of the handler function. - const std::string m_handler_type; + EventHandler<EventType> handler; }; + +} // namespace crepe + +#include "EventHandler.hpp" diff --git a/src/crepe/api/EventHandler.hpp b/src/crepe/api/EventHandler.hpp new file mode 100644 index 0000000..391dcca --- /dev/null +++ b/src/crepe/api/EventHandler.hpp @@ -0,0 +1,18 @@ +#include <typeindex> + +#include "EventHandler.h" + +namespace crepe { + +// Implementation of EventHandlerWrapper constructor +template <typename EventType> +EventHandlerWrapper<EventType>::EventHandlerWrapper(const EventHandler<EventType> & handler) + : handler(handler) {} + +// Implementation of EventHandlerWrapper::call +template <typename EventType> +bool EventHandlerWrapper<EventType>::call(const Event & e) { + return this->handler(static_cast<const EventType &>(e)); +} + +} //namespace crepe diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index e881d49..20f0dd3 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -1,6 +1,7 @@ #include "EventManager.h" using namespace crepe; +using namespace std; EventManager & EventManager::get_instance() { static EventManager instance; @@ -8,74 +9,38 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - for (std::vector<std::tuple<std::unique_ptr<Event>, int, - std::type_index>>::iterator event_it - = this->events_queue.begin(); - event_it != this->events_queue.end();) { - std::unique_ptr<Event> & event = std::get<0>(*event_it); - int channel = std::get<1>(*event_it); - std::type_index event_type = std::get<2>(*event_it); + for (auto & event : this->events_queue) { + this->handle_event(event.type, event.channel, *event.event.get()); + } + this->events_queue.clear(); +} - bool event_handled = false; +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; - if (channel) { - std::unordered_map< - std::type_index, - std::unordered_map< - int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>:: - iterator handlers_it - = subscribers_by_event_id.find(event_type); - if (handlers_it != subscribers_by_event_id.end()) { - std::unordered_map< - int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> & - handlers_map - = handlers_it->second; - std::unordered_map< - int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>:: - iterator handlers - = handlers_map.find(channel); - if (handlers != handlers_map.end()) { - std::vector<std::unique_ptr<IEventHandlerWrapper>> & - callbacks - = handlers->second; - for (std::vector<std::unique_ptr<IEventHandlerWrapper>>:: - iterator handler_it - = callbacks.begin(); - handler_it != callbacks.end(); ++handler_it) { - if ((*handler_it)->exec(*event)) { - event_it = events_queue.erase(event_it); - event_handled = true; - break; - } - } - } - } - } else { - // Handle event for all channels - std::unordered_map< - std::type_index, - std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator - handlers_it - = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers - = handlers_it->second; - for (std::vector<std::unique_ptr<IEventHandlerWrapper>>:: - iterator handler_it - = handlers.begin(); - handler_it != handlers.end(); ++handler_it) { - // remove event from queue since and continue when callback returns true - if ((*handler_it)->exec(*event)) { - event_it = this->events_queue.erase(event_it); - event_handled = true; - break; - } - } - } - } + vector<CallbackEntry> & 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(); +} - if (!event_handled) { - ++event_it; +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/api/EventManager.h b/src/crepe/api/EventManager.h index 38d2e64..348a04d 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -1,8 +1,6 @@ #pragma once -#include <functional> #include <memory> -#include <type_traits> #include <typeindex> #include <unordered_map> #include <vector> @@ -10,113 +8,154 @@ #include "Event.h" #include "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 The EventManager class is responsible for managing the subscription, triggering, - * and queueing of events. It handles events and dispatches them to appropriate subscribers. + * \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: - /** - * \brief Deleted copy constructor to prevent copying of the EventManager instance. - */ - EventManager(const EventManager &) = delete; - - /** - * \brief Deleted copy assignment operator to prevent assignment of the EventManager instance. - */ - const EventManager & operator=(const EventManager &) = delete; + 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 on the first call. - * - * \return Reference to the EventManager instance. - */ + * \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 an event. - * - * This method allows the registration of a callback for a specific event type and channel. - * - * \tparam EventType The type of the event to subscribe to. - * \param callback The callback function to invoke when the event is triggered. - * \param channel The channel number to subscribe to (default is 0). - */ + * \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 <typename EventType> - void subscribe(EventHandler<EventType> && callback, int channel = 0); + subscription_t subscribe(const EventHandler<EventType> & callback, + event_channel_t channel = CHANNEL_ALL); /** - * \brief Unsubscribe from an event. - * - * This method removes a previously registered callback from an event. - * - * \tparam EventType The type of the event to unsubscribe from. - * \param callback The callback function to remove from the subscription list. - * \param channel The event ID to unsubscribe from. - */ - template <typename EventType> - void unsubscribe(const EventHandler<EventType> &, int channel); + * \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. - * - * This method invokes the appropriate callback(s) for the specified event. - * - * \tparam EventType The type of the event to trigger. - * \param event The event data to pass to the callback. - * \param channel The channel from which to trigger the event (default is 0). - */ + * \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 <typename EventType> - void trigger_event(const EventType & event, int channel); + void trigger_event(const EventType & event, event_channel_t channel = CHANNEL_ALL); /** - * \brief Queue an event for later processing. - * - * This method adds an event to the event queue, which will be processed in the - * dispatch_events function. - * - * \tparam EventType The type of the event to queue. - * \param event The event to queue. - * \param channel The channel number for the event (default is 0). - */ + * \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 <typename EventType> - void queue_event(EventType && event, int channel); + void queue_event(const EventType & event, event_channel_t channel = CHANNEL_ALL); /** - * \brief Dispatch all queued events. - * - * This method processes all events in the event queue and triggers the corresponding - * callbacks for each event. - */ + * \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. - * - * This constructor is private to enforce the singleton pattern. - */ + * \brief Default constructor for the EventManager. + * + * Constructor is private to enforce the singleton pattern. + */ EventManager() = default; - //! The queue of events to be processed. - std::vector<std::tuple<std::unique_ptr<Event>, int, std::type_index>> - events_queue; - //! Registered event handlers. - std::unordered_map<std::type_index, - std::vector<std::unique_ptr<IEventHandlerWrapper>>> - subscribers; - //! Event handlers indexed by event ID. - std::unordered_map< - std::type_index, - std::unordered_map<int, - std::vector<std::unique_ptr<IEventHandlerWrapper>>>> - subscribers_by_event_id; + /** + * \struct QueueEntry + * \brief Represents an entry in the event queue. + */ + struct QueueEntry { + std::unique_ptr<Event> 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<IEventHandlerWrapper> 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<QueueEntry> events_queue; + + //! A map of event type to registered callbacks. + std::unordered_map<std::type_index, std::vector<CallbackEntry>> subscribers; + + //! Counter to generate unique subscription IDs. + subscription_t subscription_counter = 0; }; } // namespace crepe + #include "EventManager.hpp" diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index b509097..a5f4556 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -1,140 +1,36 @@ +#pragma once + #include "EventManager.h" + namespace crepe { template <typename EventType> -void EventManager::subscribe(EventHandler<EventType> && callback, int channel) { +subscription_t EventManager::subscribe(const EventHandler<EventType> & callback, + event_channel_t channel) { + subscription_counter++; std::type_index event_type = typeid(EventType); std::unique_ptr<EventHandlerWrapper<EventType>> handler = std::make_unique<EventHandlerWrapper<EventType>>(callback); - - if (channel) { - std::unordered_map<int, - std::vector<std::unique_ptr<IEventHandlerWrapper>>> & - handlers_map - = this->subscribers_by_event_id[event_type]; - std::unordered_map< - int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator - handlers - = handlers_map.find(channel); - if (handlers != handlers_map.end()) { - handlers->second.emplace_back(std::move(handler)); - } else { - handlers_map[channel].emplace_back(std::move(handler)); - } - } else { - std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers - = this->subscribers[event_type]; - handlers.emplace_back(std::move(handler)); - } -} - -template <typename EventType> -void EventManager::queue_event(EventType && event, int channel) { - std::type_index event_type = std::type_index(typeid(EventType)); - - std::unique_ptr<EventType> event_ptr - = std::make_unique<EventType>(std::forward<EventType>(event)); - - std::tuple<std::unique_ptr<Event>, int, std::type_index> tuple( - std::move(event_ptr), channel, event_type); - this->events_queue.push_back(std::move(tuple)); + std::vector<CallbackEntry> & handlers = this->subscribers[event_type]; + handlers.emplace_back(CallbackEntry{ + .callback = std::move(handler), .channel = channel, .id = subscription_counter}); + return subscription_counter; } template <typename EventType> -void EventManager::trigger_event(const EventType & event, int channel) { - std::type_index event_type = std::type_index(typeid(EventType)); - - if (channel > 0) { - std::unordered_map<int, - std::vector<std::unique_ptr<IEventHandlerWrapper>>> & - handlers_map - = this->subscribers_by_event_id[event_type]; - std::unordered_map< - int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator - handlers_it - = handlers_map.find(channel); - - if (handlers_it != handlers_map.end()) { - std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers - = handlers_it->second; - for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it - = handlers.begin(); - it != handlers.end();++it) { - // stops when callback returns true - if((*it)->exec(event)){ - break; - } - } - } - } else { - std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers - = this->subscribers[event_type]; - for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it - = handlers.begin(); - it != handlers.end();++it) { - // stops when callback returns true - if((*it)->exec(event)){ - break; - } - } - } +void EventManager::queue_event(const EventType & event, event_channel_t channel) { + static_assert(std::is_base_of<Event, EventType>::value, + "EventType must derive from Event"); + this->events_queue.push_back(QueueEntry{ + .event = std::make_unique<EventType>(event), + .channel = channel, + .type = typeid(EventType), + }); } template <typename EventType> -void EventManager::unsubscribe(const EventHandler<EventType> & callback, - int channel) { - std::type_index event_type(typeid(EventType)); - std::string handler_name = callback.target_type().name(); - - if (channel) { - std::unordered_map< - std::type_index, - std::unordered_map< - int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>:: - iterator subscriber_list - = this->subscribers_by_event_id.find(event_type); - if (subscriber_list != this->subscribers_by_event_id.end()) { - std::unordered_map< - int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> & - handlers_map - = subscriber_list->second; - std::unordered_map< - int, - std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator - handlers - = handlers_map.find(channel); - if (handlers != handlers_map.end()) { - std::vector<std::unique_ptr<IEventHandlerWrapper>> & callbacks - = handlers->second; - for (std::vector< - std::unique_ptr<IEventHandlerWrapper>>::iterator it - = callbacks.begin(); - it != callbacks.end(); ++it) { - if ((*it)->get_type() == handler_name) { - it = callbacks.erase(it); - return; - } - } - } - } - } else { - std::unordered_map<std::type_index, - std::vector<std::unique_ptr<IEventHandlerWrapper>>>:: - iterator handlers_it - = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers - = handlers_it->second; - for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it - = handlers.begin(); - it != handlers.end(); ++it) { - if ((*it)->get_type() == handler_name) { - it = handlers.erase(it); - return; - } - } - } - } +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/api/GameObject.cpp b/src/crepe/api/GameObject.cpp index 287e81d..4874426 100644 --- a/src/crepe/api/GameObject.cpp +++ b/src/crepe/api/GameObject.cpp @@ -23,12 +23,10 @@ void GameObject::set_parent(const GameObject & parent) { ComponentManager & mgr = this->component_manager; // Set parent on own Metadata component - vector<reference_wrapper<Metadata>> this_metadata - = mgr.get_components_by_id<Metadata>(this->id); + RefVector<Metadata> this_metadata = mgr.get_components_by_id<Metadata>(this->id); this_metadata.at(0).get().parent = parent.id; // Add own id to children list of parent's Metadata component - vector<reference_wrapper<Metadata>> parent_metadata - = mgr.get_components_by_id<Metadata>(parent.id); + RefVector<Metadata> parent_metadata = mgr.get_components_by_id<Metadata>(parent.id); parent_metadata.at(0).get().children.push_back(this->id); } diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 4fd9855..8642655 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -2,50 +2,18 @@ using namespace crepe; -IKeyListener::IKeyListener() { - this->channel = channel; - this->subscribe_events(); -} -IKeyListener::IKeyListener(int channel) { - this->channel = channel; - this->subscribe_events(); -} -IKeyListener::~IKeyListener() { this->unsubscribe_events(); } - -void IKeyListener::subscribe_events() { - key_pressed_handler = [this](const KeyPressEvent & event) { - return this->on_key_pressed(event); - }; - key_released_handler = [this](const KeyReleaseEvent & event) { - return this->on_key_released(event); - }; - EventManager::get_instance().subscribe<KeyPressEvent>( - std::move(this->key_pressed_handler), this->channel); - EventManager::get_instance().subscribe<KeyReleaseEvent>( - std::move(this->key_released_handler), this->channel); +// Constructor with specified channel +IKeyListener::IKeyListener(event_channel_t channel) + : event_manager(EventManager::get_instance()) { + this->press_id = event_manager.subscribe<KeyPressEvent>( + [this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel); + this->release_id = event_manager.subscribe<KeyReleaseEvent>( + [this](const KeyReleaseEvent & event) { return this->on_key_released(event); }, + channel); } -void IKeyListener::unsubscribe_events() { - EventManager::get_instance().unsubscribe<KeyPressEvent>( - this->key_pressed_handler, channel); - EventManager::get_instance().unsubscribe<KeyReleaseEvent>( - this->key_released_handler, channel); - std::cout << std::endl; -} -void IKeyListener::activate_keys() { - if (this->active) { - return; - } - this->subscribe_events(); -} -void IKeyListener::deactivate_keys() { - if (!this->active) { - return; - } - this->unsubscribe_events(); -} -void IKeyListener::set_channel(int channel) { - this->unsubscribe_events(); - this->channel = channel; - this->subscribe_events(); +// Destructor, unsubscribe events +IKeyListener::~IKeyListener() { + event_manager.unsubscribe(this->press_id); + event_manager.unsubscribe(this->release_id); } diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 839acbf..328a4c2 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -1,8 +1,11 @@ #pragma once + #include "Event.h" #include "EventHandler.h" #include "EventManager.h" +namespace crepe { + /** * \class IKeyListener * \brief Interface for keyboard event handling in the application. @@ -13,17 +16,12 @@ public: * \brief Constructs an IKeyListener with a specified channel. * \param channel The channel ID for event handling. */ - IKeyListener(int channel); - - /** - * \brief Default constructor for IKeyListener. - */ - IKeyListener(); - - /** - * \brief Destructor. - */ + IKeyListener(event_channel_t channel = EventManager::CHANNEL_ALL); virtual ~IKeyListener(); + IKeyListener(const IKeyListener &) = delete; + IKeyListener & operator=(const IKeyListener &) = delete; + IKeyListener & operator=(IKeyListener &&) = delete; + IKeyListener(IKeyListener &&) = delete; /** * \brief Pure virtual function to handle key press events. @@ -39,40 +37,13 @@ public: */ virtual bool on_key_released(const KeyReleaseEvent & event) = 0; - /** - * \brief Activates key listening. - */ - void activate_keys(); - - /** - * \brief Deactivates key listening. - */ - void deactivate_keys(); - - /** - * \brief Sets the channel ID for event handling. - * \param channel The channel ID to set. - */ - void set_channel(int channel); - -protected: - /** - * \brief Subscribes to key events. - */ - void subscribe_events(); - - /** - * \brief Unsubscribes from key events. - */ - void unsubscribe_events(); - private: - //! Indicates whether key listening is active. - bool active = true; - //! Channel ID for event handling. - int channel = 0; - //! Key press event handler. - EventHandler<KeyPressEvent> key_pressed_handler; - //!< Key release event handler. - EventHandler<KeyReleaseEvent> key_released_handler; + //! Key press event id + subscription_t press_id = -1; + //! Key release event id + subscription_t release_id = -1; + //! EventManager reference + EventManager & event_manager; }; + +} // namespace crepe diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 489e55b..989aeb3 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -2,63 +2,28 @@ using namespace crepe; -IMouseListener::IMouseListener(int channel) { this->channel = channel; } - -IMouseListener::IMouseListener() { this->subscribe_events(); } - -IMouseListener::~IMouseListener() { this->unsubscribe_events(); } - -void IMouseListener::subscribe_events() { - // Define handler lambdas and subscribe them - mouse_click_handler = [this](const MouseClickEvent & event) { - return this->on_mouse_clicked(event); - }; - mouse_press_handler = [this](const MousePressEvent & event) { - return this->on_mouse_pressed(event); - }; - mouse_release_handler = [this](const MouseReleaseEvent & event) { - return this->on_mouse_released(event); - }; - mouse_move_handler = [this](const MouseMoveEvent & event) { - return this->on_mouse_moved(event); - }; - EventManager::get_instance().subscribe<MouseClickEvent>( - std::move(this->mouse_click_handler), this->channel); - EventManager::get_instance().subscribe<MousePressEvent>( - std::move(this->mouse_press_handler), this->channel); - EventManager::get_instance().subscribe<MouseReleaseEvent>( - std::move(this->mouse_release_handler), this->channel); - EventManager::get_instance().subscribe<MouseMoveEvent>( - std::move(this->mouse_move_handler), this->channel); -} -// TODO: reference voor singleton -void IMouseListener::unsubscribe_events() { - EventManager::get_instance().unsubscribe<MouseClickEvent>( - this->mouse_click_handler, this->channel); - EventManager::get_instance().unsubscribe<MousePressEvent>( - this->mouse_press_handler, this->channel); - EventManager::get_instance().unsubscribe<MouseReleaseEvent>( - this->mouse_release_handler, this->channel); - EventManager::get_instance().unsubscribe<MouseMoveEvent>( - this->mouse_move_handler, this->channel); -} - -void IMouseListener::activate_mouse() { - if (this->active) { - return; - } - this->subscribe_events(); -} - -void IMouseListener::deactivate_mouse() { - if (!this->active) { - return; - } - this->unsubscribe_events(); +IMouseListener::IMouseListener(event_channel_t channel) + : event_manager(EventManager::get_instance()) { + this->click_id = event_manager.subscribe<MouseClickEvent>( + [this](const MouseClickEvent & event) { return this->on_mouse_clicked(event); }, + channel); + + this->press_id = event_manager.subscribe<MousePressEvent>( + [this](const MousePressEvent & event) { return this->on_mouse_pressed(event); }, + channel); + + this->release_id = event_manager.subscribe<MouseReleaseEvent>( + [this](const MouseReleaseEvent & event) { return this->on_mouse_released(event); }, + channel); + + this->move_id = event_manager.subscribe<MouseMoveEvent>( + [this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }, channel); } -void IMouseListener::set_channel(int channel) { - this->unsubscribe_events(); - this->channel = channel; - this->subscribe_events(); +IMouseListener::~IMouseListener() { + // Unsubscribe event handlers + event_manager.unsubscribe(this->click_id); + event_manager.unsubscribe(this->press_id); + event_manager.unsubscribe(this->release_id); + event_manager.unsubscribe(this->move_id); } diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 7e92956..15e1619 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -4,6 +4,8 @@ #include "EventHandler.h" #include "EventManager.h" +namespace crepe { + /** * \class IMouseListener * \brief Interface for mouse event handling in the application. @@ -11,34 +13,14 @@ class IMouseListener { public: /** - * \brief Default constructor. - */ - IMouseListener(); - - /** * \brief Constructs an IMouseListener with a specified channel. * \param channel The channel ID for event handling. */ - IMouseListener(int channel); - - /** - * \brief Destructor. - */ + IMouseListener(event_channel_t channel = EventManager::CHANNEL_ALL); virtual ~IMouseListener(); - - /** - * \brief Copy constructor (deleted). - */ - IMouseListener(const IMouseListener &) = delete; - - /** - * \brief Copy assignment operator (deleted). - */ IMouseListener & operator=(const IMouseListener &) = delete; - - /** - * \brief Move constructor (deleted). - */ + IMouseListener(const IMouseListener &) = delete; + IMouseListener & operator=(const IMouseListener &&) = delete; IMouseListener(IMouseListener &&) = delete; /** @@ -74,44 +56,17 @@ public: */ virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; - /** - * \brief Activates mouse listening. - */ - void activate_mouse(); - - /** - * \brief Deactivates mouse listening. - */ - void deactivate_mouse(); - - /** - * \brief Sets the channel ID for event handling. - * \param channel The channel ID to set. - */ - void set_channel(int channel); - -protected: - /** - * \brief Subscribes to mouse events on the specified channel. - */ - void subscribe_events(); - - /** - * \brief Unsubscribes from mouse events on the specified channel. - */ - void unsubscribe_events(); - private: - //! Indicates whether mouse listening is active. - bool active = true; - //! Channel ID for event handling. - int channel = 0; - //! Mouse click event handler. - EventHandler<MouseClickEvent> mouse_click_handler; - //! Mouse press event handler. - EventHandler<MousePressEvent> mouse_press_handler; - //! Mouse release event handler. - EventHandler<MouseReleaseEvent> mouse_release_handler; - //! Mouse move event handler. - EventHandler<MouseMoveEvent> mouse_move_handler; + //! Mouse click event id + subscription_t click_id = -1; + //! Mouse press event id + subscription_t press_id = -1; + //! Mouse release event id + subscription_t release_id = -1; + //! Mouse move event id + subscription_t move_id = -1; + //! EventManager reference + EventManager & event_manager; }; + +} //namespace crepe diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h index e5a91fc..9e173e0 100644 --- a/src/crepe/api/KeyCodes.h +++ b/src/crepe/api/KeyCodes.h @@ -1,94 +1,93 @@ #pragma once +//! Enumeration for mouse button inputs, including standard and extended buttons. enum class MouseButton { - NONE = 0, - LEFT_MOUSE = 1, - RIGHT_MOUSE = 2, - MIDDLE_MOUSE = 3, - X1_MOUSE = 4, - X2_MOUSE = 5, - SCROLL_UP = 6, - SCROLL_DOWN = 7, + NONE = 0, //!< No mouse button input. + LEFT_MOUSE = 1, //!< Left mouse button. + RIGHT_MOUSE = 2, //!< Right mouse button. + MIDDLE_MOUSE = 3, //!< Middle mouse button (scroll wheel press). + X1_MOUSE = 4, //!< First extended mouse button. + X2_MOUSE = 5, //!< Second extended mouse button. + SCROLL_UP = 6, //!< Scroll wheel upward movement. + SCROLL_DOWN = 7, //!< Scroll wheel downward movement. }; -enum class Keycode : int { - NONE = 0, - SPACE = 32, - APOSTROPHE = 39, /* ' */ - COMMA = 44, /* , */ - MINUS = 45, /* - */ - PERIOD = 46, /* . */ - SLASH = 47, /* / */ - - D0 = 48, /* 0 */ - D1 = 49, /* 1 */ - D2 = 50, /* 2 */ - D3 = 51, /* 3 */ - D4 = 52, /* 4 */ - D5 = 53, /* 5 */ - D6 = 54, /* 6 */ - D7 = 55, /* 7 */ - D8 = 56, /* 8 */ - D9 = 57, /* 9 */ - - SEMICOLON = 59, /* ; */ - EQUAL = 61, /* = */ - - A = 65, - B = 66, - C = 67, - D = 68, - E = 69, - F = 70, - G = 71, - H = 72, - I = 73, - J = 74, - K = 75, - L = 76, - M = 77, - N = 78, - O = 79, - P = 80, - Q = 81, - R = 82, - S = 83, - T = 84, - U = 85, - V = 86, - W = 87, - X = 88, - Y = 89, - Z = 90, - - LEFT_BRACKET = 91, /* [ */ - BACKSLASH = 92, /* \ */ - RIGHT_BRACKET = 93, /* ] */ - GRAVE_ACCENT = 96, /* ` */ - - WORLD1 = 161, /* non-US #1 */ - WORLD2 = 162, /* non-US #2 */ - - /* Function keys */ - ESCAPE = 256, - ENTER = 257, - TAB = 258, - BACKSPACE = 259, - INSERT = 260, - DELETE = 261, - RIGHT = 262, - LEFT = 263, - DOWN = 264, - UP = 265, - PAGE_UP = 266, - PAGE_DOWN = 267, - HOME = 268, - END = 269, - CAPS_LOCK = 280, - SCROLL_LOCK = 281, - NUM_LOCK = 282, - PRINT_SCREEN = 283, - PAUSE = 284, +//! Enumeration for keyboard key inputs, including printable characters, function keys, and keypad keys. +enum class Keycode { + NONE = 0, //!< No key input. + SPACE = 32, //!< Spacebar. + APOSTROPHE = 39, //!< Apostrophe ('). + COMMA = 44, //!< Comma (,). + MINUS = 45, //!< Minus (-). + PERIOD = 46, //!< Period (.). + SLASH = 47, //!< Slash (/). + D0 = 48, //!< Digit 0. + D1 = 49, //!< Digit 1. + D2 = 50, //!< Digit 2. + D3 = 51, //!< Digit 3. + D4 = 52, //!< Digit 4. + D5 = 53, //!< Digit 5. + D6 = 54, //!< Digit 6. + D7 = 55, //!< Digit 7. + D8 = 56, //!< Digit 8. + D9 = 57, //!< Digit 9. + SEMICOLON = 59, //!< Semicolon (;). + EQUAL = 61, //!< Equal sign (=). + A = 65, //!< Key 'A'. + B = 66, //!< Key 'B'. + C = 67, //!< Key 'C'. + D = 68, //!< Key 'D'. + E = 69, //!< Key 'E'. + F = 70, //!< Key 'F'. + G = 71, //!< Key 'G'. + H = 72, //!< Key 'H'. + I = 73, //!< Key 'I'. + J = 74, //!< Key 'J'. + K = 75, //!< Key 'K'. + L = 76, //!< Key 'L'. + M = 77, //!< Key 'M'. + N = 78, //!< Key 'N'. + O = 79, //!< Key 'O'. + P = 80, //!< Key 'P'. + Q = 81, //!< Key 'Q'. + R = 82, //!< Key 'R'. + S = 83, //!< Key 'S'. + T = 84, //!< Key 'T'. + U = 85, //!< Key 'U'. + V = 86, //!< Key 'V'. + W = 87, //!< Key 'W'. + X = 88, //!< Key 'X'. + Y = 89, //!< Key 'Y'. + Z = 90, //!< Key 'Z'. + LEFT_BRACKET = 91, //!< Left bracket ([). + BACKSLASH = 92, //!< Backslash (\). + RIGHT_BRACKET = 93, //!< Right bracket (]). + GRAVE_ACCENT = 96, //!< Grave accent (`). + WORLD1 = 161, //!< Non-US key #1. + WORLD2 = 162, //!< Non-US key #2. + ESCAPE = 256, //!< Escape key. + ENTER = 257, //!< Enter key. + TAB = 258, //!< Tab key. + BACKSPACE = 259, //!< Backspace key. + INSERT = 260, //!< Insert key. + DELETE = 261, //!< Delete key. + RIGHT = 262, //!< Right arrow key. + LEFT = 263, //!< Left arrow key. + DOWN = 264, //!< Down arrow key. + UP = 265, //!< Up arrow key. + PAGE_UP = 266, //!< Page Up key. + PAGE_DOWN = 267, //!< Page Down key. + HOME = 268, //!< Home key. + END = 269, //!< End key. + CAPS_LOCK = 280, //!< Caps Lock key. + SCROLL_LOCK = 281, //!< Scroll Lock key. + NUM_LOCK = 282, //!< Num Lock key. + PRINT_SCREEN = 283, //!< Print Screen key. + PAUSE = 284, //!< Pause key. + /** + * \name Function keys (F1-F25). + * \{ + */ F1 = 290, F2 = 291, F3 = 292, @@ -114,8 +113,11 @@ enum class Keycode : int { F23 = 312, F24 = 313, F25 = 314, - - /* Keypad */ + /// \} + /** + * \name Keypad digits and operators. + * \{ + */ KP0 = 320, KP1 = 321, KP2 = 322, @@ -133,7 +135,11 @@ enum class Keycode : int { KP_ADD = 334, KP_ENTER = 335, KP_EQUAL = 336, - + /// \} + /** + * \name Modifier keys. + * \{ + */ LEFT_SHIFT = 340, LEFT_CONTROL = 341, LEFT_ALT = 342, @@ -142,5 +148,6 @@ enum class Keycode : int { RIGHT_CONTROL = 345, RIGHT_ALT = 346, RIGHT_SUPER = 347, - MENU = 348 + /// \} + MENU = 348, //!< Menu key. }; diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 37f13ac..13e6dac 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -8,11 +8,24 @@ namespace crepe { +/** + * \brief Main game loop manager + * + * This class is responsible for managing the game loop, including initialization and updating. + */ class LoopManager { public: void start(); LoopManager(); + /** + * \brief Add a new concrete scene to the scene manager + * + * \tparam T Type of concrete scene + */ + template <typename T> + void add_scene(); + private: /** * \brief Setup function for one-time initialization. @@ -54,12 +67,14 @@ private: * This function updates physics and game logic based on LoopTimer's fixed_delta_time. */ void fixed_update(); + /** * \brief Set game running variable * * \param running running (false = game shutdown, true = game running) */ void set_running(bool running); + /** * \brief Function for executing render-related systems. * @@ -72,9 +87,9 @@ private: private: //! Component manager instance ComponentManager component_manager{}; -public: //! Scene manager instance SceneManager scene_manager{component_manager}; + private: /** * \brief Collection of System instances diff --git a/src/crepe/api/LoopManager.hpp b/src/crepe/api/LoopManager.hpp index 0b14fdb..9cf470b 100644 --- a/src/crepe/api/LoopManager.hpp +++ b/src/crepe/api/LoopManager.hpp @@ -11,6 +11,11 @@ namespace crepe { template <class T> +void LoopManager::add_scene() { + this->scene_manager.add_scene<T>(); +} + +template <class T> T & LoopManager::get_system() { using namespace std; static_assert(is_base_of<System, T>::value, diff --git a/src/crepe/api/Scene.cpp b/src/crepe/api/Scene.cpp index 88aa82d..849945e 100644 --- a/src/crepe/api/Scene.cpp +++ b/src/crepe/api/Scene.cpp @@ -2,6 +2,4 @@ using namespace crepe; -Scene::Scene(ComponentManager & mgr, const std::string & name) - : component_manager(mgr), - name(name) {} +Scene::Scene(ComponentManager & mgr) : component_manager(mgr) {} diff --git a/src/crepe/api/Scene.h b/src/crepe/api/Scene.h index 0e516b6..869bf6f 100644 --- a/src/crepe/api/Scene.h +++ b/src/crepe/api/Scene.h @@ -7,19 +7,36 @@ namespace crepe { class SceneManager; class ComponentManager; +/** + * \brief Represents a Scene + * + * This class represents a Scene. The Scene class is only used as an interface for the game + * programmer. + */ class Scene { protected: - Scene(ComponentManager & mgr, const std::string & name); + //TODO: Use Loek's custom reference class to set ComponentManger via SceneManager instead of via constructor + /** + * \param mgr Reference to the ComponentManager + */ + Scene(ComponentManager & mgr); + //! SceneManager instances Scene friend class SceneManager; public: virtual ~Scene() = default; public: + //! Load the scene virtual void load_scene() = 0; - const std::string name; + /** + * \brief Get the scene's name + * \return The scene's name + */ + virtual std::string get_name() const = 0; protected: + //! Reference to the ComponentManager ComponentManager & component_manager; }; diff --git a/src/crepe/api/SceneManager.cpp b/src/crepe/api/SceneManager.cpp index 7fb5cb0..1f783ad 100644 --- a/src/crepe/api/SceneManager.cpp +++ b/src/crepe/api/SceneManager.cpp @@ -18,7 +18,7 @@ void SceneManager::load_next_scene() { auto it = find_if(this->scenes.begin(), this->scenes.end(), [&next_scene = this->next_scene](unique_ptr<Scene> & scene) { - return scene->name == next_scene; + return scene.get()->get_name() == next_scene; }); // next scene not found diff --git a/src/crepe/api/SceneManager.h b/src/crepe/api/SceneManager.h index e854794..45ba668 100644 --- a/src/crepe/api/SceneManager.h +++ b/src/crepe/api/SceneManager.h @@ -1,7 +1,6 @@ #pragma once #include <memory> -#include <queue> #include <vector> #include "Scene.h" @@ -10,8 +9,15 @@ 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: + //! \param mgr Reference to the ComponentManager SceneManager(ComponentManager & mgr); public: @@ -19,10 +25,9 @@ public: * \brief Add a new concrete scene to the scene manager * * \tparam T Type of concrete scene - * \param name Name of new scene */ template <typename T> - void add_scene(const std::string & name); + void add_scene(); /** * \brief Set the next scene * @@ -35,8 +40,11 @@ public: void load_next_scene(); private: + //! Vector of concrete scenes (added by add_scene()) std::vector<std::unique_ptr<Scene>> scenes; + //! Next scene to load std::string next_scene; + //! Reference to the ComponentManager ComponentManager & component_manager; }; diff --git a/src/crepe/api/SceneManager.hpp b/src/crepe/api/SceneManager.hpp index 714f690..94e5946 100644 --- a/src/crepe/api/SceneManager.hpp +++ b/src/crepe/api/SceneManager.hpp @@ -5,16 +5,16 @@ namespace crepe { template <typename T> -void SceneManager::add_scene(const std::string & name) { +void SceneManager::add_scene() { using namespace std; static_assert(is_base_of<Scene, T>::value, "T must be derived from Scene"); - Scene * scene = new T(this->component_manager, name); + Scene * scene = new T(this->component_manager); this->scenes.emplace_back(unique_ptr<Scene>(scene)); // The first scene added, is the one that will be loaded at the beginning if (next_scene.empty()) { - next_scene = name; + next_scene = scene->get_name(); } } diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 939d142..0702e36 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -62,15 +62,15 @@ protected: * \returns List of component references */ template <typename T> - std::vector<std::reference_wrapper<T>> get_components() const; - + RefVector<T> get_components() const; + /** * \brief Gets game object id this script is attached to * * \returns game object id */ game_object_id_t get_game_object_id() const {return this->game_object_id;}; - + protected: // NOTE: Script must have a constructor without arguments so the game programmer doesn't need // to manually add `using Script::Script` to their concrete script class. diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index a064a90..a85d814 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -10,7 +10,7 @@ namespace crepe { template <typename T> T & Script::get_component() const { using namespace std; - vector<reference_wrapper<T>> all_components = this->get_components<T>(); + RefVector<T> all_components = this->get_components<T>(); if (all_components.size() < 1) throw runtime_error( format("Script: no component found with type = {}", typeid(T).name())); @@ -19,9 +19,8 @@ T & Script::get_component() const { } template <typename T> -std::vector<std::reference_wrapper<T>> Script::get_components() const { +RefVector<T> Script::get_components() const { auto & mgr = *this->component_manager_ref; - return mgr.get_components_by_id<T>(this->game_object_id); } diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp index de0d0ea..9be9421 100644 --- a/src/crepe/api/Texture.cpp +++ b/src/crepe/api/Texture.cpp @@ -26,7 +26,7 @@ Texture::~Texture() { void Texture::load(unique_ptr<Asset> res) { SDLContext & ctx = SDLContext::get_instance(); - this->texture = std::move(ctx.texture_from_path(res->get_canonical())); + this->texture = std::move(ctx.texture_from_path(res->get_path())); } int Texture::get_width() const { @@ -35,5 +35,5 @@ int Texture::get_width() const { } int Texture::get_height() const { if (this->texture == nullptr) return 0; - return SDLContext::get_instance().get_width(*this); + return SDLContext::get_instance().get_height(*this); } |