diff options
Diffstat (limited to 'src/crepe')
-rw-r--r-- | src/crepe/api/AudioSource.h | 11 | ||||
-rw-r--r-- | src/crepe/facade/Sound.h | 4 | ||||
-rw-r--r-- | src/crepe/system/AudioSystem.cpp | 17 | ||||
-rw-r--r-- | src/crepe/system/AudioSystem.h | 21 | ||||
-rw-r--r-- | src/crepe/util/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/crepe/util/Private.cpp | 29 | ||||
-rw-r--r-- | src/crepe/util/Private.h | 34 | ||||
-rw-r--r-- | src/crepe/util/Private.hpp | 31 |
8 files changed, 139 insertions, 11 deletions
diff --git a/src/crepe/api/AudioSource.h b/src/crepe/api/AudioSource.h index 0950129..9d76f0b 100644 --- a/src/crepe/api/AudioSource.h +++ b/src/crepe/api/AudioSource.h @@ -2,6 +2,7 @@ #include "../Component.h" #include "../types.h" +#include "../util/Private.h" #include "GameObject.h" #include "Asset.h" @@ -47,14 +48,8 @@ private: bool rewind = false; private: - //! Value of \c active after last system update - bool last_active = false; - //! Value of \c playing after last system update - bool last_playing = false; - //! Value of \c volume after last system update - float last_volume = 1.0; - //! Value of \c loop after last system update - bool last_loop = false; + //! AudioSystem::ComponentPrivate + Private private_data; }; } // namespace crepe diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h index b0b80f8..f33ee58 100644 --- a/src/crepe/facade/Sound.h +++ b/src/crepe/facade/Sound.h @@ -9,6 +9,10 @@ namespace crepe { class SoundContext; +struct SoundHandle { + SoLoud::handle handle; +}; + /** * \brief Sound resource facade * diff --git a/src/crepe/system/AudioSystem.cpp b/src/crepe/system/AudioSystem.cpp index 97cf966..0f943be 100644 --- a/src/crepe/system/AudioSystem.cpp +++ b/src/crepe/system/AudioSystem.cpp @@ -1,6 +1,5 @@ #include "AudioSystem.h" -#include "../api/AudioSource.h" #include "../manager/ComponentManager.h" #include "../manager/ResourceManager.h" #include "../types.h" @@ -13,12 +12,24 @@ void AudioSystem::update() { ResourceManager & resource_manager = this->mediator.resource_manager; RefVector<AudioSource> components = component_manager.get_components_by_type<AudioSource>(); - for (auto component_ref : components) { - AudioSource & component = component_ref.get(); + for (AudioSource & component : components) { if (!component.active) continue; Sound & sound = resource_manager.get<Sound>(component.source); + if (component.private_data.empty()) + component.private_data.set<ComponentPrivate>(); + auto & data = component.private_data.get<ComponentPrivate>(); // TODO: lots of state diffing + + + this->update_private(component, data); } } +void AudioSystem::update_private(const AudioSource & component, ComponentPrivate & data) { + data.last_active = component.active; + data.last_loop = component.loop; + data.last_playing = component.playing; + data.last_volume = component.volume; +} + diff --git a/src/crepe/system/AudioSystem.h b/src/crepe/system/AudioSystem.h index e037f51..7f41fda 100644 --- a/src/crepe/system/AudioSystem.h +++ b/src/crepe/system/AudioSystem.h @@ -1,6 +1,7 @@ #pragma once #include "../facade/SoundContext.h" +#include "../api/AudioSource.h" #include "System.h" @@ -12,6 +13,26 @@ public: void update() override; private: + /** + * \brief Private data stored by AudioSystem on AudioSource component + */ + struct ComponentPrivate { + //! This sample's voice handle + SoLoud::handle handle; + + //! Value of \c active after last system update + bool last_active = false; + //! Value of \c playing after last system update + bool last_playing = false; + //! Value of \c volume after last system update + float last_volume = 1.0; + //! Value of \c loop after last system update + bool last_loop = false; + }; + + void update_private(const AudioSource & component, ComponentPrivate & data); + +private: SoundContext context {}; }; diff --git a/src/crepe/util/CMakeLists.txt b/src/crepe/util/CMakeLists.txt index 94ed906..f49d851 100644 --- a/src/crepe/util/CMakeLists.txt +++ b/src/crepe/util/CMakeLists.txt @@ -1,6 +1,7 @@ target_sources(crepe PUBLIC LogColor.cpp Log.cpp + Private.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -11,5 +12,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Proxy.hpp OptionalRef.h OptionalRef.hpp + Private.h + Private.hpp ) diff --git a/src/crepe/util/Private.cpp b/src/crepe/util/Private.cpp new file mode 100644 index 0000000..c5b5b30 --- /dev/null +++ b/src/crepe/util/Private.cpp @@ -0,0 +1,29 @@ +#include "Private.h" + +using namespace crepe; + +bool Private::empty() const noexcept { + return this->instance == nullptr; +} + +Private::~Private() { + if (this->instance == nullptr) return; + this->destructor(this->instance); +} + +Private::Private(Private && other) { + *this = std::move(other); +} + +Private & Private::operator=(Private && other) { + // TODO: ideally this function checks for self-assignment + this->instance = other.instance; + this->destructor = other.destructor; + this->type = other.type; + + other.instance = nullptr; + other.destructor = [](void*){}; + + return *this; +} + diff --git a/src/crepe/util/Private.h b/src/crepe/util/Private.h new file mode 100644 index 0000000..fc3728f --- /dev/null +++ b/src/crepe/util/Private.h @@ -0,0 +1,34 @@ +#pragma once + +#include <typeindex> +#include <functional> + +namespace crepe { + +class Private { +public: + Private() = default; + ~Private(); + Private(Private &&); + Private & operator=(Private &&); + Private(const Private &) = delete; + Private & operator=(const Private &) = delete; + + template <typename T> + T & get(); + + template <typename T, typename... Args> + void set(Args &&... args); + + bool empty() const noexcept; + +private: + std::function<void(void *)> destructor; + std::type_index type = typeid(void); + void * instance = nullptr; +}; + +} + +#include "Private.hpp" + diff --git a/src/crepe/util/Private.hpp b/src/crepe/util/Private.hpp new file mode 100644 index 0000000..30c8146 --- /dev/null +++ b/src/crepe/util/Private.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <stdexcept> +#include <format> + +#include "Private.h" + +namespace crepe { + +template <typename T, typename... Args> +void Private::set(Args &&... args) { + T * instance = new T(std::forward<Args>(args)...); + this->instance = static_cast<void*>(instance); + this->destructor = [](void * instance) { + delete static_cast<T*>(instance); + }; + this->type = typeid(T); +} + +template <typename T> +T & Private::get() { + using namespace std; + if (this->empty()) + throw out_of_range("Private: get() called on empty object"); + type_index requested_type = typeid(T); + if (this->type != requested_type) + throw logic_error(format("Private: get() called with [T = {}] (actual is [T = {}])", requested_type.name(), this->type.name())); + return *static_cast<T*>(this->instance); +} + +} |