aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-11-14 18:04:03 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-11-14 18:04:03 +0100
commitab0b4923c4f49e7a28f6d17e994d3e013ca344bb (patch)
treeb385693017be292b8f4862e88b912dba7c6be619
parent213f947d0907858cace470736c15f87caa934591 (diff)
more WIP audio system + utilities
-rw-r--r--src/crepe/CMakeLists.txt2
-rw-r--r--src/crepe/Resource.cpp6
-rw-r--r--src/crepe/Resource.h12
-rw-r--r--src/crepe/api/ResourceManager.cpp13
-rw-r--r--src/crepe/api/ResourceManager.h13
-rw-r--r--src/crepe/facade/Sound.cpp22
-rw-r--r--src/crepe/facade/Sound.h7
-rw-r--r--src/crepe/util/CMakeLists.txt2
-rw-r--r--src/crepe/util/OptionalRef.h41
-rw-r--r--src/crepe/util/OptionalRef.hpp67
-rw-r--r--src/test/AssetTest.cpp2
-rw-r--r--src/test/CMakeLists.txt2
-rw-r--r--src/test/OptionalRefTest.cpp16
-rw-r--r--src/test/ResourceManagerTest.cpp21
14 files changed, 194 insertions, 32 deletions
diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt
index 05f86d7..d72d4a0 100644
--- a/src/crepe/CMakeLists.txt
+++ b/src/crepe/CMakeLists.txt
@@ -4,6 +4,7 @@ target_sources(crepe PUBLIC
Component.cpp
Collider.cpp
Exception.cpp
+ Resource.cpp
)
target_sources(crepe PUBLIC FILE_SET HEADERS FILES
@@ -15,6 +16,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
ValueBroker.hpp
Exception.h
Exception.hpp
+ Resource.h
)
add_subdirectory(api)
diff --git a/src/crepe/Resource.cpp b/src/crepe/Resource.cpp
new file mode 100644
index 0000000..e254695
--- /dev/null
+++ b/src/crepe/Resource.cpp
@@ -0,0 +1,6 @@
+#include "Resource.h"
+
+using namespace crepe;
+
+Resource::Resource(const Asset & asset) { }
+
diff --git a/src/crepe/Resource.h b/src/crepe/Resource.h
index dcf3dbd..95b4d06 100644
--- a/src/crepe/Resource.h
+++ b/src/crepe/Resource.h
@@ -12,17 +12,11 @@ class Asset;
* resource (e.g. textures, sounds).
*/
class Resource {
+public:
+ Resource(const Asset & src);
+
private:
/**
- * \brief Prototype pattern clone function.
- *
- * \param src Source file of new resource (abstraction for file saved on
- * disk)
- *
- * \returns New instance of concrete resource
- */
- virtual std::unique_ptr<Resource> clone(const Asset & src) const = 0;
- /**
* The resource manager uses \c clone to create new instances of the concrete
* resource class. This may be used to inherit references to classes that
* would otherwise need to be implemented as singletons.
diff --git a/src/crepe/api/ResourceManager.cpp b/src/crepe/api/ResourceManager.cpp
index 17fbd9b..6eb4afd 100644
--- a/src/crepe/api/ResourceManager.cpp
+++ b/src/crepe/api/ResourceManager.cpp
@@ -2,6 +2,9 @@
#include "ResourceManager.h"
+// default resource cache functions
+#include "../facade/Sound.h"
+
using namespace crepe;
ResourceManager & ResourceManager::get_instance() {
@@ -11,3 +14,13 @@ ResourceManager & ResourceManager::get_instance() {
ResourceManager::~ResourceManager() { dbg_trace(); }
ResourceManager::ResourceManager() { dbg_trace(); }
+
+void ResourceManager::clear() {
+ this->resources.clear();
+}
+
+template <>
+Sound & ResourceManager::cache<Sound>(const Asset & asset) {
+ return this->cache<Sound>(asset);
+}
+
diff --git a/src/crepe/api/ResourceManager.h b/src/crepe/api/ResourceManager.h
index a69a9fa..468af16 100644
--- a/src/crepe/api/ResourceManager.h
+++ b/src/crepe/api/ResourceManager.h
@@ -51,22 +51,23 @@ public:
* 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.
+ * \return A reference to the resource
*
* 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
+ * asset is already cached, the existing instance will be returned.
+ * Otherwise, the concrete resource will be instantiated and added to the
* cache.
*/
template <typename T>
T & cache(const Asset & asset);
- /**
- * \brief Clear the resource cache
- */
+ //! Clear the resource cache
void clear();
};
+template <>
+Sound & ResourceManager::cache<Sound>(const Asset & asset);
+
} // namespace crepe
#include "ResourceManager.hpp"
diff --git a/src/crepe/facade/Sound.cpp b/src/crepe/facade/Sound.cpp
index 726f11f..4eefcda 100644
--- a/src/crepe/facade/Sound.cpp
+++ b/src/crepe/facade/Sound.cpp
@@ -1,5 +1,3 @@
-#include <memory>
-
#include "../api/Asset.h"
#include "../util/Log.h"
@@ -9,16 +7,13 @@
using namespace crepe;
using namespace std;
-Sound::Sound(SoundContext & ctx) : context(ctx) { dbg_trace(); }
-
-unique_ptr<Resource> Sound::clone(const Asset & src) const {
- auto instance = make_unique<Sound>(*this);
- instance->sample.load(src.get_path().c_str());
- return instance;
+Sound::Sound(const Asset & src) : Resource(src) {
+ this->sample.load(src.get_path().c_str());
+ dbg_trace();
}
void Sound::play() {
- SoundContext & ctx = this->context;
+ SoundContext & ctx = this->context.get();
if (ctx.engine.getPause(this->handle)) {
// resume if paused
ctx.engine.setPause(this->handle, false);
@@ -30,13 +25,13 @@ void Sound::play() {
}
void Sound::pause() {
- SoundContext & ctx = this->context;
+ SoundContext & ctx = this->context.get();
if (ctx.engine.getPause(this->handle)) return;
ctx.engine.setPause(this->handle, true);
}
void Sound::rewind() {
- SoundContext & ctx = this->context;
+ SoundContext & ctx = this->context.get();
if (!ctx.engine.isValidVoiceHandle(this->handle)) return;
ctx.engine.seek(this->handle, 0);
}
@@ -44,7 +39,7 @@ void Sound::rewind() {
void Sound::set_volume(float volume) {
this->volume = volume;
- SoundContext & ctx = this->context;
+ SoundContext & ctx = this->context.get();
if (!ctx.engine.isValidVoiceHandle(this->handle)) return;
ctx.engine.setVolume(this->handle, this->volume);
}
@@ -52,7 +47,8 @@ void Sound::set_volume(float volume) {
void Sound::set_looping(bool looping) {
this->looping = looping;
- SoundContext & ctx = this->context;
+ SoundContext & ctx = this->context.get();
if (!ctx.engine.isValidVoiceHandle(this->handle)) return;
ctx.engine.setLooping(this->handle, this->looping);
}
+
diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h
index 8342b46..6f8462a 100644
--- a/src/crepe/facade/Sound.h
+++ b/src/crepe/facade/Sound.h
@@ -4,6 +4,7 @@
#include <soloud/soloud.h>
#include <soloud/soloud_wav.h>
+#include "../util/OptionalRef.h"
#include "../Resource.h"
namespace crepe {
@@ -18,6 +19,7 @@ class SoundContext;
*/
class Sound : public Resource {
public:
+ Sound(const Asset & src);
/**
* \brief Pause this sample
*
@@ -72,13 +74,12 @@ public:
bool get_looping() const { return this->looping; }
public:
- Sound(SoundContext & ctx);
- std::unique_ptr<Resource> clone(const Asset & src) const override;
+ void set_context(SoundContext & ctx);
private:
SoLoud::Wav sample;
SoLoud::handle handle;
- SoundContext & context;
+ OptionalRef<SoundContext> context;
float volume = 1.0f;
bool looping = false;
diff --git a/src/crepe/util/CMakeLists.txt b/src/crepe/util/CMakeLists.txt
index 4be738a..94ed906 100644
--- a/src/crepe/util/CMakeLists.txt
+++ b/src/crepe/util/CMakeLists.txt
@@ -9,5 +9,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
Log.hpp
Proxy.h
Proxy.hpp
+ OptionalRef.h
+ OptionalRef.hpp
)
diff --git a/src/crepe/util/OptionalRef.h b/src/crepe/util/OptionalRef.h
new file mode 100644
index 0000000..1ad3a6d
--- /dev/null
+++ b/src/crepe/util/OptionalRef.h
@@ -0,0 +1,41 @@
+#pragma once
+
+namespace crepe {
+
+/**
+ * \brief Optional reference utility
+ *
+ * This class doesn't need to know the full definition of \c T to be used.
+ *
+ * \tparam T Value type
+ */
+template <typename T>
+class OptionalRef {
+public:
+ OptionalRef() = default;
+ OptionalRef(T &);
+ OptionalRef<T> & operator=(T &);
+ explicit operator bool() const noexcept;
+
+ void set(T &) noexcept;
+ T & get() const;
+ void clear() noexcept;
+
+ OptionalRef(const OptionalRef<T> &);
+ OptionalRef(OptionalRef<T> &&);
+ OptionalRef<T> & operator=(const OptionalRef<T> &);
+ OptionalRef<T> & operator=(OptionalRef<T> &&);
+
+private:
+ /**
+ * \brief Reference to the value of type \c T
+ *
+ * \note This raw pointer is *not* managed, and only used as a reference!
+ */
+ T * ref = nullptr;
+};
+
+}
+
+#include "OptionalRef.hpp"
+
diff --git a/src/crepe/util/OptionalRef.hpp b/src/crepe/util/OptionalRef.hpp
new file mode 100644
index 0000000..e603a25
--- /dev/null
+++ b/src/crepe/util/OptionalRef.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <stdexcept>
+
+#include "OptionalRef.h"
+
+namespace crepe {
+
+template <typename T>
+OptionalRef<T>::OptionalRef(T & ref) {
+ this->set(ref);
+}
+
+template <typename T>
+OptionalRef<T>::OptionalRef(const OptionalRef<T> & other) {
+ this->ref = other.ref;
+}
+
+template <typename T>
+OptionalRef<T>::OptionalRef(OptionalRef<T> && other) {
+ this->ref = other.ref;
+ other.clear();
+}
+
+template <typename T>
+OptionalRef<T> & OptionalRef<T>::operator=(const OptionalRef<T> & other) {
+ this->ref = other.ref;
+ return *this;
+}
+
+template <typename T>
+OptionalRef<T> & OptionalRef<T>::operator=(OptionalRef<T> && other) {
+ this->ref = other.ref;
+ other.clear();
+ return *this;
+}
+
+template <typename T>
+T & OptionalRef<T>::get() const {
+ if (this->ref == nullptr)
+ throw std::runtime_error("OptionalRef: attempt to dereference nullptr");
+ return *this->ref;
+}
+
+template <typename T>
+void OptionalRef<T>::set(T & ref) noexcept {
+ this->ref = &ref;
+}
+
+template <typename T>
+void OptionalRef<T>::clear() noexcept {
+ this->ref = nullptr;
+}
+
+template <typename T>
+OptionalRef<T> & OptionalRef<T>::operator=(T & ref) {
+ this->set(ref);
+ return *this;
+}
+
+template <typename T>
+OptionalRef<T>::operator bool() const noexcept {
+ return this->ref == nullptr;
+}
+
+}
+
diff --git a/src/test/AssetTest.cpp b/src/test/AssetTest.cpp
index 324a3f1..563a253 100644
--- a/src/test/AssetTest.cpp
+++ b/src/test/AssetTest.cpp
@@ -1,7 +1,7 @@
-#include "api/Config.h"
#include <gtest/gtest.h>
#include <crepe/api/Asset.h>
+#include <crepe/api/Config.h>
using namespace std;
using namespace crepe;
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 5ea90f7..437c296 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -5,5 +5,7 @@ target_sources(test_main PUBLIC
ParticleTest.cpp
AudioTest.cpp
AssetTest.cpp
+ ResourceManagerTest.cpp
+ OptionalRefTest.cpp
)
diff --git a/src/test/OptionalRefTest.cpp b/src/test/OptionalRefTest.cpp
new file mode 100644
index 0000000..65bd816
--- /dev/null
+++ b/src/test/OptionalRefTest.cpp
@@ -0,0 +1,16 @@
+#include <gtest/gtest.h>
+
+#include <crepe/util/OptionalRef.h>
+
+using namespace std;
+using namespace crepe;
+using namespace testing;
+
+TEST(OptionalRefTest, Explicit) {
+ string value = "foo";
+ OptionalRef<string> ref;
+
+ EXPECT_FALSE(bool(ref));
+ ASSERT_THROW(ref.get(), runtime_error);
+}
+
diff --git a/src/test/ResourceManagerTest.cpp b/src/test/ResourceManagerTest.cpp
new file mode 100644
index 0000000..42b6b5d
--- /dev/null
+++ b/src/test/ResourceManagerTest.cpp
@@ -0,0 +1,21 @@
+#include <gtest/gtest.h>
+
+#include <crepe/api/ResourceManager.h>
+
+using namespace std;
+using namespace crepe;
+using namespace testing;
+
+class ResourceManagerTest : public Test {
+public:
+ ResourceManager & manager = ResourceManager::get_instance();
+
+ void SetUp() override {
+ this->manager.clear();
+ }
+};
+
+TEST_F(ResourceManagerTest, Main) {
+ Sound & sound = this->manager.cache<Sound>("mwe/audio/sfx1.wav");
+}
+