diff options
author | heavydemon21 <nielsstunnebrink1@gmail.com> | 2024-12-06 10:44:42 +0100 |
---|---|---|
committer | heavydemon21 <nielsstunnebrink1@gmail.com> | 2024-12-06 10:44:42 +0100 |
commit | d5f63024ebed7df2fff8e016bd1c7c26f8fdfa27 (patch) | |
tree | b26e35cb0482d04a33cc96d97ba21c21d0012229 /src/crepe | |
parent | 9cde6875186b335c75eafa6402f0957cd4252c76 (diff) | |
parent | 1f4e961d7f9d6887c807cac1a362f2d178b0860b (diff) |
Merge branch 'master' into decoupling
Diffstat (limited to 'src/crepe')
53 files changed, 1009 insertions, 249 deletions
diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 7e176e7..da9d492 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -1,13 +1,10 @@ target_sources(crepe PUBLIC Particle.cpp - ComponentManager.cpp Component.cpp Collider.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES - ComponentManager.h - ComponentManager.hpp Component.h Collider.h ValueBroker.h @@ -16,6 +13,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES add_subdirectory(api) add_subdirectory(facade) +add_subdirectory(manager) add_subdirectory(system) add_subdirectory(util) diff --git a/src/crepe/api/BehaviorScript.cpp b/src/crepe/api/BehaviorScript.cpp index 7bbace0..d22afdf 100644 --- a/src/crepe/api/BehaviorScript.cpp +++ b/src/crepe/api/BehaviorScript.cpp @@ -4,12 +4,12 @@ using namespace crepe; -BehaviorScript::BehaviorScript(game_object_id_t id, ComponentManager & mgr) +BehaviorScript::BehaviorScript(game_object_id_t id, Mediator & mediator) : Component(id), - component_manager(mgr) {} + mediator(mediator) {} template <> BehaviorScript & GameObject::add_component<BehaviorScript>() { ComponentManager & mgr = this->component_manager; - return mgr.add_component<BehaviorScript>(this->id, mgr); + return mgr.add_component<BehaviorScript>(this->id, mgr.mediator); } diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h index d556fe5..3909b96 100644 --- a/src/crepe/api/BehaviorScript.h +++ b/src/crepe/api/BehaviorScript.h @@ -23,14 +23,13 @@ class BehaviorScript : public Component { protected: /** * \param id Parent \c GameObject id - * \param component_manager Reference to component manager (passed through to \c Script - * instance) + * \param mediator Mediator reference * * \note Calls to this constructor (should) always pass through \c GameObject::add_component, * which has an exception for this specific component type. This was done so the user does * not have to pass references used within \c Script to each \c BehaviorScript instance. */ - BehaviorScript(game_object_id_t id, ComponentManager & component_manager); + BehaviorScript(game_object_id_t id, Mediator & mediator); //! Only ComponentManager is allowed to instantiate BehaviorScript friend class ComponentManager; @@ -55,8 +54,8 @@ protected: friend class ScriptSystem; protected: - //! Reference to component manager (passed to Script) - ComponentManager & component_manager; + //! Reference mediator + Mediator & mediator; }; /** diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp index bd59337..b9bb1e2 100644 --- a/src/crepe/api/BehaviorScript.hpp +++ b/src/crepe/api/BehaviorScript.hpp @@ -13,14 +13,12 @@ template <class T, typename... Args> BehaviorScript & BehaviorScript::set_script(Args &&... args) { dbg_trace(); static_assert(std::is_base_of<Script, T>::value); - Script * s = new T(std::forward<Args>(args)...); + this->script = std::unique_ptr<Script>(new T(std::forward<Args>(args)...)); - s->game_object_id = this->game_object_id; - s->active = this->active; - s->component_manager = this->component_manager; - s->event_manager = EventManager::get_instance(); + this->script->game_object_id = this->game_object_id; + this->script->active = this->active; + this->script->mediator = this->mediator; - this->script = std::unique_ptr<Script>(s); return *this; } diff --git a/src/crepe/api/Button.cpp b/src/crepe/api/Button.cpp new file mode 100644 index 0000000..76f74f0 --- /dev/null +++ b/src/crepe/api/Button.cpp @@ -0,0 +1,11 @@ +#include "Button.h" + +namespace crepe { + +Button::Button(game_object_id_t id, const vec2 & dimensions, const vec2 & offset, + const std::function<void()> & on_click, bool is_toggle) + : UIObject(id, dimensions, offset), + is_toggle(is_toggle), + on_click(on_click) {} + +} // namespace crepe diff --git a/src/crepe/api/Button.h b/src/crepe/api/Button.h new file mode 100644 index 0000000..26e7526 --- /dev/null +++ b/src/crepe/api/Button.h @@ -0,0 +1,67 @@ +#pragma once + +#include <functional> + +#include "UIObject.h" + +namespace crepe { + +//! Represents a clickable UI button, derived from the UiObject class. +class Button : public UIObject { +public: + /** + * \brief Constructs a Button with the specified game object ID and dimensions. + * + * \param id The unique ID of the game object associated with this button. + * \param dimensions The width and height of the UIObject + * \param offset The offset relative this GameObjects Transform + * \param is_toggle Optional flag to indicate if the button is a toggle button. Defaults to false. + * \param on_click callback function that will be invoked when the button is clicked. + */ + Button(game_object_id_t id, const vec2 & dimensions, const vec2 & offset, + const std::function<void()> & on_click, bool is_toggle = false); + + /** + * \brief Indicates if the button is a toggle button (can be pressed and released). + * + * A toggle button allows for a pressed/released state, whereas a regular button + * typically only has an on-click state. + */ + bool is_toggle = false; + // TODO: create separate toggle button class + /** + * \brief The callback function to be executed when the button is clicked. + * + * This function is invoked whenever the button is clicked. It can be set to any + * function that matches the signature `void()`. + */ + std::function<void()> on_click = nullptr; + + /** + * \brief Callback function to be executed when the mouse enters the button's boundaries. + * + * This function is triggered when the mouse cursor moves over the button, allowing + * custom actions like visual effects, highlighting, or sound effects. + */ + std::function<void()> on_mouse_enter = nullptr; + + /** + * \brief Callback function to be executed when the mouse exits the button's boundaries. + * + * This function is triggered when the mouse cursor moves out of the button's area, + * allowing custom actions like resetting visual effects or playing exit-related effects. + */ + std::function<void()> on_mouse_exit = nullptr; + +private: + //! friend relation for is_pressed and hover variables + friend class InputSystem; + //! Indicates whether the toggle button is pressed + bool is_pressed = false; + //! Indicates whether the mouse is currently hovering over the button + bool hover = false; + +public: +}; + +} // namespace crepe diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 50c51ed..ac8f301 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -9,13 +9,10 @@ target_sources(crepe PUBLIC Texture.cpp AssetManager.cpp Sprite.cpp - SaveManager.cpp Config.cpp Metadata.cpp - SceneManager.cpp Camera.cpp Animator.cpp - EventManager.cpp IKeyListener.cpp IMouseListener.cpp LoopManager.cpp @@ -23,6 +20,8 @@ target_sources(crepe PUBLIC Asset.cpp EventHandler.cpp Script.cpp + Button.cpp + UIObject.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -41,15 +40,10 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Texture.h AssetManager.h AssetManager.hpp - SaveManager.h Scene.h Metadata.h - SceneManager.h - SceneManager.hpp Camera.h Animator.h - EventManager.h - EventManager.hpp EventHandler.h EventHandler.hpp Event.h @@ -58,4 +52,6 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES LoopManager.h LoopTimer.h Asset.h + Button.h + UIObject.h ) diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index b267e3e..6298118 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -88,9 +88,31 @@ public: //! Y-coordinate of the mouse position at the time of the event. int mouse_y = 0; + + // Movement since last event in x + int delta_x = 0; + + // Movement since last event in y + int delta_y = 0; }; /** + * \brief Event triggered when the mouse is moved. + */ +class MouseScrollEvent : 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; + + //! scroll direction (-1 = down, 1 = up) + int scroll_direction = 0; + //! scroll amount in y axis (from and away from the person). + float scroll_delta = 0; +}; +/** * \brief Event triggered during a collision between objects. */ class CollisionEvent : public Event {}; diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index ef659fd..7bdd9a3 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -29,29 +29,29 @@ using EventHandler = std::function<bool(const EventType & e)>; class IEventHandlerWrapper { public: /** - * \brief Virtual destructor for IEventHandlerWrapper. - */ + * \brief Virtual destructor for IEventHandlerWrapper. + */ virtual ~IEventHandlerWrapper() = default; /** - * \brief Executes the handler with the given event. - * - * This method calls the `call()` method of the derived class, passing the event to the handler. - * - * \param e The event to be processed. - * \return A boolean value indicating whether the event is handled. - */ + * \brief Executes the handler with the given event. + * + * This method calls the `call()` method of the derived class, passing the event to the handler. + * + * \param e The event to be processed. + * \return A boolean value indicating whether the event is handled. + */ bool exec(const Event & e); private: /** - * \brief The method responsible for handling the event. - * - * This method is implemented by derived classes to process the event. - * - * \param e The event to be processed. - * \return A boolean value indicating whether the event is handled. - */ + * \brief The method responsible for handling the event. + * + * This method is implemented by derived classes to process the event. + * + * \param e The event to be processed. + * \return A boolean value indicating whether the event is handled. + */ virtual bool call(const Event & e) = 0; }; @@ -69,23 +69,23 @@ template <typename EventType> class EventHandlerWrapper : public IEventHandlerWrapper { public: /** - * \brief Constructs an EventHandlerWrapper with a given handler. - * - * The constructor takes an event handler function and stores it in the wrapper. - * - * \param handler The event handler function. - */ + * \brief Constructs an EventHandlerWrapper with a given handler. + * + * The constructor takes an event handler function and stores it in the wrapper. + * + * \param handler The event handler function. + */ explicit EventHandlerWrapper(const EventHandler<EventType> & handler); private: /** - * \brief Calls the stored event handler with the event. - * - * This method casts the event to the appropriate type and calls the handler. - * - * \param e The event to be handled. - * \return A boolean value indicating whether the event is handled. - */ + * \brief Calls the stored event handler with the event. + * + * This method casts the event to the appropriate type and calls the handler. + * + * \param e The event to be handled. + * \return A boolean value indicating whether the event is handled. + */ bool call(const Event & e) override; //! The event handler function. EventHandler<EventType> handler; diff --git a/src/crepe/api/GameObject.hpp b/src/crepe/api/GameObject.hpp index 17b17d7..a6b45b0 100644 --- a/src/crepe/api/GameObject.hpp +++ b/src/crepe/api/GameObject.hpp @@ -1,6 +1,6 @@ #pragma once -#include "../ComponentManager.h" +#include "../manager/ComponentManager.h" #include "GameObject.h" diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 328a4c2..180a0a6 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -1,8 +1,9 @@ #pragma once +#include "../manager/EventManager.h" + #include "Event.h" #include "EventHandler.h" -#include "EventManager.h" namespace crepe { @@ -13,9 +14,9 @@ namespace crepe { class IKeyListener { public: /** - * \brief Constructs an IKeyListener with a specified channel. - * \param channel The channel ID for event handling. - */ + * \brief Constructs an IKeyListener with a specified channel. + * \param channel The channel ID for event handling. + */ IKeyListener(event_channel_t channel = EventManager::CHANNEL_ALL); virtual ~IKeyListener(); IKeyListener(const IKeyListener &) = delete; @@ -24,17 +25,17 @@ public: IKeyListener(IKeyListener &&) = delete; /** - * \brief Pure virtual function to handle key press events. - * \param event The key press event to handle. - * \return True if the event was handled, false otherwise. - */ + * \brief Pure virtual function to handle key press events. + * \param event The key press event to handle. + * \return True if the event was handled, false otherwise. + */ virtual bool on_key_pressed(const KeyPressEvent & event) = 0; /** - * \brief Pure virtual function to handle key release events. - * \param event The key release event to handle. - * \return True if the event was handled, false otherwise. - */ + * \brief Pure virtual function to handle key release events. + * \param event The key release event to handle. + * \return True if the event was handled, false otherwise. + */ virtual bool on_key_released(const KeyReleaseEvent & event) = 0; private: diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 15e1619..e19897d 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -1,8 +1,9 @@ #pragma once +#include "../manager/EventManager.h" + #include "Event.h" #include "EventHandler.h" -#include "EventManager.h" namespace crepe { @@ -13,9 +14,9 @@ namespace crepe { class IMouseListener { public: /** - * \brief Constructs an IMouseListener with a specified channel. - * \param channel The channel ID for event handling. - */ + * \brief Constructs an IMouseListener with a specified channel. + * \param channel The channel ID for event handling. + */ IMouseListener(event_channel_t channel = EventManager::CHANNEL_ALL); virtual ~IMouseListener(); IMouseListener & operator=(const IMouseListener &) = delete; @@ -24,36 +25,36 @@ public: IMouseListener(IMouseListener &&) = delete; /** - * \brief Move assignment operator (deleted). - */ + * \brief Move assignment operator (deleted). + */ IMouseListener & operator=(IMouseListener &&) = delete; /** - * \brief Handles a mouse click event. - * \param event The mouse click event to handle. - * \return True if the event was handled, false otherwise. - */ + * \brief Handles a mouse click event. + * \param event The mouse click event to handle. + * \return True if the event was handled, false otherwise. + */ virtual bool on_mouse_clicked(const MouseClickEvent & event) = 0; /** - * \brief Handles a mouse press event. - * \param event The mouse press event to handle. - * \return True if the event was handled, false otherwise. - */ + * \brief Handles a mouse press event. + * \param event The mouse press event to handle. + * \return True if the event was handled, false otherwise. + */ virtual bool on_mouse_pressed(const MousePressEvent & event) = 0; /** - * \brief Handles a mouse release event. - * \param event The mouse release event to handle. - * \return True if the event was handled, false otherwise. - */ + * \brief Handles a mouse release event. + * \param event The mouse release event to handle. + * \return True if the event was handled, false otherwise. + */ virtual bool on_mouse_released(const MouseReleaseEvent & event) = 0; /** - * \brief Handles a mouse move event. - * \param event The mouse move event to handle. - * \return True if the event was handled, false otherwise. - */ + * \brief Handles a mouse move event. + * \param event The mouse move event to handle. + * \return True if the event was handled, false otherwise. + */ virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; private: diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h index 9e173e0..fcfc080 100644 --- a/src/crepe/api/KeyCodes.h +++ b/src/crepe/api/KeyCodes.h @@ -1,5 +1,5 @@ #pragma once - +namespace crepe { //! Enumeration for mouse button inputs, including standard and extended buttons. enum class MouseButton { NONE = 0, //!< No mouse button input. @@ -85,9 +85,9 @@ enum class Keycode { PRINT_SCREEN = 283, //!< Print Screen key. PAUSE = 284, //!< Pause key. /** - * \name Function keys (F1-F25). - * \{ - */ + * \name Function keys (F1-F25). + * \{ + */ F1 = 290, F2 = 291, F3 = 292, @@ -115,9 +115,9 @@ enum class Keycode { F25 = 314, /// \} /** - * \name Keypad digits and operators. - * \{ - */ + * \name Keypad digits and operators. + * \{ + */ KP0 = 320, KP1 = 321, KP2 = 322, @@ -137,9 +137,9 @@ enum class Keycode { KP_EQUAL = 336, /// \} /** - * \name Modifier keys. - * \{ - */ + * \name Modifier keys. + * \{ + */ LEFT_SHIFT = 340, LEFT_CONTROL = 341, LEFT_ALT = 342, @@ -151,3 +151,4 @@ enum class Keycode { /// \} MENU = 348, //!< Menu key. }; +} // namespace crepe diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 51d9122..3e9a88e 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,30 +1,30 @@ -#include "../facade/SDLContext.h" - #include "../system/AnimatorSystem.h" #include "../system/CollisionSystem.h" +#include "../system/InputSystem.h" #include "../system/ParticleSystem.h" #include "../system/PhysicsSystem.h" #include "../system/RenderSystem.h" #include "../system/ScriptSystem.h" #include "LoopManager.h" -#include "LoopTimer.h" using namespace crepe; using namespace std; LoopManager::LoopManager() { + this->mediator.component_manager = this->component_manager; + this->mediator.scene_manager = this->scene_manager; + this->load_system<AnimatorSystem>(); this->load_system<CollisionSystem>(); this->load_system<ParticleSystem>(); this->load_system<PhysicsSystem>(); this->load_system<RenderSystem>(); this->load_system<ScriptSystem>(); + this->load_system<InputSystem>(); } -void LoopManager::process_input() { - SDLContext::get_instance().handle_events(this->game_running); -} +void LoopManager::process_input() { this->get_system<InputSystem>().update(); } void LoopManager::start() { this->setup(); @@ -35,7 +35,7 @@ void LoopManager::set_running(bool running) { this->game_running = running; } void LoopManager::fixed_update() {} void LoopManager::loop() { - LoopTimer & timer = LoopTimer::get_instance(); + LoopTimer & timer = this->loop_timer; timer.start(); while (game_running) { @@ -55,19 +55,18 @@ void LoopManager::loop() { } void LoopManager::setup() { + LoopTimer & timer = this->loop_timer; + this->game_running = true; - LoopTimer::get_instance().start(); - LoopTimer::get_instance().set_fps(200); + timer.start(); + timer.set_fps(200); this->scene_manager.load_next_scene(); } void LoopManager::render() { - if (this->game_running) { - this->get_system<RenderSystem>().update(); - } -} + if (!this->game_running) return; -void LoopManager::update() { - LoopTimer & timer = LoopTimer::get_instance(); - this->get_system<AnimatorSystem>().update(); + this->get_system<RenderSystem>().update(); } + +void LoopManager::update() {} diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 13e6dac..d8910a0 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -2,9 +2,12 @@ #include <memory> -#include "../ComponentManager.h" +#include "../facade/SDLContext.h" +#include "../manager/ComponentManager.h" +#include "../manager/SceneManager.h" #include "../system/System.h" -#include "api/SceneManager.h" + +#include "LoopTimer.h" namespace crepe { @@ -85,10 +88,18 @@ private: bool game_running = false; private: + //! Global context + Mediator mediator; + //! Component manager instance - ComponentManager component_manager{}; + ComponentManager component_manager{mediator}; //! Scene manager instance - SceneManager scene_manager{component_manager}; + SceneManager scene_manager{mediator}; + + //! SDL context \todo no more singletons! + SDLContext & sdl_context = SDLContext::get_instance(); + //! Loop timer \todo no more singletons! + LoopTimer & loop_timer = LoopTimer::get_instance(); private: /** diff --git a/src/crepe/api/LoopManager.hpp b/src/crepe/api/LoopManager.hpp index 9cf470b..266758a 100644 --- a/src/crepe/api/LoopManager.hpp +++ b/src/crepe/api/LoopManager.hpp @@ -38,8 +38,11 @@ void LoopManager::load_system() { static_assert(is_base_of<System, T>::value, "load_system must recieve a derivative class of System"); - System * system = new T(this->component_manager); - this->systems[typeid(T)] = unique_ptr<System>(system); + const type_info & type = typeid(T); + if (this->systems.contains(type)) + throw runtime_error(format("LoopManager: {} is already initialized", type.name())); + System * system = new T(this->mediator); + this->systems[type] = unique_ptr<System>(system); } } // namespace crepe diff --git a/src/crepe/api/Scene.h b/src/crepe/api/Scene.h index f6fdb2a..9f1e8ce 100644 --- a/src/crepe/api/Scene.h +++ b/src/crepe/api/Scene.h @@ -2,6 +2,7 @@ #include <string> +#include "../manager/Mediator.h" #include "../util/OptionalRef.h" namespace crepe { @@ -34,6 +35,9 @@ public: */ virtual std::string get_name() const = 0; + // 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 @@ -46,8 +50,8 @@ protected: * * \{ */ - //! Reference to the ComponentManager - OptionalRef<ComponentManager> component_manager; + //! Mediator reference + OptionalRef<Mediator> mediator; //! \} }; diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp index fcbe4c7..4091fd4 100644 --- a/src/crepe/api/Script.cpp +++ b/src/crepe/api/Script.cpp @@ -1,11 +1,17 @@ +#include <string> + +#include "../manager/SceneManager.h" + #include "Script.h" using namespace crepe; +using namespace std; Script::~Script() { - EventManager & evmgr = this->event_manager; + Mediator & mediator = this->mediator; + EventManager & mgr = mediator.event_manager; for (auto id : this->listeners) { - evmgr.unsubscribe(id); + mgr.unsubscribe(id); } } @@ -13,3 +19,9 @@ template <> void Script::subscribe(const EventHandler<CollisionEvent> & callback) { this->subscribe_internal(callback, this->game_object_id); } + +void Script::set_next_scene(const string & name) { + Mediator & mediator = this->mediator; + 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 a0870cb..1b339b0 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -2,11 +2,11 @@ #include <vector> +#include "../manager/EventManager.h" +#include "../manager/Mediator.h" #include "../types.h" #include "../util/OptionalRef.h" -#include "EventManager.h" - namespace crepe { class ScriptSystem; @@ -106,6 +106,12 @@ protected: template <typename EventType> void subscribe(const EventHandler<EventType> & callback); + /** + * \brief Set the next scene using SceneManager + * \see SceneManager::set_next_scene + */ + void set_next_scene(const std::string & name); + //! \} private: @@ -160,10 +166,8 @@ private: game_object_id_t game_object_id; //! Reference to parent component OptionalRef<bool> active; - //! Reference to component manager instance - OptionalRef<ComponentManager> component_manager; - //! Reference to event manager instance - OptionalRef<EventManager> event_manager; + //! Mediator reference + OptionalRef<Mediator> mediator; //! \} private: diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index a2463bf..45f1ff1 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -1,6 +1,6 @@ #pragma once -#include "../ComponentManager.h" +#include "../manager/ComponentManager.h" #include "BehaviorScript.h" #include "Script.h" @@ -20,7 +20,8 @@ T & Script::get_component() const { template <typename T> RefVector<T> Script::get_components() const { - ComponentManager & mgr = this->component_manager; + Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; return mgr.get_components_by_id<T>(this->game_object_id); } @@ -33,7 +34,8 @@ void Script::logf(Args &&... args) { template <typename EventType> void Script::subscribe_internal(const EventHandler<EventType> & callback, event_channel_t channel) { - EventManager & mgr = this->event_manager; + Mediator & mediator = this->mediator; + EventManager & mgr = mediator.event_manager; subscription_t listener = mgr.subscribe<EventType>( [this, callback](const EventType & data) -> bool { bool & active = this->active; diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp index 3a1acac..b52a344 100644 --- a/src/crepe/api/Sprite.cpp +++ b/src/crepe/api/Sprite.cpp @@ -18,8 +18,8 @@ Sprite::Sprite(game_object_id_t id, Texture & texture, const Sprite::Data & ctx) dbg_trace(); - this->mask.w = this->texture.get_width(); - this->mask.h = this->texture.get_height(); + this->mask.w = this->texture.get_size().x; + this->mask.h = this->texture.get_size().y; this->aspect_ratio = static_cast<double>(this->mask.w) / this->mask.h; } diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp index e43bdaa..2b56271 100644 --- a/src/crepe/api/Texture.cpp +++ b/src/crepe/api/Texture.cpp @@ -3,6 +3,7 @@ #include "Asset.h" #include "Texture.h" +#include "types.h" using namespace crepe; using namespace std; @@ -31,11 +32,7 @@ void Texture::load(const Asset & res) { this->texture = ctx.texture_from_path(res.get_path()); } -int Texture::get_width() const { - if (this->texture == nullptr) return 0; - return SDLContext::get_instance().get_width(*this); -} -int Texture::get_height() const { - if (this->texture == nullptr) return 0; - return SDLContext::get_instance().get_height(*this); +ivec2 Texture::get_size() const { + if (this->texture == nullptr) return {}; + return SDLContext::get_instance().get_size(*this); } diff --git a/src/crepe/api/Texture.h b/src/crepe/api/Texture.h index 7206a66..1817910 100644 --- a/src/crepe/api/Texture.h +++ b/src/crepe/api/Texture.h @@ -8,6 +8,7 @@ #include <memory> #include "Asset.h" +#include "types.h" namespace crepe { @@ -42,16 +43,10 @@ public: Texture & operator=(const Texture &) = delete; /** - * \brief Gets the width of the texture. - * \return Width of the texture in pixels. + * \brief Gets the width and height of the texture. + * \return Width and height of the texture in pixels. */ - int get_width() const; - - /** - * \brief Gets the height of the texture. - * \return Height of the texture in pixels. - */ - int get_height() const; + ivec2 get_size() const; private: /** diff --git a/src/crepe/api/UIObject.cpp b/src/crepe/api/UIObject.cpp new file mode 100644 index 0000000..d239b89 --- /dev/null +++ b/src/crepe/api/UIObject.cpp @@ -0,0 +1,8 @@ +#include "UIObject.h" + +using namespace crepe; + +UIObject::UIObject(game_object_id_t id, const vec2 & dimensions, const vec2 & offset) + : Component(id), + dimensions(dimensions), + offset(offset) {} diff --git a/src/crepe/api/UIObject.h b/src/crepe/api/UIObject.h new file mode 100644 index 0000000..f7f4fba --- /dev/null +++ b/src/crepe/api/UIObject.h @@ -0,0 +1,25 @@ +#pragma once + +#include "../Component.h" + +namespace crepe { + +/** + * \brief Represents a UI object in the game, derived from the Component class. + */ +class UIObject : public Component { +public: + /** + * \brief Constructs a UiObject with the specified game object ID. + * \param id The unique ID of the game object associated with this UI object. + * \param dimensions width and height of the UIObject + * \param offset Offset relative to the GameObject Transform + */ + UIObject(game_object_id_t id, const vec2 & dimensions, const vec2 & offset); + //! Width and height of the UIObject + vec2 dimensions; + //! Position offset relative to this GameObjects Transform + vec2 offset; +}; + +} // namespace crepe diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 86969ed..72b4e42 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -1,13 +1,17 @@ #include <SDL2/SDL.h> +#include <SDL2/SDL_blendmode.h> #include <SDL2/SDL_image.h> #include <SDL2/SDL_keycode.h> #include <SDL2/SDL_rect.h> #include <SDL2/SDL_render.h> #include <SDL2/SDL_surface.h> #include <SDL2/SDL_video.h> +#include <array> #include <cmath> #include <cstddef> +#include <cstdint> #include <functional> +#include <iostream> #include <memory> #include <stdexcept> @@ -15,9 +19,11 @@ #include "../api/Config.h" #include "../api/Sprite.h" #include "../api/Texture.h" +#include "../manager/EventManager.h" #include "../util/Log.h" #include "SDLContext.h" +#include "api/Color.h" #include "types.h" using namespace crepe; @@ -72,25 +78,141 @@ SDLContext::~SDLContext() { IMG_Quit(); SDL_Quit(); } -void SDLContext::handle_events(bool & running) { - //TODO: wouter i need events - /* - SDL_Event event; - SDL_PollEvent(&event); - switch (event.type) { - case SDL_QUIT: - running = false; - break; - case SDL_KEYDOWN: - triggerEvent(KeyPressedEvent(getCustomKey(event.key.keysym.sym))); - break; - case SDL_MOUSEBUTTONDOWN: - int x, y; - SDL_GetMouseState(&x, &y); - triggerEvent(MousePressedEvent(x, y)); - break; + +Keycode SDLContext::sdl_to_keycode(SDL_Keycode sdl_key) { + static const std::array<Keycode, SDL_NUM_SCANCODES> LOOKUP_TABLE = [] { + std::array<Keycode, SDL_NUM_SCANCODES> table{}; + table.fill(Keycode::NONE); + + table[SDL_SCANCODE_SPACE] = Keycode::SPACE; + table[SDL_SCANCODE_APOSTROPHE] = Keycode::APOSTROPHE; + table[SDL_SCANCODE_COMMA] = Keycode::COMMA; + table[SDL_SCANCODE_MINUS] = Keycode::MINUS; + table[SDL_SCANCODE_PERIOD] = Keycode::PERIOD; + table[SDL_SCANCODE_SLASH] = Keycode::SLASH; + table[SDL_SCANCODE_0] = Keycode::D0; + table[SDL_SCANCODE_1] = Keycode::D1; + table[SDL_SCANCODE_2] = Keycode::D2; + table[SDL_SCANCODE_3] = Keycode::D3; + table[SDL_SCANCODE_4] = Keycode::D4; + table[SDL_SCANCODE_5] = Keycode::D5; + table[SDL_SCANCODE_6] = Keycode::D6; + table[SDL_SCANCODE_7] = Keycode::D7; + table[SDL_SCANCODE_8] = Keycode::D8; + table[SDL_SCANCODE_9] = Keycode::D9; + table[SDL_SCANCODE_SEMICOLON] = Keycode::SEMICOLON; + table[SDL_SCANCODE_EQUALS] = Keycode::EQUAL; + table[SDL_SCANCODE_A] = Keycode::A; + table[SDL_SCANCODE_B] = Keycode::B; + table[SDL_SCANCODE_C] = Keycode::C; + table[SDL_SCANCODE_D] = Keycode::D; + table[SDL_SCANCODE_E] = Keycode::E; + table[SDL_SCANCODE_F] = Keycode::F; + table[SDL_SCANCODE_G] = Keycode::G; + table[SDL_SCANCODE_H] = Keycode::H; + table[SDL_SCANCODE_I] = Keycode::I; + table[SDL_SCANCODE_J] = Keycode::J; + table[SDL_SCANCODE_K] = Keycode::K; + table[SDL_SCANCODE_L] = Keycode::L; + table[SDL_SCANCODE_M] = Keycode::M; + table[SDL_SCANCODE_N] = Keycode::N; + table[SDL_SCANCODE_O] = Keycode::O; + table[SDL_SCANCODE_P] = Keycode::P; + table[SDL_SCANCODE_Q] = Keycode::Q; + table[SDL_SCANCODE_R] = Keycode::R; + table[SDL_SCANCODE_S] = Keycode::S; + table[SDL_SCANCODE_T] = Keycode::T; + table[SDL_SCANCODE_U] = Keycode::U; + table[SDL_SCANCODE_V] = Keycode::V; + table[SDL_SCANCODE_W] = Keycode::W; + table[SDL_SCANCODE_X] = Keycode::X; + table[SDL_SCANCODE_Y] = Keycode::Y; + table[SDL_SCANCODE_Z] = Keycode::Z; + table[SDL_SCANCODE_LEFTBRACKET] = Keycode::LEFT_BRACKET; + table[SDL_SCANCODE_BACKSLASH] = Keycode::BACKSLASH; + table[SDL_SCANCODE_RIGHTBRACKET] = Keycode::RIGHT_BRACKET; + table[SDL_SCANCODE_GRAVE] = Keycode::GRAVE_ACCENT; + table[SDL_SCANCODE_ESCAPE] = Keycode::ESCAPE; + table[SDL_SCANCODE_RETURN] = Keycode::ENTER; + table[SDL_SCANCODE_TAB] = Keycode::TAB; + table[SDL_SCANCODE_BACKSPACE] = Keycode::BACKSPACE; + table[SDL_SCANCODE_INSERT] = Keycode::INSERT; + table[SDL_SCANCODE_DELETE] = Keycode::DELETE; + table[SDL_SCANCODE_RIGHT] = Keycode::RIGHT; + table[SDL_SCANCODE_LEFT] = Keycode::LEFT; + table[SDL_SCANCODE_DOWN] = Keycode::DOWN; + table[SDL_SCANCODE_UP] = Keycode::UP; + table[SDL_SCANCODE_PAGEUP] = Keycode::PAGE_UP; + table[SDL_SCANCODE_PAGEDOWN] = Keycode::PAGE_DOWN; + table[SDL_SCANCODE_HOME] = Keycode::HOME; + table[SDL_SCANCODE_END] = Keycode::END; + table[SDL_SCANCODE_CAPSLOCK] = Keycode::CAPS_LOCK; + table[SDL_SCANCODE_SCROLLLOCK] = Keycode::SCROLL_LOCK; + table[SDL_SCANCODE_NUMLOCKCLEAR] = Keycode::NUM_LOCK; + table[SDL_SCANCODE_PRINTSCREEN] = Keycode::PRINT_SCREEN; + table[SDL_SCANCODE_PAUSE] = Keycode::PAUSE; + table[SDL_SCANCODE_F1] = Keycode::F1; + table[SDL_SCANCODE_F2] = Keycode::F2; + table[SDL_SCANCODE_F3] = Keycode::F3; + table[SDL_SCANCODE_F4] = Keycode::F4; + table[SDL_SCANCODE_F5] = Keycode::F5; + table[SDL_SCANCODE_F6] = Keycode::F6; + table[SDL_SCANCODE_F7] = Keycode::F7; + table[SDL_SCANCODE_F8] = Keycode::F8; + table[SDL_SCANCODE_F9] = Keycode::F9; + table[SDL_SCANCODE_F10] = Keycode::F10; + table[SDL_SCANCODE_F11] = Keycode::F11; + table[SDL_SCANCODE_F12] = Keycode::F12; + table[SDL_SCANCODE_KP_0] = Keycode::KP0; + table[SDL_SCANCODE_KP_1] = Keycode::KP1; + table[SDL_SCANCODE_KP_2] = Keycode::KP2; + table[SDL_SCANCODE_KP_3] = Keycode::KP3; + table[SDL_SCANCODE_KP_4] = Keycode::KP4; + table[SDL_SCANCODE_KP_5] = Keycode::KP5; + table[SDL_SCANCODE_KP_6] = Keycode::KP6; + table[SDL_SCANCODE_KP_7] = Keycode::KP7; + table[SDL_SCANCODE_KP_8] = Keycode::KP8; + table[SDL_SCANCODE_KP_9] = Keycode::KP9; + table[SDL_SCANCODE_LSHIFT] = Keycode::LEFT_SHIFT; + table[SDL_SCANCODE_LCTRL] = Keycode::LEFT_CONTROL; + table[SDL_SCANCODE_LALT] = Keycode::LEFT_ALT; + table[SDL_SCANCODE_LGUI] = Keycode::LEFT_SUPER; + table[SDL_SCANCODE_RSHIFT] = Keycode::RIGHT_SHIFT; + table[SDL_SCANCODE_RCTRL] = Keycode::RIGHT_CONTROL; + table[SDL_SCANCODE_RALT] = Keycode::RIGHT_ALT; + table[SDL_SCANCODE_RGUI] = Keycode::RIGHT_SUPER; + table[SDL_SCANCODE_MENU] = Keycode::MENU; + + return table; + }(); + + if (sdl_key < 0 || sdl_key >= SDL_NUM_SCANCODES) { + return Keycode::NONE; + } + + return LOOKUP_TABLE[sdl_key]; +} + +MouseButton SDLContext::sdl_to_mousebutton(Uint8 sdl_button) { + static const std::array<MouseButton, 5> MOUSE_BUTTON_LOOKUP_TABLE = [] { + std::array<MouseButton, 5> table{}; + table.fill(MouseButton::NONE); + + table[SDL_BUTTON_LEFT] = MouseButton::LEFT_MOUSE; + table[SDL_BUTTON_RIGHT] = MouseButton::RIGHT_MOUSE; + table[SDL_BUTTON_MIDDLE] = MouseButton::MIDDLE_MOUSE; + table[SDL_BUTTON_X1] = MouseButton::X1_MOUSE; + table[SDL_BUTTON_X2] = MouseButton::X2_MOUSE; + + return table; + }(); + + if (sdl_button >= MOUSE_BUTTON_LOOKUP_TABLE.size()) { + // Return NONE for invalid or unmapped button + return MouseButton::NONE; } - */ + + return MOUSE_BUTTON_LOOKUP_TABLE[sdl_button]; } void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer.get()); } @@ -151,6 +273,7 @@ void SDLContext::draw(const RenderContext & ctx) { double angle = ctx.angle + data.angle_offset; + this->set_color_texture(ctx.sprite.sprite_image, ctx.sprite.color); SDL_RenderCopyExF(this->game_renderer.get(), ctx.sprite.texture.texture.get(), &srcrect, &dstrect, angle, NULL, render_flip); } @@ -236,16 +359,79 @@ SDLContext::texture_from_path(const std::string & path) { std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> img_texture; img_texture = {tmp_texture, [](SDL_Texture * texture) { SDL_DestroyTexture(texture); }}; + SDL_SetTextureBlendMode(img_texture.get(), SDL_BLENDMODE_BLEND); return img_texture; } -int SDLContext::get_width(const Texture & ctx) const { - int w; - SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &w, NULL); - return w; -} -int SDLContext::get_height(const Texture & ctx) const { - int h; - SDL_QueryTexture(ctx.texture.get(), NULL, NULL, NULL, &h); - return h; + +ivec2 SDLContext::get_size(const Texture & ctx) { + ivec2 size; + SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &size.x, &size.y); + return size; } + void SDLContext::delay(int ms) const { SDL_Delay(ms); } + +std::vector<SDLContext::EventData> SDLContext::get_events() { + std::vector<SDLContext::EventData> event_list; + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::SHUTDOWN, + }); + break; + case SDL_KEYDOWN: + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::KEYDOWN, + .key = sdl_to_keycode(event.key.keysym.scancode), + .key_repeat = (event.key.repeat != 0), + }); + break; + case SDL_KEYUP: + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::KEYUP, + .key = sdl_to_keycode(event.key.keysym.scancode), + }); + break; + case SDL_MOUSEBUTTONDOWN: + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::MOUSEDOWN, + .mouse_button = sdl_to_mousebutton(event.button.button), + .mouse_position = {event.button.x, event.button.y}, + }); + break; + case SDL_MOUSEBUTTONUP: { + int x, y; + SDL_GetMouseState(&x, &y); + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::MOUSEUP, + .mouse_button = sdl_to_mousebutton(event.button.button), + .mouse_position = {event.button.x, event.button.y}, + }); + } break; + + case SDL_MOUSEMOTION: { + event_list.push_back( + EventData{.event_type = SDLContext::EventType::MOUSEMOVE, + .mouse_position = {event.motion.x, event.motion.y}, + .rel_mouse_move = {event.motion.xrel, event.motion.yrel}}); + } break; + + case SDL_MOUSEWHEEL: { + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::MOUSEWHEEL, + .mouse_position = {event.motion.x, event.motion.y}, + // TODO: why is this needed? + .scroll_direction = event.wheel.y < 0 ? -1 : 1, + .scroll_delta = event.wheel.preciseY, + }); + } break; + } + } + return event_list; +} +void SDLContext::set_color_texture(const Texture & texture, const Color & color) { + SDL_SetTextureColorMod(texture.texture.get(), color.r, color.g, color.b); + SDL_SetTextureAlphaMod(texture.texture.get(), color.a); +} diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index d662bee..dfdaa56 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -1,5 +1,6 @@ #pragma once +#include <SDL2/SDL.h> #include <SDL2/SDL_keycode.h> #include <SDL2/SDL_rect.h> #include <SDL2/SDL_render.h> @@ -8,18 +9,21 @@ #include <functional> #include <memory> #include <string> - -#include "../api/Camera.h" -#include "../api/Sprite.h" - +#include <utility> + +#include "api/Camera.h" +#include "api/Color.h" +#include "api/Event.h" +#include "api/KeyCodes.h" +#include "api/Sprite.h" +#include "api/Texture.h" +#include "api/Transform.h" #include "types.h" namespace crepe { -// TODO: SDL_Keycode is defined in a header not distributed with crepe, which means this -// typedef is unusable when crepe is packaged. Wouter will fix this later. -typedef SDL_Keycode CREPE_KEYCODES; - +class LoopManager; +class InputSystem; /** * \class SDLContext * \brief Facade for the SDL library @@ -46,6 +50,29 @@ public: }; public: + //! EventType enum for passing eventType + enum EventType { + NONE = 0, + MOUSEDOWN, + MOUSEUP, + MOUSEMOVE, + MOUSEWHEEL, + KEYUP, + KEYDOWN, + SHUTDOWN, + + }; + //! EventData struct for passing event data from facade + struct EventData { + SDLContext::EventType event_type = SDLContext::EventType::NONE; + Keycode key = Keycode::NONE; + bool key_repeat = false; + MouseButton mouse_button = MouseButton::NONE; + ivec2 mouse_position = {-1, -1}; + int scroll_direction = -1; + float scroll_delta = INFINITY; + ivec2 rel_mouse_move = {-1, -1}; + }; /** * \brief Gets the singleton instance of SDLContext. * \return Reference to the SDLContext instance. @@ -58,13 +85,40 @@ public: SDLContext & operator=(SDLContext &&) = delete; private: - //! will only use handle_events - friend class LoopManager; + //! will only use get_events + friend class InputSystem; /** - * \brief Handles SDL events such as window close and input. - * \param running Reference to a boolean flag that controls the main loop. + * \brief Retrieves a list of all events from the SDL context. + * + * This method retrieves all the events from the SDL context that are currently + * available. It is primarily used by the InputSystem to process various + * input events such as mouse clicks, mouse movements, and keyboard presses. + * + * \return Events that occurred since last call to `get_events()` */ - void handle_events(bool & running); + std::vector<SDLContext::EventData> get_events(); + + /** + * \brief Converts an SDL key code to the custom Keycode type. + * + * This method maps an SDL key code to the corresponding `Keycode` enum value, + * which is used internally by the system to identify the keys. + * + * \param sdl_key The SDL key code to convert. + * \return The corresponding `Keycode` value or `Keycode::NONE` if the key is unrecognized. + */ + Keycode sdl_to_keycode(SDL_Keycode sdl_key); + + /** + * \brief Converts an SDL mouse button code to the custom MouseButton type. + * + * This method maps an SDL mouse button code to the corresponding `MouseButton` + * enum value, which is used internally by the system to identify mouse buttons. + * + * \param sdl_button The SDL mouse button code to convert. + * \return The corresponding `MouseButton` value or `MouseButton::NONE` if the key is unrecognized + */ + MouseButton sdl_to_mousebutton(Uint8 sdl_button); private: //! Will only use delay @@ -109,18 +163,11 @@ private: std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> texture_from_path(const std::string & path); /** - * \brief Gets the width of a texture. + * \brief Gets the size of a texture. * \param texture Reference to the Texture object. - * \return Width of the texture as an integer. + * \return Width and height of the texture as an integer. */ - int get_width(const Texture & texture) const; - - /** - * \brief Gets the height of a texture. - * \param texture Reference to the Texture object. - * \return Height of the texture as an integer. - */ - int get_height(const Texture & texture) const; + ivec2 get_size(const Texture & ctx); private: //! Will use draw,clear_screen, present_screen, camera. @@ -170,6 +217,13 @@ private: * \return sdl rectangle to draw a dst image to draw on the screen */ SDL_FRect get_dst_rect(const DstRect & ctx) const; + /** + * \brief Set an additional color value multiplied into render copy operations. + * + * \param texture the given texture to adjust + * \param color the color data for the texture + */ + void set_color_texture(const Texture & texture, const Color & color); private: //! sdl Window 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/ComponentManager.cpp b/src/crepe/manager/ComponentManager.cpp index 5b73009..80cf8b4 100644 --- a/src/crepe/ComponentManager.cpp +++ b/src/crepe/manager/ComponentManager.cpp @@ -1,13 +1,16 @@ -#include "api/GameObject.h" -#include "util/Log.h" +#include "../api/GameObject.h" +#include "../types.h" +#include "../util/Log.h" #include "ComponentManager.h" -#include "types.h" using namespace crepe; using namespace std; -ComponentManager::ComponentManager() { dbg_trace(); } +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) { diff --git a/src/crepe/ComponentManager.h b/src/crepe/manager/ComponentManager.h index 480124f..ad37586 100644 --- a/src/crepe/ComponentManager.h +++ b/src/crepe/manager/ComponentManager.h @@ -5,8 +5,10 @@ #include <unordered_map> #include <vector> -#include "Component.h" -#include "types.h" +#include "../Component.h" +#include "../types.h" + +#include "Manager.h" namespace crepe { @@ -17,7 +19,7 @@ class GameObject; * * This class manages all components. It provides methods to add, delete and get components. */ -class ComponentManager { +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 @@ -26,7 +28,7 @@ class ComponentManager { friend class SceneManager; public: - ComponentManager(); // dbg_trace + ComponentManager(Mediator & mediator); ~ComponentManager(); // dbg_trace /** diff --git a/src/crepe/ComponentManager.hpp b/src/crepe/manager/ComponentManager.hpp index ffb38ec..ffb38ec 100644 --- a/src/crepe/ComponentManager.hpp +++ b/src/crepe/manager/ComponentManager.hpp diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/manager/EventManager.cpp index 20f0dd3..20f0dd3 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/manager/EventManager.cpp diff --git a/src/crepe/api/EventManager.h b/src/crepe/manager/EventManager.h index 1a33023..d634f54 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/manager/EventManager.h @@ -5,8 +5,8 @@ #include <unordered_map> #include <vector> -#include "Event.h" -#include "EventHandler.h" +#include "../api/Event.h" +#include "../api/EventHandler.h" namespace crepe { diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/manager/EventManager.hpp index a5f4556..a5f4556 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/manager/EventManager.hpp diff --git a/src/crepe/manager/Manager.cpp b/src/crepe/manager/Manager.cpp new file mode 100644 index 0000000..1182785 --- /dev/null +++ b/src/crepe/manager/Manager.cpp @@ -0,0 +1,5 @@ +#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..84d80fe --- /dev/null +++ b/src/crepe/manager/Manager.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Mediator.h" + +namespace crepe { + +/** + * \brief Base manager class + * + * Managers are used for various tasks that fall outside the ECS system category. All managers + * are required to register themselves to the mediator passed to the constructor, and this + * mutable reference is saved for convenience, even though not all managers use the mediator + * directly. + */ +class Manager { +public: + Manager(Mediator & mediator); + virtual ~Manager() = default; + +protected: + Mediator & mediator; +}; + +} // namespace crepe diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h new file mode 100644 index 0000000..71bd1c9 --- /dev/null +++ b/src/crepe/manager/Mediator.h @@ -0,0 +1,33 @@ +#pragma once + +#include "../util/OptionalRef.h" + +// TODO: remove these singletons: +#include "EventManager.h" +#include "SaveManager.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. + * + * \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<ComponentManager> component_manager; + OptionalRef<SceneManager> scene_manager; + OptionalRef<SaveManager> save_manager = SaveManager::get_instance(); + OptionalRef<EventManager> event_manager = EventManager::get_instance(); +}; + +} // namespace crepe diff --git a/src/crepe/api/SaveManager.cpp b/src/crepe/manager/SaveManager.cpp index c5f43ea..d4ed1c1 100644 --- a/src/crepe/api/SaveManager.cpp +++ b/src/crepe/manager/SaveManager.cpp @@ -1,9 +1,9 @@ +#include "../ValueBroker.h" +#include "../api/Config.h" #include "../facade/DB.h" #include "../util/Log.h" -#include "Config.h" #include "SaveManager.h" -#include "ValueBroker.h" using namespace std; using namespace crepe; diff --git a/src/crepe/api/SaveManager.h b/src/crepe/manager/SaveManager.h index 3d8c852..3d8c852 100644 --- a/src/crepe/api/SaveManager.h +++ b/src/crepe/manager/SaveManager.h diff --git a/src/crepe/api/SceneManager.cpp b/src/crepe/manager/SceneManager.cpp index 1f783ad..50a9fbb 100644 --- a/src/crepe/api/SceneManager.cpp +++ b/src/crepe/manager/SceneManager.cpp @@ -1,14 +1,15 @@ #include <algorithm> #include <memory> -#include "../ComponentManager.h" - +#include "ComponentManager.h" #include "SceneManager.h" using namespace crepe; using namespace std; -SceneManager::SceneManager(ComponentManager & mgr) : component_manager(mgr) {} +SceneManager::SceneManager(Mediator & mediator) : Manager(mediator) { + mediator.scene_manager = *this; +} void SceneManager::set_next_scene(const string & name) { next_scene = name; } @@ -26,7 +27,7 @@ void SceneManager::load_next_scene() { unique_ptr<Scene> & scene = *it; // Delete all components of the current scene - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; mgr.delete_all_components(); // Load the new scene diff --git a/src/crepe/api/SceneManager.h b/src/crepe/manager/SceneManager.h index f6f62cd..e0955c2 100644 --- a/src/crepe/api/SceneManager.h +++ b/src/crepe/manager/SceneManager.h @@ -3,7 +3,9 @@ #include <memory> #include <vector> -#include "Scene.h" +#include "../api/Scene.h" + +#include "Manager.h" namespace crepe { @@ -15,10 +17,9 @@ class ComponentManager; * This class manages scenes. It can add new scenes and load them. It also manages the current scene * and the next scene. */ -class SceneManager { +class SceneManager : public Manager { public: - //! \param mgr Reference to the ComponentManager - SceneManager(ComponentManager & mgr); + SceneManager(Mediator & mediator); public: /** @@ -44,8 +45,6 @@ private: std::vector<std::unique_ptr<Scene>> scenes; //! Next scene to load std::string next_scene; - //! Reference to the ComponentManager - ComponentManager & component_manager; }; } // namespace crepe diff --git a/src/crepe/api/SceneManager.hpp b/src/crepe/manager/SceneManager.hpp index 5c8e417..dff4e51 100644 --- a/src/crepe/api/SceneManager.hpp +++ b/src/crepe/manager/SceneManager.hpp @@ -12,7 +12,7 @@ void SceneManager::add_scene(Args &&... args) { Scene * scene = new T(std::forward<Args>(args)...); unique_ptr<Scene> unique_scene(scene); - unique_scene->component_manager = this->component_manager; + unique_scene->mediator = this->mediator; this->scenes.emplace_back(std::move(unique_scene)); diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index a2ae529..9aede7f 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -1,14 +1,15 @@ -#include "api/Animator.h" +#include "../api/Animator.h" +#include "../facade/SDLContext.h" +#include "../manager/ComponentManager.h" #include "AnimatorSystem.h" -#include "ComponentManager.h" using namespace crepe; void AnimatorSystem::update() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<Animator> animations = mgr.get_components_by_type<Animator>(); diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt index d658b25..95f6e33 100644 --- a/src/crepe/system/CMakeLists.txt +++ b/src/crepe/system/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources(crepe PUBLIC CollisionSystem.cpp RenderSystem.cpp AnimatorSystem.cpp + InputSystem.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -15,4 +16,5 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES CollisionSystem.h RenderSystem.h AnimatorSystem.h + InputSystem.h ) diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp new file mode 100644 index 0000000..7cc8d30 --- /dev/null +++ b/src/crepe/system/InputSystem.cpp @@ -0,0 +1,187 @@ +#include "../api/Button.h" +#include "../manager/ComponentManager.h" +#include "../manager/EventManager.h" + +#include "InputSystem.h" + +using namespace crepe; + +void InputSystem::update() { + ComponentManager & mgr = this->mediator.component_manager; + EventManager & event_mgr = this->mediator.event_manager; + std::vector<SDLContext::EventData> event_list = SDLContext::get_instance().get_events(); + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + RefVector<Camera> cameras = mgr.get_components_by_type<Camera>(); + OptionalRef<Camera> curr_cam_ref; + // Find the active camera + for (Camera & cam : cameras) { + if (!cam.active) continue; + curr_cam_ref = cam; + break; + } + if (!curr_cam_ref) return; + Camera & current_cam = curr_cam_ref; + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(current_cam.game_object_id); + Transform & cam_transform = transform_vec.front().get(); + int camera_origin_x + = cam_transform.position.x + current_cam.offset.x - (current_cam.viewport_size.x / 2); + int camera_origin_y + = cam_transform.position.y + current_cam.offset.y - (current_cam.viewport_size.y / 2); + + for (const SDLContext::EventData & event : event_list) { + int world_mouse_x = event.mouse_position.x + camera_origin_x; + int world_mouse_y = event.mouse_position.y + camera_origin_y; + // check if the mouse is within the viewport + bool mouse_in_viewport + = !(world_mouse_x < camera_origin_x + || world_mouse_x > camera_origin_x + current_cam.viewport_size.x + || world_mouse_y < camera_origin_y + || world_mouse_y > camera_origin_y + current_cam.viewport_size.y); + + switch (event.event_type) { + case SDLContext::EventType::KEYDOWN: + event_mgr.queue_event<KeyPressEvent>(KeyPressEvent{ + .repeat = event.key_repeat, + .key = event.key, + }); + break; + case SDLContext::EventType::KEYUP: + event_mgr.queue_event<KeyReleaseEvent>(KeyReleaseEvent{ + .key = event.key, + }); + break; + case SDLContext::EventType::MOUSEDOWN: + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MousePressEvent>(MousePressEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + this->last_mouse_down_position = {world_mouse_x, world_mouse_y}; + this->last_mouse_button = event.mouse_button; + break; + case SDLContext::EventType::MOUSEUP: { + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MouseReleaseEvent>(MouseReleaseEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + //check if its a click by checking the last button down + int delta_x = world_mouse_x - this->last_mouse_down_position.x; + int delta_y = world_mouse_y - this->last_mouse_down_position.y; + + if (this->last_mouse_button == event.mouse_button + && std::abs(delta_x) <= click_tolerance + && std::abs(delta_y) <= click_tolerance) { + event_mgr.queue_event<MouseClickEvent>(MouseClickEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + + this->handle_click(event.mouse_button, world_mouse_x, world_mouse_y); + } + } break; + case SDLContext::EventType::MOUSEMOVE: + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MouseMoveEvent>(MouseMoveEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .delta_x = event.rel_mouse_move.x, + .delta_y = event.rel_mouse_move.y, + }); + this->handle_move(event, world_mouse_x, world_mouse_y); + break; + case SDLContext::EventType::MOUSEWHEEL: + event_mgr.queue_event<MouseScrollEvent>(MouseScrollEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .scroll_direction = event.scroll_direction, + .scroll_delta = event.scroll_delta, + }); + break; + case SDLContext::EventType::SHUTDOWN: + event_mgr.queue_event<ShutDownEvent>(ShutDownEvent{}); + break; + default: + break; + } + } +} +void InputSystem::handle_move(const SDLContext::EventData & event_data, + const int world_mouse_x, const int world_mouse_y) { + ComponentManager & mgr = this->mediator.component_manager; + + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + + for (Button & button : buttons) { + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(button.game_object_id); + Transform & transform(transform_vec.front().get()); + + bool was_hovering = button.hover; + if (button.active + && this->is_mouse_inside_button(world_mouse_x, world_mouse_y, button, transform)) { + button.hover = true; + if (!was_hovering && button.on_mouse_enter) { + button.on_mouse_enter(); + } + } else { + button.hover = false; + // Trigger the on_exit callback if the hover state just changed to false + if (was_hovering && button.on_mouse_exit) { + button.on_mouse_exit(); + } + } + } +} + +void InputSystem::handle_click(const MouseButton & mouse_button, const int world_mouse_x, + const int world_mouse_y) { + ComponentManager & mgr = this->mediator.component_manager; + + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + + for (Button & button : buttons) { + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(button.game_object_id); + Transform & transform = transform_vec.front().get(); + + if (button.active + && this->is_mouse_inside_button(world_mouse_x, world_mouse_y, button, transform)) { + this->handle_button_press(button); + } + } +} + +bool InputSystem::is_mouse_inside_button(const int mouse_x, const int mouse_y, + const Button & button, const Transform & transform) { + int actual_x = transform.position.x + button.offset.x; + int actual_y = transform.position.y + button.offset.y; + + int half_width = button.dimensions.x / 2; + int half_height = button.dimensions.y / 2; + + // Check if the mouse is within the button's boundaries + return mouse_x >= actual_x - half_width && mouse_x <= actual_x + half_width + && mouse_y >= actual_y - half_height && mouse_y <= actual_y + half_height; +} + +void InputSystem::handle_button_press(Button & button) { + if (button.is_toggle) { + if (!button.is_pressed && button.on_click) { + button.on_click(); + } + button.is_pressed = !button.is_pressed; + } else if (button.on_click) { + button.on_click(); + } +} diff --git a/src/crepe/system/InputSystem.h b/src/crepe/system/InputSystem.h new file mode 100644 index 0000000..87e86f8 --- /dev/null +++ b/src/crepe/system/InputSystem.h @@ -0,0 +1,85 @@ +#pragma once + +#include "../facade/SDLContext.h" +#include "../types.h" +#include "../util/OptionalRef.h" + +#include "System.h" + +namespace crepe { + +class Camera; +class Button; +class Transform; + +/** + * \brief Handles the processing of input events created by SDLContext + * + * This system processes events such as mouse clicks, mouse movement, and keyboard + * actions. It is responsible for detecting interactions with UI buttons and + * passing the corresponding events to the registered listeners. + */ +class InputSystem : public System { +public: + using System::System; + + /** + * \brief Updates the system, processing all input events. + * This method processes all events and triggers corresponding actions. + */ + void update() override; + +private: + //! Stores the last position of the mouse when the button was pressed. + ivec2 last_mouse_down_position; + // TODO: specify world/hud space and make regular `vec2` + + //! Stores the last mouse button pressed. + MouseButton last_mouse_button = MouseButton::NONE; + + //! The maximum allowable distance between mouse down and mouse up to register as a click. + const int click_tolerance = 5; + + /** + * \brief Handles the mouse click event. + * \param mouse_button The mouse button involved in the click. + * \param world_mouse_x The X coordinate of the mouse in world space. + * \param world_mouse_y The Y coordinate of the mouse in world space. + * + * This method processes the mouse click event and triggers the corresponding button action. + */ + void handle_click(const MouseButton & mouse_button, const int world_mouse_x, + const int world_mouse_y); + + /** + * \brief Handles the mouse movement event. + * \param event_data The event data containing information about the mouse movement. + * \param world_mouse_x The X coordinate of the mouse in world space. + * \param world_mouse_y The Y coordinate of the mouse in world space. + * + * This method processes the mouse movement event and updates the button hover state. + */ + void handle_move(const SDLContext::EventData & event_data, const int world_mouse_x, + const int world_mouse_y); + + /** + * \brief Checks if the mouse position is inside the bounds of the button. + * \param world_mouse_x The X coordinate of the mouse in world space. + * \param world_mouse_y The Y coordinate of the mouse in world space. + * \param button The button to check. + * \param transform The transform component of the button. + * \return True if the mouse is inside the button, false otherwise. + */ + bool is_mouse_inside_button(const int world_mouse_x, const int world_mouse_y, + const Button & button, const Transform & transform); + + /** + * \brief Handles the button press event, calling the on_click callback if necessary. + * \param button The button being pressed. + * + * This method triggers the on_click action for the button when it is pressed. + */ + void handle_button_press(Button & button); +}; + +} // namespace crepe diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp index 0e62a57..b14c52f 100644 --- a/src/crepe/system/ParticleSystem.cpp +++ b/src/crepe/system/ParticleSystem.cpp @@ -2,17 +2,17 @@ #include <cstdlib> #include <ctime> -#include "api/ParticleEmitter.h" -#include "api/Transform.h" +#include "../api/ParticleEmitter.h" +#include "../api/Transform.h" +#include "../manager/ComponentManager.h" -#include "ComponentManager.h" #include "ParticleSystem.h" using namespace crepe; void ParticleSystem::update() { // Get all emitters - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<ParticleEmitter> emitters = mgr.get_components_by_type<ParticleEmitter>(); for (ParticleEmitter & emitter : emitters) { diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index 514a4b3..bebcf3d 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -1,17 +1,17 @@ #include <cmath> -#include "../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" using namespace crepe; void PhysicsSystem::update() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<Rigidbody> rigidbodies = mgr.get_components_by_type<Rigidbody>(); RefVector<Transform> transforms = mgr.get_components_by_type<Transform>(); diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 4c618d8..111ad7d 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -5,12 +5,12 @@ #include <stdexcept> #include <vector> -#include "../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" @@ -22,7 +22,7 @@ void RenderSystem::clear_screen() { this->context.clear_screen(); } void RenderSystem::present_screen() { this->context.present_screen(); } SDLContext::CameraValues RenderSystem::update_camera() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<Camera> cameras = mgr.get_components_by_type<Camera>(); @@ -63,7 +63,7 @@ void RenderSystem::update() { bool RenderSystem::render_particle(const Sprite & sprite, const SDLContext::CameraValues & cam, const double & scale) { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; vector<reference_wrapper<ParticleEmitter>> emitters = mgr.get_components_by_id<ParticleEmitter>(sprite.game_object_id); @@ -71,7 +71,7 @@ bool RenderSystem::render_particle(const Sprite & sprite, const SDLContext::Came bool rendering_particles = false; for (const ParticleEmitter & em : emitters) { - if (!(&em.data.sprite == &sprite)) continue; + if (&em.data.sprite != &sprite) continue; rendering_particles = true; if (!em.active) continue; @@ -101,7 +101,7 @@ void RenderSystem::render_normal(const Sprite & sprite, const SDLContext::Camera } void RenderSystem::render() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; const SDLContext::CameraValues & cam = this->update_camera(); RefVector<Sprite> sprites = mgr.get_components_by_type<Sprite>(); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 9c306c5..eaf1213 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -46,7 +46,10 @@ private: * \brief Renders all the particles on the screen from a given sprite. * * \param sprite renders the particles with given texture - * \param tm the Transform component for scale + * \param tm the Transform component for scale. This is not a const reference because each + * particle has a position and rotation that needs to overwrite the transform position and + * rotation without overwriting the current transform. and because the transform + * constructor is now protected i cannot make tmp inside * \return true if particles have been rendered */ bool render_particle(const Sprite & sprite, const SDLContext::CameraValues & cam, @@ -70,13 +73,13 @@ private: RefVector<Sprite> sort(RefVector<Sprite> & objs) const; /** - * \todo Include color handling for sprites. * \todo Add text rendering using SDL_ttf for text components. * \todo Implement a text component and a button component. * \todo Consider adding text input functionality. */ private: + // FIXME: retrieve sdlcontext via mediator after #PR57 SDLContext & context = SDLContext::get_instance(); }; diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index 20a83f7..d6b2ca1 100644 --- a/src/crepe/system/ScriptSystem.cpp +++ b/src/crepe/system/ScriptSystem.cpp @@ -1,6 +1,6 @@ -#include "../ComponentManager.h" #include "../api/BehaviorScript.h" #include "../api/Script.h" +#include "../manager/ComponentManager.h" #include "ScriptSystem.h" @@ -10,7 +10,7 @@ using namespace crepe; void ScriptSystem::update() { dbg_trace(); - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<BehaviorScript> behavior_scripts = mgr.get_components_by_type<BehaviorScript>(); for (BehaviorScript & behavior_script : behavior_scripts) { diff --git a/src/crepe/system/System.cpp b/src/crepe/system/System.cpp index 937a423..f68549b 100644 --- a/src/crepe/system/System.cpp +++ b/src/crepe/system/System.cpp @@ -4,4 +4,4 @@ using namespace crepe; -System::System(ComponentManager & mgr) : component_manager(mgr) { 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 28ea20e..063dfbf 100644 --- a/src/crepe/system/System.h +++ b/src/crepe/system/System.h @@ -1,5 +1,7 @@ #pragma once +#include "../manager/Mediator.h" + namespace crepe { class ComponentManager; @@ -7,9 +9,8 @@ class ComponentManager; /** * \brief Base ECS system class * - * This class is used as the base for all system classes. Classes derived from - * System must implement the System::update() method and copy Script::Script - * with the `using`-syntax. + * This class is used as the base for all system classes. Classes derived from System must + * implement the System::update() method and copy Script::Script with the `using`-syntax. */ class System { public: @@ -19,11 +20,11 @@ public: virtual void update() = 0; public: - System(ComponentManager &); + System(const Mediator & m); virtual ~System() = default; protected: - ComponentManager & component_manager; + const Mediator & mediator; }; } // namespace crepe |