From 66763b223de52798856c8ba3d064eee0843f61d3 Mon Sep 17 00:00:00 2001 From: Dennis Meinen Date: Fri, 29 Mar 2024 12:19:22 +0100 Subject: [PATCH] Changed Textures to AssetHandler. Moved the tile/rectangle methods to a future spritesheet util. Moved loading of fonts/sounds/musics into the AssetHandler. Added GetAudioEngine() so the AssetHandler can call this to load sounds with. Added GetLoadedMusics() to AssetHandler so the AudioHandler can check all the musics that need to play. --- CMakeLists.txt | 4 +- .../assethandler.cpp | 123 ++++++++++----- assethandler/assethandler.h | 139 +++++++++++++++++ {texture => assethandler}/stb_image_write.h | 0 assettypes/music.h | 9 +- audio/audiohandler.cpp | 90 +++-------- audio/audiohandler.h | 42 ++--- log/loghandler.cpp | 3 +- luminoveau.h | 2 +- render2d/render2dhandler.h | 2 +- text/texthandler.cpp | 27 ---- text/texthandler.h | 18 +-- texture/texturehandler.h | 143 ------------------ utils/helpers.cpp | 4 +- window/windowhandler.cpp | 6 +- 15 files changed, 271 insertions(+), 341 deletions(-) rename texture/texturehandler.cpp => assethandler/assethandler.cpp (50%) create mode 100644 assethandler/assethandler.h rename {texture => assethandler}/stb_image_write.h (100%) delete mode 100644 texture/texturehandler.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a50154..2ebcb5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,8 +36,8 @@ add_library("luminoveau" STATIC state/state.h state/state.cpp - texture/texturehandler.cpp - texture/texturehandler.h + assethandler/assethandler.cpp + assethandler/assethandler.h utils/camera.h utils/colors.h utils/constants.h diff --git a/texture/texturehandler.cpp b/assethandler/assethandler.cpp similarity index 50% rename from texture/texturehandler.cpp rename to assethandler/assethandler.cpp index a0f69c6..95fa6ed 100644 --- a/texture/texturehandler.cpp +++ b/assethandler/assethandler.cpp @@ -1,11 +1,11 @@ -#include "texturehandler.h" +#include "assethandler.h" #include "window/windowhandler.h" #define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" -Texture Textures::_getTexture(const std::string &fileName) { +Texture AssetHandler::_getTexture(const std::string &fileName) { if (_textures.find(fileName) == _textures.end()) { Texture _tex = _loadTexture(fileName); _textures[std::string(fileName)] = _tex; @@ -16,46 +16,9 @@ Texture Textures::_getTexture(const std::string &fileName) { } } -rectf Textures::_getRectangle(int x, int y) { - const rectf rect = {(float) (x * Configuration::tileWidth), (float) (y * Configuration::tileHeight), - (float) (Configuration::tileWidth), - (float) (Configuration::tileHeight)}; - return rect; -}; -rectf Textures::_getRectangle(int x, int y, int spriteWidth, int spriteHeight) { - - const rectf rect = {(float) (x * spriteWidth), (float) (y * spriteHeight), - (float) (spriteWidth), - (float) (spriteHeight)}; - return rect; -}; - -rectf Textures::_getTile(int tileId) { - return GetRectangle(tileId % 16, (int) tileId / 16); -}; - -rectf Textures::_getTile(int tileId, bool doubleHeight) { - rectf r = GetRectangle(tileId % 16, (int) tileId / 16); - if (doubleHeight) { - r.y -= r.height; - r.height *= 2; - } - return r; -} - -rectf Textures::_getTile(int tileId, bool doubleHeight, int spriteWidth, int spriteHeight) { - rectf r = GetRectangle(tileId % 16, (int) tileId / 16, spriteWidth, spriteHeight); - if (doubleHeight) { - r.y -= r.height; - r.height *= 2; - } - return r; -} - - -Texture Textures::_loadTexture(const std::string &fileName) { +Texture AssetHandler::_loadTexture(const std::string &fileName) { Texture texture; @@ -93,7 +56,7 @@ Texture Textures::_loadTexture(const std::string &fileName) { } -Texture Textures::_createEmptyTexture(const vf2d &size) { +Texture AssetHandler::_createEmptyTexture(const vf2d &size) { Texture texture; texture.width = size.x; @@ -107,7 +70,7 @@ Texture Textures::_createEmptyTexture(const vf2d &size) { return texture; } -void Textures::_saveTextureAsPNG(Texture texture, const char *fileName) { +void AssetHandler::_saveTextureAsPNG(Texture texture, const char *fileName) { SDL_Surface *surface = texture.surface; @@ -115,7 +78,13 @@ void Textures::_saveTextureAsPNG(Texture texture, const char *fileName) { int texWidth, texHeight; SDL_QueryTexture(texture.texture, NULL, NULL, &texWidth, &texHeight); surface = SDL_CreateSurface(texWidth, texHeight, 32); + + if (!surface) { + SDL_Log("%s", SDL_GetError()); + } + SDL_RenderReadPixels(Window::GetRenderer(), NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch); + } SDL_Surface *rgbaSurface = surface; @@ -138,3 +107,73 @@ void Textures::_saveTextureAsPNG(Texture texture, const char *fileName) { SDL_DestroySurface(rgbaSurface); } } + +Sound AssetHandler::_getSound(const std::string &fileName) { + if (_sounds.find(fileName) == _sounds.end()) { + Sound _sound; + _sound.sound = new ma_sound(); + ma_result result = ma_sound_init_from_file(Audio::GetAudioEngine(), fileName.c_str(), MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, nullptr, nullptr, _sound.sound); + + if (result != MA_SUCCESS) { + std::string error = Helpers::TextFormat("GetSound failed: %s", fileName.c_str()); + + SDL_Log("%s", error.c_str()); + throw std::runtime_error(error.c_str()); + } + + _sounds[fileName] = _sound; + + return _sounds[fileName]; + } else { + return _sounds[fileName]; + } +} + +Music AssetHandler::_getMusic(const std::string &fileName) { + if (_musics.find(fileName) == _musics.end()) { + MusicAsset _music; + + _music.music = new ma_sound(); + ma_result result = ma_sound_init_from_file(Audio::GetAudioEngine(), fileName.c_str(), MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, nullptr, nullptr, _music.music); + + if (result != MA_SUCCESS) { + std::string error = Helpers::TextFormat("GetMusic failed: %s", fileName.c_str()); + + SDL_Log("%s", error.c_str()); + throw std::runtime_error(error.c_str()); + } + + _musics[fileName] = _music; + + return _musics[fileName]; + } else { + return _musics[fileName]; + } +} + + +Font AssetHandler::_getFont(const std::string &fileName, const int fontSize) { + std::string index = std::string(Helpers::TextFormat("%s%d", fileName.c_str(), fontSize)); + + auto it = _fonts.find(index); + + if (it == _fonts.end()) { + + Font _font; + _font.font = TTF_OpenFont(fileName.c_str(), fontSize); + + if (_font.font == nullptr) { + std::string error = Helpers::TextFormat("Couldn't load %d pt font from %s: %s\n", + fontSize, fileName.c_str(), SDL_GetError()); + + SDL_Log("%s", error.c_str()); + throw std::runtime_error(error.c_str()); + } + + _fonts[index] = _font; + + return _fonts[index]; + } else { + return _fonts[index]; + } +} \ No newline at end of file diff --git a/assethandler/assethandler.h b/assethandler/assethandler.h new file mode 100644 index 0000000..e70b3e9 --- /dev/null +++ b/assethandler/assethandler.h @@ -0,0 +1,139 @@ +#pragma once + +#include +#include + +#include "SDL3/SDL.h" +#include "SDL3_image/SDL_image.h" + +#include "utils/vectors.h" +#include "utils/rectangles.h" + +#include "audio/audiohandler.h" + +#include "assettypes/font.h" +#include "assettypes/music.h" +#include "assettypes/sound.h" +#include "assettypes/texture.h" + +/** + * @brief Manages assets and provides utility functions for working with assets. + */ +class AssetHandler { +public: + /** + * @brief Retrieves a texture by its file name. + * + * @param fileName The name of the texture file. + * @return The texture corresponding to the file name. + */ + static Texture GetTexture(const char *fileName) { return get()._getTexture(fileName); } + + /** + * @brief Loads a texture from the specified file. + * + * @param fileName The name of the texture file to load. + */ + static void LoadTexture(const char *fileName) { get()._loadTexture(fileName); } + + /** + * @brief Saves the given texture as a PNG file. + * + * @param texture The texture to save. + * @param fileName The name of the PNG file to save. + */ + static void SaveTextureAsPNG(Texture texture, const char *fileName) { get()._saveTextureAsPNG(texture, fileName); } + + /** + * @brief Creates an empty texture with the specified size. + * + * @param size The size of the empty texture. + * @return The created empty texture. + */ + static Texture CreateEmptyTexture(vf2d size) { return get()._createEmptyTexture(size); } + + /** + * @brief Retrieves a map of all loaded textures. + * + * @return The map of loaded textures. + */ + static std::unordered_map GetTextures() { return get()._textures; } + + /** + * @brief Retrieves a font asset with the specified filename and font size. + * + * @param fileName The filename of the font asset. + * @param fontSize The size of the font. + * @return The font asset. + */ + static Font GetFont(const char *fileName, const int fontSize) { + return get()._getFont(fileName, fontSize); + } + + /** + * @brief Retrieves a music asset. + * + * @param fileName The filename of the music asset. + * @return The music asset. + */ + static Music& GetMusic(const char *fileName) { + return get()._getMusic(fileName); + } + + /** + * @brief Retrieves a sound asset. + * + * @param fileName The filename of the sound asset. + * @return The sound asset. + */ + static Sound GetSound(const char *fileName) { + return get()._getSound(fileName); + } + + + static std::unordered_map &GetLoadedMusics() { + return get()._musics; + } + + +private: + // Textures + + Texture _getTexture(const std::string &fileName); + + Texture _loadTexture(const std::string &fileName); + + Texture _createEmptyTexture(const vf2d &size); + + void _saveTextureAsPNG(Texture texture, const char *fileName); + + // Fonts + + Font _getFont(const std::string &fileName, int fontSize); + + // Audio + + Sound _getSound(const std::string &fileName); + + Music _getMusic(const std::string &fileName); + + //Containers + + std::unordered_map _fonts; + std::unordered_map _musics; + std::unordered_map _sounds; + std::unordered_map _textures; + +public: + AssetHandler(const AssetHandler &) = delete; + + static AssetHandler &get() { + static AssetHandler instance; + return instance; + } + +private: + AssetHandler() = default; +}; + +//*/ \ No newline at end of file diff --git a/texture/stb_image_write.h b/assethandler/stb_image_write.h similarity index 100% rename from texture/stb_image_write.h rename to assethandler/stb_image_write.h diff --git a/assettypes/music.h b/assettypes/music.h index ad1e5c1..200f133 100644 --- a/assettypes/music.h +++ b/assettypes/music.h @@ -4,10 +4,15 @@ /** * @brief Represents a music asset for playing audio using miniaudio. + * @typedef Music Music */ -struct Music { +struct MusicAsset { ma_sound *music = nullptr; /**< Pointer to the audio data loaded with miniaudio. */ bool shouldPlay = false; /**< Flag indicating whether the music should play. */ bool started = false; /**< Flag indicating whether the music playback has started. */ -}; \ No newline at end of file + + bool isSame = false; +}; + +using Music = MusicAsset&; \ No newline at end of file diff --git a/audio/audiohandler.cpp b/audio/audiohandler.cpp index 2a28851..d95c17c 100644 --- a/audio/audiohandler.cpp +++ b/audio/audiohandler.cpp @@ -4,63 +4,16 @@ #include "miniaudio.h" -Sound Audio::_getSound(const char *fileName) { - if (_sounds.find(fileName) == _sounds.end()) { - Sound _sound; - _sound.sound = new ma_sound(); - ma_result result = ma_sound_init_from_file(&engine, fileName, MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, nullptr, nullptr, _sound.sound); +#include "assethandler/assethandler.h" - if (result != MA_SUCCESS) { - std::string error = Helpers::TextFormat("GetSound failed: %s", fileName); - - SDL_Log(error.c_str()); - throw std::runtime_error(error.c_str()); - } - - _sounds[fileName] = _sound; - - return _sounds[fileName]; - } else { - return _sounds[fileName]; - } -} - -Music Audio::_getMusic(const char *fileName) { - if (_musics.find(fileName) == _musics.end()) { - Music _music; - - _music.music = new ma_sound(); - ma_result result = ma_sound_init_from_file(&engine, fileName, MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, nullptr, nullptr, _music.music); - - if (result != MA_SUCCESS) { - std::string error = Helpers::TextFormat("GetMusic failed: %s", fileName); - - SDL_Log(error.c_str()); - throw std::runtime_error(error.c_str()); - } - - _musics[fileName] = _music; - - return _musics[fileName]; - } else { - return _musics[fileName]; +void Audio::_playSound(Sound sound) { + if (ma_sound_is_playing(sound.sound)) { + ma_sound_seek_to_pcm_frame(sound.sound, 0); + return; } -} -void Audio::_playSound(const char *fileName) { - if (_sounds.find(fileName) == _sounds.end()) { - static_assert(true, "File not loaded yet."); - } else { - - if (ma_sound_is_playing(_sounds[fileName].sound)) { - ma_sound_seek_to_pcm_frame(_sounds[fileName].sound, 0); - return; - } - - ma_sound_set_looping(_sounds[fileName].sound, false); - ma_sound_start(_sounds[fileName].sound); - - } + ma_sound_set_looping(sound.sound, false); + ma_sound_start(sound.sound); } void Audio::_updateMusicStreams() { @@ -68,7 +21,7 @@ void Audio::_updateMusicStreams() { ma_resource_manager_process_next_job(&resourceManager); #endif - for (auto &music: _musics) { + for (auto &music: AssetHandler::GetLoadedMusics()) { if (music.second.shouldPlay) { // if(ma_sound_is_playing(music.second.music)) @@ -86,7 +39,7 @@ void Audio::_updateMusicStreams() { } void Audio::_stopMusic() { - for (auto &music: _musics) { + for (auto& music: AssetHandler::GetLoadedMusics()) { if (music.second.shouldPlay) { music.second.shouldPlay = false; ma_sound_stop(music.second.music); @@ -96,28 +49,23 @@ void Audio::_stopMusic() { } bool Audio::_isMusicPlaying() { - for (const auto &music: _musics) { + for (const auto &music: AssetHandler::GetLoadedMusics()) { if (music.second.shouldPlay) return true; } return false; } -void Audio::_playMusic(const char *fileName) { - if (_musics.find(fileName) == _musics.end()) { - static_assert(true, "File not loaded yet."); - } else { - _musics[fileName].shouldPlay = true; - if (!_musics[fileName].started) { - if (ma_sound_is_playing(_musics[fileName].music)) { - ma_sound_seek_to_pcm_frame(_musics[fileName].music, 0); - return; - } - - ma_sound_set_looping(_musics[fileName].music, true); - ma_sound_start(_musics[fileName].music); +void Audio::_playMusic(Music &music) { +music.isSame = true; + music.shouldPlay = true; + if (!music.started) { + if (ma_sound_is_playing(music.music)) { + ma_sound_seek_to_pcm_frame(music.music, 0); + return; } - + ma_sound_set_looping(music.music, true); + ma_sound_start(music.music); } } diff --git a/audio/audiohandler.h b/audio/audiohandler.h index 073ba25..9be8835 100644 --- a/audio/audiohandler.h +++ b/audio/audiohandler.h @@ -40,33 +40,13 @@ class Audio { get()._stopMusic(); } - /** - * @brief Retrieves a music asset. - * - * @param fileName The filename of the music asset. - * @return The music asset. - */ - static Music GetMusic(const char *fileName) { - return get()._getMusic(fileName); - } - - /** - * @brief Retrieves a sound asset. - * - * @param fileName The filename of the sound asset. - * @return The sound asset. - */ - static Sound GetSound(const char *fileName) { - return get()._getSound(fileName); - } - /** * @brief Plays music from the specified file. * * @param fileName The filename of the music to play. */ - static void PlayMusic(const char *fileName) { - get()._playMusic(fileName); + static void PlayMusic(Music &music) { + get()._playMusic(music); } /** @@ -74,8 +54,8 @@ class Audio { * * @param fileName The filename of the sound effect to play. */ - static void PlaySound(const char *fileName) { - get()._playSound(fileName); + static void PlaySound(Sound sound) { + get()._playSound(sound); } /** @@ -87,15 +67,15 @@ class Audio { return get()._isMusicPlaying(); } -private: - std::unordered_map _sounds; - std::unordered_map _musics; + static ma_engine* GetAudioEngine() { + return &get().engine; + } + - Sound _getSound(const char *fileName); - Music _getMusic(const char *fileName); +private: - void _playSound(const char *fileName); + void _playSound(Sound sound); void _updateMusicStreams(); @@ -103,7 +83,7 @@ class Audio { bool _isMusicPlaying(); - void _playMusic(const char *fileName); + void _playMusic(Music music); void _init(); diff --git a/log/loghandler.cpp b/log/loghandler.cpp index eb303d6..c90c7db 100644 --- a/log/loghandler.cpp +++ b/log/loghandler.cpp @@ -1,9 +1,10 @@ #include "loghandler.h" #include "text/texthandler.h" +#include "assethandler/assethandler.h" void Log::_addLine(const char *line1, const char *line2) { - auto font = Text::GetFont("assets/fonts/APL386.ttf", 20); + auto font = AssetHandler::GetFont("assets/fonts/APL386.ttf", 20); headerWidth = std::max(Text::MeasureText(font, line1), headerWidth); diff --git a/luminoveau.h b/luminoveau.h index 9ab41c8..36e449b 100644 --- a/luminoveau.h +++ b/luminoveau.h @@ -7,12 +7,12 @@ #include //Engine components +#include #include