diff options
Diffstat (limited to 'src/crepe/api')
28 files changed, 179 insertions, 811 deletions
diff --git a/src/crepe/api/AssetManager.cpp b/src/crepe/api/AssetManager.cpp deleted file mode 100644 index 3925758..0000000 --- a/src/crepe/api/AssetManager.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "util/Log.h" - -#include "AssetManager.h" - -using namespace crepe; - -AssetManager & AssetManager::get_instance() { - static AssetManager instance; - return instance; -} - -AssetManager::~AssetManager() { - dbg_trace(); - this->asset_cache.clear(); -} - -AssetManager::AssetManager() { dbg_trace(); } diff --git a/src/crepe/api/AssetManager.h b/src/crepe/api/AssetManager.h deleted file mode 100644 index fee6780..0000000 --- a/src/crepe/api/AssetManager.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include <any> -#include <memory> -#include <string> -#include <unordered_map> - -namespace crepe { - -/** - * \brief The AssetManager is responsible for storing and managing assets over multiple scenes. - * - * The AssetManager ensures that assets are loaded once and can be accessed across different - * scenes. It caches assets to avoid reloading them every time a scene is loaded. Assets are - * retained in memory until the AssetManager is destroyed, at which point the cached assets are - * cleared. - */ -class AssetManager { - -private: - //! A cache that holds all the assets, accessible by their file path, over multiple scenes. - std::unordered_map<std::string, std::any> asset_cache; - -private: - AssetManager(); - virtual ~AssetManager(); - -public: - AssetManager(const AssetManager &) = delete; - AssetManager(AssetManager &&) = delete; - AssetManager & operator=(const AssetManager &) = delete; - AssetManager & operator=(AssetManager &&) = delete; - - /** - * \brief Retrieves the singleton instance of the AssetManager. - * - * \return A reference to the single instance of the AssetManager. - */ - static AssetManager & get_instance(); - -public: - /** - * \brief Caches an asset by loading it from the given file path. - * - * \param file_path The path to the asset file to load. - * \param reload If true, the asset will be reloaded from the file, even if it is already - * cached. - * \tparam T The type of asset to cache (e.g., texture, sound, etc.). - * - * \return A shared pointer to the cached asset. - * - * This template function caches the asset at the given file path. If the asset is already - * cached and `reload` is false, the existing cached version will be returned. Otherwise, the - * asset will be reloaded and added to the cache. - */ - template <typename T> - std::shared_ptr<T> cache(const std::string & file_path, bool reload = false); -}; - -} // namespace crepe - -#include "AssetManager.hpp" diff --git a/src/crepe/api/AssetManager.hpp b/src/crepe/api/AssetManager.hpp deleted file mode 100644 index 1c0e978..0000000 --- a/src/crepe/api/AssetManager.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "AssetManager.h" - -namespace crepe { - -template <typename asset> -std::shared_ptr<asset> AssetManager::cache(const std::string & file_path, bool reload) { - auto it = asset_cache.find(file_path); - - if (!reload && it != asset_cache.end()) { - return std::any_cast<std::shared_ptr<asset>>(it->second); - } - - std::shared_ptr<asset> new_asset = std::make_shared<asset>(file_path.c_str()); - - asset_cache[file_path] = new_asset; - - return new_asset; -} - -} // namespace crepe diff --git a/src/crepe/api/AudioSource.cpp b/src/crepe/api/AudioSource.cpp new file mode 100644 index 0000000..cc70801 --- /dev/null +++ b/src/crepe/api/AudioSource.cpp @@ -0,0 +1,19 @@ +#include "AudioSource.h" + +using namespace crepe; +using namespace std; + +AudioSource::AudioSource(game_object_id_t id, const Asset & src) : + Component(id), + source(src) +{ } + +void AudioSource::play(bool looping) { + this->loop = looping; + this->oneshot_play = true; +} + +void AudioSource::stop() { + this->oneshot_stop = true; +} + diff --git a/src/crepe/api/AudioSource.h b/src/crepe/api/AudioSource.h new file mode 100644 index 0000000..1899c22 --- /dev/null +++ b/src/crepe/api/AudioSource.h @@ -0,0 +1,65 @@ +#pragma once + +#include "../Component.h" +#include "../types.h" +#include "../util/Private.h" + +#include "GameObject.h" +#include "Asset.h" + +namespace crepe { + +class AudioSystem; + +//! Audio source component +class AudioSource : public Component { + //! AudioSource components are handled by AudioSystem + friend class AudioSystem; + +protected: + AudioSource(game_object_id_t id, const Asset & source); + //! Only ComponentManager can create components + friend class ComponentManager; +public: + // But std::unique_ptr needs to be able to destoy this component again + virtual ~AudioSource() = default; + +public: + //! Start or resume this audio source + void play(bool looping = false); + //! Stop this audio source + void stop(); + +public: + //! Play when this component becomes active + bool play_on_awake = false; + //! Repeat the current audio clip during playback + bool loop = false; + //! Normalized volume (0.0 - 1.0) + float volume = 1.0; + +private: + //! This audio source's clip + const Asset source; + + /** + * \name One-shot state variables + * + * These variables trigger function calls when set to true, and are unconditionally reset on + * every system update. + * + * \{ + */ + //! Play this sample + bool oneshot_play = false; + //! Stop this sample + bool oneshot_stop = false; + //! \} + +private: + //! AudioSystem::ComponentPrivate + Private private_data; +}; + +} // namespace crepe + 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..6de0157 100644 --- a/src/crepe/api/BehaviorScript.hpp +++ b/src/crepe/api/BehaviorScript.hpp @@ -14,11 +14,11 @@ 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)...); + Mediator & mediator = this->mediator; s->game_object_id = this->game_object_id; s->active = this->active; - s->component_manager = this->component_manager; - s->event_manager = EventManager::get_instance(); + s->mediator = mediator; this->script = std::unique_ptr<Script>(s); return *this; diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 50c51ed..0808612 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -1,5 +1,5 @@ target_sources(crepe PUBLIC - # AudioSource.cpp + AudioSource.cpp BehaviorScript.cpp GameObject.cpp Rigidbody.cpp @@ -7,15 +7,11 @@ target_sources(crepe PUBLIC Transform.cpp Color.cpp 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 @@ -26,7 +22,7 @@ target_sources(crepe PUBLIC ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES - # AudioSource.h + AudioSource.h BehaviorScript.h Config.h Script.h @@ -39,17 +35,10 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Vector2.hpp Color.h 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 diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 225e9b9..7be506e 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -1,8 +1,10 @@ #pragma once +#include <string> + #include "../util/Log.h" + #include "types.h" -#include <string> namespace crepe { @@ -13,20 +15,10 @@ namespace crepe { * modified *before* execution is handed over from the game programmer to the engine (i.e. the * main loop is started). */ -class Config final { -public: +struct Config final { //! Retrieve handle to global Config instance static Config & get_instance(); -private: - Config() = default; - ~Config() = default; - Config(const Config &) = default; - Config(Config &&) = default; - Config & operator=(const Config &) = default; - Config & operator=(Config &&) = default; - -public: //! Logging-related settings struct { /** @@ -85,6 +77,12 @@ public: */ std::string root_pattern = ".crepe-root"; } asset; + + //! Audio system settings + struct { + //! Max amount of simultanious voices + unsigned int voices = 32; + } audio; }; } // namespace crepe diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp deleted file mode 100644 index 20f0dd3..0000000 --- a/src/crepe/api/EventManager.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "EventManager.h" - -using namespace crepe; -using namespace std; - -EventManager & EventManager::get_instance() { - static EventManager instance; - return instance; -} - -void EventManager::dispatch_events() { - for (auto & event : this->events_queue) { - this->handle_event(event.type, event.channel, *event.event.get()); - } - this->events_queue.clear(); -} - -void EventManager::handle_event(type_index type, event_channel_t channel, const Event & data) { - auto handlers_it = this->subscribers.find(type); - if (handlers_it == this->subscribers.end()) return; - - vector<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(); -} - -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 deleted file mode 100644 index 1a33023..0000000 --- a/src/crepe/api/EventManager.h +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -#include <memory> -#include <typeindex> -#include <unordered_map> -#include <vector> - -#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 Manages event subscriptions, triggers, and queues, enabling decoupled event handling. - * - * The `EventManager` acts as a centralized event system. It allows for registering callbacks - * for specific event types, triggering events synchronously, queueing events for later - * processing, and managing subscriptions via unique identifiers. - */ -class EventManager { -public: - static constexpr const event_channel_t CHANNEL_ALL = -1; - - /** - * \brief Get the singleton instance of the EventManager. - * - * This method returns the unique instance of the EventManager, creating it if it - * doesn't already exist. Ensures only one instance is active in the program. - * - * \return Reference to the singleton instance of the EventManager. - */ - static EventManager & get_instance(); - - /** - * \brief Subscribe to a specific event type. - * - * Registers a callback for a given event type and optional channel. Each callback - * is assigned a unique subscription ID that can be used for later unsubscription. - * - * \tparam EventType The type of the event to subscribe to. - * \param callback The callback function to be invoked when the event is triggered. - * \param channel The channel number to subscribe to (default is CHANNEL_ALL, which listens to all channels). - * \return A unique subscription ID associated with the registered callback. - */ - template <typename EventType> - subscription_t subscribe(const EventHandler<EventType> & callback, - event_channel_t channel = CHANNEL_ALL); - - /** - * \brief Unsubscribe a previously registered callback. - * - * Removes a callback from the subscription list based on its unique subscription ID. - * - * \param event_id The unique subscription ID of the callback to remove. - */ - void unsubscribe(subscription_t event_id); - - /** - * \brief Trigger an event immediately. - * - * Synchronously invokes all registered callbacks for the given event type on the specified channel. - * - * \tparam EventType The type of the event to trigger. - * \param event The event instance to pass to the callbacks. - * \param channel The channel to trigger the event on (default is CHANNEL_ALL, which triggers on all channels). - */ - template <typename EventType> - void trigger_event(const EventType & event = {}, event_channel_t channel = CHANNEL_ALL); - - /** - * \brief Queue an event for later processing. - * - * Adds an event to the event queue to be processed during the next call to `dispatch_events`. - * - * \tparam EventType The type of the event to queue. - * \param event The event instance to queue. - * \param channel The channel to associate with the event (default is CHANNEL_ALL). - */ - template <typename EventType> - void queue_event(const EventType & event = {}, event_channel_t channel = CHANNEL_ALL); - - /** - * \brief Process all queued events. - * - * Iterates through the event queue and triggers callbacks for each queued event. - * Events are removed from the queue once processed. - */ - void dispatch_events(); - - /** - * \brief Clear all subscriptions. - * - * Removes all registered event handlers and clears the subscription list. - */ - void clear(); - -private: - /** - * \brief Default constructor for the EventManager. - * - * Constructor is private to enforce the singleton pattern. - */ - EventManager() = default; - - /** - * \struct QueueEntry - * \brief Represents an entry in the event queue. - */ - struct QueueEntry { - std::unique_ptr<Event> 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 deleted file mode 100644 index a5f4556..0000000 --- a/src/crepe/api/EventManager.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "EventManager.h" - -namespace crepe { - -template <typename EventType> -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); - 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::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::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.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..6ded107 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 { diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 15e1619..9e4fdf7 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 { diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 7edf4d1..b277185 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,5 +1,3 @@ -#include "../facade/SDLContext.h" - #include "../system/AnimatorSystem.h" #include "../system/CollisionSystem.h" #include "../system/ParticleSystem.h" @@ -8,12 +6,14 @@ #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>(); @@ -23,7 +23,7 @@ LoopManager::LoopManager() { } void LoopManager::process_input() { - SDLContext::get_instance().handle_events(this->game_running); + this->sdl_context.handle_events(this->game_running); } void LoopManager::start() { @@ -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,15 +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); } void LoopManager::render() { - if (this->game_running) { - this->get_system<RenderSystem>().update(); - } + if (!this->game_running) return; + + this->get_system<RenderSystem>().update(); } -void LoopManager::update() { LoopTimer & timer = LoopTimer::get_instance(); } +void LoopManager::update() {} + diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 13e6dac..6ea5ccc 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -2,9 +2,12 @@ #include <memory> -#include "../ComponentManager.h" +#include "../manager/ComponentManager.h" +#include "../manager/SceneManager.h" #include "../system/System.h" -#include "api/SceneManager.h" +#include "../facade/SDLContext.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..cd6bd02 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); + System * system = new T(this->mediator); + const type_info & type = typeid(T); + if (this->systems.contains(type)) + throw runtime_error(format("LoopManager: {} is already initialized", type.name())); + this->systems[type] = unique_ptr<System>(system); } } // namespace crepe diff --git a/src/crepe/api/SaveManager.cpp b/src/crepe/api/SaveManager.cpp deleted file mode 100644 index c5f43ea..0000000 --- a/src/crepe/api/SaveManager.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "../facade/DB.h" -#include "../util/Log.h" - -#include "Config.h" -#include "SaveManager.h" -#include "ValueBroker.h" - -using namespace std; -using namespace crepe; - -template <> -string SaveManager::serialize(const string & value) const noexcept { - return value; -} -template <typename T> -string SaveManager::serialize(const T & value) const noexcept { - return to_string(value); -} -template string SaveManager::serialize(const uint8_t &) const noexcept; -template string SaveManager::serialize(const int8_t &) const noexcept; -template string SaveManager::serialize(const uint16_t &) const noexcept; -template string SaveManager::serialize(const int16_t &) const noexcept; -template string SaveManager::serialize(const uint32_t &) const noexcept; -template string SaveManager::serialize(const int32_t &) const noexcept; -template string SaveManager::serialize(const uint64_t &) const noexcept; -template string SaveManager::serialize(const int64_t &) const noexcept; -template string SaveManager::serialize(const float &) const noexcept; -template string SaveManager::serialize(const double &) const noexcept; - -template <> -uint64_t SaveManager::deserialize(const string & value) const noexcept { - try { - return stoul(value); - } catch (std::invalid_argument &) { - return 0; - } -} -template <> -int64_t SaveManager::deserialize(const string & value) const noexcept { - try { - return stol(value); - } catch (std::invalid_argument &) { - return 0; - } -} -template <> -float SaveManager::deserialize(const string & value) const noexcept { - try { - return stof(value); - } catch (std::invalid_argument &) { - return 0; - } - return stof(value); -} -template <> -double SaveManager::deserialize(const string & value) const noexcept { - try { - return stod(value); - } catch (std::invalid_argument &) { - return 0; - } -} -template <> -string SaveManager::deserialize(const string & value) const noexcept { - return value; -} - -template <> -uint8_t SaveManager::deserialize(const string & value) const noexcept { - return deserialize<uint64_t>(value); -} -template <> -int8_t SaveManager::deserialize(const string & value) const noexcept { - return deserialize<int64_t>(value); -} -template <> -uint16_t SaveManager::deserialize(const string & value) const noexcept { - return deserialize<uint64_t>(value); -} -template <> -int16_t SaveManager::deserialize(const string & value) const noexcept { - return deserialize<int64_t>(value); -} -template <> -uint32_t SaveManager::deserialize(const string & value) const noexcept { - return deserialize<uint64_t>(value); -} -template <> -int32_t SaveManager::deserialize(const string & value) const noexcept { - return deserialize<int64_t>(value); -} - -SaveManager::SaveManager() { dbg_trace(); } - -SaveManager & SaveManager::get_instance() { - dbg_trace(); - static SaveManager instance; - return instance; -} - -DB & SaveManager::get_db() { - Config & cfg = Config::get_instance(); - // TODO: make this path relative to XDG_DATA_HOME on Linux and whatever the - // default equivalent is on Windows using some third party library - static DB db(cfg.savemgr.location); - return db; -} - -bool SaveManager::has(const string & key) { - DB & db = this->get_db(); - return db.has(key); -} - -template <> -void SaveManager::set(const string & key, const string & value) { - DB & db = this->get_db(); - db.set(key, value); -} -template <typename T> -void SaveManager::set(const string & key, const T & value) { - DB & db = this->get_db(); - db.set(key, std::to_string(value)); -} -template void SaveManager::set(const string &, const uint8_t &); -template void SaveManager::set(const string &, const int8_t &); -template void SaveManager::set(const string &, const uint16_t &); -template void SaveManager::set(const string &, const int16_t &); -template void SaveManager::set(const string &, const uint32_t &); -template void SaveManager::set(const string &, const int32_t &); -template void SaveManager::set(const string &, const uint64_t &); -template void SaveManager::set(const string &, const int64_t &); -template void SaveManager::set(const string &, const float &); -template void SaveManager::set(const string &, const double &); - -template <typename T> -ValueBroker<T> SaveManager::get(const string & key, const T & default_value) { - if (!this->has(key)) this->set<T>(key, default_value); - return this->get<T>(key); -} -template ValueBroker<uint8_t> SaveManager::get(const string &, const uint8_t &); -template ValueBroker<int8_t> SaveManager::get(const string &, const int8_t &); -template ValueBroker<uint16_t> SaveManager::get(const string &, const uint16_t &); -template ValueBroker<int16_t> SaveManager::get(const string &, const int16_t &); -template ValueBroker<uint32_t> SaveManager::get(const string &, const uint32_t &); -template ValueBroker<int32_t> SaveManager::get(const string &, const int32_t &); -template ValueBroker<uint64_t> SaveManager::get(const string &, const uint64_t &); -template ValueBroker<int64_t> SaveManager::get(const string &, const int64_t &); -template ValueBroker<float> SaveManager::get(const string &, const float &); -template ValueBroker<double> SaveManager::get(const string &, const double &); -template ValueBroker<string> SaveManager::get(const string &, const string &); - -template <typename T> -ValueBroker<T> SaveManager::get(const string & key) { - T value; - return { - [this, key](const T & target) { this->set<T>(key, target); }, - [this, key, value]() mutable -> const T & { - value = this->deserialize<T>(this->get_db().get(key)); - return value; - }, - }; -} -template ValueBroker<uint8_t> SaveManager::get(const string &); -template ValueBroker<int8_t> SaveManager::get(const string &); -template ValueBroker<uint16_t> SaveManager::get(const string &); -template ValueBroker<int16_t> SaveManager::get(const string &); -template ValueBroker<uint32_t> SaveManager::get(const string &); -template ValueBroker<int32_t> SaveManager::get(const string &); -template ValueBroker<uint64_t> SaveManager::get(const string &); -template ValueBroker<int64_t> SaveManager::get(const string &); -template ValueBroker<float> SaveManager::get(const string &); -template ValueBroker<double> SaveManager::get(const string &); -template ValueBroker<string> SaveManager::get(const string &); diff --git a/src/crepe/api/SaveManager.h b/src/crepe/api/SaveManager.h deleted file mode 100644 index 3d8c852..0000000 --- a/src/crepe/api/SaveManager.h +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once - -#include <memory> - -#include "../ValueBroker.h" - -namespace crepe { - -class DB; - -/** - * \brief Save data manager - * - * This class provides access to a simple key-value store that stores - * - integers (8-64 bit, signed or unsigned) - * - real numbers (float or double) - * - string (std::string) - * - * The underlying database is a key-value store. - */ -class SaveManager { -public: - /** - * \brief Get a read/write reference to a value and initialize it if it does not yet exist - * - * \param key The value key - * \param default_value Value to initialize \c key with if it does not already exist in the - * database - * - * \return Read/write reference to the value - */ - template <typename T> - ValueBroker<T> get(const std::string & key, const T & default_value); - - /** - * \brief Get a read/write reference to a value - * - * \param key The value key - * - * \return Read/write reference to the value - * - * \note Attempting to read this value before it is initialized (i.e. set) will result in an - * exception - */ - template <typename T> - ValueBroker<T> get(const std::string & key); - - /** - * \brief Set a value directly - * - * \param key The value key - * \param value The value to store - */ - template <typename T> - void set(const std::string & key, const T & value); - - /** - * \brief Check if the save file has a value for this \c key - * - * \param key The value key - * - * \returns True if the key exists, or false if it does not - */ - bool has(const std::string & key); - -private: - SaveManager(); - virtual ~SaveManager() = default; - -private: - /** - * \brief Serialize an arbitrary value to STL string - * - * \tparam T Type of arbitrary value - * - * \returns String representation of value - */ - template <typename T> - std::string serialize(const T &) const noexcept; - - /** - * \brief Deserialize an STL string back to type \c T - * - * \tparam T Type of value - * \param value Serialized value - * - * \returns Deserialized value - */ - template <typename T> - T deserialize(const std::string & value) const noexcept; - -public: - // singleton - static SaveManager & get_instance(); - SaveManager(const SaveManager &) = delete; - SaveManager(SaveManager &&) = delete; - SaveManager & operator=(const SaveManager &) = delete; - SaveManager & operator=(SaveManager &&) = delete; - -private: - /** - * \brief Create an instance of DB and return its reference - * - * \returns DB instance - * - * This function exists because DB is a facade class, which can't directly be used in the API - * without workarounds - * - * TODO: better solution - */ - static DB & get_db(); -}; - -} // namespace crepe diff --git a/src/crepe/api/Scene.h b/src/crepe/api/Scene.h index f6fdb2a..66dad17 100644 --- a/src/crepe/api/Scene.h +++ b/src/crepe/api/Scene.h @@ -3,6 +3,7 @@ #include <string> #include "../util/OptionalRef.h" +#include "../manager/Mediator.h" namespace crepe { @@ -34,6 +35,8 @@ 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 +49,8 @@ protected: * * \{ */ - //! Reference to the ComponentManager - OptionalRef<ComponentManager> component_manager; + //! Mediator reference + OptionalRef<Mediator> mediator; //! \} }; diff --git a/src/crepe/api/SceneManager.cpp b/src/crepe/api/SceneManager.cpp deleted file mode 100644 index 1f783ad..0000000 --- a/src/crepe/api/SceneManager.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include <algorithm> -#include <memory> - -#include "../ComponentManager.h" - -#include "SceneManager.h" - -using namespace crepe; -using namespace std; - -SceneManager::SceneManager(ComponentManager & mgr) : component_manager(mgr) {} - -void SceneManager::set_next_scene(const string & name) { next_scene = name; } - -void SceneManager::load_next_scene() { - // next scene not set - if (this->next_scene.empty()) return; - - auto it = find_if(this->scenes.begin(), this->scenes.end(), - [&next_scene = this->next_scene](unique_ptr<Scene> & scene) { - return scene.get()->get_name() == next_scene; - }); - - // next scene not found - if (it == this->scenes.end()) return; - unique_ptr<Scene> & scene = *it; - - // Delete all components of the current scene - ComponentManager & mgr = this->component_manager; - mgr.delete_all_components(); - - // Load the new scene - scene->load_scene(); -} diff --git a/src/crepe/api/SceneManager.h b/src/crepe/api/SceneManager.h deleted file mode 100644 index f6f62cd..0000000 --- a/src/crepe/api/SceneManager.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include <memory> -#include <vector> - -#include "Scene.h" - -namespace crepe { - -class ComponentManager; - -/** - * \brief Manages scenes - * - * This class manages scenes. It can add new scenes and load them. It also manages the current scene - * and the next scene. - */ -class SceneManager { -public: - //! \param mgr Reference to the ComponentManager - SceneManager(ComponentManager & mgr); - -public: - /** - * \brief Add a new concrete scene to the scene manager - * - * \tparam T Type of concrete scene - */ - template <typename T, typename... Args> - void add_scene(Args &&... args); - /** - * \brief Set the next scene - * - * This scene will be loaded at the end of the frame - * - * \param name Name of the next scene - */ - void set_next_scene(const std::string & name); - //! Load a new scene (if there is one) - void load_next_scene(); - -private: - //! Vector of concrete scenes (added by add_scene()) - std::vector<std::unique_ptr<Scene>> scenes; - //! Next scene to load - std::string next_scene; - //! Reference to the ComponentManager - ComponentManager & component_manager; -}; - -} // namespace crepe - -#include "SceneManager.hpp" diff --git a/src/crepe/api/SceneManager.hpp b/src/crepe/api/SceneManager.hpp deleted file mode 100644 index 5c8e417..0000000 --- a/src/crepe/api/SceneManager.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "SceneManager.h" - -namespace crepe { - -template <typename T, typename... Args> -void SceneManager::add_scene(Args &&... args) { - using namespace std; - static_assert(is_base_of<Scene, T>::value, "T must be derived from Scene"); - - Scene * scene = new T(std::forward<Args>(args)...); - unique_ptr<Scene> unique_scene(scene); - - unique_scene->component_manager = this->component_manager; - - this->scenes.emplace_back(std::move(unique_scene)); - - // The first scene added, is the one that will be loaded at the beginning - if (next_scene.empty()) { - next_scene = scene->get_name(); - } -} - -} // namespace crepe diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp index fcbe4c7..a27838e 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,10 @@ 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..e1f86b2 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -4,8 +4,8 @@ #include "../types.h" #include "../util/OptionalRef.h" - -#include "EventManager.h" +#include "../manager/Mediator.h" +#include "../manager/EventManager.h" namespace crepe { @@ -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; |