From f3eeedc91a04ca0651e0fe78a2119e7e3e38e391 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 25 Sep 2024 17:36:31 +0200 Subject: WIP Audio API + facade --- src/crepe/CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/crepe/CMakeLists.txt') diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 392b7d7..aa64262 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -1,3 +1,6 @@ -target_sources(main PUBLIC - main.cpp +target_sources(crepe PUBLIC + Sound.cpp ) + +add_subdirectory(api) + -- cgit v1.2.3 From 3cb7227c3c9678141ff74915331b706265c380cb Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 28 Sep 2024 17:07:56 +0200 Subject: more WIP audio facade --- src/CMakeLists.txt | 15 +++++++++--- src/crepe/CMakeLists.txt | 6 +++++ src/crepe/Sound.cpp | 19 ++++++++++++++-- src/crepe/Sound.h | 54 ++++++++++++++++++++++++++++++++++++++------ src/crepe/SoundSystem.cpp | 25 ++++++++++++++++++++ src/crepe/SoundSystem.h | 27 ++++++++++++++++++++++ src/crepe/api/CMakeLists.txt | 9 +++++++- src/crepe/api/Resource.cpp | 12 ++++++++++ src/crepe/api/Resource.h | 11 ++++++--- src/dummy_audio.cpp | 37 ++++++++++++++++++++++++++++++ test/CMakeLists.txt | 2 +- 11 files changed, 200 insertions(+), 17 deletions(-) create mode 100644 src/crepe/SoundSystem.cpp create mode 100644 src/crepe/SoundSystem.h create mode 100644 src/crepe/api/Resource.cpp create mode 100644 src/dummy_audio.cpp (limited to 'src/crepe/CMakeLists.txt') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc71435..232d330 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,13 +15,22 @@ project(crepe C CXX) add_library(crepe SHARED) target_include_directories(crepe - SYSTEM INTERFACE . + PUBLIC SYSTEM INTERFACE . ) -# NOTE: all libraries *must* be linked as PRIVATE +# TODO: libraries should be linked as PRIVATE target_link_libraries(crepe - PRIVATE soloud + PUBLIC soloud ) add_subdirectory(crepe) +install( + TARGETS crepe + FILE_SET HEADERS DESTINATION include/crepe +) + + +add_executable(dummy_audio dummy_audio.cpp) +target_link_libraries(dummy_audio PUBLIC crepe) + diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index aa64262..13d9be5 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -1,5 +1,11 @@ target_sources(crepe PUBLIC Sound.cpp + SoundSystem.cpp +) + +target_sources(crepe PUBLIC FILE_SET HEADERS FILES + Sound.h + SoundSystem.h ) add_subdirectory(api) diff --git a/src/crepe/Sound.cpp b/src/crepe/Sound.cpp index f45a697..d48393c 100644 --- a/src/crepe/Sound.cpp +++ b/src/crepe/Sound.cpp @@ -1,9 +1,24 @@ #include "Sound.h" +#include "SoundSystem.h" using namespace crepe; -Sound::Sound(std::unique_ptr res) { - _res = std::move(res); +Sound::Sound(std::unique_ptr res, SoundSystem & system) : system(system) { + this->res = std::move(res); } +void Sound::play() { + if (this->system.engine.getPause(this->handle)) { + // resume if paused + this->system.engine.setPause(this->handle, false); + } else { + // or start new sound + this->handle = this->system.engine.play(this->sample); + } +} + +void Sound::pause() { + if (this->system.engine.getPause(this->handle)) return; + this->system.engine.setPause(this->handle, true); +} diff --git a/src/crepe/Sound.h b/src/crepe/Sound.h index ac4b7f4..71fe390 100644 --- a/src/crepe/Sound.h +++ b/src/crepe/Sound.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -8,22 +9,61 @@ namespace crepe { -class Sound { -public: - Sound(std::unique_ptr res); - virtual ~Sound() = default; +class SoundSystem; +class Sound { public: + /** + * \brief Pause this sample + * + * Pauses this sound if it is playing, or does nothing if it is already + * paused. The playhead position is saved, such that calling \c play() after + * this function makes the sound resume. + */ void pause(); + /** + * \brief Play this sample + * + * Resume playback if this sound is paused, or start from the beginning of + * the sample. + * + * \note This class only saves a reference to the most recent 'voice' of this + * sound. Calling \c play() while the sound is already playing causes + * multiple instances of the sample to play simultaniously. The sample + * started last is the one that is controlled afterwards. + */ void play(); + /** + * \brief Reset playhead position + * + * Resets the playhead position so that calling \c play() after this function + * makes it play from the start of the sample. If the sound is not paused + * before calling this function, this function will stop playback. + */ void rewind(); + /** + * \brief Set playback volume / gain + * + * \param volume Volume (0 = muted, 1 = full volume) + */ void set_volume(float volume); + /** + * \brief Set looping behavior for this sample + * + * \param looping Looping behavior (false = one-shot, true = loop) + */ void set_looping(bool looping); private: - std::unique_ptr _res; - SoLoud::handle _handle; - bool _paused; + Sound(std::unique_ptr res, SoundSystem & system); + SoundSystem & system; + friend class SoundSystem; + +private: + std::unique_ptr res; + SoLoud::Wav sample; + SoLoud::handle handle; + bool paused; }; } diff --git a/src/crepe/SoundSystem.cpp b/src/crepe/SoundSystem.cpp new file mode 100644 index 0000000..30b0157 --- /dev/null +++ b/src/crepe/SoundSystem.cpp @@ -0,0 +1,25 @@ +#include "SoundSystem.h" +#include + +using namespace crepe; + +SoundSystem SoundSystem::instance { }; + +std::unique_ptr SoundSystem::sound(const std::string & src) { + auto res = std::make_unique(src); + return SoundSystem::sound(std::move(res)); +} + +std::unique_ptr SoundSystem::sound(std::unique_ptr res) { + Sound * out = new Sound(std::move(res), SoundSystem::instance); + return std::unique_ptr(out); +} + +SoundSystem::SoundSystem() { + engine.init(); +} + +SoundSystem::~SoundSystem() { + engine.deinit(); +} + diff --git a/src/crepe/SoundSystem.h b/src/crepe/SoundSystem.h new file mode 100644 index 0000000..23bb00a --- /dev/null +++ b/src/crepe/SoundSystem.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include + +#include "Sound.h" + +namespace crepe { + +class SoundSystem { +public: + static std::unique_ptr sound(const std::string & res); + static std::unique_ptr sound(std::unique_ptr res); + +private: + SoundSystem(); + virtual ~SoundSystem(); + static SoundSystem instance; + +private: + SoLoud::Soloud engine; + friend class Sound; +}; + +} + diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 94617a4..feb03ef 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -1,4 +1,11 @@ target_sources(crepe PUBLIC - AudioSource.cpp + # AudioSource.cpp + Resource.cpp +) + +target_sources(crepe PUBLIC FILE_SET HEADERS FILES + AudioSource.h + Component.h + Resource.h ) diff --git a/src/crepe/api/Resource.cpp b/src/crepe/api/Resource.cpp new file mode 100644 index 0000000..a38900b --- /dev/null +++ b/src/crepe/api/Resource.cpp @@ -0,0 +1,12 @@ +#include "Resource.h" + +using namespace crepe::api; + +Resource::Resource(const std::string & src) : src(src) { + this->file = std::ifstream(src, std::ios::in | std::ios::binary); +} + +const std::istream & Resource::read() { + return this->file; +} + diff --git a/src/crepe/api/Resource.h b/src/crepe/api/Resource.h index 620a10e..2260b1a 100644 --- a/src/crepe/api/Resource.h +++ b/src/crepe/api/Resource.h @@ -1,16 +1,21 @@ #pragma once #include +#include +#include namespace crepe::api { class Resource { public: - Resource(const std::string & source); - virtual ~Resource(); + Resource(const std::string & src); + +public: + const std::istream & read(); private: - std::string _source; + std::string src; + std::ifstream file; }; } diff --git a/src/dummy_audio.cpp b/src/dummy_audio.cpp new file mode 100644 index 0000000..5e0000e --- /dev/null +++ b/src/dummy_audio.cpp @@ -0,0 +1,37 @@ +#include "crepe/SoundSystem.h" + +#include +#include + +using namespace crepe; +using namespace std; +using namespace std::chrono_literals; + +int main() { + auto bgm = SoundSystem::sound("../mwe/audio/bgm.ogg"); + auto sfx1 = SoundSystem::sound("../mwe/audio/sfx1.wav"); + auto sfx2 = SoundSystem::sound("../mwe/audio/sfx2.wav"); + auto sfx3 = SoundSystem::sound("../mwe/audio/sfx3.wav"); + + bgm->play(); + + // play each sample sequentially + this_thread::sleep_for(500ms); + sfx1->play(); + this_thread::sleep_for(500ms); + sfx2->play(); + bgm->pause(); + this_thread::sleep_for(500ms); + sfx3->play(); + bgm->play(); + this_thread::sleep_for(500ms); + + // play all samples simultaniously + sfx1->play(); + sfx2->play(); + sfx3->play(); + this_thread::sleep_for(1000ms); + + return 0; +} + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d103b9a..f015570 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,7 +13,7 @@ add_subdirectory(../src crepe) add_executable(test dummy.cpp - audio.cpp + # audio.cpp ) target_link_libraries(test -- cgit v1.2.3 From feea4cbb648d67e46b413880ddbf203c88c2a2b1 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 29 Sep 2024 16:15:49 +0200 Subject: implement debug logging functions and fix sound system segfault --- src/crepe/CMakeLists.txt | 1 + src/crepe/Sound.cpp | 17 ++++++++++----- src/crepe/Sound.h | 3 +-- src/crepe/SoundSystem.cpp | 11 ++++++++-- src/crepe/SoundSystem.h | 8 ++++++- src/crepe/util/CMakeLists.txt | 9 ++++++++ src/crepe/util/color.h | 42 +++++++++++++++++++++++++++++++++++ src/crepe/util/debug.cpp | 0 src/crepe/util/debug.h | 0 src/crepe/util/log.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++ src/crepe/util/log.h | 33 ++++++++++++++++++++++++++++ src/dummy_audio.cpp | 3 +++ 12 files changed, 167 insertions(+), 11 deletions(-) create mode 100644 src/crepe/util/color.h delete mode 100644 src/crepe/util/debug.cpp delete mode 100644 src/crepe/util/debug.h create mode 100644 src/crepe/util/log.cpp create mode 100644 src/crepe/util/log.h (limited to 'src/crepe/CMakeLists.txt') diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 13d9be5..9f7c91c 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -9,4 +9,5 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES ) add_subdirectory(api) +add_subdirectory(util) diff --git a/src/crepe/Sound.cpp b/src/crepe/Sound.cpp index d48393c..94f97af 100644 --- a/src/crepe/Sound.cpp +++ b/src/crepe/Sound.cpp @@ -1,24 +1,29 @@ +#include "util/log.h" + #include "Sound.h" #include "SoundSystem.h" using namespace crepe; -Sound::Sound(std::unique_ptr res, SoundSystem & system) : system(system) { +Sound::Sound(std::unique_ptr res) { + dbg_trace(); this->res = std::move(res); } void Sound::play() { - if (this->system.engine.getPause(this->handle)) { + SoundSystem & system = SoundSystem::instance(); + if (system.engine.getPause(this->handle)) { // resume if paused - this->system.engine.setPause(this->handle, false); + system.engine.setPause(this->handle, false); } else { // or start new sound - this->handle = this->system.engine.play(this->sample); + this->handle = system.engine.play(this->sample); } } void Sound::pause() { - if (this->system.engine.getPause(this->handle)) return; - this->system.engine.setPause(this->handle, true); + SoundSystem & system = SoundSystem::instance(); + if (system.engine.getPause(this->handle)) return; + system.engine.setPause(this->handle, true); } diff --git a/src/crepe/Sound.h b/src/crepe/Sound.h index 71fe390..333465b 100644 --- a/src/crepe/Sound.h +++ b/src/crepe/Sound.h @@ -55,9 +55,8 @@ public: void set_looping(bool looping); private: - Sound(std::unique_ptr res, SoundSystem & system); - SoundSystem & system; friend class SoundSystem; + Sound(std::unique_ptr res); private: std::unique_ptr res; diff --git a/src/crepe/SoundSystem.cpp b/src/crepe/SoundSystem.cpp index 30b0157..29bd196 100644 --- a/src/crepe/SoundSystem.cpp +++ b/src/crepe/SoundSystem.cpp @@ -1,9 +1,14 @@ +#include "util/log.h" + #include "SoundSystem.h" #include using namespace crepe; -SoundSystem SoundSystem::instance { }; +SoundSystem & SoundSystem::instance() { + static SoundSystem instance; + return instance; +} std::unique_ptr SoundSystem::sound(const std::string & src) { auto res = std::make_unique(src); @@ -11,15 +16,17 @@ std::unique_ptr SoundSystem::sound(const std::string & src) { } std::unique_ptr SoundSystem::sound(std::unique_ptr res) { - Sound * out = new Sound(std::move(res), SoundSystem::instance); + Sound * out = new Sound(std::move(res)); return std::unique_ptr(out); } SoundSystem::SoundSystem() { + dbg_trace(); engine.init(); } SoundSystem::~SoundSystem() { + dbg_trace(); engine.deinit(); } diff --git a/src/crepe/SoundSystem.h b/src/crepe/SoundSystem.h index 23bb00a..515cb29 100644 --- a/src/crepe/SoundSystem.h +++ b/src/crepe/SoundSystem.h @@ -16,7 +16,13 @@ public: private: SoundSystem(); virtual ~SoundSystem(); - static SoundSystem instance; + + // singleton + static SoundSystem & instance(); + SoundSystem(const SoundSystem &) = delete; + SoundSystem(SoundSystem &&) = delete; + SoundSystem &operator=(const SoundSystem &) = delete; + SoundSystem &operator=(SoundSystem &&) = delete; private: SoLoud::Soloud engine; diff --git a/src/crepe/util/CMakeLists.txt b/src/crepe/util/CMakeLists.txt index e69de29..100f028 100644 --- a/src/crepe/util/CMakeLists.txt +++ b/src/crepe/util/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(crepe PUBLIC + log.cpp +) + +target_sources(crepe PUBLIC FILE_SET HEADERS FILES + color.h + log.h +) + diff --git a/src/crepe/util/color.h b/src/crepe/util/color.h new file mode 100644 index 0000000..1af6c8f --- /dev/null +++ b/src/crepe/util/color.h @@ -0,0 +1,42 @@ +#pragma once + +namespace crepe::util::color { + +constexpr const char * RESET = "\e[0m"; + +constexpr const char * FG_BLACK = "\e[30m"; +constexpr const char * FG_RED = "\e[31m"; +constexpr const char * FG_GREEN = "\e[32m"; +constexpr const char * FG_YELLOW = "\e[33m"; +constexpr const char * FG_BLUE = "\e[34m"; +constexpr const char * FG_MAGENTA = "\e[35m"; +constexpr const char * FG_CYAN = "\e[36m"; +constexpr const char * FG_WHITE = "\e[37m"; +constexpr const char * BG_BLACK = "\e[40m"; +constexpr const char * BG_RED = "\e[41m"; +constexpr const char * BG_GREEN = "\e[42m"; +constexpr const char * BG_YELLOW = "\e[43m"; +constexpr const char * BG_BLUE = "\e[44m"; +constexpr const char * BG_MAGENTA = "\e[45m"; +constexpr const char * BG_CYAN = "\e[46m"; +constexpr const char * BG_WHITE = "\e[47m"; + +constexpr const char * FG_BLACK_BRIGHT = "\e[90m"; +constexpr const char * FG_RED_BRIGHT = "\e[91m"; +constexpr const char * FG_GREEN_BRIGHT = "\e[92m"; +constexpr const char * FG_YELLOW_BRIGHT = "\e[93m"; +constexpr const char * FG_BLUE_BRIGHT = "\e[94m"; +constexpr const char * FG_MAGENTA_BRIGHT = "\e[95m"; +constexpr const char * FG_CYAN_BRIGHT = "\e[96m"; +constexpr const char * FG_WHITE_BRIGHT = "\e[97m"; +constexpr const char * BG_BLACK_BRIGHT = "\e[100m"; +constexpr const char * BG_RED_BRIGHT = "\e[101m"; +constexpr const char * BG_GREEN_BRIGHT = "\e[102m"; +constexpr const char * BG_YELLOW_BRIGHT = "\e[103m"; +constexpr const char * BG_BLUE_BRIGHT = "\e[104m"; +constexpr const char * BG_MAGENTA_BRIGHT = "\e[105m"; +constexpr const char * BG_CYAN_BRIGHT = "\e[106m"; +constexpr const char * BG_WHITE_BRIGHT = "\e[107m"; + +} + diff --git a/src/crepe/util/debug.cpp b/src/crepe/util/debug.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/crepe/util/debug.h b/src/crepe/util/debug.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/crepe/util/log.cpp b/src/crepe/util/log.cpp new file mode 100644 index 0000000..796df49 --- /dev/null +++ b/src/crepe/util/log.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +#include "log.h" + +using namespace crepe::util; + +static const char * const LOG_PREFIX[] = { + [log_level::debug] = "[DBG] ", + [log_level::info] = "[INFO] ", + [log_level::warning] = "[WARN] ", + [log_level::error] = "[ERR] ", +}; + +static void va_logf(enum log_level level, va_list args, const std::string fmt) { + va_list args_copy; + va_copy(args_copy, args); + + // prepend log level and ensure newline + std::string format_fixed = LOG_PREFIX[level] + fmt; + if (!format_fixed.ends_with("\n")) format_fixed += "\n"; + + size_t sz = vsnprintf(NULL, 0, format_fixed.c_str(), args_copy) + 1; + char * msg = (char *) malloc(sz); + va_end(args_copy); + + vsnprintf(msg, sz, format_fixed.c_str(), args); + + // TODO: also log to file or smth + printf("%s", msg); + fflush(stdout); + + free(msg); +} + +void crepe::util::logf(const char * fmt, ...) { + va_list args; + va_start(args, fmt); + va_logf(crepe::util::log_level::debug, args, fmt); + va_end(args); +} + +void crepe::util::logf(log_level level, const char * fmt, ...) { + va_list args; + va_start(args, fmt); + va_logf(level, args, fmt); + va_end(args); +} + diff --git a/src/crepe/util/log.h b/src/crepe/util/log.h new file mode 100644 index 0000000..5295cb9 --- /dev/null +++ b/src/crepe/util/log.h @@ -0,0 +1,33 @@ +#pragma once + +// allow user to disable debug macros +#ifndef CREPE_DISABLE_MACROS + +#include "color.h" + +// utility macros +#define _crepe_logf_here(fmt, ...) \ + crepe::util::logf(util::log_level::debug, "%s%s (%s:%d)" fmt "\n", \ + crepe::util::color::FG_WHITE, \ + __PRETTY_FUNCTION__, \ + __FILE_NAME__, \ + __LINE__, \ + crepe::util::color::RESET, \ + __VA_ARGS__) + +#define dbg_logf(fmt, ...) _crepe_logf_here(": " fmt, __VA_ARGS__) +#define dbg_log(str) _crepe_logf_here(": %s", str) +#define dbg_trace() _crepe_logf_here("%s", "") + +#endif + +namespace crepe::util { + +enum log_level { debug, info, warning, error, }; + +void logf(const char * fmt, ...); +void logf(enum log_level level, const char * fmt, ...); + +} + + diff --git a/src/dummy_audio.cpp b/src/dummy_audio.cpp index 5e0000e..fb1e3ab 100644 --- a/src/dummy_audio.cpp +++ b/src/dummy_audio.cpp @@ -1,4 +1,5 @@ #include "crepe/SoundSystem.h" +#include "crepe/util/log.h" #include #include @@ -8,6 +9,8 @@ using namespace std; using namespace std::chrono_literals; int main() { + dbg_trace(); + auto bgm = SoundSystem::sound("../mwe/audio/bgm.ogg"); auto sfx1 = SoundSystem::sound("../mwe/audio/sfx1.wav"); auto sfx2 = SoundSystem::sound("../mwe/audio/sfx2.wav"); -- cgit v1.2.3 From 8e67adc6828181b1df7c95da76f32962444fc7fd Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 1 Oct 2024 17:25:06 +0200 Subject: rename SoundSystem to SoundContext (2/2) --- src/crepe/CMakeLists.txt | 4 ++-- src/crepe/Sound.cpp | 36 ++++++++++++++++++------------------ src/crepe/SoundContext.cpp | 10 +++++----- src/crepe/SoundContext.h | 16 ++++++++-------- 4 files changed, 33 insertions(+), 33 deletions(-) (limited to 'src/crepe/CMakeLists.txt') diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 9f7c91c..3a60840 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -1,11 +1,11 @@ target_sources(crepe PUBLIC Sound.cpp - SoundSystem.cpp + SoundContext.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES Sound.h - SoundSystem.h + SoundContext.h ) add_subdirectory(api) diff --git a/src/crepe/Sound.cpp b/src/crepe/Sound.cpp index 20f1787..1758282 100644 --- a/src/crepe/Sound.cpp +++ b/src/crepe/Sound.cpp @@ -1,7 +1,7 @@ #include "util/log.h" #include "Sound.h" -#include "SoundSystem.h" +#include "SoundContext.h" using namespace crepe; @@ -20,42 +20,42 @@ void Sound::load(std::unique_ptr res) { } void Sound::play() { - SoundSystem & system = SoundSystem::get_instance(); - if (system.engine.getPause(this->handle)) { + SoundContext & ctx = SoundContext::get_instance(); + if (ctx.engine.getPause(this->handle)) { // resume if paused - system.engine.setPause(this->handle, false); + ctx.engine.setPause(this->handle, false); } else { // or start new sound - this->handle = system.engine.play(this->sample, this->volume); - system.engine.setLooping(this->handle, this->looping); + this->handle = ctx.engine.play(this->sample, this->volume); + ctx.engine.setLooping(this->handle, this->looping); } } void Sound::pause() { - SoundSystem & system = SoundSystem::get_instance(); - if (system.engine.getPause(this->handle)) return; - system.engine.setPause(this->handle, true); + SoundContext & ctx = SoundContext::get_instance(); + if (ctx.engine.getPause(this->handle)) return; + ctx.engine.setPause(this->handle, true); } void Sound::rewind() { - SoundSystem & system = SoundSystem::get_instance(); - if (!system.engine.isValidVoiceHandle(this->handle)) return; - system.engine.seek(this->handle, 0); + SoundContext & ctx = SoundContext::get_instance(); + if (!ctx.engine.isValidVoiceHandle(this->handle)) return; + ctx.engine.seek(this->handle, 0); } void Sound::set_volume(float volume) { this->volume = volume; - SoundSystem & system = SoundSystem::get_instance(); - if (!system.engine.isValidVoiceHandle(this->handle)) return; - system.engine.setVolume(this->handle, this->volume); + SoundContext & ctx = SoundContext::get_instance(); + if (!ctx.engine.isValidVoiceHandle(this->handle)) return; + ctx.engine.setVolume(this->handle, this->volume); } void Sound::set_looping(bool looping) { this->looping = looping; - SoundSystem & system = SoundSystem::get_instance(); - if (!system.engine.isValidVoiceHandle(this->handle)) return; - system.engine.setLooping(this->handle, this->looping); + SoundContext & ctx = SoundContext::get_instance(); + if (!ctx.engine.isValidVoiceHandle(this->handle)) return; + ctx.engine.setLooping(this->handle, this->looping); } diff --git a/src/crepe/SoundContext.cpp b/src/crepe/SoundContext.cpp index b57e51a..cfb7d82 100644 --- a/src/crepe/SoundContext.cpp +++ b/src/crepe/SoundContext.cpp @@ -1,20 +1,20 @@ #include "util/log.h" -#include "SoundSystem.h" +#include "SoundContext.h" using namespace crepe; -SoundSystem & SoundSystem::get_instance() { - static SoundSystem instance; +SoundContext & SoundContext::get_instance() { + static SoundContext instance; return instance; } -SoundSystem::SoundSystem() { +SoundContext::SoundContext() { dbg_trace(); engine.init(); } -SoundSystem::~SoundSystem() { +SoundContext::~SoundContext() { dbg_trace(); engine.deinit(); } diff --git a/src/crepe/SoundContext.h b/src/crepe/SoundContext.h index 34dd6c5..d361d83 100644 --- a/src/crepe/SoundContext.h +++ b/src/crepe/SoundContext.h @@ -6,17 +6,17 @@ namespace crepe { -class SoundSystem { +class SoundContext { private: - SoundSystem(); - virtual ~SoundSystem(); + SoundContext(); + virtual ~SoundContext(); // singleton - static SoundSystem & get_instance(); - SoundSystem(const SoundSystem &) = delete; - SoundSystem(SoundSystem &&) = delete; - SoundSystem &operator=(const SoundSystem &) = delete; - SoundSystem &operator=(SoundSystem &&) = delete; + static SoundContext & get_instance(); + SoundContext(const SoundContext &) = delete; + SoundContext(SoundContext &&) = delete; + SoundContext &operator=(const SoundContext &) = delete; + SoundContext &operator=(SoundContext &&) = delete; private: SoLoud::Soloud engine; -- cgit v1.2.3 From b99e38badb82c5cc79771a77c5f6ea180c67ee4f Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 5 Oct 2024 14:24:39 +0200 Subject: move Asset from crepe::api to crepe --- src/crepe/Asset.cpp | 14 ++++++++++++++ src/crepe/Asset.h | 24 ++++++++++++++++++++++++ src/crepe/CMakeLists.txt | 2 ++ src/crepe/Sound.cpp | 6 +++--- src/crepe/Sound.h | 6 +++--- src/crepe/api/Asset.cpp | 14 -------------- src/crepe/api/Asset.h | 24 ------------------------ src/crepe/api/CMakeLists.txt | 2 -- 8 files changed, 46 insertions(+), 46 deletions(-) create mode 100644 src/crepe/Asset.cpp create mode 100644 src/crepe/Asset.h delete mode 100644 src/crepe/api/Asset.cpp delete mode 100644 src/crepe/api/Asset.h (limited to 'src/crepe/CMakeLists.txt') diff --git a/src/crepe/Asset.cpp b/src/crepe/Asset.cpp new file mode 100644 index 0000000..15ddc27 --- /dev/null +++ b/src/crepe/Asset.cpp @@ -0,0 +1,14 @@ +#include + +#include "Asset.h" + +using namespace crepe; + +Asset::Asset(const std::string & src) { + this->src = std::filesystem::canonical(src); + this->file = std::ifstream(this->src, std::ios::in | std::ios::binary); +} + +const std::istream & Asset::read() { return this->file; } + +const char * Asset::canonical() { return this->src.c_str(); } diff --git a/src/crepe/Asset.h b/src/crepe/Asset.h new file mode 100644 index 0000000..736ba44 --- /dev/null +++ b/src/crepe/Asset.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +namespace crepe { + +class Asset { +public: + Asset(const std::string & src); + +public: + //! Get an input stream to the contents of this resource + const std::istream & read(); + //! Get the canonical path to this resource + const char * canonical(); + +private: + std::string src; + std::ifstream file; +}; + +} // namespace crepe diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 3a60840..208ba1f 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -1,9 +1,11 @@ target_sources(crepe PUBLIC + Asset.cpp Sound.cpp SoundContext.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES + Asset.h Sound.h SoundContext.h ) diff --git a/src/crepe/Sound.cpp b/src/crepe/Sound.cpp index c6e87d5..73ad69c 100644 --- a/src/crepe/Sound.cpp +++ b/src/crepe/Sound.cpp @@ -5,17 +5,17 @@ using namespace crepe; -Sound::Sound(std::unique_ptr res) { +Sound::Sound(std::unique_ptr res) { dbg_trace(); this->load(std::move(res)); } Sound::Sound(const char * src) { dbg_trace(); - this->load(std::make_unique(src)); + this->load(std::make_unique(src)); } -void Sound::load(std::unique_ptr res) { +void Sound::load(std::unique_ptr res) { this->sample.load(res->canonical()); } diff --git a/src/crepe/Sound.h b/src/crepe/Sound.h index 339dd7c..1ac20a7 100644 --- a/src/crepe/Sound.h +++ b/src/crepe/Sound.h @@ -5,7 +5,7 @@ #include -#include "api/Asset.h" +#include "Asset.h" namespace crepe { @@ -66,10 +66,10 @@ public: public: Sound(const char * src); - Sound(std::unique_ptr res); + Sound(std::unique_ptr res); private: - void load(std::unique_ptr res); + void load(std::unique_ptr res); private: SoLoud::Wav sample; diff --git a/src/crepe/api/Asset.cpp b/src/crepe/api/Asset.cpp deleted file mode 100644 index 92ee50e..0000000 --- a/src/crepe/api/Asset.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#include "Asset.h" - -using namespace crepe::api; - -Asset::Asset(const std::string & src) { - this->src = std::filesystem::canonical(src); - this->file = std::ifstream(this->src, std::ios::in | std::ios::binary); -} - -const std::istream & Asset::read() { return this->file; } - -const char * Asset::canonical() { return this->src.c_str(); } diff --git a/src/crepe/api/Asset.h b/src/crepe/api/Asset.h deleted file mode 100644 index 259c696..0000000 --- a/src/crepe/api/Asset.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace crepe::api { - -class Asset { -public: - Asset(const std::string & src); - -public: - //! Get an input stream to the contents of this resource - const std::istream & read(); - //! Get the canonical path to this resource - const char * canonical(); - -private: - std::string src; - std::ifstream file; -}; - -} // namespace crepe::api diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 54c7fdc..9548594 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -1,11 +1,9 @@ target_sources(crepe PUBLIC # AudioSource.cpp - Asset.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES AudioSource.h Component.h - Asset.h ) -- cgit v1.2.3 From 7c9d3452c99fcb89ea6df55755e90f741b23cf10 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 6 Oct 2024 13:22:10 +0200 Subject: copy homemade ECS to crepe + correct code style --- .clang-format | 1 + contributing.md | 5 + mwe/ecs-homemade/inc/ComponentManager.h | 43 +++++---- mwe/ecs-homemade/inc/ComponentManager.hpp | 154 +++++++++++++++++++----------- mwe/ecs-homemade/inc/GameObjectMax.h | 3 +- mwe/ecs-homemade/inc/GameObjectMax.hpp | 5 +- mwe/ecs-homemade/src/ComponentManager.cpp | 20 ++-- mwe/ecs-homemade/src/Components.cpp | 3 +- mwe/ecs-homemade/src/GameObjectMax.cpp | 4 +- mwe/ecs-homemade/src/main.cpp | 35 ++++--- src/crepe/CMakeLists.txt | 8 ++ src/crepe/ComponentManager.cpp | 25 +++++ src/crepe/ComponentManager.h | 55 +++++++++++ src/crepe/ComponentManager.hpp | 134 ++++++++++++++++++++++++++ src/crepe/Components.cpp | 13 +++ src/crepe/Components.h | 39 ++++++++ src/crepe/GameObject.cpp | 9 ++ src/crepe/GameObject.h | 22 +++++ src/crepe/GameObject.hpp | 15 +++ 19 files changed, 487 insertions(+), 106 deletions(-) create mode 100644 src/crepe/ComponentManager.cpp create mode 100644 src/crepe/ComponentManager.h create mode 100644 src/crepe/ComponentManager.hpp create mode 100644 src/crepe/Components.cpp create mode 100644 src/crepe/Components.h create mode 100644 src/crepe/GameObject.cpp create mode 100644 src/crepe/GameObject.h create mode 100644 src/crepe/GameObject.hpp (limited to 'src/crepe/CMakeLists.txt') diff --git a/.clang-format b/.clang-format index 5d233eb..d2918db 100644 --- a/.clang-format +++ b/.clang-format @@ -22,6 +22,7 @@ AlignTrailingComments: ReflowComments: false AlignEscapedNewlines: DontAlign BreakBeforeBinaryOperators: All +BreakTemplateDeclarations: Yes ... # vim: ft=yaml diff --git a/contributing.md b/contributing.md index 2ff411a..933f1bf 100644 --- a/contributing.md +++ b/contributing.md @@ -17,6 +17,11 @@ # Code style - ASCII only +- Explanatory comments are placed above the line(s) they are explaining +- Source files should only contain comments that plainly state what the code is + supposed to do +- Explanatory comments in headers may be used to clarify implementation design + decisions - Formatting nitty-gritty is handled by clang-format/clang-tidy (run `make format` in the root folder of this repository to format all sources files) - When using libraries of which the header include order is important, make diff --git a/mwe/ecs-homemade/inc/ComponentManager.h b/mwe/ecs-homemade/inc/ComponentManager.h index 1a58b01..d368516 100644 --- a/mwe/ecs-homemade/inc/ComponentManager.h +++ b/mwe/ecs-homemade/inc/ComponentManager.h @@ -2,39 +2,44 @@ #include "Components.h" #include -#include -#include -#include #include +#include +#include #include +#include class ComponentManager { public: - static ComponentManager& GetInstance(); //Singleton + static ComponentManager & GetInstance(); //Singleton - ComponentManager(const ComponentManager&) = delete; //Singleton - ComponentManager(ComponentManager&&) = delete; //Singleton - ComponentManager& operator=(const ComponentManager&) = delete; //Singleton - ComponentManager& operator=(ComponentManager&&) = delete; //Singleton + ComponentManager(const ComponentManager &) = delete; //Singleton + ComponentManager(ComponentManager &&) = delete; //Singleton + ComponentManager & operator=(const ComponentManager &) = delete; //Singleton + ComponentManager & operator=(ComponentManager &&) = delete; //Singleton template - void AddComponent(std::uint32_t id, Args&&... args); //Add a component of a specific type + void AddComponent(std::uint32_t id, + Args &&... args); //Add a component of a specific type template - void DeleteComponentsById(std::uint32_t id); //Deletes all components of a specific type and id + void DeleteComponentsById( + std::uint32_t id); //Deletes all components of a specific type and id template - void DeleteComponents(); //Deletes all components of a specific type - void DeleteAllComponentsOfId(std::uint32_t id); //Deletes all components of a specific id - void DeleteAllComponents(); //Deletes all components + void DeleteComponents(); //Deletes all components of a specific type + void DeleteAllComponentsOfId( + std::uint32_t id); //Deletes all components of a specific id + void DeleteAllComponents(); //Deletes all components template - std::vector> GetComponentsByID(std::uint32_t id) const; //Get a vector<> of all components at specific type and id + std::vector> GetComponentsByID(std::uint32_t id) + const; //Get a vector<> of all components at specific type and id template - std::vector> GetComponentsByType() const; //Get a vector<> of all components of a specific type + std::vector> GetComponentsByType() + const; //Get a vector<> of all components of a specific type private: - static ComponentManager mInstance; //Singleton + static ComponentManager mInstance; //Singleton - ComponentManager(); //Singleton + ComponentManager(); //Singleton /* * The std::unordered_map>>> below might seem a bit strange, let me explain this structure: @@ -42,7 +47,9 @@ private: * The first std::vector<> stores another vector<>. This first vector<> is to bind the entity's id to a component. * The second std::vector<> stores unique_ptrs. Each component can be gathered via an unique_ptr. This second vector<> allows multiple components of the same std::type_index for one entity (id). */ - std::unordered_map>>> mComponents; + std::unordered_map>>> + mComponents; }; #include "ComponentManager.hpp" diff --git a/mwe/ecs-homemade/inc/ComponentManager.hpp b/mwe/ecs-homemade/inc/ComponentManager.hpp index 720ee79..161ce71 100644 --- a/mwe/ecs-homemade/inc/ComponentManager.hpp +++ b/mwe/ecs-homemade/inc/ComponentManager.hpp @@ -1,88 +1,126 @@ template -void ComponentManager::AddComponent(std::uint32_t id, Args&&... args) { - std::type_index type = typeid(T); //Determine the type of T (this is used as the key of the unordered_map<>) - - if (mComponents.find(type) == mComponents.end()) { //Check if this component type is already in the unordered_map<> - mComponents[type] = std::vector>>(); //If not, create a new (empty) vector<> of vector> - } +void ComponentManager::AddComponent(std::uint32_t id, Args &&... args) { + std::type_index type = typeid( + T); //Determine the type of T (this is used as the key of the unordered_map<>) + + if (mComponents.find(type) + == mComponents + .end()) { //Check if this component type is already in the unordered_map<> + mComponents[type] = std::vector>>(); //If not, create a new (empty) vector<> of vector> + } - if (id >= mComponents[type].size()) { //Resize the vector<> if the id is greater than the current size - mComponents[type].resize(id + 1); //Initialize new slots to nullptr (resize does automatically init to nullptr) - } + if (id + >= mComponents[type] + .size()) { //Resize the vector<> if the id is greater than the current size + mComponents[type].resize( + id + + 1); //Initialize new slots to nullptr (resize does automatically init to nullptr) + } - mComponents[type][id].push_back(std::make_unique(std::forward(args)...)); //Create a new component of type T using perfect forwarding and store its unique_ptr in the vector<> + mComponents[type][id].push_back(std::make_unique(std::forward( + args)...)); //Create a new component of type T using perfect forwarding and store its unique_ptr in the vector<> } template void ComponentManager::DeleteComponentsById(std::uint32_t id) { - std::type_index type = typeid(T); //Determine the type of T (this is used as the key of the unordered_map<>) - - if (mComponents.find(type) != mComponents.end()) { //Find the type (in the unordered_map<>) - std::vector>>& componentArray = mComponents[type]; //Get the correct vector<> - - if (id < componentArray.size()) { //Make sure that the id (that we are looking for) is within the boundaries of the vector<> - componentArray[id].clear(); //Clear the whole vector<> of this specific type and id - } + std::type_index type = typeid( + T); //Determine the type of T (this is used as the key of the unordered_map<>) + + if (mComponents.find(type) + != mComponents.end()) { //Find the type (in the unordered_map<>) + std::vector>> & componentArray + = mComponents[type]; //Get the correct vector<> + + if (id + < componentArray + .size()) { //Make sure that the id (that we are looking for) is within the boundaries of the vector<> + componentArray[id] + .clear(); //Clear the whole vector<> of this specific type and id + } } } -template -void ComponentManager::DeleteComponents() { - std::type_index type = typeid(T); //Determine the type of T (this is used as the key of the unordered_map<>) +template void ComponentManager::DeleteComponents() { + std::type_index type = typeid( + T); //Determine the type of T (this is used as the key of the unordered_map<>) - if (mComponents.find(type) != mComponents.end()) { //Find the type (in the unordered_map<>) - mComponents[type].clear(); //Clear the whole vector<> of this specific type + if (mComponents.find(type) + != mComponents.end()) { //Find the type (in the unordered_map<>) + mComponents[type] + .clear(); //Clear the whole vector<> of this specific type } } template -std::vector> ComponentManager::GetComponentsByID(std::uint32_t id) const { - std::type_index type = typeid(T); //Determine the type of T (this is used as the key of the unordered_map<>) - - std::vector> componentVector; //Create an empty vector<> - - if (mComponents.find(type) != mComponents.end()) { //Find the type (in the unordered_map<>) - - const std::vector>>& componentArray = mComponents.at(type); //Get the correct vector<> - - if (id < componentArray.size()) { //Make sure that the id (that we are looking for) is within the boundaries of the vector<> - for (const std::unique_ptr& componentPtr : componentArray[id]) { //Loop trough the whole vector<> - T* castedComponent = static_cast(componentPtr.get()); //Cast the unique_ptr to a raw pointer - - if (castedComponent) { //Ensure that the cast was successful - componentVector.push_back(*castedComponent); //Add the dereferenced raw pointer to the vector<> - } - } - } - } +std::vector> +ComponentManager::GetComponentsByID(std::uint32_t id) const { + std::type_index type = typeid( + T); //Determine the type of T (this is used as the key of the unordered_map<>) + + std::vector> + componentVector; //Create an empty vector<> + + if (mComponents.find(type) + != mComponents.end()) { //Find the type (in the unordered_map<>) + + const std::vector>> & + componentArray + = mComponents.at(type); //Get the correct vector<> + + if (id + < componentArray + .size()) { //Make sure that the id (that we are looking for) is within the boundaries of the vector<> + for (const std::unique_ptr & componentPtr : + componentArray[id]) { //Loop trough the whole vector<> + T * castedComponent = static_cast( + componentPtr.get()); //Cast the unique_ptr to a raw pointer + + if (castedComponent) { //Ensure that the cast was successful + componentVector.push_back( + *castedComponent); //Add the dereferenced raw pointer to the vector<> + } + } + } + } - return componentVector; //Return the vector<> + return componentVector; //Return the vector<> } template -std::vector> ComponentManager::GetComponentsByType() const { - std::type_index type = typeid(T); //Determine the type of T (this is used as the key of the unordered_map<>) +std::vector> +ComponentManager::GetComponentsByType() const { + std::type_index type = typeid( + T); //Determine the type of T (this is used as the key of the unordered_map<>) - std::vector> componentVector; //Create an empty vector<> + std::vector> + componentVector; //Create an empty vector<> //std::uint32_t id = 0; //Set the id to 0 (the id will also be stored in the returned vector<>) - if (mComponents.find(type) != mComponents.end()) { //Find the type (in the unordered_map<>) + if (mComponents.find(type) + != mComponents.end()) { //Find the type (in the unordered_map<>) - const std::vector>>& componentArray = mComponents.at(type); //Get the correct vector<> + const std::vector>> & + componentArray + = mComponents.at(type); //Get the correct vector<> - for (const std::vector>& component : componentArray) { //Loop through the whole vector<> - for (const std::unique_ptr& componentPtr : component) { //Loop trough the whole vector<> - T* castedComponent = static_cast(componentPtr.get()); //Cast the unique_ptr to a raw pointer + for (const std::vector> & component : + componentArray) { //Loop through the whole vector<> + for (const std::unique_ptr & componentPtr : + component) { //Loop trough the whole vector<> + T * castedComponent = static_cast( + componentPtr.get()); //Cast the unique_ptr to a raw pointer - if (castedComponent) { //Ensure that the cast was successful - componentVector.emplace_back(std::ref(*castedComponent)); //Pair the dereferenced raw pointer and the id and add it to the vector<> - } - } + if (castedComponent) { //Ensure that the cast was successful + componentVector.emplace_back(std::ref( + *castedComponent)); //Pair the dereferenced raw pointer and the id and add it to the vector<> + } + } //++id; //Increase the id (the id will also be stored in the returned vector<>) - } - } + } + } - return componentVector; //Return the vector<> + return componentVector; //Return the vector<> } diff --git a/mwe/ecs-homemade/inc/GameObjectMax.h b/mwe/ecs-homemade/inc/GameObjectMax.h index f0bcec9..c88a834 100644 --- a/mwe/ecs-homemade/inc/GameObjectMax.h +++ b/mwe/ecs-homemade/inc/GameObjectMax.h @@ -7,8 +7,7 @@ class GameObject { public: GameObject(std::uint32_t id, std::string name, std::string tag, int layer); - template - void AddComponent(Args&&... args); + template void AddComponent(Args &&... args); std::uint32_t mId; std::string mName; diff --git a/mwe/ecs-homemade/inc/GameObjectMax.hpp b/mwe/ecs-homemade/inc/GameObjectMax.hpp index 1e952ba..91d51ea 100644 --- a/mwe/ecs-homemade/inc/GameObjectMax.hpp +++ b/mwe/ecs-homemade/inc/GameObjectMax.hpp @@ -1,6 +1,7 @@ #include "ComponentManager.h" template -void GameObject::AddComponent(Args&&... args) { - ComponentManager::GetInstance().AddComponent(mId, std::forward(args)...); +void GameObject::AddComponent(Args &&... args) { + ComponentManager::GetInstance().AddComponent( + mId, std::forward(args)...); } diff --git a/mwe/ecs-homemade/src/ComponentManager.cpp b/mwe/ecs-homemade/src/ComponentManager.cpp index 16cc2b6..536c152 100644 --- a/mwe/ecs-homemade/src/ComponentManager.cpp +++ b/mwe/ecs-homemade/src/ComponentManager.cpp @@ -2,20 +2,22 @@ ComponentManager ComponentManager::mInstance; -ComponentManager& ComponentManager::GetInstance() { - return mInstance; -} +ComponentManager & ComponentManager::GetInstance() { return mInstance; } ComponentManager::ComponentManager() {} void ComponentManager::DeleteAllComponentsOfId(std::uint32_t id) { - for(auto& [type, componentArray] : mComponents) { //Loop through all the types (in the unordered_map<>) - if (id < componentArray.size()) { //Make sure that the id (that we are looking for) is within the boundaries of the vector<> - componentArray[id].clear(); //Clear the components at this specific id - } - } + for (auto & [type, componentArray] : + mComponents) { //Loop through all the types (in the unordered_map<>) + if (id + < componentArray + .size()) { //Make sure that the id (that we are looking for) is within the boundaries of the vector<> + componentArray[id] + .clear(); //Clear the components at this specific id + } + } } void ComponentManager::DeleteAllComponents() { - mComponents.clear(); //Clear the whole unordered_map<> + mComponents.clear(); //Clear the whole unordered_map<> } diff --git a/mwe/ecs-homemade/src/Components.cpp b/mwe/ecs-homemade/src/Components.cpp index 69b5eaa..c8347b3 100644 --- a/mwe/ecs-homemade/src/Components.cpp +++ b/mwe/ecs-homemade/src/Components.cpp @@ -5,6 +5,7 @@ Component::Component() : mActive(true) {} Sprite::Sprite(std::string path) : mPath(path) {} -Rigidbody::Rigidbody(int mass, int gravityScale, int bodyType) : mMass(mass), mGravityScale(gravityScale), mBodyType(bodyType) {} +Rigidbody::Rigidbody(int mass, int gravityScale, int bodyType) + : mMass(mass), mGravityScale(gravityScale), mBodyType(bodyType) {} Colider::Colider(int size) : mSize(size) {} diff --git a/mwe/ecs-homemade/src/GameObjectMax.cpp b/mwe/ecs-homemade/src/GameObjectMax.cpp index 62c41de..b0c5af7 100644 --- a/mwe/ecs-homemade/src/GameObjectMax.cpp +++ b/mwe/ecs-homemade/src/GameObjectMax.cpp @@ -2,4 +2,6 @@ #include "ComponentManager.h" -GameObject::GameObject(std::uint32_t id, std::string name, std::string tag, int layer) : mId(id), mName(name), mTag(tag), mActive(true), mLayer(layer) {} +GameObject::GameObject(std::uint32_t id, std::string name, std::string tag, + int layer) + : mId(id), mName(name), mTag(tag), mActive(true), mLayer(layer) {} diff --git a/mwe/ecs-homemade/src/main.cpp b/mwe/ecs-homemade/src/main.cpp index 41f7d6d..330e154 100644 --- a/mwe/ecs-homemade/src/main.cpp +++ b/mwe/ecs-homemade/src/main.cpp @@ -1,54 +1,59 @@ +#include +#include #include #include -#include -#include #include "ComponentManager.h" -#include "GameObjectMax.h" #include "Components.h" +#include "GameObjectMax.h" int main() { auto startAdding = std::chrono::high_resolution_clock::now(); - GameObject* gameObject[100000]; + GameObject * gameObject[100000]; - for(int i = 0; i < 100000; ++i) { + for (int i = 0; i < 100000; ++i) { gameObject[i] = new GameObject(i, "Name", "Tag", 0); gameObject[i]->AddComponent("C:/Test"); gameObject[i]->AddComponent(0, 0, i); gameObject[i]->AddComponent(i); } - + auto stopAdding = std::chrono::high_resolution_clock::now(); //This is what systems would do: - std::vector> sprites = ComponentManager::GetInstance().GetComponentsByType(); - for(Sprite& sprite : sprites) { + std::vector> sprites + = ComponentManager::GetInstance().GetComponentsByType(); + for (Sprite & sprite : sprites) { //std::cout << sprite.get().mPath << std::endl; } //std::cout << std::endl; - std::vector> rigidBodies = ComponentManager::GetInstance().GetComponentsByType(); - for(Rigidbody& rigidbody : rigidBodies) { + std::vector> rigidBodies + = ComponentManager::GetInstance().GetComponentsByType(); + for (Rigidbody & rigidbody : rigidBodies) { //std::cout << rigidbody.get().mMass << " " << rigidbody.get().mGravityScale << " " << rigidbody.get().mBodyType << std::endl; } //std::cout << std::endl; - std::vector> coliders = ComponentManager::GetInstance().GetComponentsByType(); - for(Colider& colider : coliders) { + std::vector> coliders + = ComponentManager::GetInstance().GetComponentsByType(); + for (Colider & colider : coliders) { //std::cout << colider.get().mSize << std::endl; } auto stopLooping = std::chrono::high_resolution_clock::now(); for (int i = 0; i < 100000; ++i) { - delete gameObject[i]; + delete gameObject[i]; } - auto Addtime = std::chrono::duration_cast(stopAdding - startAdding); - auto LoopTime = std::chrono::duration_cast(stopLooping - stopAdding); + auto Addtime = std::chrono::duration_cast( + stopAdding - startAdding); + auto LoopTime = std::chrono::duration_cast( + stopLooping - stopAdding); std::cout << "AddTime: " << Addtime.count() << " us" << std::endl; std::cout << "LoopTime: " << LoopTime.count() << " us" << std::endl; } diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 208ba1f..5840208 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -2,12 +2,20 @@ target_sources(crepe PUBLIC Asset.cpp Sound.cpp SoundContext.cpp + ComponentManager.cpp + Components.cpp + GameObject.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES Asset.h Sound.h SoundContext.h + ComponentManager.h + ComponentManager.hpp + Components.h + GameObject.h + GameObject.hpp ) add_subdirectory(api) diff --git a/src/crepe/ComponentManager.cpp b/src/crepe/ComponentManager.cpp new file mode 100644 index 0000000..b7a1bea --- /dev/null +++ b/src/crepe/ComponentManager.cpp @@ -0,0 +1,25 @@ +#include "ComponentManager.h" + +using namespace crepe; + +ComponentManager & ComponentManager::get_instance() { + static ComponentManager instance; + return instance; +} + +void ComponentManager::DeleteAllComponentsOfId(std::uint32_t id) { + // Loop through all the types (in the unordered_map<>) + for (auto & [type, componentArray] : components) { + // Make sure that the id (that we are looking for) is within the boundaries of the vector<> + if (id < componentArray.size()) { + // Clear the components at this specific id + componentArray[id].clear(); + } + } +} + +void ComponentManager::DeleteAllComponents() { + // Clear the whole unordered_map<> + components.clear(); +} + diff --git a/src/crepe/ComponentManager.h b/src/crepe/ComponentManager.h new file mode 100644 index 0000000..003cd0b --- /dev/null +++ b/src/crepe/ComponentManager.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "Components.h" + +namespace crepe { + +class ComponentManager { +public: + // Singleton + static ComponentManager & get_instance(); + ComponentManager(const ComponentManager &) = delete; + ComponentManager(ComponentManager &&) = delete; + ComponentManager & operator=(const ComponentManager &) = delete; + ComponentManager & operator=(ComponentManager &&) = delete; + +public: + //! Add a component of a specific type + template void AddComponent(std::uint32_t id, Args &&... args); + //! Deletes all components of a specific type and id + template void DeleteComponentsById(std::uint32_t id); + //! Deletes all components of a specific type + template void DeleteComponents(); + //! Deletes all components of a specific id + void DeleteAllComponentsOfId(std::uint32_t id); + //! Deletes all components + void DeleteAllComponents(); + + //! Get a vector<> of all components at specific type and id + template std::vector> GetComponentsByID(std::uint32_t id) const; + //! Get a vector<> of all components of a specific type + template std::vector> GetComponentsByType() const; + +private: + ComponentManager() = default; + + /* + * The std::unordered_map>>> below might seem a bit strange, let me explain this structure: + * The std::unordered_map<> has a key and value. The key is a std::type_index and the value is a std::vector. So, a new std::vector will be created for each new std::type_index. + * The first std::vector<> stores another vector<>. This first vector<> is to bind the entity's id to a component. + * The second std::vector<> stores unique_ptrs. Each component can be gathered via an unique_ptr. This second vector<> allows multiple components of the same std::type_index for one entity (id). + */ + std::unordered_map>>> components; +}; + +} + +// #include "ComponentManager.hpp" + diff --git a/src/crepe/ComponentManager.hpp b/src/crepe/ComponentManager.hpp new file mode 100644 index 0000000..602490e --- /dev/null +++ b/src/crepe/ComponentManager.hpp @@ -0,0 +1,134 @@ +#pragma once + +#include "ComponentManager.h" + +namespace crepe { + +template +void ComponentManager::AddComponent(std::uint32_t id, Args &&... args) { + // Determine the type of T (this is used as the key of the unordered_map<>) + std::type_index type = typeid(T); + + // Check if this component type is already in the unordered_map<> + if (components.find(type) == components.end()) { + //If not, create a new (empty) vector<> of vector> + components[type] = std::vector>>(); + } + + // Resize the vector<> if the id is greater than the current size + if (id >= components[type].size()) { + // Initialize new slots to nullptr (resize does automatically init to nullptr) + components[type].resize(id + 1); + } + + // Create a new component of type T using perfect forwarding and store its + // unique_ptr in the vector<> + components[type][id].push_back(std::make_unique(std::forward(args)...)); +} + +template +void ComponentManager::DeleteComponentsById(std::uint32_t id) { + // Determine the type of T (this is used as the key of the unordered_map<>) + std::type_index type = typeid(T); + + // Find the type (in the unordered_map<>) + if (components.find(type) != components.end()) { + // Get the correct vector<> + std::vector>> & componentArray = components[type]; + + // Make sure that the id (that we are looking for) is within the boundaries of the vector<> + if (id < componentArray.size()) { + // Clear the whole vector<> of this specific type and id + componentArray[id].clear(); + } + } +} + +template +void ComponentManager::DeleteComponents() { + // Determine the type of T (this is used as the key of the unordered_map<>) + std::type_index type = typeid(T); + + // Find the type (in the unordered_map<>) + if (components.find(type) != components.end()) { + // Clear the whole vector<> of this specific type + components[type].clear(); + } +} + +template +std::vector> +ComponentManager::GetComponentsByID(std::uint32_t id) const { + // Determine the type of T (this is used as the key of the unordered_map<>) + std::type_index type = typeid(T); + + // Create an empty vector<> + std::vector> componentVector; + + // Find the type (in the unordered_map<>) + if (components.find(type) != components.end()) { + // Get the correct vector<> + const std::vector>> & componentArray = components.at(type); + + // Make sure that the id (that we are looking for) is within the boundaries of the vector<> + if (id < componentArray .size()) { + // Loop trough the whole vector<> + for (const std::unique_ptr & componentPtr : componentArray[id]) { + // Cast the unique_ptr to a raw pointer + T * castedComponent = static_cast(componentPtr.get()); + + // Ensure that the cast was successful + if (castedComponent) { + // Add the dereferenced raw pointer to the vector<> + componentVector.push_back(*castedComponent); + } + } + } + } + + // Return the vector<> + return componentVector; +} + +template +std::vector> +ComponentManager::GetComponentsByType() const { + // Determine the type of T (this is used as the key of the unordered_map<>) + std::type_index type = typeid(T); + + // Create an empty vector<> + std::vector> componentVector; + // Set the id to 0 (the id will also be stored in the returned vector<>) + // std::uint32_t id = 0; + + // Find the type (in the unordered_map<>) + if (components.find(type) != components.end()) { + + // Get the correct vector<> + const std::vector>> & componentArray = components.at(type); + + // Loop through the whole vector<> + for (const std::vector> & component : componentArray) { + // Loop trough the whole vector<> + for (const std::unique_ptr & componentPtr : component) { + // Cast the unique_ptr to a raw pointer + T * castedComponent = static_cast(componentPtr.get()); + + // Ensure that the cast was successful + if (castedComponent) { + // Pair the dereferenced raw pointer and the id and add it to the vector<> + componentVector.emplace_back(std::ref(*castedComponent)); + } + } + + // Increase the id (the id will also be stored in the returned vector<>) + //++id; + } + } + + // Return the vector<> + return componentVector; +} + +} + diff --git a/src/crepe/Components.cpp b/src/crepe/Components.cpp new file mode 100644 index 0000000..9760daa --- /dev/null +++ b/src/crepe/Components.cpp @@ -0,0 +1,13 @@ +#include "Components.h" +#include + +using namespace crepe; + +Component::Component() : mActive(true) {} + +Sprite::Sprite(std::string path) : mPath(path) {} + +Rigidbody::Rigidbody(int mass, int gravityScale, int bodyType) + : mMass(mass), mGravityScale(gravityScale), mBodyType(bodyType) {} + +Colider::Colider(int size) : mSize(size) {} diff --git a/src/crepe/Components.h b/src/crepe/Components.h new file mode 100644 index 0000000..7cb6fbb --- /dev/null +++ b/src/crepe/Components.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace crepe { + +class Component { +public: + Component(); + + bool mActive; +}; + +// TODO: these should be in separate files + +class Sprite : public Component { +public: + Sprite(std::string path); + + std::string mPath; +}; + +class Rigidbody : public Component { +public: + Rigidbody(int mass, int gravityScale, int bodyType); + + int mMass; + int mGravityScale; + int mBodyType; +}; + +class Colider : public Component { +public: + Colider(int size); + + int mSize; +}; + +} diff --git a/src/crepe/GameObject.cpp b/src/crepe/GameObject.cpp new file mode 100644 index 0000000..5ac9d7a --- /dev/null +++ b/src/crepe/GameObject.cpp @@ -0,0 +1,9 @@ +#include "GameObject.h" + +#include "ComponentManager.h" + +using namespace crepe; + +GameObject::GameObject(std::uint32_t id, std::string name, std::string tag, + int layer) + : mId(id), mName(name), mTag(tag), mActive(true), mLayer(layer) {} diff --git a/src/crepe/GameObject.h b/src/crepe/GameObject.h new file mode 100644 index 0000000..71ef60d --- /dev/null +++ b/src/crepe/GameObject.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace crepe { + +class GameObject { +public: + GameObject(std::uint32_t id, std::string name, std::string tag, int layer); + + template void AddComponent(Args &&... args); + + std::uint32_t mId; + std::string mName; + std::string mTag; + bool mActive; + int mLayer; +}; + +} + diff --git a/src/crepe/GameObject.hpp b/src/crepe/GameObject.hpp new file mode 100644 index 0000000..5a672cf --- /dev/null +++ b/src/crepe/GameObject.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "GameObject.h" + +#include "ComponentManager.h" + +namespace crepe { + +template +void GameObject::AddComponent(Args &&... args) { + ComponentManager::get_instance().AddComponent(mId, std::forward(args)...); +} + +} + -- cgit v1.2.3 From aa8755148cbca29b584f7a146636b506070717f9 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 6 Oct 2024 15:28:12 +0200 Subject: move components to separate files --- contributing.md | 1 + src/crepe/CMakeLists.txt | 10 ++++++++-- src/crepe/Collider.cpp | 6 ++++++ src/crepe/Collider.h | 15 ++++++++++++++ src/crepe/Component.cpp | 6 ++++++ src/crepe/Component.h | 15 ++++++++++++++ src/crepe/ComponentManager.h | 2 +- src/crepe/Components.cpp | 13 ------------- src/crepe/Components.h | 39 ------------------------------------- src/crepe/Rigidbody.cpp | 7 +++++++ src/crepe/Rigidbody.h | 16 +++++++++++++++ src/crepe/Sprite.cpp | 9 +++++++++ src/crepe/Sprite.h | 17 ++++++++++++++++ src/example/components_internal.cpp | 5 ++++- 14 files changed, 105 insertions(+), 56 deletions(-) create mode 100644 src/crepe/Collider.cpp create mode 100644 src/crepe/Collider.h create mode 100644 src/crepe/Component.cpp create mode 100644 src/crepe/Component.h delete mode 100644 src/crepe/Components.cpp delete mode 100644 src/crepe/Components.h create mode 100644 src/crepe/Rigidbody.cpp create mode 100644 src/crepe/Rigidbody.h create mode 100644 src/crepe/Sprite.cpp create mode 100644 src/crepe/Sprite.h (limited to 'src/crepe/CMakeLists.txt') diff --git a/contributing.md b/contributing.md index 933f1bf..b79f7a7 100644 --- a/contributing.md +++ b/contributing.md @@ -17,6 +17,7 @@ # Code style - ASCII only +- Class names are always singular - Explanatory comments are placed above the line(s) they are explaining - Source files should only contain comments that plainly state what the code is supposed to do diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 5840208..d7d563e 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -3,8 +3,11 @@ target_sources(crepe PUBLIC Sound.cpp SoundContext.cpp ComponentManager.cpp - Components.cpp + Component.cpp GameObject.cpp + Collider.cpp + Rigidbody.cpp + Sprite.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -13,9 +16,12 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES SoundContext.h ComponentManager.h ComponentManager.hpp - Components.h + Component.h GameObject.h GameObject.hpp + Collider.h + Rigidbody.h + Sprite.h ) add_subdirectory(api) diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp new file mode 100644 index 0000000..b7040eb --- /dev/null +++ b/src/crepe/Collider.cpp @@ -0,0 +1,6 @@ +#include "Collider.h" + +using namespace crepe; + +Collider::Collider(int size) : size(size) {} + diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h new file mode 100644 index 0000000..666386d --- /dev/null +++ b/src/crepe/Collider.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Component.h" + +namespace crepe { + +class Collider : public Component { +public: + Collider(int size); + + int size; +}; + +} + diff --git a/src/crepe/Component.cpp b/src/crepe/Component.cpp new file mode 100644 index 0000000..9a7731a --- /dev/null +++ b/src/crepe/Component.cpp @@ -0,0 +1,6 @@ +#include "Component.h" + +using namespace crepe; + +Component::Component() : active(true) {} + diff --git a/src/crepe/Component.h b/src/crepe/Component.h new file mode 100644 index 0000000..6e23d93 --- /dev/null +++ b/src/crepe/Component.h @@ -0,0 +1,15 @@ +#pragma once + +namespace crepe { + +class Component { +public: + Component(); + // TODO: shouldn't this constructor be deleted because this class will never + // directly be instantiated? + + bool active; +}; + +} // namespace crepe + diff --git a/src/crepe/ComponentManager.h b/src/crepe/ComponentManager.h index 9e559dd..9463558 100644 --- a/src/crepe/ComponentManager.h +++ b/src/crepe/ComponentManager.h @@ -7,7 +7,7 @@ #include #include -#include "Components.h" +#include "Component.h" namespace crepe { diff --git a/src/crepe/Components.cpp b/src/crepe/Components.cpp deleted file mode 100644 index f27c7a4..0000000 --- a/src/crepe/Components.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "Components.h" - -using namespace crepe; -using namespace std; - -Component::Component() : active(true) {} - -Sprite::Sprite(string path) : path(path) {} - -Rigidbody::Rigidbody(int mass, int gravityScale, int bodyType) - : mass(mass), gravity_scale(gravityScale), body_type(bodyType) {} - -Collider::Collider(int size) : size(size) {} diff --git a/src/crepe/Components.h b/src/crepe/Components.h deleted file mode 100644 index 139599c..0000000 --- a/src/crepe/Components.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include - -namespace crepe { - -class Component { -public: - Component(); - - bool active; -}; - -// TODO: these should be in separate files - -class Sprite : public Component { -public: - Sprite(std::string path); - - std::string path; -}; - -class Rigidbody : public Component { -public: - Rigidbody(int mass, int gravityScale, int bodyType); - - int mass; - int gravity_scale; - int body_type; -}; - -class Collider : public Component { -public: - Collider(int size); - - int size; -}; - -} // namespace crepe diff --git a/src/crepe/Rigidbody.cpp b/src/crepe/Rigidbody.cpp new file mode 100644 index 0000000..1518d28 --- /dev/null +++ b/src/crepe/Rigidbody.cpp @@ -0,0 +1,7 @@ +#include "Rigidbody.h" + +using namespace crepe; + +Rigidbody::Rigidbody(int mass, int gravityScale, int bodyType) + : mass(mass), gravity_scale(gravityScale), body_type(bodyType) {} + diff --git a/src/crepe/Rigidbody.h b/src/crepe/Rigidbody.h new file mode 100644 index 0000000..67edb03 --- /dev/null +++ b/src/crepe/Rigidbody.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Component.h" + +namespace crepe { + +class Rigidbody : public Component { +public: + Rigidbody(int mass, int gravityScale, int bodyType); + + int mass; + int gravity_scale; + int body_type; +}; + +} diff --git a/src/crepe/Sprite.cpp b/src/crepe/Sprite.cpp new file mode 100644 index 0000000..c835d83 --- /dev/null +++ b/src/crepe/Sprite.cpp @@ -0,0 +1,9 @@ +#include + +#include "Sprite.h" + +using namespace crepe; +using namespace std; + +Sprite::Sprite(string path) : path(path) {} + diff --git a/src/crepe/Sprite.h b/src/crepe/Sprite.h new file mode 100644 index 0000000..029064b --- /dev/null +++ b/src/crepe/Sprite.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "Component.h" + +namespace crepe { + +class Sprite : public Component { +public: + Sprite(std::string path); + + std::string path; +}; + +} + diff --git a/src/example/components_internal.cpp b/src/example/components_internal.cpp index 821a7de..4246dd7 100644 --- a/src/example/components_internal.cpp +++ b/src/example/components_internal.cpp @@ -9,7 +9,10 @@ #include #include #include -#include +#include +#include +#include +#include using namespace crepe; using namespace std; -- cgit v1.2.3 From 2969fe8c0fca4826ca129fe12d2e125bb7955c78 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 6 Oct 2024 17:39:15 +0200 Subject: WIP ScriptSystem --- src/crepe/CMakeLists.txt | 4 ++++ src/crepe/ComponentManager.hpp | 14 ++++++++++---- src/crepe/Script.cpp | 7 +++++++ src/crepe/Script.h | 16 ++++++++++++++++ src/crepe/ScriptSystem.cpp | 22 ++++++++++++++++++++++ src/crepe/ScriptSystem.h | 18 ++++++++++++++++++ src/crepe/System.h | 23 +++++++++++++++++++++++ src/crepe/api/BehaviorScript.cpp | 10 ++++++++++ src/crepe/api/BehaviorScript.h | 17 +++++++++++++++++ src/crepe/api/CMakeLists.txt | 5 +++-- src/crepe/api/Component.h | 10 ---------- src/example/CMakeLists.txt | 1 + src/example/script.cpp | 33 +++++++++++++++++++++++++++++++++ 13 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 src/crepe/Script.cpp create mode 100644 src/crepe/Script.h create mode 100644 src/crepe/ScriptSystem.cpp create mode 100644 src/crepe/ScriptSystem.h create mode 100644 src/crepe/System.h create mode 100644 src/crepe/api/BehaviorScript.cpp create mode 100644 src/crepe/api/BehaviorScript.h delete mode 100644 src/crepe/api/Component.h create mode 100644 src/example/script.cpp (limited to 'src/crepe/CMakeLists.txt') diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index d7d563e..d85aef0 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -8,6 +8,8 @@ target_sources(crepe PUBLIC Collider.cpp Rigidbody.cpp Sprite.cpp + ScriptSystem.cpp + Script.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -22,6 +24,8 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Collider.h Rigidbody.h Sprite.h + System.h + ScriptSystem.h ) add_subdirectory(api) diff --git a/src/crepe/ComponentManager.hpp b/src/crepe/ComponentManager.hpp index 999cdcf..084cd33 100644 --- a/src/crepe/ComponentManager.hpp +++ b/src/crepe/ComponentManager.hpp @@ -1,13 +1,17 @@ #pragma once +#include + #include "ComponentManager.h" namespace crepe { -template +template void ComponentManager::add_component(uint32_t id, Args &&... args) { using namespace std; + static_assert(is_base_of::value, "add_component must recieve a derivative class of Component"); + // Determine the type of T (this is used as the key of the unordered_map<>) type_index type = typeid(T); @@ -23,9 +27,11 @@ void ComponentManager::add_component(uint32_t id, Args &&... args) { components[type].resize(id + 1); } - // Create a new component of type T using perfect forwarding and store its - // unique_ptr in the vector<> - components[type][id].push_back(make_unique(forward(args)...)); + // Create a new component of type T (arguments directly forwarded). The + // constructor must be called by ComponentManager. + T * instance = new T(forward(args)...); + // store its unique_ptr in the vector<> + components[type][id].push_back(unique_ptr(instance)); } template diff --git a/src/crepe/Script.cpp b/src/crepe/Script.cpp new file mode 100644 index 0000000..42e3666 --- /dev/null +++ b/src/crepe/Script.cpp @@ -0,0 +1,7 @@ +#include "Script.h" + +using namespace crepe; + +void Script::init() { } +void Script::update() { } + diff --git a/src/crepe/Script.h b/src/crepe/Script.h new file mode 100644 index 0000000..ba4073a --- /dev/null +++ b/src/crepe/Script.h @@ -0,0 +1,16 @@ +#pragma once + +namespace crepe { + +class Script { +protected: + virtual void init(); + virtual void update(); + // NOTE: additional *events* (like unity's OnDisable and OnEnable) should be + // implemented as member methods in derivative user script classes and + // registered in init(), otherwise this class will balloon in size with each + // added event. +}; + +} + diff --git a/src/crepe/ScriptSystem.cpp b/src/crepe/ScriptSystem.cpp new file mode 100644 index 0000000..e301c71 --- /dev/null +++ b/src/crepe/ScriptSystem.cpp @@ -0,0 +1,22 @@ +#include "util/log.h" + +#include "ScriptSystem.h" + +using namespace crepe; + +ScriptSystem::ScriptSystem() { + dbg_trace(); +} +ScriptSystem::~ScriptSystem() { + dbg_trace(); +} + +ScriptSystem & ScriptSystem::get_instance() { + static ScriptSystem instance; + return instance; +} + +void ScriptSystem::update() { + dbg_trace(); +} + diff --git a/src/crepe/ScriptSystem.h b/src/crepe/ScriptSystem.h new file mode 100644 index 0000000..e1ed290 --- /dev/null +++ b/src/crepe/ScriptSystem.h @@ -0,0 +1,18 @@ +#pragma once + +#include "System.h" + +namespace crepe { + +class ScriptSystem : public System { +public: + static ScriptSystem & get_instance(); + virtual void update(); + +private: + ScriptSystem(); + ~ScriptSystem(); +}; + +} + diff --git a/src/crepe/System.h b/src/crepe/System.h new file mode 100644 index 0000000..3fe3d66 --- /dev/null +++ b/src/crepe/System.h @@ -0,0 +1,23 @@ +#pragma once + +namespace crepe { + +class System { +public: + static System & get_instance(); + virtual void update() = 0; + +protected: + System() { }; + virtual ~System() { }; + +private: + // singleton + System(const System &) = delete; + System(System &&) = delete; + System & operator=(const System &) = delete; + System & operator=(System &&) = delete; +}; + +} + diff --git a/src/crepe/api/BehaviorScript.cpp b/src/crepe/api/BehaviorScript.cpp new file mode 100644 index 0000000..2dd933e --- /dev/null +++ b/src/crepe/api/BehaviorScript.cpp @@ -0,0 +1,10 @@ +#include "../util/log.h" + +#include "BehaviorScript.h" + +using namespace crepe::api; + +BehaviorScript::BehaviorScript() { + dbg_trace(); +} + diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h new file mode 100644 index 0000000..e9542c1 --- /dev/null +++ b/src/crepe/api/BehaviorScript.h @@ -0,0 +1,17 @@ +#pragma once + +#include "../Script.h" +#include "../Component.h" + +namespace crepe::api { + +class BehaviorScript : public Script, public Component { + // only allow ComponentManager to instantiate scripts + friend class ComponentManager; + +protected: + BehaviorScript(); +}; + +} + diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 9548594..86623de 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -1,9 +1,10 @@ target_sources(crepe PUBLIC # AudioSource.cpp + BehaviorScript.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES - AudioSource.h - Component.h + # AudioSource.h + BehaviorScript.h ) diff --git a/src/crepe/api/Component.h b/src/crepe/api/Component.h deleted file mode 100644 index d5e0499..0000000 --- a/src/crepe/api/Component.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace crepe::api { - -class Component { -public: - bool active; -}; - -} // namespace crepe::api diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index eef38fd..6df4ce7 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -14,4 +14,5 @@ endfunction() add_example(audio_internal) add_example(components_internal) +add_example(script) diff --git a/src/example/script.cpp b/src/example/script.cpp new file mode 100644 index 0000000..28605c7 --- /dev/null +++ b/src/example/script.cpp @@ -0,0 +1,33 @@ +/** \file + * + * Standalone example for usage of the script component and system + */ + +#include +#include +#include +#include + +#include + +using namespace crepe; +using namespace std; + +class MyScript : public api::BehaviorScript { + void update() { + dbg_trace(); + } +}; + +int main() { + dbg_trace(); + + auto obj = GameObject(0, "name", "tag", 0); + obj.add_component(); + + auto & sys = ScriptSystem::get_instance(); + sys.update(); // -> MyScript::update + + return 0; +} + -- cgit v1.2.3 From 1f82ffa4d3ee8355215d43bf43edf8cecaca0d1d Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 16 Oct 2024 17:21:04 +0200 Subject: fix user script implementation --- src/crepe/CMakeLists.txt | 1 - src/crepe/ComponentManager.h | 2 +- src/crepe/ComponentManager.hpp | 5 +++-- src/crepe/GameObject.h | 2 +- src/crepe/GameObject.hpp | 4 ++-- src/crepe/Script.cpp | 7 ------- src/crepe/Script.h | 16 ---------------- src/crepe/ScriptSystem.cpp | 27 ++++++++++++++++++++++----- src/crepe/ScriptSystem.h | 12 +++++++++++- src/crepe/api/BehaviorScript.h | 24 ++++++++++++++++++------ src/crepe/api/BehaviorScript.hpp | 18 ++++++++++++++++++ src/crepe/api/CMakeLists.txt | 2 ++ src/crepe/api/Script.cpp | 5 +++++ src/crepe/api/Script.h | 21 +++++++++++++++++++++ src/example/script.cpp | 7 ++++--- 15 files changed, 108 insertions(+), 45 deletions(-) delete mode 100644 src/crepe/Script.cpp delete mode 100644 src/crepe/Script.h create mode 100644 src/crepe/api/BehaviorScript.hpp create mode 100644 src/crepe/api/Script.cpp create mode 100644 src/crepe/api/Script.h (limited to 'src/crepe/CMakeLists.txt') diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index d85aef0..8323490 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -9,7 +9,6 @@ target_sources(crepe PUBLIC Rigidbody.cpp Sprite.cpp ScriptSystem.cpp - Script.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES diff --git a/src/crepe/ComponentManager.h b/src/crepe/ComponentManager.h index eab9b45..38f32e4 100644 --- a/src/crepe/ComponentManager.h +++ b/src/crepe/ComponentManager.h @@ -23,7 +23,7 @@ public: public: //! Add a component of a specific type template - void add_component(uint32_t id, Args &&... args); + T & add_component(uint32_t id, Args &&... args); //! Deletes all components of a specific type and id template void delete_components_by_id(uint32_t id); diff --git a/src/crepe/ComponentManager.hpp b/src/crepe/ComponentManager.hpp index c872594..e0242a2 100644 --- a/src/crepe/ComponentManager.hpp +++ b/src/crepe/ComponentManager.hpp @@ -3,12 +3,11 @@ #include #include "ComponentManager.h" -#include "api/BehaviorScript.h" namespace crepe { template -void ComponentManager::add_component(uint32_t id, Args &&... args) { +T & ComponentManager::add_component(uint32_t id, Args &&... args) { using namespace std; static_assert(is_base_of::value, "add_component must recieve a derivative class of Component"); @@ -33,6 +32,8 @@ void ComponentManager::add_component(uint32_t id, Args &&... args) { T * instance = new T(forward(args)...); // store its unique_ptr in the vector<> components[type][id].push_back(unique_ptr(instance)); + + return *instance; } template diff --git a/src/crepe/GameObject.h b/src/crepe/GameObject.h index 3588d9a..b5d6399 100644 --- a/src/crepe/GameObject.h +++ b/src/crepe/GameObject.h @@ -10,7 +10,7 @@ public: GameObject(uint32_t id, std::string name, std::string tag, int layer); template - void add_component(Args &&... args); + T & add_component(Args &&... args); uint32_t id; std::string name; diff --git a/src/crepe/GameObject.hpp b/src/crepe/GameObject.hpp index 5966fbf..8cd1abe 100644 --- a/src/crepe/GameObject.hpp +++ b/src/crepe/GameObject.hpp @@ -7,9 +7,9 @@ namespace crepe { template -void GameObject::add_component(Args &&... args) { +T & GameObject::add_component(Args &&... args) { auto & mgr = ComponentManager::get_instance(); - mgr.add_component(id, std::forward(args)...); + return mgr.add_component(id, std::forward(args)...); } } // namespace crepe diff --git a/src/crepe/Script.cpp b/src/crepe/Script.cpp deleted file mode 100644 index 42e3666..0000000 --- a/src/crepe/Script.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "Script.h" - -using namespace crepe; - -void Script::init() { } -void Script::update() { } - diff --git a/src/crepe/Script.h b/src/crepe/Script.h deleted file mode 100644 index ba4073a..0000000 --- a/src/crepe/Script.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace crepe { - -class Script { -protected: - virtual void init(); - virtual void update(); - // NOTE: additional *events* (like unity's OnDisable and OnEnable) should be - // implemented as member methods in derivative user script classes and - // registered in init(), otherwise this class will balloon in size with each - // added event. -}; - -} - diff --git a/src/crepe/ScriptSystem.cpp b/src/crepe/ScriptSystem.cpp index e40909e..0537c16 100644 --- a/src/crepe/ScriptSystem.cpp +++ b/src/crepe/ScriptSystem.cpp @@ -1,12 +1,16 @@ +#include +#include #include + +#include "ScriptSystem.h" #include "ComponentManager.h" #include "api/BehaviorScript.h" -#include "util/fmt.h" +#include "api/Script.h" #include "util/log.h" -#include "ScriptSystem.h" - +using namespace std; using namespace crepe; +using namespace crepe::api; ScriptSystem::ScriptSystem() { dbg_trace(); @@ -24,10 +28,23 @@ void ScriptSystem::update() { using namespace std; dbg_trace(); + forward_list