diff --git a/include/Nazara/Core/ResourceLoader.hpp b/include/Nazara/Core/ResourceLoader.hpp index c2139cfec..83a3f8ce5 100644 --- a/include/Nazara/Core/ResourceLoader.hpp +++ b/include/Nazara/Core/ResourceLoader.hpp @@ -20,6 +20,7 @@ class NzResourceLoader public: using ExtensionGetter = bool (*)(const NzString& extension); using FileLoader = bool (*)(Type* resource, const NzString& filePath, const Parameters& parameters); + using MemoryLoader = bool (*)(Type* resource, const void* data, std::size_t size, const Parameters& parameters); using StreamChecker = nzTernary (*)(NzInputStream& stream, const Parameters& parameters); using StreamLoader = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters); @@ -29,10 +30,10 @@ class NzResourceLoader static bool LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters = Parameters()); static bool LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters = Parameters()); - static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); - static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); + static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr); + static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr); - using Loader = std::tuple; + using Loader = std::tuple; using LoaderList = std::list; }; diff --git a/include/Nazara/Core/ResourceLoader.inl b/include/Nazara/Core/ResourceLoader.inl index 8e4fef13d..e716434d0 100644 --- a/include/Nazara/Core/ResourceLoader.inl +++ b/include/Nazara/Core/ResourceLoader.inl @@ -117,9 +117,77 @@ bool NzResourceLoader::LoadFromFile(Type* resource, const NzSt template bool NzResourceLoader::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters) { + #if NAZARA_CORE_SAFE + if (!parameters.IsValid()) + { + NazaraError("Invalid parameters"); + return false; + } + + if (size == 0) + { + NazaraError("No data to load"); + return false; + } + #endif + NzMemoryStream stream(data, size); - return LoadFromStream(resource, stream, parameters); + bool found = false; + for (Loader& loader : Type::s_loaders) + { + StreamChecker checkFunc = std::get<1>(loader); + StreamLoader streamLoader = std::get<2>(loader); + MemoryLoader memoryLoader = std::get<4>(loader); + + nzTernary recognized = nzTernary_Unknown; + if (memoryLoader) + { + if (checkFunc) + { + stream.SetCursorPos(0); + + recognized = checkFunc(stream, parameters); + if (recognized == nzTernary_False) + continue; + else + found = true; + } + else + { + recognized = nzTernary_Unknown; + found = true; + } + + if (memoryLoader(resource, data, size, parameters)) + return true; + } + else + { + stream.SetCursorPos(0); + + recognized = checkFunc(stream, parameters); + if (recognized == nzTernary_False) + continue; + else if (recognized == nzTernary_True) + found = true; + + stream.SetCursorPos(0); + + if (streamLoader(resource, stream, parameters)) + return true; + } + + if (recognized == nzTernary_True) + NazaraWarning("Loader failed"); + } + + if (found) + NazaraError("Failed to load file: all loaders failed"); + else + NazaraError("Failed to load file: no loader found"); + + return false; } template @@ -175,7 +243,7 @@ bool NzResourceLoader::LoadFromStream(Type* resource, NzInputS } template -void NzResourceLoader::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) +void NzResourceLoader::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader) { #if NAZARA_CORE_SAFE if (streamLoader) @@ -186,20 +254,20 @@ void NzResourceLoader::RegisterLoader(ExtensionGetter extensio return; } } - else if (!fileLoader) + else if (!fileLoader && !memoryLoader) { - NazaraError("Neither FileLoader nor StreamLoader were present"); + NazaraError("Neither FileLoader nor MemoryLoader nor StreamLoader were present"); return; } #endif - Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); + Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader)); } template -void NzResourceLoader::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) +void NzResourceLoader::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader) { - Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); + Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader)); } #include diff --git a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp index d60d4e2de..918455ecd 100644 --- a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp +++ b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp @@ -106,13 +106,21 @@ namespace bool Open(const NzString& filePath, bool forceMono) { - if (!m_file.Open(filePath, NzFile::ReadOnly)) + std::unique_ptr file(new NzFile); + if (!file->Open(filePath, NzFile::ReadOnly)) { NazaraError("Failed to open stream from file: " + NzError::GetLastError()); return false; } + m_ownedStream = std::move(file); - return Open(m_file, forceMono); + return Open(*m_ownedStream, forceMono); + } + + bool Open(const void* data, std::size_t size, bool forceMono) + { + m_ownedStream.reset(new NzMemoryStream(data, size)); + return Open(*m_ownedStream, forceMono); } bool Open(NzInputStream& stream, bool forceMono) @@ -185,8 +193,8 @@ namespace private: std::vector m_mixBuffer; + std::unique_ptr m_ownedStream; nzAudioFormat m_format; - NzFile m_file; SNDFILE* m_handle; bool m_mixToMono; unsigned int m_duration; @@ -243,6 +251,28 @@ namespace return true; } + bool LoadMusicMemory(NzMusic* music, const void* data, std::size_t size, const NzMusicParams& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr musicStream(new sndfileStream); + if (!musicStream->Open(data, size, parameters.forceMono)) + { + NazaraError("Failed to open music stream"); + return false; + } + + if (!music->Create(musicStream.get())) + { + NazaraError("Failed to create music"); + return false; + } + + musicStream.release(); + + return true; + } + bool LoadMusicStream(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) { NazaraUnused(parameters); @@ -342,12 +372,12 @@ namespace void NzLoaders_sndfile_Register() { - NzMusicLoader::RegisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); + NzMusicLoader::RegisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile, LoadMusicMemory); NzSoundBufferLoader::RegisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); } void NzLoaders_sndfile_Unregister() { - NzMusicLoader::UnregisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); + NzMusicLoader::UnregisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile, LoadMusicMemory); NzSoundBufferLoader::UnregisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); } diff --git a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp index 1bf65dcbd..435ec0023 100644 --- a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp +++ b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp @@ -9,6 +9,7 @@ #include FT_OUTLINE_H #include #include +#include #include #include #include @@ -260,16 +261,24 @@ namespace bool SetFile(const NzString& filePath) { - if (!m_file.Open(filePath, NzFile::ReadOnly)) + std::unique_ptr file(new NzFile); + if (!file->Open(filePath, NzFile::ReadOnly)) { NazaraError("Failed to open stream from file: " + NzError::GetLastError()); return false; } + m_ownedStream = std::move(file); - SetStream(m_file); + SetStream(*m_ownedStream); return true; } + void SetMemory(const void* data, std::size_t size) + { + m_ownedStream.reset(new NzMemoryStream(data, size)); + SetStream(*m_ownedStream); + } + void SetStream(NzInputStream& stream) { m_stream.base = nullptr; @@ -303,7 +312,7 @@ namespace FT_Open_Args m_args; FT_Face m_face; FT_StreamRec m_stream; - NzFile m_file; + std::unique_ptr m_ownedStream; mutable unsigned int m_characterSize; }; @@ -357,6 +366,28 @@ namespace return false; } + bool LoadMemory(NzFont* font, const void* data, std::size_t size, const NzFontParams& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr face(new FreeTypeStream); + face->SetMemory(data, size); + + if (!face->Open()) + { + NazaraError("Failed to open face"); + return false; + } + + if (font->Create(face.get())) + { + face.release(); + return true; + } + else + return false; + } + bool LoadStream(NzFont* font, NzInputStream& stream, const NzFontParams& parameters) { NazaraUnused(parameters); @@ -383,7 +414,7 @@ namespace void NzLoaders_FreeType_Register() { if (FT_Init_FreeType(&s_library) == 0) - NzFontLoader::RegisterLoader(IsSupported, Check, LoadStream, LoadFile); + NzFontLoader::RegisterLoader(IsSupported, Check, LoadStream, LoadFile, LoadMemory); else { s_library = nullptr; // On s'assure que le pointeur ne pointe pas sur n'importe quoi @@ -395,7 +426,7 @@ void NzLoaders_FreeType_Unregister() { if (s_library) { - NzFontLoader::UnregisterLoader(IsSupported, Check, LoadStream, LoadFile); + NzFontLoader::UnregisterLoader(IsSupported, Check, LoadStream, LoadFile, LoadMemory); FT_Done_FreeType(s_library); s_library = nullptr;